feat(opencode): переход на v2 HTTP API opencode (хардпин модели, поллинг вердикта)
- 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)
This commit is contained in:
31
README.md
31
README.md
@@ -17,7 +17,7 @@ internal/
|
||||
analyst/ # аналитик: промпт + разбор JSON-решения (opencode agent, классы A1–A4)
|
||||
worker/ # polling-планировщик + dev/reviewer-конвейер (классы W*, E*, R*)
|
||||
agents/ # встроенные агенты opencode (analyst.md, dev.md, reviewer.md) через go:embed
|
||||
opencode/ # обёртка запуска opencode-процесса, парсинг вердикта (классы O1–O4)
|
||||
opencode/ # HTTP-клиент v2 API opencode serve, поллинг вердикта (классы O1–O5)
|
||||
storage/ # SQLite (modernc.org/sqlite, без CGO): tasks, traces, task_history (S1–S5)
|
||||
update/ # автообновление из Gitea Packages (классы U1–U6)
|
||||
```
|
||||
@@ -129,6 +129,33 @@ update:
|
||||
| `/status` | версия бинаря + есть ли доступное обновление |
|
||||
| `/help` | справка по всем командам |
|
||||
|
||||
## Интеграция с opencode (субагенты)
|
||||
|
||||
Субагенты (analyst / dev / reviewer) запускаются через **headless** `opencode serve`
|
||||
по **v2 HTTP API** (префикс `/api/*`). Требуемая версия opencode: **>= 1.18.18**
|
||||
(сборки с v2 HTTP API). Старый бинарь, отвечающий только на `/global/health`,
|
||||
не подходит: healthcheck падает с понятной ошибкой (класс O1).
|
||||
|
||||
Что делает обёртка (`internal/opencode`):
|
||||
|
||||
- **Хардпин модели.** При создании сессии в конфиге opencode ищется top-level
|
||||
`"model"` (`internal/opencode/config.go`) и передаётся в `POST /api/session`
|
||||
как `{"model":{providerID,id}}`. Это убирает зависимость от fallback-логики
|
||||
opencode (которая молча выбирает «дефолтную» запись, если модель не задана).
|
||||
- **Весь код резолва модели устойчив к этому классу проблем (класс O5 WARN):**
|
||||
- если конфиг не читается / в нём нет `model` — в логи пишется warning;
|
||||
- фактическая модель ответа (из финального assistant-сообщения) сравнивается
|
||||
с ожидаемой; расхождение логируется как warning;
|
||||
- конфиг, написанный по **старой v1-схеме** (`provider.X.npm` / `options`),
|
||||
молча игнорируется v2 — обёртка этого не «чинит» сама, но предупреждает.
|
||||
Правильный v2-вид провайдера — `api: { type:"aisdk", package, url }` и
|
||||
`request.headers` вместо `options.headers`.
|
||||
- **Поллинг вердикта.** Промпт отправляется неблокирующе (`POST .../prompt` →
|
||||
durable admit), вердикт собирается из новых assistant-сообщений
|
||||
(`GET .../message`); завершение ответа — сессия ушла из активных дренажей
|
||||
(`GET .../active`) и появилось финальное assistant-сообщение, стабильное
|
||||
несколько опросов подряд.
|
||||
|
||||
## Фазы аналитика
|
||||
|
||||
Аналитик (`internal/analyst`) возвращает JSON-вердикт с полем `phase`:
|
||||
@@ -198,7 +225,7 @@ curl -s -H "Authorization: token $TOKEN" "$B/api/packages/kamelion/generic/ratat
|
||||
| C | C1–C4 | `internal/config` |
|
||||
| A | A1–A4 | `internal/analyst` |
|
||||
| M | M1–M5 | `internal/chat` |
|
||||
| O | O1–O4 | `internal/opencode` |
|
||||
| O | O1–O5 | `internal/opencode` |
|
||||
| S | S1–S5 | `internal/storage` |
|
||||
| W | W1–W5 | `internal/worker` |
|
||||
| E | E1–E4 | `internal/worker` (репозитории) |
|
||||
|
||||
Reference in New Issue
Block a user