feat(migration): phase 5 — root agent factory + entry point
Three new modules that wire Phases 0-4 into a runnable Strix scan: - strix/agents/sdk_prompt.py: standalone Jinja-based system prompt renderer. Reuses the existing strix/agents/StrixAgent/system_prompt. jinja template (508 lines, the actual production prompt) so behavior parity with the legacy LLM._load_system_prompt is byte-identical. Skill resolution mirrors LLM._get_skills_to_load (caller skills → scan_modes/<mode> → whitebox pair, deduped). Fail-soft: template errors return empty string and log; agent construction must never blow up on prompt load. - strix/agents/sdk_factory.py: build_strix_agent(name, skills, is_root) assembles an agents.Agent. Root carries finish_scan and stops there; child carries agent_finish and stops there (C4). Caido tools come from CaidoCapability automatically — we don't include them in _BASE_TOOLS to avoid double-registration when the SDK runtime merges capability tools. model=None so RunConfig drives the model alias through MultiProvider rather than the SDK default. make_child_factory returns a closure over scan-level config (scan_mode, is_whitebox, interactive, scope context) for ctx.context['agent_factory'] — the Phase 3 create_agent tool calls it with (name, skills) per child. - strix/sdk_entry.py: run_strix_scan() — the top-level coroutine. Builds the bus, brings up (or reuses) a sandbox session via session_manager, builds the root Agent and the child factory, builds the per-agent context dict, registers the root in the bus, builds the RunConfig, calls Runner.run, and cleans up the session in a finally. Cancels descendants before re-raising any exception (C9). cleanup_on_exit toggle preserves the cached session for resume scenarios. _build_root_task and _build_scope_context preserve the legacy StrixAgent.execute_scan task formatting + scope context shape so the prompt template sees identical inputs. Tests: 21 new tests (10 for factory + prompt, 11 for entry point). Factory: root vs child tool list parity, finish_scan/agent_finish placement, tool_use_behavior dict shape, Caido absence (capability- provided), make_child_factory closure semantics. Entry point (all mocked, no real Docker/LLM): wiring shape verification — context dict carries every field downstream consumers read, session manager called with correct scan_id, cleanup runs even on Runner.run failure, cleanup skipped when disabled, scan_id auto-generation, scan-level config (scan_mode, is_whitebox) flows into the factory. Task and scope builders verified against the same shape as legacy. Per-file ruff ignores added: TC002 on sdk_factory (Tool used at runtime in _BASE_TOOLS tuple), TC003 + PLR0912 on sdk_entry (Path runtime-imported; _build_root_task's per-target-type branches are intentional and well-bounded). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -303,6 +303,15 @@ ignore = [
|
||||
# CaidoCapability uses agents.tool.Tool at runtime — pydantic Field
|
||||
# annotations and the cached _CAIDO_TOOLS tuple need it eagerly.
|
||||
"strix/sandbox/caido_capability.py" = ["TC002"]
|
||||
# Agent factory: agents.tool.Tool is used at runtime in the _BASE_TOOLS
|
||||
# tuple type, not just for annotations.
|
||||
"strix/agents/sdk_factory.py" = ["TC002"]
|
||||
# Entry point: ``Path`` is used at runtime by the typing of the
|
||||
# session_manager call; importing under TYPE_CHECKING would defer
|
||||
# resolution past where mypy needs it. ``_build_root_task`` legitimately
|
||||
# walks every supported target type — splitting it into per-type
|
||||
# helpers would add indirection without simplifying anything.
|
||||
"strix/sdk_entry.py" = ["TC003", "PLR0912"]
|
||||
# Sandbox dispatch helper has many short-circuit error returns (auth fail,
|
||||
# size cap, decode fail, etc). Each is a distinct, documented failure mode
|
||||
# the model needs to see verbatim — collapsing them harms readability.
|
||||
|
||||
Reference in New Issue
Block a user