eva-agent/ARCHITECTURE.md
Andrey Epifancev acdd52742e check, README, сквозной прогон с хабом (#1)
cmd_check проверяет хаб и Eva (код 0 или 3), флаг run --once,
scripts/e2e-hub.sh поднимает тестовый хаб во временном JIRA_HUB_HOME.
Решения 33–35 в design.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 05:32:32 +04:00

45 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Архитектура
Агент — один файл `src/agent.py` и запускатель `src/run.py` (Python 3.9, только стандартная библиотека). Тесты в
`tests/` работают на фейках хаба и Eva. Спека: `../jira-hub/openspec/changes/wiki-module/`; решения агента:
`openspec/changes/eva-agent-mvp/design.md`. Общие части — копия jira-agent v14 (`../jira-agent/ARCHITECTURE.md`).
## Разделы файла `src/agent.py`
| Раздел | Классы и функции | Ответственность | Что использует |
|---|---|---|---|
| Настройки | `load_config` | читает `agent.json`, проверяет обязательные поля (`hub_url`, `hub_token`, `eva.base_url`, `eva.token`) | — |
| Самообновление (состояние) | `read_update_state`, `write_update_state` | `update.json` рядом с `agent.py` | `os`, `json` |
| HTTP | `Http`, `HttpError`, `RedirectAway`, `TooBig`, `_SameOriginRedirect` | запросы; `Http.send` — запрос с готовым телом; `fetch_bytes` — содержимое файла байтами, не больше предела; перенаправление на другой адрес — `RedirectAway` без перехода | `urllib` |
| Eva | `EvaClient` | клиент Eva (Bearer-токен): счётчики вызовов и 429, время последнего вызова. Каркас; JSON-RPC и повторы — в задачах 2–3 | `Http` |
| Папка | `FolderTransport` | транспорт `folder:` к хабу через общую папку: `req/<id>.json` → реле хаба → `resp/<id>.json`; ошибки как у `Http` | `os`, `uuid` |
| Хаб | `HubClient` | `claim`, `release`, `settings`, `command`, `result`, `upload_file` (`POST /agent/files`), `wiki_pages` (`POST /agent/wiki/pages`); при `hub_url = folder:…` делегирует `FolderTransport` | `Http`, `FolderTransport` |
| Журнал | `Journal`, `_parse_at` | дозапись `journal.jsonl`: `claimed` → `started` → `finished` → `acked`; восстановление; `prune` | файловая система |
| Исполнитель | `Executor`, `HubError` | по методу `do_<тип>` на команду: `do_wiki_sync`, `do_wiki_fetch` (в каркасе — `failed` «не реализовано»); сбой хаба внутри команды — `HubError` | `EvaClient`, `HubClient` |
| Самообновление | `Updater`, `launcher_version` | после `claim` без команды — проверка `agent_release`, скачивание, sha256, компиляция, `selftest`, `staged`; подтверждение `ok` новой версией | `HubClient`, `subprocess` |
| Цикл | `Runner` | claim, пауза до команды (по времени последнего вызова Eva), журнал, выполнение, отчёт до подтверждения, восстановление при старте; выход `EXIT_UPDATE` (75) | `HubClient`, `EvaClient`, `Journal`, `Executor` |
| CLI | `cmd_run`, `cmd_check`, `cmd_selftest`, `cmd_prune`, `main`, `acquire_lock` | команды `run` (`--once` — выйти при первом пустом claim), `check` (хаб `GET /agent/settings` + Eva `CmfDocument.list`; код 0 или 3), `selftest`, `prune` (`run` и `prune` берут блокировку `<журнал>.lock`); сигналы | `Runner`, `Journal` |
## Запускатель `src/run.py`
Дословная копия запускателя jira-agent (`LAUNCHER_VERSION = 2`, переменная окружения `JIRA_AGENT_LAUNCHER`). Не импортирует
`agent.py`. Запускает `agent.py run` дочерним процессом; код 75 — подмена на `agent.py.new` с пробным периодом и
откатом; иначе перезапуск с паузой. Проверка идентичности — `test_run_py_is_copy`.
## Границы
- Код новой версии приходит только через API хаба (`GET /agent/release`); общая папка для кода не используется.
- Токены хаба и Eva — только в `agent.json`; в журнал, хаб, логи и тексты ошибок не попадают.
- Темп вызовов Eva задаёт хаб (`wiki_pacing` в `GET /agent/settings`), агент его не хранит.
- Одна команда в полёте: следующая берётся после выполнения и подтверждения отчёта.
- Отчёт до подтверждения: `send_result` повторяет каждые 10 с; 404/409/422 от хаба считаются закрытием.
- Команды только читают Eva, поэтому после перезапуска выполняются заново (design 9).
- Поля протокола `jira_calls`/`rate_limited` — общие для агентов хаба; агент кладёт в них число вызовов Eva и 429.
- Тесты не ходят во внешние сервисы.
## Сквозной прогон
`scripts/e2e-hub.sh`: настоящий хаб (`jira-hub serve` из worktree `jira-hub/.wt/wiki`, временный `JIRA_HUB_HOME`, свободный
порт) + `scripts/fake_eva_serve.py` + `agent.py run --once` по HTTP. Живой хаб и его данные не затрагиваются.
## Открытые вопросы
- Живая проверка на виртуалке с настоящей Eva (после merge hub#92).