diff --git a/extensions/business/cybersec/red_mesh/AGENTS.md b/extensions/business/cybersec/red_mesh/AGENTS.md index bc950fd3..ca545a07 100644 --- a/extensions/business/cybersec/red_mesh/AGENTS.md +++ b/extensions/business/cybersec/red_mesh/AGENTS.md @@ -302,7 +302,7 @@ Only append entries for critical or fundamental RedMesh backend changes, discove ### 2026-03-16T20:40:00Z -- Change: introduced a dedicated LLM payload-shaping boundary in [`mixins/llm_agent.py`](./mixins/llm_agent.py) so RedMesh no longer sends the full aggregated report directly to the LLM path. +- Change: introduced a dedicated LLM payload-shaping boundary in [`mixins/llm_agent_mixin.py`](mixins/llm_agent_mixin.py) so RedMesh no longer sends the full aggregated report directly to the LLM path. - Change: added network and webapp-specific compact payload shaping, finding deduplication/ranking/capping, analysis-type budgets, and runtime payload-size observability. - Verification: the known failing job `a3a357bc` dropped from `303,760` raw bytes to `21,559` shaped bytes for `security_assessment` and completed manually in `38.97s` on rm1 instead of timing out. - Horizontal insight: RedMesh archive/report data and LLM reasoning data must remain separate contracts; future LLM work should extend the bounded payload model rather than re-coupling the agent to raw archived aggregates. diff --git a/extensions/business/cybersec/red_mesh/mixins/__init__.py b/extensions/business/cybersec/red_mesh/mixins/__init__.py index ec68a976..56157685 100644 --- a/extensions/business/cybersec/red_mesh/mixins/__init__.py +++ b/extensions/business/cybersec/red_mesh/mixins/__init__.py @@ -2,7 +2,7 @@ from .risk import _RiskScoringMixin from .report import _ReportMixin from .live_progress import _LiveProgressMixin -from .llm_agent import _RedMeshLlmAgentMixin +from .llm_agent_mixin import _RedMeshLlmAgentMixin __all__ = [ "_AttestationMixin", diff --git a/extensions/business/cybersec/red_mesh/mixins/llm_agent.py b/extensions/business/cybersec/red_mesh/mixins/llm_agent_mixin.py similarity index 100% rename from extensions/business/cybersec/red_mesh/mixins/llm_agent.py rename to extensions/business/cybersec/red_mesh/mixins/llm_agent_mixin.py diff --git a/extensions/business/cybersec/red_mesh/tests/test_hardening.py b/extensions/business/cybersec/red_mesh/tests/test_hardening.py index 7a4ccbe6..e14c5afd 100644 --- a/extensions/business/cybersec/red_mesh/tests/test_hardening.py +++ b/extensions/business/cybersec/red_mesh/tests/test_hardening.py @@ -92,7 +92,7 @@ def P(self, *_args, **_kwargs): class TestLlmRetryHardening(unittest.TestCase): def test_build_llm_analysis_payload_network_is_compact_and_structured(self): - from extensions.business.cybersec.red_mesh.mixins.llm_agent import _RedMeshLlmAgentMixin + from extensions.business.cybersec.red_mesh.mixins.llm_agent_mixin import _RedMeshLlmAgentMixin class MockHost(_RedMeshLlmAgentMixin): def __init__(self): @@ -146,7 +146,7 @@ def __init__(self): self.assertEqual(payload["findings_summary"]["total_findings"], 2) def test_run_aggregated_llm_analysis_uses_shaped_payload(self): - from extensions.business.cybersec.red_mesh.mixins.llm_agent import _RedMeshLlmAgentMixin + from extensions.business.cybersec.red_mesh.mixins.llm_agent_mixin import _RedMeshLlmAgentMixin class MockHost(_RedMeshLlmAgentMixin): def __init__(self): @@ -186,7 +186,7 @@ def _auto_analyze_report(self, job_id, report, target, scan_type="network", anal self.assertGreater(host._last_llm_payload_stats["reduction_bytes"], 0) def test_build_llm_analysis_payload_deduplicates_and_tracks_truncation(self): - from extensions.business.cybersec.red_mesh.mixins.llm_agent import _RedMeshLlmAgentMixin + from extensions.business.cybersec.red_mesh.mixins.llm_agent_mixin import _RedMeshLlmAgentMixin class MockHost(_RedMeshLlmAgentMixin): def __init__(self): @@ -246,7 +246,7 @@ def __init__(self): self.assertTrue(all(len(finding["evidence"]) <= 220 for finding in payload["top_findings"])) def test_quick_summary_payload_is_smaller_than_security_assessment(self): - from extensions.business.cybersec.red_mesh.mixins.llm_agent import _RedMeshLlmAgentMixin + from extensions.business.cybersec.red_mesh.mixins.llm_agent_mixin import _RedMeshLlmAgentMixin class MockHost(_RedMeshLlmAgentMixin): def __init__(self): @@ -291,7 +291,7 @@ def __init__(self): self.assertEqual(quick_payload["truncation"]["finding_limit"], 12) def test_record_llm_payload_stats_tracks_size_reduction(self): - from extensions.business.cybersec.red_mesh.mixins.llm_agent import _RedMeshLlmAgentMixin + from extensions.business.cybersec.red_mesh.mixins.llm_agent_mixin import _RedMeshLlmAgentMixin class MockHost(_RedMeshLlmAgentMixin): def __init__(self): @@ -314,7 +314,7 @@ def Pd(self, *_args, **_kwargs): self.assertEqual(host._last_llm_payload_stats["job_id"], "job-obs") def test_extract_report_findings_includes_graybox_results(self): - from extensions.business.cybersec.red_mesh.mixins.llm_agent import _RedMeshLlmAgentMixin + from extensions.business.cybersec.red_mesh.mixins.llm_agent_mixin import _RedMeshLlmAgentMixin class MockHost(_RedMeshLlmAgentMixin): def __init__(self): @@ -337,7 +337,7 @@ def __init__(self): self.assertEqual(findings[0]["scenario_id"], "S-1") def test_build_llm_analysis_payload_webapp_is_compact_and_structured(self): - from extensions.business.cybersec.red_mesh.mixins.llm_agent import _RedMeshLlmAgentMixin + from extensions.business.cybersec.red_mesh.mixins.llm_agent_mixin import _RedMeshLlmAgentMixin class MockHost(_RedMeshLlmAgentMixin): def __init__(self): @@ -423,7 +423,7 @@ def __init__(self): self.assertEqual(payload["probe_summary"]["top_probes"][0]["probe"], "_graybox_authz") def test_call_llm_agent_api_retries_transient_connection_error(self): - from extensions.business.cybersec.red_mesh.mixins.llm_agent import _RedMeshLlmAgentMixin + from extensions.business.cybersec.red_mesh.mixins.llm_agent_mixin import _RedMeshLlmAgentMixin class MockHost(_RedMeshLlmAgentMixin): def __init__(self): @@ -465,7 +465,7 @@ def flaky_post(*_args, **_kwargs): self.assertEqual(calls["count"], 2) def test_call_llm_agent_api_does_not_retry_non_retryable_provider_rejection(self): - from extensions.business.cybersec.red_mesh.mixins.llm_agent import _RedMeshLlmAgentMixin + from extensions.business.cybersec.red_mesh.mixins.llm_agent_mixin import _RedMeshLlmAgentMixin class MockHost(_RedMeshLlmAgentMixin): def __init__(self): diff --git a/requirements.txt b/requirements.txt index 564eb02c..6bc7fedd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,6 +5,8 @@ python-telegram-bot[rate-limiter] protobuf ngrok +bitsandbytes + openai sqlfluff pypdf diff --git a/ver.py b/ver.py index bcf81497..b8aa0682 100644 --- a/ver.py +++ b/ver.py @@ -1 +1 @@ -__VER__ = '2.10.160' +__VER__ = '2.10.170'