feat(watch,server): t3_watch to turn thread events off and back on

This commit is contained in:
hh
2026-09-01 13:37:04 +00:00
parent a98211b79f
commit a29c526ee9
5 changed files with 159 additions and 11 deletions
+3 -2
View File
@@ -8,15 +8,16 @@ MCP-коннектор к серверам [T3 Code](https://github.com/pingdotg
|---|---|
| `t3_machines()` | машины из конфига, кто сейчас online (`/.well-known/t3/environment`), allowlist проектов |
| `t3_projects(machine)` | проекты машины, прошедшие allowlist: путь, модель по умолчанию, число тредов |
| `t3_dispatch(machine, project, prompt, title?, model?, thread_id?)` | `thread.create` + `thread.turn.start` (или только `turn.start` в существующий тред) → `thread_id` сразу |
| `t3_dispatch(machine, project, prompt, title?, model?, thread_id?, watch?)` | `thread.create` + `thread.turn.start` (или только `turn.start` в существующий тред) → `thread_id` сразу; `watch=false` - не слать по треду события |
| `t3_thread(thread_id, turns?)` | состояние без ожидания: тёрн, сессия, последние сообщения, тулзы, файлы, `pending` (вопрос/аппрув) |
| `t3_wait(thread_id, timeout?)` | блокируется до `completed` / `interrupted` / `error`, вопроса или таймаута; та же вьюха |
| `t3_answer(thread_id, answers)` | `thread.user-input.respond` на висящий вопрос треда (`answers`: id вопроса → label, список для multi_select) |
| `t3_interrupt(thread_id)` | `thread.turn.interrupt` |
| `t3_watch(thread_id?, enabled?)` | без аргументов - списки `watched` / `unwatched`; с обоими - включить или выключить события по треду |
## События
Коннектор держит WS-подписку `orchestration.subscribeShell` на каждую машину (Effect RPC поверх JSON: `Request``Chunk` + `Ack`, `Ping` раз в 20 с, реконнект с `afterSequence`, снапшот при реконнекте переигрывает пропущенное). Треды, запущенные через `t3_dispatch`, отслеживаются (`T3CODE_MCP_STATE`, json на volume); переходы `running → completed/interrupted/error` и появление вопроса (`hasPendingUserInput`) превращаются в события `completed` / `interrupted` / `failed` / `question` и уходят `POST` в `T3CODE_MCP_HOOK_URL` (gateway `/hooks/t3code`, bearer `T3CODE_MCP_GATEWAY_TOKEN`, scope `api`) через persisted outbox с ретраями. Gateway делает из события инжект в мастер (`beaver-agent/config.py`, job `t3code`).
Коннектор держит WS-подписку `orchestration.subscribeShell` на каждую машину (Effect RPC поверх JSON: `Request``Chunk` + `Ack`, `Ping` раз в 20 с, реконнект с `afterSequence`, снапшот при реконнекте переигрывает пропущенное). Треды, запущенные через `t3_dispatch`, отслеживаются (`T3CODE_MCP_STATE`, json на volume); переходы `running → completed/interrupted/error` и появление вопроса (`hasPendingUserInput`) превращаются в события `completed` / `interrupted` / `failed` / `question` и уходят `POST` в `T3CODE_MCP_HOOK_URL` (gateway `/hooks/t3code`, bearer `T3CODE_MCP_GATEWAY_TOKEN`, scope `api`) через persisted outbox с ретраями. Gateway делает из события инжект в мастер (`beaver-agent/config.py`, job `t3code`). Подписка включается на каждый `t3_dispatch` (в том числе на продолжение треда); снять её - `t3_watch(thread_id, enabled=false)` или сразу `t3_dispatch(..., watch=false)`: тред продолжает работать, просто молча.
`t3_wait` - обычный долгий вызов, не MCP Task: Claude Code расширение Tasks не поддерживает, зато сам уводит вызов дольше двух минут в фоновую задачу (`CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS`). Треды бегут в `full-access` без аппрувов; тред ищется по всем машинам, если коннектор перезапускался.