feat(agent): strip raw tool-scaffolding from streamed answers — deterministic filter with one bounded recovery

This commit is contained in:
2026-09-03 13:39:15 -04:00
parent 801639efcc
commit 575d6c88d0
38 changed files with 2793 additions and 50 deletions
+12 -1
View File
@@ -11,7 +11,7 @@ from __future__ import annotations
import json
import uuid
from collections.abc import Iterator
from typing import Any
from typing import TYPE_CHECKING, Any
import pytest
from fastapi.testclient import TestClient
@@ -25,6 +25,9 @@ from app.rag.llm import StreamPiece
from app.rag.retriever import RetrievedChunk, weak_hit_titles
from app.rag.suggestions import MAX_SUGGESTIONS, derive_suggestions
if TYPE_CHECKING:
from app.rag.scaffolding import ScaffoldingFilter
ANSWER = "I haven't done anything like that — try one of these instead!"
#: A small KB outline standing in for the lite-generated one (phase 31).
@@ -332,6 +335,11 @@ def test_low_prompt_has_titles_only_no_content() -> None:
assert "<relevance>LOW</relevance>" in prompt
assert "DEFLECT_MODE" in prompt
assert "HONESTY GATE" in prompt # the LOW rule is what the model follows
# Phase 71 (owner-permitted 2026-09-03): the deflection plain-text
# line — the LOW turn offers no tools, so any tool markup there is
# always wrong (prevention at the prompt; the filter + recovery is
# the backstop).
assert "Reply in plain text only — you have no tools in this mode." in prompt
assert "- Kubernetes Homelab Cluster" in prompt
assert "- Backup Strategy" in prompt
assert "ALPHA_DOC_CONTENT" not in prompt
@@ -347,6 +355,8 @@ def test_high_path_unaffected() -> None:
assert plan.suggestions == []
assert "<relevance>HIGH</relevance>" in plan.system_prompt
assert "DEFLECT_MODE" not in plan.system_prompt
# Phase 71: the deflection plain-text line never leaks into HIGH.
assert "Reply in plain text only" not in plan.system_prompt
assert "ALPHA_DOC_CONTENT" in plan.system_prompt
assert "BETA_DOC_CONTENT" in plan.system_prompt
assert [d.title for d in plan.docs] == ["Kubernetes Homelab Cluster", "Backup Strategy"]
@@ -438,6 +448,7 @@ class _CannedLLM:
self,
messages: list[dict[str, str]],
tools: list[dict[str, Any]] | None = None,
scaffolding: ScaffoldingFilter | None = None, # phase 71 pass-through
):
self.seen.append(messages)
self.seen_tools.append(tools)