refactor: scrub migration scars, dead code, and unused helpers

- Strip PLAYBOOK / AUDIT / Phase-N / C-numbered references from
  module docstrings across 16 files; rename
  ``_PHASE1_PARALLEL_DEFAULT`` → ``_PARALLEL_TOOL_CALLS_DEFAULT``.
- Delete unused exception classes: ``SandboxInitializationError``,
  ``ImplementedInClientSideOnlyError``.
- Delete the no-op ``on_handoff`` hook (we don't use SDK handoffs).
- Delete the unreachable backward-compat tab-delimited fallback in
  ``_parse_git_diff_output``.
- Delete orphaned ``strix/tools/load_skill/`` (dir contained only a
  pycache) and stale pycache files.
- Rewrite ``strix/skills/__init__.py``: 168 → 56 LoC. Drop seven
  helper functions (``get_available_skills``, ``get_all_skill_names``,
  ``validate_skill_names``, ``parse_skill_list``,
  ``validate_requested_skills``, ``generate_skills_description``,
  ``_get_all_categories``) — none had external callers; only
  ``load_skills`` is used.
- Drop the stale ``strix/agents/sdk_factory.py`` per-file ruff ignore
  (file no longer exists).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
0xallam
2026-04-25 12:05:24 -07:00
parent e4be5f9588
commit 4146174503
23 changed files with 212 additions and 525 deletions
+1 -8
View File
@@ -17,13 +17,7 @@ from .finish import * # noqa: F403
from .notes import * # noqa: F403
from .proxy import * # noqa: F403
from .python import * # noqa: F403
from .registry import (
ImplementedInClientSideOnlyError,
get_tool_by_name,
get_tool_names,
register_tool,
tools,
)
from .registry import get_tool_by_name, get_tool_names, register_tool, tools
from .reporting import * # noqa: F403
from .terminal import * # noqa: F403
from .thinking import * # noqa: F403
@@ -32,7 +26,6 @@ from .web_search import * # noqa: F403
__all__ = [
"ImplementedInClientSideOnlyError",
"get_tool_by_name",
"get_tool_names",
"register_tool",
+12 -28
View File
@@ -1,24 +1,15 @@
"""strix_tool — function_tool factory with Strix defaults.
"""``strix_tool````function_tool`` factory with Strix defaults.
Every tool in the migrated harness should be decorated with ``@strix_tool``
instead of bare ``@function_tool`` so the team's defaults stay consistent
without per-tool boilerplate. Override per call when needed.
Every tool uses ``@strix_tool`` instead of bare ``@function_tool`` so
defaults stay consistent across the suite. Override per call when
needed.
Defaults:
- ``timeout``: 120s (matches the legacy tool server's
``STRIX_SANDBOX_EXECUTION_TIMEOUT``).
- ``timeout``: 120s.
- ``timeout_behavior``: ``"error_as_result"`` for idempotent tools.
Critical sandbox tools (terminal, browser, python) should pass
``timeout_behavior="raise_exception"`` explicitly so the SDK can fail
the run rather than letting the model retry the same hung call (C20).
The SDK auto-threads sync function bodies via ``asyncio.to_thread``
(``tool.py:1820-1829``), so libtmux / IPython / blocking httpx code can be
written as plain ``def`` and the decorator will not block the event loop.
References:
- PLAYBOOK.md §2.6
- AUDIT_R3.md C20 (per-tool timeout_behavior discrimination)
Critical sandbox tools (terminal, browser, python) opt into
``timeout_behavior="raise_exception"`` explicitly so the SDK
fails the run rather than letting the model retry a hung call.
"""
from __future__ import annotations
@@ -44,17 +35,10 @@ def strix_tool(
) -> Callable[[_ToolFn], FunctionTool]:
"""Wrap ``agents.function_tool`` with Strix defaults.
The SDK's ``FunctionTool`` requires ``async def`` for ``timeout_seconds``
to apply (sync handlers cannot be cleanly cancelled). All Strix tools are
``async def``; sync libraries (libtmux, IPython) get wrapped in
``asyncio.to_thread`` inside the async tool body.
The SDK enforces ``strict_mode=True`` by default, which forbids
free-form ``dict[str, X]`` parameters (the strict JSON schema needs
``additionalProperties: false``). A handful of legacy tools
(``send_request``, ``repeat_request``) take arbitrary header /
modification dicts whose keys can't be enumerated, so they must
opt out of strict mode to preserve parity with the XML schema.
Strict mode is on by default (forbids free-form ``dict[str, X]``
parameters because the strict JSON schema needs
``additionalProperties: false``). A few tools that take arbitrary
header / modification dicts opt out via ``strict_mode=False``.
Usage::
+10 -25
View File
@@ -1,24 +1,14 @@
"""post_to_sandbox — host-to-container HTTP transport for sandbox tools.
"""``post_to_sandbox`` — host-to-container HTTP transport for sandbox tools.
Every Strix tool that runs inside the Kali container (browser, terminal,
python, the seven Caido tools) has the same wire shape: POST a JSON body
to ``http://localhost:{tool_server_host_port}/execute`` with a Bearer
token header and ``{"agent_id", "tool_name", "kwargs"}`` as the body.
Every Strix tool that runs inside the Kali container (browser,
terminal, python, file_edit, the seven Caido tools) has the same wire
shape: POST JSON to ``http://localhost:{tool_server_host_port}/execute``
with a Bearer token and ``{"agent_id", "tool_name", "kwargs"}`` body.
This helper centralizes that transport so:
- Every sandbox tool gets the same timeout policy
(``connect=10s`` / ``read=150s``).
- Every sandbox tool inherits the same response-size cap (50 MB) so a
runaway tool body cannot OOM the host (C18).
- Auth/transport errors surface as predictable error strings instead of
exceptions, so the model can retry / pick a different tool without the
run dying.
References:
- PLAYBOOK.md §3.4
- AUDIT_R3.md C18 (sandbox response size cap)
- HARNESS_WIKI.md §7.2 (legacy executor.py wire format we mirror)
The helper centralizes timeouts (``connect=10s`` / ``read=150s``), a
50 MB response-size cap so a runaway tool can't OOM the host, and
predictable error-string shaping so transport failures don't tear
down the run.
"""
from __future__ import annotations
@@ -36,14 +26,9 @@ if TYPE_CHECKING:
logger = logging.getLogger(__name__)
# Connect: how long to wait for the TCP handshake to complete.
# Read: how long the tool may spend executing before we abandon the call.
# Mirrors the legacy executor.py (``SANDBOX_EXECUTION_TIMEOUT = 120 + 30``).
_SANDBOX_TIMEOUT = httpx.Timeout(connect=10.0, read=150.0, write=150.0, pool=150.0)
#: Cap on response body size from the tool server. Anything bigger is
#: replaced by an error string so the model sees something coherent and
#: the host doesn't OOM trying to allocate the buffer (C18).
# Cap so a runaway tool body never blows up the host heap.
_MAX_RESPONSE_BYTES = 50 * 1024 * 1024 # 50 MB
+12 -26
View File
@@ -1,29 +1,16 @@
"""SDK function-tool wrappers for the multi-agent graph tools.
"""Multi-agent graph tools — read/write the :class:`AgentMessageBus`.
Six tools that read/write the :class:`AgentMessageBus` (built in Phase 0,
``strix.orchestration.bus``):
- ``view_agent_graph``: render the parent/child tree from ``bus.parent_of``.
- ``view_agent_graph``: render the parent/child tree.
- ``agent_status``: per-agent status + pending message count.
- ``send_message_to_agent``: peer-to-peer message into a child/sibling inbox.
- ``wait_for_message``: poll our own inbox until a message arrives or the
timeout expires (the legacy harness's "I'm idle, wake me on inbox").
- ``create_agent``: spawn a child via ``asyncio.create_task(Runner.run(...))``;
registers the child with the bus and stores its task handle so root cancels
cascade (C9, ``bus.cancel_descendants``).
- ``agent_finish``: subagents only — flips ``agent_finish_called`` so the
on_agent_end hook records "completed" rather than "crashed" (C8), and
posts a structured completion report to the parent's inbox.
The legacy ``strix.tools.agents_graph.agents_graph_actions`` is left
untouched — it still drives the legacy harness. These wrappers only
target the bus and don't touch the legacy ``_agent_graph`` dict.
References:
- PLAYBOOK.md §4.3
- AUDIT_R2.md §1.4 (cancel_descendants — Runner.run task handle stored
in bus.tasks so a root cancel walks the tree)
- AUDIT_R3.md C8 (crash detection via on_agent_end + agent_finish_called)
- ``send_message_to_agent``: queue a message in another agent's inbox.
- ``wait_for_message``: pause this agent until a message arrives or
``timeout_seconds`` elapses.
- ``create_agent``: spawn a child via
``asyncio.create_task(Runner.run(...))``; the task handle is stored
so a root-level cancel cascades to descendants.
- ``agent_finish``: subagents only — flips ``agent_finish_called`` so
the ``on_agent_end`` hook records "completed" rather than "crashed",
and posts a structured completion report to the parent's inbox.
"""
from __future__ import annotations
@@ -223,8 +210,7 @@ async def send_message_to_agent(
)
# Polling cadence for ``wait_for_message``. 1s matches the PLAYBOOK
# skeleton; tighter would burn CPU, slacker would feel laggy when a sibling
# Tighter would burn CPU; slacker would feel laggy when a sibling
# delivers a message right after the wait starts.
_WAIT_POLL_SECONDS = 1.0
+4 -15
View File
@@ -1,14 +1,14 @@
"""Minimal in-container tool registry.
Used inside the sandbox container by ``strix.runtime.tool_server`` to
look up `@register_tool`-decorated functions by name. Sandbox-bound
tools (browser, terminal, python, file_edit, proxy) live as legacy
look up ``@register_tool``-decorated functions by name. Sandbox-bound
tools (browser, terminal, python, file_edit, proxy) live as
``*_actions.py`` modules with this decoration; the host POSTs to
:func:`tool_server.execute_tool` which dispatches via
:func:`get_tool_by_name`.
Host-side tools are pure SDK function tools wired through
:mod:`strix.agents.factory` and don't touch this registry at all.
Host-side SDK function tools are wired through
:mod:`strix.agents.factory` and don't touch this registry.
"""
import logging
@@ -25,17 +25,6 @@ tools: list[dict[str, Any]] = []
_tools_by_name: dict[str, Callable[..., Any]] = {}
class ImplementedInClientSideOnlyError(Exception):
"""Raised by sandbox-side stubs whose real implementation lives host-side."""
def __init__(
self,
message: str = "This tool is implemented in the client side only",
) -> None:
self.message = message
super().__init__(self.message)
def _is_sandbox_mode() -> bool:
return os.getenv("STRIX_SANDBOX_MODE", "false").lower() == "true"