refactor: nuke gratuitous XML serialization + delete argument_parser

Argument parser:
- Delete ``strix/tools/argument_parser.py`` and its tests. The SDK
  validates and types tool arguments via Pydantic before they hit our
  wrappers, and the in-container tool server receives JSON-typed
  kwargs over the wire. The string-coercion belt-and-suspenders is no
  longer pulling its weight.

XML → JSON / typed structures:
- ``create_vulnerability_report``: ``cvss_breakdown`` is now a
  ``dict[str, str]`` of the 8 metrics; ``code_locations`` is a
  ``list[dict]``. No more XML parsing in the tool or the renderer.
- ``check_duplicate``: the dedup judge now emits a single JSON object
  instead of an ``<dedupe_result>`` block. Strict JSON parser handles
  optional code-fence wrappers.
- ``agent_finish``: completion report posted to the parent inbox is a
  JSON object (``kind``, ``from``, ``agent_id``, ``success``,
  ``summary``, ``findings``, ``recommendations``) rather than a
  hand-rolled ``<agent_completion_report>`` XML envelope.
- ``create_agent``: identity preamble + inherited-context markers are
  plain bracketed labels rather than ``<agent_delegation>`` /
  ``<inherited_context_from_parent>`` envelopes.
- ``inject_messages_filter``: peer messages get a
  ``[Message from agent <id> | type=... | priority=...]`` header line
  instead of an ``<inter_agent_message>`` envelope.
- Crash + system-warning messages: bracketed labels, no XML.
- System prompt: the inter-agent block now describes the new header
  format and drops the "never echo XML envelope" rule.
- ``strix/llm/utils.py``: deleted. ``clean_content`` collapsed into a
  one-line blank-line normalizer in the agent-message renderer (the
  XML envelope scrub had nothing left to scrub).

Tests updated to match the new shapes.
This commit is contained in:
0xallam
2026-04-25 12:31:07 -07:00
parent e473b2d6d8
commit 1aeee5dc29
17 changed files with 219 additions and 667 deletions
@@ -1,3 +1,4 @@
import re
from functools import cache
from typing import Any, ClassVar
@@ -11,6 +12,9 @@ from .base_renderer import BaseToolRenderer
from .registry import register_tool_renderer
_BLANK_LINE_RUNS = re.compile(r"\n\s*\n")
_HEADER_STYLES = [
("###### ", 7, "bold #4ade80"),
("##### ", 6, "bold #22c55e"),
@@ -180,11 +184,7 @@ class AgentMessageRenderer(BaseToolRenderer):
def render_simple(cls, content: str) -> Text:
if not content:
return Text()
from strix.llm.utils import clean_content
cleaned = clean_content(content)
cleaned = _BLANK_LINE_RUNS.sub("\n\n", content).strip()
if not cleaned:
return Text()
return _apply_markdown_styles(cleaned)
@@ -6,17 +6,22 @@ from pygments.styles import get_style_by_name
from rich.text import Text
from textual.widgets import Static
from strix.tools.reporting.tool import (
_parse_code_locations_xml as parse_code_locations_xml,
)
from strix.tools.reporting.tool import (
_parse_cvss_xml as parse_cvss_xml,
)
from .base_renderer import BaseToolRenderer
from .registry import register_tool_renderer
def _coerce_dict(value: Any) -> dict[str, Any]:
if isinstance(value, dict):
return value
return {}
def _coerce_list_of_dicts(value: Any) -> list[dict[str, Any]]:
if isinstance(value, list):
return [item for item in value if isinstance(item, dict)]
return []
@cache
def _get_style_colors() -> dict[Any, str]:
style = get_style_by_name("native")
@@ -94,8 +99,8 @@ class CreateVulnerabilityReportRenderer(BaseToolRenderer):
poc_script_code = args.get("poc_script_code", "")
remediation_steps = args.get("remediation_steps", "")
cvss_breakdown_xml = args.get("cvss_breakdown", "")
code_locations_xml = args.get("code_locations", "")
cvss_breakdown = _coerce_dict(args.get("cvss_breakdown"))
code_locations = _coerce_list_of_dicts(args.get("code_locations"))
endpoint = args.get("endpoint", "")
method = args.get("method", "")
@@ -154,8 +159,7 @@ class CreateVulnerabilityReportRenderer(BaseToolRenderer):
text.append("CWE: ", style=FIELD_STYLE)
text.append(cwe)
parsed_cvss = parse_cvss_xml(cvss_breakdown_xml) if cvss_breakdown_xml else None
if parsed_cvss:
if cvss_breakdown:
text.append("\n\n")
cvss_parts = []
for key, prefix in [
@@ -168,7 +172,7 @@ class CreateVulnerabilityReportRenderer(BaseToolRenderer):
("integrity", "I"),
("availability", "A"),
]:
val = parsed_cvss.get(key)
val = cvss_breakdown.get(key)
if val:
cvss_parts.append(f"{prefix}:{val}")
text.append("CVSS Vector: ", style=FIELD_STYLE)
@@ -192,13 +196,10 @@ class CreateVulnerabilityReportRenderer(BaseToolRenderer):
text.append("\n")
text.append(technical_analysis)
parsed_locations = (
parse_code_locations_xml(code_locations_xml) if code_locations_xml else None
)
if parsed_locations:
if code_locations:
text.append("\n\n")
text.append("Code Locations", style=FIELD_STYLE)
for i, loc in enumerate(parsed_locations):
for i, loc in enumerate(code_locations):
text.append("\n\n")
text.append(f" Location {i + 1}: ", style=DIM_STYLE)
text.append(loc.get("file", "unknown"), style=FILE_STYLE)