Files
wiki/tasks/orchestrator/reports/dev-2026-06-05-orch41-agent-models.md
2026-06-05 19:20:02 +03:00

5.8 KiB
Raw Blame History

Dev Report: ORCH-41 — Конфигурируемые модели LLM + effort агентов

Дата: 2026-06-05 Статус: DONE

Задача

Вынести модель LLM и режим работы (--effort) агентов конвейера из хардкода src/agents/launcher.py в конфиг — per-agent (env) + per-project (projects_json). Репо orchestrator, ветка feat/ORCH-41-agent-models от main (HEAD 8da571d), PR в main, НЕ мержить.

Сделано

  • config.py: per-agent модель + effort + fallback (Settings, префикс ORCH_)
  • projects.py: ProjectConfig.agent_models / agent_efforts (frozen → field(default_factory=dict)) + парсинг из projects_json
  • launcher.py: резолверы resolve_agent_model / resolve_agent_effort, убран хардкод "model":"opus", сборка флагов --model/--effort/--fallback-model
  • Тесты: test_resolve_agent_model.py (12), test_resolve_agent_effort.py (9) = 21 новых
  • Docs: INFRA.md, internals.md, CHANGELOG.md
  • pytest tests/ -q из клона ветки в прод-образе → 423 passed, 0 failed
  • push + git log origin/main..origin/feat/ORCH-41-agent-models показывает коммит
  • PR #36 создан (НЕ смержен)

Изменённые файлы

  • src/config.py — поля Settings:
    • agent_model_default="claude-opus-4-8" + agent_model_<analyst|architect|developer|reviewer|tester|deployer>=""
    • agent_effort_default="high" + per-agent (думающие=high, tester/deployer=medium)
    • agent_fallback_model=""
    • env: ORCH_AGENT_MODEL_<AGENT>, ORCH_AGENT_EFFORT_<AGENT>, ORCH_AGENT_FALLBACK_MODEL
  • src/projects.pyfrom dataclasses import dataclass, field; ProjectConfig.agent_models: dict = field(default_factory=dict) + agent_efforts: dict = field(default_factory=dict); хелпер _coerce_str_map(...) (валидация → {str:str}, мусор → {}); парсинг обоих полей в _parse_projects_json.
  • src/agents/launcher.py:
    • VALID_EFFORTS = {low,medium,high,xhigh,max}
    • _resolve_agent_attr(...) — общий приватный резолвер приоритета
    • resolve_agent_model(agent, project_id=None) / resolve_agent_effort(agent, project_id=None) (effort валидируется, невалид → warning + опускается)
    • убран "model":"opus" из architect/reviewer в AGENT_CONFIGS
    • в _spawn: project_id резолвится из repo через get_project_by_repo(repo).plane_project_id
    • сборка model_flag / effort_flag / fb_flag и подстановка {model_flag}{effort_flag}{fb_flag} в cmd
  • tests/test_resolve_agent_model.py, tests/test_resolve_agent_effort.py — новые
  • docs/operations/INFRA.md — env-карта + раздел «Модель и effort агентов»
  • docs/architecture/internals.md — конфиг-буллеты ORCH-41
  • CHANGELOG.md — запись в [Unreleased] → Added

Приоритет резолвинга (оба резолвера)

  1. ProjectConfig.agent_models[agent] / agent_efforts[agent] (per-project, из projects_json)
  2. settings.agent_model_<agent> / agent_effort_<agent> (per-agent env, если непусто)
  3. settings.agent_model_default / agent_effort_default
  4. пусто → флаг не передаётся, дефолт CLI

Результат

  • pytest tests/ -q -p no:cacheprovider (клон ветки, окружение прод-образа orchestrator): 423 passed, 1 warning (402 baseline + 21 новых), 0 failed.
  • Ручная проверка резолвинга:
    • resolve_agent_model("developer")claude-opus-4-8
    • resolve_agent_model("architect")claude-opus-4-8 (раньше резолвилось в opus-4-7 через хардкод "opus")
    • resolve_agent_effort("developer")high, resolve_agent_effort("tester")medium
  • Коммит на origin: git log origin/main..origin/feat/ORCH-41-agent-models8a292b9 feat(agents): ... (ORCH-41)
  • PR: admin/orchestrator#36 (status: open, НЕ смержен)

Пример конфига per-project (ORCH_PROJECTS_JSON)

{"plane_project_id":"8da6aa25-a60e-44d6-a1e2-d8ae59aa7d6a","repo":"orchestrator","work_item_prefix":"ORCH",
 "agent_models":{"developer":"claude-opus-4-8","reviewer":"claude-sonnet-4-6"},
 "agent_efforts":{"developer":"xhigh","tester":"low"}}

Оба поля опциональны → старые записи реестра работают без изменений (default = {}).

Проблемы и решения

  • Nested-heredoc через ssh+docker рвал кавычки → перешёл на патч-скрипты, передаваемые base64 в контейнер и запускаемые python3 (детерминированные assert count==1 на якорях).
  • 3 теста effort падали: autouse-фикстура задавала per-agent effort (level 2), поэтому смена только *_default не влияла → в этих тестах дополнительно обнуляю per-agent значение.
  • curl в контейнере отсутствует → PR создан через httpx (зависимость проекта).

Off-limits соблюдено

  • Гейты/webhook/HMAC/очередь не тронуты.
  • Версия модели НЕ хардкодится — только default в коде (configurable).
  • frozen dataclass + dict → field(default_factory=dict).
  • Прод/env не менялся; раннеры не регистрировались; nohup не использовался.
  • PR НЕ смержен.