From 6396ccc701799eab733400af89ccb91765a32d27 Mon Sep 17 00:00:00 2001 From: fengxiangdebaozi <10845145+fengxiangdebaozi@user.noreply.gitee.com> Date: Mon, 25 May 2026 14:14:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/app/gateway/routers/intent.py | 50 +++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/offline-backend-20260512/backend/app/gateway/routers/intent.py b/offline-backend-20260512/backend/app/gateway/routers/intent.py index 8001d2e4..0835bb73 100644 --- a/offline-backend-20260512/backend/app/gateway/routers/intent.py +++ b/offline-backend-20260512/backend/app/gateway/routers/intent.py @@ -111,13 +111,26 @@ async def stream_intent(request: Request, payload: dict = Body(...)) -> Streamin model_name=model_name, thread_id=thread_id, new_message=message, - # Intent agent shouldn't dispatch, search, write files, or - # view images — its only tool of note is ask_clarification. + # Intent agent only ever needs ask_clarification. Block + # everything else so the model can't drift into solutioning + # (e.g. saving a design doc with write_file) — the model + # tends to ignore SOUL prose, hard exclusion is reliable. excluded_tools=[ "web_search", "present_files", "view_image", "agent_orchestration", + "bash", + "ls", + "read_file", + "write_file", + "str_replace", + "memory", + "hindsight_recall", + "hindsight_reflect", + "hindsight_retain", + "task", + "write_todos", ], skill_stop_names=[], ) @@ -163,14 +176,33 @@ async def stream_intent(request: Request, payload: dict = Body(...)) -> Streamin parts.append(question) content = "\n\n".join(parts) if parts else content + # Scan ALL AI messages for the [INTENT_READY] marker, not just + # dispatch_msg.content. The model often emits the summary in an + # earlier AI message and then keeps yapping (or doing extra + # tool calls) — the marker is the source of truth, wherever it + # appears in the run. summary: dict[str, Any] | None = None - match = _INTENT_READY_PATTERN.search(content) - if match: - try: - summary = json.loads(match.group(1)) - except json.JSONDecodeError as exc: - logger.warning("intent summary JSON parse failed: %s", exc) - summary = None + ready_text: str = "" + for msg in reversed(messages): + if not isinstance(msg, dict): + continue + if (msg.get("type") or "").lower() not in ("ai", "aimessage", "aimessagechunk"): + continue + msg_text = _flatten_content(msg.get("content", "")) + m = _INTENT_READY_PATTERN.search(msg_text) + if m: + try: + summary = json.loads(m.group(1)) + except json.JSONDecodeError as exc: + logger.warning("intent summary JSON parse failed: %s", exc) + summary = None + ready_text = msg_text + break + # When the marker was found in an earlier message, surface that + # message's text (which contains the user-facing 📋 汇总 + JSON) + # instead of the final filler AI text like "好的,收到". + if summary and ready_text: + content = ready_text status_value = "done" if summary else "asking" final_frame: dict[str, Any] = {