Five rounds of sweep across the tree. Net ~544 lines removed.
Removed:
- Section-divider banners and one-line section labels (# Display
utilities, # ----- list_requests -----, # CVSS breakdown, etc.).
- Module-level prose docstrings on internal modules. Kept one-line
summaries; trimmed multi-paragraph narration about SDK/Strix
responsibility splits, cache strategies, three-source precedence.
- Internal-helper docstrings that just restate the function name —
caido_api helpers (caido_url, get_client, view_request, etc.),
settings-class one-liners (LLMSettings, RuntimeSettings, ...),
UI helper docstrings.
- Args/Returns blocks on non-LLM-facing internal helpers
(build_strix_agent, render_system_prompt, create_or_reuse,
bootstrap_caido) — kept only the genuinely non-obvious params.
- Internal-history phrasing — "Mirrors main-branch shape",
"pre-SDK harness", "previous lookup matched no attribute".
- Narrative comments inside function bodies that explained what the
next line does, design rationale obvious from the surrounding code,
or "we used to..." asides.
- Trailing periods on every error-string literal across the tool tree.
- Duplicated roundtripTime quirk comment (kept the LLM-facing copy in
tools/proxy/tools.py).
Kept (every one names an upstream bug, vendored-code provenance, or
non-obvious data quirk):
- core/runner.py: SDK replay-with-empty-initial-input + on_agent_end
lifecycle gap.
- runtime/docker_client.py: VERBATIM COPY block of the upstream
_create_container body, pinned to SDK v0.14.6.
- runtime/session_manager.py: NO_PROXY for agent-browser CDP loopback.
- tools/proxy/caido_api.py: generated-pydantic Request.raw quirk,
replay double-history pitfall.
- tools/proxy/tools.py: Caido roundtripTime=0 quirk for proxy
captures.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
``STRIX_RUNTIME_BACKEND`` was already declared on ``Config`` but never
read — ``session_manager`` hard-coded ``StrixDockerSandboxClient`` plus
``DockerSandboxClientOptions`` plus ``docker.from_env()`` directly into
the call site. Adding a second backend would have meant retrofitting
every Docker-specific import.
Move all of that behind a registry:
- ``strix/runtime/backends.py``: maps backend names to async factories
``(image, manifest, exposed_ports) -> (client, session)``. Ships with
``"docker"``; ``register_backend`` lets downstream users plug in
Daytona / K8s / Modal / etc. without forking.
- Each backend's deps are imported lazily inside its factory, so a
K8s-only deployment doesn't need ``docker-py`` installed (and
vice-versa).
- ``session_manager`` reads the config name, looks up the backend,
calls it. Zero Docker imports remain.
- Unknown backend name raises ``ValueError`` with the supported list,
so ``STRIX_RUNTIME_BACKEND=docke`` typos surface immediately.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The ``strix`` prefix on a file inside ``strix/runtime/`` was pure
redundancy. Class name ``StrixDockerSandboxClient`` keeps the prefix
since it disambiguates from the upstream SDK class it subclasses.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The split between ``strix/sandbox/`` and ``strix/runtime/`` was
artificial — both were managing the same backend. ``strix/sandbox/``
also collided uncomfortably with the SDK's ``agents.sandbox.*``
namespace. ``runtime/`` (which matches ``STRIX_RUNTIME_BACKEND``) is
the canonical home for everything Docker / Daytona / K8s lifecycle.
While merging, also rip out two pieces of Docker-specific coupling:
- ``caido_bootstrap`` was POSTing ``loginAsGuest`` from the host via
``aiohttp`` to ``http://127.0.0.1:{forwarded_port}``. That assumed
Docker port forwarding; Daytona / K8s expose ports differently.
Now we ``session.exec`` curl from *inside* the container — the
SDK's runtime-agnostic exec primitive — so any backend works as
long as it implements ``exec``. The host-side Caido ``Client``
still uses the runtime's exposed-port URL for post-bootstrap calls,
but that goes through the SDK's own ``resolve_exposed_port``
abstraction (also runtime-agnostic).
- The bootstrap retry loop now doubles as the readiness probe, so
``healthcheck.wait_for_tcp_ready`` (and the entire
``healthcheck.py`` module) goes away.
Drive-by simplification: drop ``caido_host_port`` plumbing entirely.
It was only piped through ``make_agent_context`` → child contexts
without ever being read; only ``caido_client`` is consumed.
Drops ``aiohttp`` runtime dep (it stays only as a transitive of the
Caido SDK).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tail end of the sandbox-tools migration:
- Drop ``ENV STRIX_SANDBOX_MODE=true`` and ``ENV PYTHONPATH=/app`` from
the Dockerfile — both only mattered for the now-deleted in-container
tool server (the legacy ``register_tool`` registry gated on the env
var, and the entrypoint set ``PYTHONPATH`` so it could ``-m
strix.runtime.tool_server``).
- Drop ``strix_disable_browser`` from the Config defaults — the legacy
registry used it to skip ``browser_action`` registration; agent-browser
is unconditional now.
- Strip the ``tool_server.py`` blurb from ``strix/runtime/__init__.py``.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The SDK harness is the only path now; legacy host-side code is gone.
File names no longer carry the ``sdk_`` distinction.
Deleted legacy host-side modules:
- strix/agents/StrixAgent/ (template moved to strix/agents/prompts/)
- strix/agents/base_agent.py, state.py
- strix/llm/llm.py, config.py
- strix/runtime/docker_runtime.py, runtime.py
- strix/tools/executor.py, agents_graph/agents_graph_actions.py
- strix/interface/sdk_dispatch.py + the env-flag dispatch in cli.py
Renamed (drop ``sdk_`` prefix):
- strix/sdk_entry.py → strix/entry.py
- strix/agents/sdk_factory.py → strix/agents/factory.py
- strix/agents/sdk_prompt.py → strix/agents/prompt.py
- strix/tools/<x>/<x>_sdk_tool[s].py → strix/tools/<x>/tool[s].py
- strix/tools/_legacy_adapter.py → strix/tools/_state_adapter.py
- ``_legacy`` aliases inside the wrappers → ``_impl``
CLI + TUI now call ``run_strix_scan`` directly — they build the
sandbox image / sources_path locally and rely on
``session_manager.cleanup`` (called inside ``run_strix_scan``'s finally)
for teardown. Three TUI handlers that reached into legacy multi-agent
globals (``_agent_instances``, ``send_user_message_to_agent``,
``stop_agent``) are now no-ops with a TODO; reconnecting them to the
``AgentMessageBus`` is a follow-up.
Tracer.get_total_llm_stats no longer reaches into the deleted
``agents_graph_actions`` globals — the orchestration hooks now feed the
tracer via ``Tracer.record_llm_usage`` (live + completed buckets).
finish_scan's ``_check_active_agents`` and load_skill's runtime
``_agent_instances`` reach-in are no-op stubs; the
``AgentMessageBus`` is the source of truth post-migration.
llm/utils.py rewritten to keep only the streaming-parser helpers
(``normalize_tool_format``, ``parse_tool_invocations``,
``fix_incomplete_tool_call``, ``format_tool_call``, ``clean_content``).
``STRIX_MODEL_MAP`` moved to ``llm/multi_provider_setup.py`` (its only
remaining caller).
Per-file ruff ignores added for legacy interface modules (TUI / main /
CLI / utils / streaming_parser / tool_components) and tracer.py —
pre-existing PLC0415/BLE001/PLR0915 patterns are out of scope.
Tests: 287/287 passing. Renamed test files to drop ``sdk_`` prefix.
``test_tracer.py::test_get_total_llm_stats_aggregates_live_and_completed``
rewritten to feed ``Tracer.record_llm_usage`` instead of legacy globals.
Test file annotations added so pre-commit's strict mypy passes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add automatic cleanup of Docker containers when the application exits.
Uses a singleton runtime pattern and spawns a detached subprocess for
cleanup to ensure fast exit without blocking the UI.
- Add Config class with all env var defaults in one place
- Auto-load saved config on startup (env vars take precedence)
- Auto-save config after successful LLM warm-up
- Replace scattered os.getenv() calls with Config.get()
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>