mirror of
https://github.com/usestrix/strix.git
synced 2026-08-19 10:05:12 +02:00
fix: address audit findings — SDK plumbing, TUI bus, dead code
Critical fixes: - ``StrixOrchestrationHooks.on_agent_start`` now finds the ``CaidoCapability`` via ``ctx.context['caido_capability']`` instead of ``agent.capabilities`` (we use plain ``Agent``, not ``SandboxAgent``, so the latter never existed). The session manager's bundle already exposes the capability; ``run_strix_scan`` threads it through ``make_agent_context`` and ``create_agent`` forwards it to children. - ``run_strix_scan`` registers the ``StrixTracingProcessor`` with the SDK's tracing provider via ``add_trace_processor`` so SDK trace spans hit ``run_dir/events.jsonl`` (was previously a parallel stream the SDK ignored). - ``on_llm_end`` now writes to ``Tracer.record_llm_usage`` in addition to ``bus.record_usage`` so the CLI/TUI stats panel sees real numbers instead of zeros. - ``run_strix_scan`` accepts an externally-built ``AgentMessageBus`` + an explicit ``model`` arg. The TUI pre-creates the bus so its stop and chat-input handlers can submit ``bus.send`` / ``bus.cancel_descendants`` coroutines onto the scan thread's loop via ``asyncio.run_coroutine_threadsafe`` — replacing the TODO-stub no-ops. - ``model`` config now propagates root → context → child agents in ``create_agent`` (was hardcoded fallback). Dead-code removal: - Deleted the ``load_skill`` tool entirely (host module, sandbox module, TUI renderer, tests). The legacy implementation reached into a global ``_agent_instances`` registry that no longer exists; the post-migration stub returned ``success=True`` without injecting anything — pure theater. Skills are still preloaded via the system prompt at scan-bring-up. - Dropped ``tenacity`` and ``xmltodict`` from ``[project.dependencies]`` — neither is imported anywhere post-migration. - Stripped the system prompt's "use the load_skill tool" lines. Tests: 278/278 passing. Removed two ``load_skill`` test cases and a ``test_tool_registration_modes::test_load_skill_import_...`` assertion that exercised the deleted module. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
af42499b95
commit
572ef2a2af
@@ -4,7 +4,6 @@ from . import (
|
||||
browser_renderer,
|
||||
file_edit_renderer,
|
||||
finish_renderer,
|
||||
load_skill_renderer,
|
||||
notes_renderer,
|
||||
proxy_renderer,
|
||||
python_renderer,
|
||||
@@ -29,7 +28,6 @@ __all__ = [
|
||||
"file_edit_renderer",
|
||||
"finish_renderer",
|
||||
"get_tool_renderer",
|
||||
"load_skill_renderer",
|
||||
"notes_renderer",
|
||||
"proxy_renderer",
|
||||
"python_renderer",
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
from typing import Any, ClassVar
|
||||
|
||||
from rich.text import Text
|
||||
from textual.widgets import Static
|
||||
|
||||
from .base_renderer import BaseToolRenderer
|
||||
from .registry import register_tool_renderer
|
||||
|
||||
|
||||
@register_tool_renderer
|
||||
class LoadSkillRenderer(BaseToolRenderer):
|
||||
tool_name: ClassVar[str] = "load_skill"
|
||||
css_classes: ClassVar[list[str]] = ["tool-call", "load-skill-tool"]
|
||||
|
||||
@classmethod
|
||||
def render(cls, tool_data: dict[str, Any]) -> Static:
|
||||
args = tool_data.get("args", {})
|
||||
status = tool_data.get("status", "completed")
|
||||
|
||||
requested = args.get("skills", "")
|
||||
|
||||
text = Text()
|
||||
text.append("◇ ", style="#10b981")
|
||||
text.append("loading skill", style="dim")
|
||||
|
||||
if requested:
|
||||
text.append(" ")
|
||||
text.append(requested, style="#10b981")
|
||||
elif not tool_data.get("result"):
|
||||
text.append("\n ")
|
||||
text.append("Loading...", style="dim")
|
||||
|
||||
return Static(text, classes=cls.get_css_classes(status))
|
||||
+31
-14
@@ -711,6 +711,13 @@ class StrixTUIApp(App): # type: ignore[misc]
|
||||
self.tracer.set_scan_config(self.scan_config)
|
||||
set_global_tracer(self.tracer)
|
||||
|
||||
# Pre-create the bus here (rather than letting ``run_strix_scan``
|
||||
# build its own) so the TUI can hold a handle for stop / chat
|
||||
# routing while the scan loop runs in a worker thread.
|
||||
from strix.orchestration.bus import AgentMessageBus
|
||||
|
||||
self.bus: AgentMessageBus = AgentMessageBus()
|
||||
|
||||
self.agent_nodes: dict[str, TreeNode] = {}
|
||||
|
||||
self._displayed_agents: set[str] = set()
|
||||
@@ -720,6 +727,7 @@ class StrixTUIApp(App): # type: ignore[misc]
|
||||
self._last_streaming_len: dict[str, int] = {}
|
||||
|
||||
self._scan_thread: threading.Thread | None = None
|
||||
self._scan_loop: asyncio.AbstractEventLoop | None = None
|
||||
self._scan_stop_event = threading.Event()
|
||||
self._scan_completed = threading.Event()
|
||||
|
||||
@@ -1496,6 +1504,10 @@ class StrixTUIApp(App): # type: ignore[misc]
|
||||
try:
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
# Stash the loop so synchronous TUI handlers (stop /
|
||||
# chat) can submit bus coroutines onto it from the
|
||||
# main thread.
|
||||
self._scan_loop = loop
|
||||
|
||||
try:
|
||||
if not self._scan_stop_event.is_set():
|
||||
@@ -1508,6 +1520,7 @@ class StrixTUIApp(App): # type: ignore[misc]
|
||||
image=str(image),
|
||||
sources_path=sources_path,
|
||||
tracer=self.tracer,
|
||||
bus=self.bus,
|
||||
interactive=True,
|
||||
),
|
||||
)
|
||||
@@ -1827,10 +1840,6 @@ class StrixTUIApp(App): # type: ignore[misc]
|
||||
metadata={"interrupted": True},
|
||||
)
|
||||
|
||||
# TODO: route user→agent messages through the AgentMessageBus
|
||||
# once the TUI has a handle on it. The bus currently lives
|
||||
# inside ``run_strix_scan`` scope only.
|
||||
|
||||
if self.tracer:
|
||||
self.tracer.log_chat_message(
|
||||
content=message,
|
||||
@@ -1838,11 +1847,18 @@ class StrixTUIApp(App): # type: ignore[misc]
|
||||
agent_id=self.selected_agent_id,
|
||||
)
|
||||
|
||||
logging.warning(
|
||||
"User-message-to-agent dispatch is not wired post-migration; "
|
||||
"message %r logged to tracer but not delivered.",
|
||||
message,
|
||||
)
|
||||
# Route to the agent's bus inbox. The scan loop runs on a
|
||||
# worker thread; ``run_coroutine_threadsafe`` submits the
|
||||
# coroutine onto that loop and returns immediately so the TUI
|
||||
# stays responsive.
|
||||
if self._scan_loop is not None and not self._scan_loop.is_closed():
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
self.bus.send(
|
||||
self.selected_agent_id,
|
||||
{"from": "user", "content": message, "type": "instruction"},
|
||||
),
|
||||
self._scan_loop,
|
||||
)
|
||||
|
||||
self._displayed_events.clear()
|
||||
self._update_chat_view()
|
||||
@@ -1941,11 +1957,12 @@ class StrixTUIApp(App): # type: ignore[misc]
|
||||
return agent_name, False
|
||||
|
||||
def action_confirm_stop_agent(self, agent_id: str) -> None:
|
||||
# TODO: route to ``bus.cancel_descendants(agent_id)`` once the TUI
|
||||
# has a handle on the AgentMessageBus.
|
||||
logging.warning(
|
||||
"Stop-agent dispatch is not wired post-migration; agent %s left running.",
|
||||
agent_id,
|
||||
if self._scan_loop is None or self._scan_loop.is_closed():
|
||||
logging.warning("No active scan loop; cannot stop agent %s", agent_id)
|
||||
return
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
self.bus.cancel_descendants(agent_id),
|
||||
self._scan_loop,
|
||||
)
|
||||
|
||||
def action_custom_quit(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user