Commit Graph

107 Commits

Author SHA1 Message Date
ki.sagidullin
cd0619926e perf(chat,update): пул воркеров per-user вместо сериальной очереди + HEAD-проба обновлений
Some checks failed
CI / test (push) Failing after 1m15s
CI / build-and-package (amd64, linux) (push) Failing after 58s
CI / build-and-package (amd64, windows) (push) Successful in 30s
- chat.Router: ограниченный пул chatWorkers=4 воркеров + FIFO-очереди
  per-user (userState/workerLoop/runUser). Порядок сообщений одного UserID
  сохраняется; разные пользователи обрабатываются параллельно (до 4
  одновременных LLM-вызовов), long-poll Telegram не блокируется чужим
  аналитиком. Backpressure по jobs — только на перегруженного пользователя.
- app.FreeChat: sessions под sync.Mutex (защита от data race при параллельных
  воркерах роутера).
- update: ResolveLatest проверяет наличие бинаря HEAD-пробой без скачивания
  тела (fallback GET Range 0-0 при 405/501), сортировка версий по id убыв.;
  один общий http.Client (keep-alive) вместо нового на каждый запрос.
- тесты: порядок/параллелизм per-user в router, HEAD-без-тела и фоллбэк на
  версию без бинаря в update.
- память Serena: инварианты Router/update, примечания по форматированию на Windows.
2026-08-22 11:44:34 +05:00
ki.sagidullin
2854697415 chore(opencode): не логировать тела API-запросов/ответов, только метаданные
Some checks failed
CI / test (push) Failing after 1m18s
CI / build-and-package (amd64, linux) (push) Failing after 57s
CI / build-and-package (amd64, windows) (push) Successful in 29s
2026-08-22 10:15:30 +05:00
ki.sagidullin
ef812bb3d7 feat(ui): кнопка «Перезапустить» — полный аналог /retry N
Some checks failed
CI / test (push) Failing after 1m14s
CI / build-and-package (amd64, linux) (push) Failing after 59s
CI / build-and-package (amd64, windows) (push) Successful in 30s
2026-08-22 00:32:06 +05:00
23bae9a68f Merge pull request 'perf(ui): инкрементальный рендер ленты логов (дельта вместо полного пересбора)' (#13) from feat/213d506fe05a8608 into main
Some checks failed
CI / test (push) Failing after 1m12s
CI / build-and-package (amd64, linux) (push) Failing after 1m5s
CI / build-and-package (amd64, windows) (push) Successful in 40s
Reviewed-on: http://gitea.hal9000.home/kamelion/ratatoskr-go/pulls/13
2026-08-22 00:10:58 +05:00
ki.sagidullin
70287140ec perf(ui): инкрементальный рендер ленты логов (дельта вместо полного пересбора)
Some checks failed
CI / test (pull_request) Failing after 1m14s
CI / build-and-package (amd64, linux) (pull_request) Failing after 1m3s
CI / build-and-package (amd64, windows) (pull_request) Successful in 28s
2026-08-21 23:59:59 +05:00
ki.sagidullin
d9d043ec8e feat(scripts): GCC_PATH из .gitea-creds для gcc в build-publish-ui.ps1
Some checks failed
CI / test (push) Failing after 1m14s
CI / build-and-package (amd64, linux) (push) Failing after 1m4s
CI / build-and-package (amd64, windows) (push) Successful in 25s
- проверка gcc перенесена после чтения creds (шаг 1a)
- GCC_PATH дописывается в PATH (абсолютный или относительно scripts/);
  без него — gcc из текущего PATH
- комментарии в шапку: GCC_PATH и уточнённый PROJECT_PATH
2026-08-21 23:12:20 +05:00
b87092aa98 Merge pull request 'feat(ui): filtr urovney logov + cap bufera 10MB' (#12) from feat/710a3625da1aa989 into main
Some checks failed
CI / test (push) Failing after 1m18s
CI / build-and-package (amd64, linux) (push) Failing after 1m2s
CI / build-and-package (amd64, windows) (push) Successful in 29s
2026-08-21 23:04:08 +05:00
ki.sagidullin
ee47785e1a perf(ui): кап буфера логов 10MB, O(1) вытеснение, дебаунс рендера
Some checks failed
CI / test (pull_request) Failing after 1m21s
CI / build-and-package (amd64, linux) (pull_request) Failing after 1m9s
CI / build-and-package (amd64, windows) (pull_request) Successful in 31s
- LogBuffer: ленивое вытеснение через start + инкрементальный total убирает
  O(n^2) копирование entries[1:] при большом числе записей
- LogPanel: лимит 10MB (maxLogBytes), перерисовка ленты коалесцируется
  (200мс) — строка не пересобирается на каждый append
- build-publish-ui.ps1: корень проекта задаётся через PROJECT_PATH в
  .gitea-creds (относительно scripts/), без него — папка рядом со скриптом
- тесты: живые записи Entries/Render, кап по байтам
2026-08-21 23:01:54 +05:00
ki.sagidullin
a762a1df80 feat(ui): фильтр уровней логов в панели «Логи» 2026-08-21 21:35:37 +05:00
ki.sagidullin
ee76f9d89f fix(ui): поле ввода композитора в центр (не за край окна)
Some checks failed
CI / test (push) Failing after 1m14s
CI / build-and-package (amd64, linux) (push) Failing after 1m4s
CI / build-and-package (amd64, windows) (push) Successful in 31s
2026-08-21 20:41:28 +05:00
ki.sagidullin
37cc29e4cd feat(ui): нативный максимум окна через Win32 (над панелью задач)
Some checks failed
CI / test (push) Failing after 1m20s
CI / build-and-package (amd64, linux) (push) Failing after 1m4s
CI / build-and-package (amd64, windows) (push) Successful in 29s
2026-08-21 20:14:43 +05:00
ki.sagidullin
180afb1336 chore(serena): актуализировать память cgo-winlibs-gcc (PATH не гарантирован) 2026-08-21 18:51:33 +05:00
0c88272bf0 Merge pull request 'feat(ui): каждая вкладка chat — независимая LLM-сессия' (#11) from feat/ui_llm_chat into main
Some checks failed
CI / test (push) Failing after 1m12s
CI / build-and-package (amd64, linux) (push) Failing after 58s
CI / build-and-package (amd64, windows) (push) Successful in 29s
Reviewed-on: http://gitea.hal9000.home/kamelion/ratatoskr-go/pulls/11
2026-08-21 18:44:27 +05:00
ki.sagidullin
9420b276e9 feat(ui): каждая вкладка chat — независимая LLM-сессия
Some checks failed
CI / test (pull_request) Failing after 1m20s
CI / build-and-package (amd64, linux) (pull_request) Failing after 1m2s
CI / build-and-package (amd64, windows) (pull_request) Successful in 36s
- ui.Session (UserID/Address/Title/BoundTask) + фабрики NewFreeSession/NewTaskSession и префикс ui://sess-*
- свободная вкладка без задачи: свой UserID, диалог с LLM в памяти (agent=chat, resume по sessionID)
- /start в свободной вкладке создаёт задачу с ChatID == UserID вкладки -> вкладка становится task-сессией
- desktop окно: container.AppTabs с вкладками, кнопка «Новый чат», маршрутизация Send/Ask/истории по Address вкладки
- app.FreeChat: in-memory связка uid -> opencode sessionID; роутинг свободного чата в handleIncoming
- агент chat.md + регистрация 'chat' в agents.Names
- тесты: session_test.go (фабрики/хелперы)
2026-08-21 10:33:05 +05:00
de21ec9f31 Merge pull request 'feat/project_utils' (#10) from feat/project_utils into main
Some checks failed
CI / test (push) Failing after 1m12s
CI / build-and-package (amd64, linux) (push) Failing after 59s
CI / build-and-package (amd64, windows) (push) Successful in 29s
Reviewed-on: http://gitea.hal9000.home/kamelion/ratatoskr-go/pulls/10
2026-08-21 00:10:21 +05:00
ki.sagidullin
5c82229a00 chore(serena): обновить память проекта (onboarding)
Some checks failed
CI / test (pull_request) Failing after 1m13s
CI / build-and-package (amd64, linux) (pull_request) Failing after 1m2s
CI / build-and-package (amd64, windows) (pull_request) Successful in 28s
2026-08-21 00:08:45 +05:00
ki.sagidullin
612446d65b chore(scripts): add build-publish-ui.ps1 2026-08-21 00:05:54 +05:00
307a2b4173 Merge pull request 'feat/ui-refactor' (#9) from feat/ui-refactor into main
Some checks failed
CI / test (push) Failing after 1m15s
CI / build-and-package (amd64, linux) (push) Failing after 1m1s
CI / build-and-package (amd64, windows) (push) Successful in 29s
Reviewed-on: http://gitea.hal9000.home/kamelion/ratatoskr-go/pulls/9
2026-08-21 00:00:18 +05:00
ki.sagidullin
8ba1a8aa00 refactor(ui): вынести панель «Состояние» (StatePanel) из монолита окна
Some checks failed
CI / test (pull_request) Failing after 1m17s
CI / build-and-package (amd64, linux) (pull_request) Failing after 1m2s
CI / build-and-package (amd64, windows) (pull_request) Successful in 28s
Спеца 12.13: интерфейс + Nil + чистые хелперы (StateText/TraceLine/
ActivityLine/TaskStatusText/StatusBadge/Itoa) в internal/ui/state_panel.go,
Fyne-реализация в internal/ui/desktop/state_panel.go. window.go — чистая
компоновка: все 5 панелей вынесены как контракты.
2026-08-20 23:54:27 +05:00
ki.sagidullin
5c93642cf8 refactor(ui): вынести панель «Диалог» (ChatPanel) из монолита окна
Спеца 12.12: интерфейс + Nil + FormatRole в internal/ui/chat_panel.go,
Fyne-реализация в internal/ui/desktop/chat_panel.go (транскрипт + композитор).
Окно как chat.Channel рендерит Send/Ask/историю через Append; state_panel
не трогаем.
2026-08-20 23:48:54 +05:00
ki.sagidullin
4c44956d3e refactor(ui): вынести панель «Детали задачи» (TaskDetailPanel) из монолита окна
Спеца 12.11: интерфейс + Nil + TaskDetailText в internal/ui/task_detail.go,
Fyne-реализация в internal/ui/desktop/task_detail_panel.go. selectTask
делегирует в панель; диалог и «Состояние» — отдельные панели, не трогаем.
2026-08-20 23:43:52 +05:00
ki.sagidullin
6274aad369 refactor(ui): вынести панель «Список задач» (TaskListPanel) из монолита окна
Спеца 12.10: интерфейс + Nil + TaskTitle в internal/ui/task_list_panel.go,
Fyne-реализация в internal/ui/desktop/task_list_panel.go. Состояние выбора
живёт в окне; выбранная строка подсвечивается (Select/Unselect).
2026-08-20 23:31:08 +05:00
ki.sagidullin
fdd73cab61 refactor(ui): вынести панель «Логи» (LogPanel) из монолита окна
Спеца 12.8-12.9: интерфейс + Nil в internal/ui/log_panel.go, Fyne-реализация
в internal/ui/desktop/log_panel.go, окно использует контракт вместо logsLbl.
2026-08-20 23:26:18 +05:00
60a6966a95 Merge pull request 'feat/new_ui' (#8) from feat/new_ui into main
Some checks failed
CI / test (push) Failing after 1m8s
CI / build-and-package (amd64, linux) (push) Failing after 58s
CI / build-and-package (amd64, windows) (push) Successful in 28s
Reviewed-on: http://gitea.hal9000.home/kamelion/ratatoskr-go/pulls/8
2026-08-20 14:50:07 +05:00
ki.sagidullin
c2272137b3 feat(ui): команды, snapshots, Fyne-окно и интеграция (--noui)
Some checks failed
CI / test (pull_request) Failing after 1m19s
CI / build-and-package (amd64, linux) (pull_request) Failing after 58s
CI / build-and-package (amd64, windows) (pull_request) Successful in 53s
Команды (спец 12.2):
- ui.Commands: действия UI → текстовые команды канала (start/cancel/skip/
  retry/continue/approve/send), единый путь через chat.Channel.
- ui.Window = chat.Channel + View; NilWindow для headless/тестов.

Snapshots (спец 12.5):
- ui.Store: чтение-модель, возвращает только копии (ListTasks/GetTask/
  GetHistory/GetTraces); ui.DBStore поверх storage.

Fyne-окно (internal/ui/desktop, build-tag cgo):
- список задач слева, сплиты рабочей области и панели «Логи»/«Состояние»,
  ввод+кнопки команд, тёмная тема, fullscreen, сохранение layout в
  Preferences, сворачивание при закрытии крестиком.
- Колбэки View через fyne.Do (спец 12.4).

Интеграция:
- app.New(..., noUI); флаг --noui; UI собирается только с cgo (ui_cgo/
  ui_noui фабрики), приложение headless без него.
- Run: окно блокирует главную горутину; «Завершить» → cancel → graceful
  shutdown (спец 12.6).
- go.mod: fyne.io/fyne/v2 v2.6.0 (direct).
2026-08-20 08:54:55 +05:00
ki.sagidullin
baf2ad7147 feat(ui): контроллер — подписчик шин и мост к Fyne-представлению
- View — интерфейс Fyne-слоя: колбэки на все доменные события + логи.
- Controller подписывается на доменную и логовую шины (через events.Hub)
  и диспатчит события в View; колбэки выполняются в горутинах Hub, поэтому
  реализация Fyne обязана обновлять виджеты через fyne.Do (спец 12.4).
- Close отписывает контроллер (сворачивание окна) без остановки Core.
- NilView — no-op для headless (--noui) и тестов.
- Юнит-тесты: доставка доменных/логовых событий, остановка после Close.
2026-08-20 08:15:42 +05:00
ki.sagidullin
66e40d384e feat(events): типизированный Hub — подписчик шины с диспетчеризацией
- Hub слушает *Bus в собственной горутине и вызывает зарегистрированные
  обработчики по типу события (On[T]); порядок сохраняется.
- Мост к UI: колбэки выполняются в горутине Hub → внутри можно переложить
  работу на поток Fyne (fyne.Do) или thread-safe binding.
- Close останавливает горутину и отписывается; Start идемпотентен.
- Юнит-тесты: доставка по типу, игнор посторонних типов, несколько
  обработчиков одного типа, остановка после Close.
2026-08-20 07:17:57 +05:00
ki.sagidullin
4957a5552e feat(events): внедрить Publisher в Core/Worker/Analyst + шины в app
- Core: setStatus публикует TaskStatusChanged на каждом переходе
  (handleStart/Cancel/Retry/Consent/Edit/Turn, runDecide).
- Worker: setStatus публикует TaskStatusChanged (running/timeout/failed/
  success, failTask), notify остаётся авто-уведомлением.
- Analyst: Decide публикует AgentActivity (stage=decide).
- app: создаёт доменную (256) и логовую (1024) шины, подключает их к
  Core/Worker/Analyst, редиректит log в обе (stderr + логовая шина).
2026-08-20 04:30:29 +05:00
ki.sagidullin
1f7ab9a67e feat(events): EventBus + domain-модель статусов
- internal/model: единый источник статусов задачи (Status, TraceStatus,
  машина переходов), без зависимости от storage.
- internal/storage: совместимый мост (type Status = model.Status,
  re-export констант) — внешний код не меняется.
- internal/events: шина событий (fan-out, блокирующий Publish с гарантией
  порядка), события задач/трейсов, отдельная логовая шина + LogWriter,
  Publisher/NilPublisher для внедрения в Core/Worker.
- docs/ui-spec.md: спецификация десктопного UI (Fyne).
2026-08-20 01:02:31 +05:00
408d137747 Merge pull request 'fix(opencode): считать реальный прогресс стрима для idle-детекции' (#7) from feat/3c8528d into main
All checks were successful
CI / test (push) Successful in 1m3s
CI / build-and-package (amd64, linux) (push) Successful in 54s
CI / build-and-package (amd64, windows) (push) Successful in 53s
Reviewed-on: http://gitea.hal9000.home/kamelion/ratatoskr-go/pulls/7
2026-08-19 19:12:56 +05:00
ki.sagidullin
be4d749c45 fix(opencode): считать реальный прогресс стрима для idle-детекции
All checks were successful
CI / test (pull_request) Successful in 1m9s
CI / build-and-package (amd64, linux) (pull_request) Successful in 53s
CI / build-and-package (amd64, windows) (pull_request) Successful in 52s
Растущий в один text-парт стрим (text-delta) и reasoning больше не
выглядят как зависшая нейронка: idle-таймер сбрасывается по росту
числа партов и суммарной длины text/reasoning.
2026-08-19 19:11:26 +05:00
0b31e18d85 Merge pull request 'test: починить тесты на Windows' (#6) from feat/3c8528d into main
All checks were successful
CI / test (push) Successful in 35s
CI / build-and-package (amd64, linux) (push) Successful in 45s
CI / build-and-package (amd64, windows) (push) Successful in 42s
Reviewed-on: http://gitea.hal9000.home/kamelion/ratatoskr-go/pulls/6
2026-08-19 10:50:23 +05:00
ki.sagidullin
b5fb583c90 test: починить тесты на Windows
All checks were successful
CI / test (pull_request) Successful in 41s
CI / build-and-package (amd64, linux) (pull_request) Successful in 37s
CI / build-and-package (amd64, windows) (pull_request) Successful in 34s
- E2E (app): e2eFakeAPI переведён на v2 HTTP API opencode (/api/*) с
  определением агента по тексту промпта; Router получает processed-счётчик
  и WaitProcessed, e2eChannel.deliver ждёт асинхронную обработку — убирает
  гонку «запрос сразу после deliver» и коллатеральный 'database is closed'.
- app_test: одинарные YAML-кавычки для путей Windows (backslash-escape) +
  закрытие Store в TestNew/TestNew_RunCtxCancel/TestNew_UpdateWiring.
- config_test: абсолютный путь строится с корнем тома (C:\...) и одинарными
  кавычками YAML.
- opencode/server_test: fakeServeBin на Windows — .cmd с ping (#!/bin/sh
  не исполняется).
- worker_test: TestWorkerSemaphore поллит до целевого статуса вместо
  фиксированных sleep (git на Windows медленнее).
2026-08-19 10:47:55 +05:00
3c8528dbd9 Merge pull request 'feat(opencode): переход на v2 HTTP API opencode (хардпин модели, поллинг вердикта)' (#5) from feat/ad025c1 into main
Some checks failed
CI / test (push) Failing after 30s
CI / build-and-package (amd64, linux) (push) Successful in 49s
CI / build-and-package (amd64, windows) (push) Successful in 52s
Reviewed-on: http://gitea.hal9000.home/kamelion/ratatoskr-go/pulls/5
2026-08-19 08:55:16 +05:00
ki.sagidullin
9f64be4ea5 feat(opencode): переход на v2 HTTP API opencode (хардпин модели, поллинг вердикта)
Some checks failed
CI / test (pull_request) Failing after 32s
CI / build-and-package (amd64, linux) (pull_request) Successful in 42s
CI / build-and-package (amd64, windows) (pull_request) Successful in 42s
- client.go: эндпоинты /api/* (create+model, prompt-admit, message, active, interrupt)
- runner.go: неблокирующий prompt + поллинг новых assistant-сообщений;
  завершение = сессия ушла из активных дренажей + стабильное финальное сообщение
- config.go: чтение top-level model из opencode.jsonc (JSONC-стрип) + хардпин в сессию
- server.go: healthcheck /api/health, MinVersion=1.18.18, понятная ошибка для старого бинаря
- класс O5 WARN: устойчивость к v1-конфигу провайдера (npm/options игнорируются v2)
- README: раздел интеграции, минимальная версия opencode, предупреждения
- .serena: актуализация памяти (core, tech_stack)
2026-08-19 08:29:11 +05:00
ad025c1668 Merge pull request 'refactor: чистка мёртвого кода, лимит ходов D3, HTML-экранирование и UTF-8 обрезка в Telegram' (#4) from feat/83bf5b6fbb8b238c into main
Some checks failed
CI / test (push) Failing after 31s
CI / build-and-package (amd64, linux) (push) Successful in 35s
CI / build-and-package (amd64, windows) (push) Successful in 35s
Reviewed-on: http://gitea.hal9000.home/kamelion/ratatoskr-go/pulls/4
2026-08-18 23:14:50 +05:00
ki.sagidullin
1459670ce9 refactor: чистка мёртвого кода, лимит ходов D3, HTML-экранирование и UTF-8 обрезка в Telegram
Some checks failed
CI / test (pull_request) Failing after 34s
CI / build-and-package (amd64, linux) (pull_request) Successful in 34s
CI / build-and-package (amd64, windows) (pull_request) Successful in 36s
2026-08-18 23:13:04 +05:00
Hermes
7eb3a0292c fix(opencode): убрать смешение слоёв API — перейти целиком на experimental (/session)
Some checks failed
CI / test (push) Failing after 32s
CI / build-and-package (amd64, linux) (push) Successful in 38s
CI / build-and-package (amd64, windows) (push) Successful in 38s
Корень проблемы «не получаем результаты»: клиент смешивал два слоя opencode
serve. CreateSession ходил на /api/session (v2, ждал {data.id}), Verdict — на
/api/session/{id}/message?order=desc и ждал {data:[{type,content}]}, где поле
content[].type/text физически отсутствует, поэтому вердикт никогда не находился
и поллинг уходил в вечный таймаут. Abort и вовсе звал несуществующий /interrupt.

Теперь весь код на experimental-слое, как сверено с sst/opencode (ветка dev):
- CreateSession: POST /session → голая Session, id в .id.
- Send: блокирующий POST /session/{id}/message, тело {parts:[{type:text,text}]},
  вердикт из частей parts[].type=="text" ответа. Это и есть результат — метод
  Verdict и отдельный GET удалены.
- textCount (прогресс): GET /session/{id}/message → голый массив [{info, parts}].
- Abort: POST /session/{id}/abort.

Runner: блокирующий Send запускается в горутине (канал вердикта/ошибки),
параллельно поллим textCount (рост text-частей сбрасывает idle-таймер). При
idle/hard-таймауте или отмене контекста — Abort + cancel() Send-горутины → rc=-1.

Send ходит через отдельный http.Client без жёсткого Timeout (управляется ctx),
чтобы длинная генерация не обрывалась на 30s. Тесты/fakeAPIServer переведены на
экспериментальный формат. Версия → 0.2.2.
2026-08-18 20:49:34 +05:00
Hermes
a64e3d6cc3 feat(chat): асинхронная обработка входящих — отзывчивый интерфейс
Some checks failed
CI / test (push) Failing after 31s
CI / build-and-package (amd64, linux) (push) Successful in 43s
CI / build-and-package (amd64, windows) (push) Successful in 43s
Router теперь обрабатывает входящие в воркер-горутине (FIFO-очередь с
буфером 256) вместо синхронного вызова onUserMsg из long-poll цикла
канала. Долгий вызов аналитика (Decide) больше не блокирует приём
новых сообщений от Telegram: цикл getUpdates продолжает работать.

- router.go: NewRouter запускает processLoop; handleIncoming кладёт
  событие в канал и возвращается; маршрутизация + pending по-прежнему
  обновляются синхронно под мьютексом.
- router_test.go: fakeOnMsg стал потокобезопасным с ожиданием числа
  входящих (wait), т.к. обработка теперь асинхронная.

Преимущества: интерфейс не замирает на время анализа; порядок входящих
сохраняется (FIFO). Ограничение: воркер один — при очень долгом аналитике
следующие сообщения ждут в очереди, но канал их продолжает принимать.
2026-08-18 19:55:46 +05:00
Hermes
774ebf135a fix(opencode): отправка сообщения — путь без /api (POST /session/:id/message)
All checks were successful
CI / test (push) Successful in 40s
CI / build-and-package (amd64, linux) (push) Successful in 35s
CI / build-and-package (amd64, windows) (push) Successful in 39s
Убран префикс /api из POST-запроса на отправку сообщения, чтобы
совпадать с фактическим роутом serve v1.18. GET чтения сообщений
остаётся на /api/session/:id/message.

- client.go: Send → POST /session/:id/message
- тесты: fakeAPIServer отвечает на POST /session/{id}/message (GET — /api)
2026-08-18 19:28:45 +05:00
Hermes
e1167c9537 feat(opencode): v1.18 — перейти с POST /session/:id/prompt на /session/:id/message
All checks were successful
CI / test (push) Successful in 40s
CI / build-and-package (amd64, linux) (push) Successful in 36s
CI / build-and-package (amd64, windows) (push) Successful in 36s
Промпт отправляется в /api/session/:id/message (v1.18) с новым форматом
тела parts:[{type:"text"}], вместо {prompt:{text}}. Причина перехода:
/prompt сам подставляет не ту модель, что в конфиге; /message использует
модель из конфига.

- client.go: Send → POST /message + тело parts; шапка-док v1.18
- тесты: fakeAPIServer + e2eFakeAPI отвечают на POST /message (GET уже был)
2026-08-18 18:58:23 +05:00
Hermes
ad9c2dd522 feat(config): уровень логирования log.level (info|debug), по умолчанию info
All checks were successful
CI / test (push) Successful in 41s
CI / build-and-package (amd64, linux) (push) Successful in 38s
CI / build-and-package (amd64, windows) (push) Successful in 35s
Отладочные логи API-вызовов к opencode serve теперь включаются только при
log.level=debug (гейт через Client.Debug <- Runner.Debug <- cfg.Log.Debug()).
По умолчанию 'info' — отладочных логов нет.

- config: добавлен LogCfg{Level}, дефолт 'info', валидация (info|debug)
- opencode: Client.Debug и Runner.Debug — гейттят логи do()
- app: Runner.Debug из cfg.Log.Debug()
- config.yaml.example: задокументирован log.level
- тесты: дефолт=info, level=debug, невалидный уровень
2026-08-18 18:44:37 +05:00
Hermes
f77a6000c7 build: bump version to 0.2.1
All checks were successful
CI / test (push) Successful in 41s
CI / build-and-package (amd64, linux) (push) Successful in 37s
CI / build-and-package (amd64, windows) (push) Successful in 36s
2026-08-18 18:32:04 +05:00
Hermes
ae00556923 feat(debug): логировать все API-вызовы к opencode serve с содержимым
All checks were successful
CI / test (push) Successful in 46s
CI / build-and-package (amd64, linux) (push) Successful in 44s
CI / build-and-package (amd64, windows) (push) Successful in 1m4s
В единой точке Client.do добавлены отладочные логи (всегда включены):
- строка вызова: opencode api <op> -> <METHOD> <url><path>
- тело запроса (усечено до 5000 байт)
- тело ответа 2xx (усечено до 5000 байт)
- тело ответа при ошибке/не-2xx (усечено до 1000 байт)

Нужно для диагностики проблемы аналитика (serve отвечал на модель
opencode/nemotron, ratatoskr не видел вердикт).
2026-08-18 18:23:56 +05:00
Hermes
baf7179085 fix: windows-сборка — заглушка setpgid/killGroup для отсутствия POSIX process-group
All checks were successful
CI / test (push) Successful in 40s
CI / build-and-package (amd64, linux) (push) Successful in 36s
CI / build-and-package (amd64, windows) (push) Successful in 36s
procgroup_unix.go имеет unix build-tag; под windows setpgid/killGroup не
определялись → GOOS=windows сборка падала. Добавлен procgroup_windows.go:
setpgid — no-op (нет Setpgid), killGroup — Process.Kill (дочерние группы не
завершаются).
2026-08-18 13:45:05 +05:00
Hermes
733e63339a feat: opencode через HTTP API — пул serve-серверов вместо spawn/NDJSON
Some checks failed
CI / test (push) Successful in 40s
CI / build-and-package (amd64, linux) (push) Successful in 35s
CI / build-and-package (amd64, windows) (push) Failing after 26s
Runner теперь ходит к постоянным serve по HTTP API (v1.17+, /api):
- клиент Client (create/send/wait/abort/messages/verdict)
- Pool: по одному serve на каталог, ленивый подъём, root-сервер в worktree,
  выделение портов, ReleaseTask при завершении задачи
- Run: CreateSession('ratatoskr-<агент>') -> Send -> поллинг Verdict из
  text-частей assistant-сообщений; idle/hard таймауты дают RC=-1
- вердикт извлекается из последнего assistant text-парта (плоский text)
- тесты: unit на фейковом HTTP-сервере; e2e эмулирует serve через httptest,
  агент определяется по title сессии
2026-08-18 13:36:54 +05:00
Hermes
b60978121d chore: bump version to 0.2.0
All checks were successful
CI / test (push) Successful in 39s
CI / build-and-package (amd64, linux) (push) Successful in 30s
CI / build-and-package (amd64, windows) (push) Successful in 30s
2026-08-18 08:59:42 +05:00
Hermes
2f26b6ae88 feat: opencode serve — постоянный сервер вместо разовых subprocess (вариант A)
Some checks failed
CI / test (push) Successful in 54s
CI / build-and-package (amd64, linux) (push) Failing after 1h58m55s
CI / build-and-package (amd64, windows) (push) Successful in 59s
Супервайзер Server spawn'ит opencode serve (или ходит на внешний URL),
Runner ходит к нему через 'opencode run --attach <url>'. По умолчанию
serve.enabled=false — историческая spawn-модель сохранена; наличие
serve.url переключает на внешний сервер.

- config: ServeCfg (enabled/hostname/port/url/password) + дефолты; лоадер
  научился int/bool (раньше только string/Duration/struct).
- opencode: Server (Start/Run/Close, /global/health, рестарт упавшего,
  reaper-горутина владеет Wait; .Exited() непригоден для SIGKILL).
- Runner.AttachURL: run --attach <url> при заданном URL, иначе как раньше.
- app: composition root — при включённом serve запускает супервайзер.
- тесты: TestRun_AttachMode, TestServer_{ExternalURL,OwnProcess,Restart}.
2026-08-18 08:35:16 +05:00
ed11879cbd Merge pull request 'feat: авто-уведомления о статусах и хендоффах задачи' (#3) from feat/48f52f8bf4354293 into main
All checks were successful
CI / test (push) Successful in 44s
CI / build-and-package (amd64, linux) (push) Successful in 38s
CI / build-and-package (amd64, windows) (push) Successful in 43s
Reviewed-on: http://gitea.hal9000.home/kamelion/ratatoskr-go/pulls/3
2026-08-17 23:54:45 +05:00
Hermes
631387fda7 fix: CI — тесты падали на сборке пакета app и на старом переходе
All checks were successful
CI / test (push) Successful in 49s
CI / build-and-package (amd64, linux) (push) Successful in 47s
CI / build-and-package (amd64, windows) (push) Successful in 46s
- e2e_channel.OnMessage принимал func(chat.Incoming), а интерфейс
  chat.Channel требует chat.Handler (named type) — пакет app не компилировался;
- storage_test готовил цепочку ready→running напрямую, но ready→running
  больше невалиден (нужен approved): вставлен переход approved.

Всё проверено локально: go build ./... + go test ./... зелёные.
2026-08-17 23:50:50 +05:00