Soften short-intent gates and add tool-result refs plus MCP wire invalidate.

Prefer report tools without hard-hiding CLI, keep soft CLI budgets, store compact+result_ref for the model, and clear frozen wire after MCP sync.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-08-12 21:48:05 +08:00
parent 3785e78a72
commit 605751b6a6
13 changed files with 636 additions and 65 deletions

View file

@ -5,9 +5,9 @@ from runtime.application.gateway.ops_short_intent import (
filter_tool_specs_for_ops_short_intent,
is_ops_short_intent_suppressed_tool,
maybe_ops_short_intent_system_hint,
ops_short_intent_cli_soft_budgets,
)
from runtime.tools.base import ToolSpec
from runtime.tools.tool_error_hints import enrich_exec_managed_ne_error, enrich_get_managed_ne_error
def test_detect_ops_short_intent_english_field() -> None:
@ -20,18 +20,19 @@ def test_detect_ops_short_intent_english_field() -> None:
assert detect_ops_short_intent("hello there how are you doing today with something else") is None
def test_ops_short_intent_suppresses_inventory_cli_tools() -> None:
assert is_ops_short_intent_suppressed_tool("mcp__netx__listCliTargets", intent="fiber_cut")
assert is_ops_short_intent_suppressed_tool("mcp__netx__execManagedNe", intent="offline")
def test_ops_short_intent_suppresses_diy_xlsx_shell_only() -> None:
assert is_ops_short_intent_suppressed_tool("run_command", intent="excel_export")
assert is_ops_short_intent_suppressed_tool("write_xlsx", intent="fiber_cut")
assert is_ops_short_intent_suppressed_tool("write_xlsx", intent="excel_export")
# Soft preference: CLI/inventory stay available for device confirmation.
assert not is_ops_short_intent_suppressed_tool("mcp__netx__listCliTargets", intent="fiber_cut")
assert not is_ops_short_intent_suppressed_tool("mcp__netx__execManagedNe", intent="offline")
assert not is_ops_short_intent_suppressed_tool("ume_alarm_xlsx_report", intent="fiber_cut")
assert not is_ops_short_intent_suppressed_tool("mcp__netx__queryUmeAlarmsRaw", intent="alarm_tally")
assert not is_ops_short_intent_suppressed_tool("mcp__netx__execManagedNe", intent="continue")
def test_filter_tool_specs_for_ops_short_intent_keeps_report_path() -> None:
def test_filter_tool_specs_for_ops_short_intent_keeps_cli_and_report() -> None:
def _spec(name: str) -> ToolSpec:
return ToolSpec(
name=name,
@ -52,20 +53,33 @@ def test_filter_tool_specs_for_ops_short_intent_keeps_report_path() -> None:
names = {t.name for t in kept}
assert "ume_alarm_xlsx_report" in names
assert "mcp__netx__aggregateUmeAlarms" in names
assert "mcp__netx__listCliTargets" in names
assert "mcp__netx__execManagedNe" in names
assert "write_xlsx" not in names
assert "mcp__netx__listCliTargets" not in names
assert "mcp__netx__execManagedNe" not in names
assert "run_command" not in names
assert len(filter_tool_specs_for_ops_short_intent(tools, intent="continue")) == len(tools)
def test_ops_short_intent_cli_soft_budgets() -> None:
soft = ops_short_intent_cli_soft_budgets("fiber_cut")
assert soft is not None
assert int(soft["single"]) <= 2
assert int(soft["batch"]) == 1
assert ops_short_intent_cli_soft_budgets("continue") is None
assert ops_short_intent_cli_soft_budgets(None) is None
def test_ops_short_intent_hint_english_default() -> None:
hint = maybe_ops_short_intent_system_hint(text="LOS on these sites", lang="en")
assert "fiber" in hint.lower() or "LOS" in hint
assert "ume_alarm_xlsx_report" in hint
assert "soft budget" in hint.lower() or "targets" in hint.lower()
assert "断纤" not in hint
from runtime.tools.tool_error_hints import enrich_exec_managed_ne_error, enrich_get_managed_ne_error
def test_enrich_exec_timeout() -> None:
out = enrich_exec_managed_ne_error(
{"ok": False, "error_code": "tool_timeout_or_failed", "error": "timeout"}

View file

@ -0,0 +1,47 @@
from __future__ import annotations
from pathlib import Path
from runtime.chat.tool_result_store import (
attach_result_ref,
load_tool_result_blob,
save_tool_result_blob,
)
from runtime.tools.public.fetch_tool_result_tool import fetch_tool_result_tool
def test_save_and_fetch_tool_result_blob(monkeypatch, tmp_path: Path) -> None:
monkeypatch.setattr("runtime.chat.tool_result_store.attachments_dir", lambda: tmp_path)
big = {"ok": True, "rows": ["x" * 100 for _ in range(80)]}
ref = save_tool_result_blob(session_id="sess-1", tool_call_id="tc1", result=big)
assert ref and ref.startswith("tr:")
loaded = load_tool_result_blob(ref, session_id="sess-1")
assert loaded["ok"] is True
assert loaded["result"]["ok"] is True
assert loaded["truncated"] is False
def test_attach_result_ref_adds_fetch_hint() -> None:
out = attach_result_ref({"ok": True, "_truncated_for_llm": True, "preview": "p"}, result_ref="tr:abcd")
assert out["result_ref"] == "tr:abcd"
assert out["fetch_tool"] == "fetch_tool_result"
assert "fetch_tool_result" in str(out.get("hint") or "")
def test_fetch_tool_result_public_tool(monkeypatch, tmp_path: Path) -> None:
monkeypatch.setattr("runtime.chat.tool_result_store.attachments_dir", lambda: tmp_path)
ref = save_tool_result_blob(
session_id="sess-2",
tool_call_id="tc2",
result={"ok": True, "data": "hello" * 2000},
force=True,
)
assert ref
monkeypatch.setattr(
"runtime.tools.public.fetch_tool_result_tool.current_tool_lane_sessions",
lambda: (None, "sess-2"),
)
tool = fetch_tool_result_tool()
out = tool.handler({"result_ref": ref})
assert out["ok"] is True
assert out["result_ref"] == ref

View file

@ -10,6 +10,14 @@ class _DummyStore:
def get_setting(self, key: str) -> str:
return str(self.settings.get(key, ""))
def list_mcp_servers(self, *, enabled_only: bool = False):
del enabled_only
return []
def list_mcp_server_tools(self, *, server_id: str):
del server_id
return []
def test_tool_wire_freeze_default_on(monkeypatch) -> None:
monkeypatch.setattr(dl, "_prepare_llm_tools", lambda **kwargs: [])
@ -52,3 +60,35 @@ def test_warm_tool_wire_cache_clears_frozen_stale_entries(monkeypatch) -> None:
st = dl.tool_wire_freeze_status(store=store)
assert st["frozen"] is True
assert st["last_warm_count"] == 2
def test_invalidate_tool_wire_cache_clears_freeze(monkeypatch) -> None:
monkeypatch.setattr(dl, "_prepare_llm_tools", lambda **kwargs: [])
store = _DummyStore({"AIA_TOOL_WIRE_FROZEN_ON_STARTUP": "1"})
_ = dl.warm_tool_wire_cache(store=store, tools=object(), base_url="", roles=["generalist"])
assert dl.tool_wire_freeze_status(store=store)["frozen"] is True
out = dl.invalidate_tool_wire_cache(reason="test")
assert out["ok"] is True
assert dl.tool_wire_freeze_status(store=store)["frozen"] is False
def test_mcp_tools_fingerprint_changes_with_catalog() -> None:
class _Store(_DummyStore):
def __init__(self):
super().__init__()
self.tools = [{"tool_name": "a"}]
def list_mcp_servers(self, *, enabled_only: bool = False):
del enabled_only
return [{"server_id": "netx"}]
def list_mcp_server_tools(self, *, server_id: str):
del server_id
return list(self.tools)
store = _Store()
fp1 = dl._mcp_tools_fingerprint(store)
store.tools = [{"tool_name": "a"}, {"tool_name": "b"}]
fp2 = dl._mcp_tools_fingerprint(store)
assert fp1 != fp2
assert fp1 != "x"