From 70792af967a7826fad8e19d800d44977183f046b Mon Sep 17 00:00:00 2001 From: Liang Jiaqing Date: Tue, 23 Jun 2026 10:06:09 +0800 Subject: [PATCH] fix(desktop_bridge): collect all mixin members for inMixin check; simplify ask_user schema; enhance turn-25 prompt - desktop_bridge.py: iterate all keys to collect mixin llm_nos, fixing inMixin bug when multiple mixins exist - tools_schema*.json: trim verbose descriptions for token efficiency - ga.py: clarify turn-25 prompt to write to file (not only working_checkpoint) --- assets/tools_schema.json | 6 +++--- assets/tools_schema_cn.json | 6 +++--- frontends/desktop_bridge.py | 13 +++++++++---- ga.py | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/assets/tools_schema.json b/assets/tools_schema.json index 01078937..27b00a38 100644 --- a/assets/tools_schema.json +++ b/assets/tools_schema.json @@ -60,10 +60,10 @@ }}, {"type": "function", "function": { "name": "ask_user", - "description": "Interrupt task to ask user when needing decisions, extra info, or facing unresolvable blockers. For multiple questions, use one call and put all in question—do not call repeatedly.", + "description": "Interrupt task to ask user when needing decisions, extra info, or facing unresolvable blockers. Multiple questions should in one call", "parameters": {"type": "object", "properties": { - "question": {"type": "string", "description": "Question for the user. For multiple questions, one per line (e.g. \"1. …\" / \"2. …\" or \"Q1: …\"); put A/B/C options under each question in this field. Do not cram multiple questions on one line. candidates is for single-question quick picks only."}, - "candidates": {"type": "array", "items": {"type": "string"}, "description": "Optional quick-select choices for a single question only. Leave empty for multi-question prompts; put per-question options in question instead."}}} + "question": {"type": "string", "description": "For multiple questions, one per line (contain candidates)"}, + "candidates": {"type": "array", "items": {"type": "string"}, "description": "Optional quick-select choices for a single question only. Leave empty for multi-questions"}}} }}, {"type": "function", "function": { "name": "start_long_term_update", diff --git a/assets/tools_schema_cn.json b/assets/tools_schema_cn.json index 0b70328c..98fbc211 100644 --- a/assets/tools_schema_cn.json +++ b/assets/tools_schema_cn.json @@ -60,10 +60,10 @@ }}, {"type": "function", "function": { "name": "ask_user", - "description": "当需要用户决策、提供额外信息或遇到无法自动解决的阻碍时,调用此工具中断任务并提问。多题应一次调用、全部写在 question 里,不要多次调用。", + "description": "当需要用户决策、提供额外信息或遇到无法自动解决的阻碍时,调用此工具中断任务并提问。多题时应一次调用", "parameters": {"type": "object", "properties": { - "question": {"type": "string", "description": "向用户提出的明确问题。多题时每题独占一行(如「1. …」「2. …」或「问题1: …」),每题下的选项用 A. B. C. 写在 question 内;不要用一行挤多题。candidates 仅用于单题快捷选项。"}, - "candidates": {"type": "array", "items": {"type": "string"}, "description": "单题时的可选快捷选项(纯文字)。多题时留空,各题选项写在 question 里,勿把多题选项平铺到此数组。"}}} + "question": {"type": "string", "description": "多题时每题*独占*一行(带选项)"}, + "candidates": {"type": "array", "items": {"type": "string"}, "description": "仅单题时可用。多题时留空"}}} }}, {"type": "function", "function": { "name": "start_long_term_update", diff --git a/frontends/desktop_bridge.py b/frontends/desktop_bridge.py index 0d441275..2ff937aa 100644 --- a/frontends/desktop_bridge.py +++ b/frontends/desktop_bridge.py @@ -418,21 +418,26 @@ class AgentManager: except Exception as e: print(f"get model profiles failed: {e}", file=sys.stderr) return [] - _, mcfg = self._mixin_entry(keys, mk) - members = [str(m) for m in (mcfg.get("llm_nos") or [])] if mcfg else [] active = self.config.get("llmNo", 0) + # collect all mixin members for inMixin check + all_mixin_members: set = set() + for k in keys: + if "mixin" in k: + c = mk.get(k) if isinstance(mk.get(k), dict) else {} + all_mixin_members.update(str(m) for m in (c.get("llm_nos") or [])) out = [] for i, k in enumerate(keys): cfg = mk.get(k) if isinstance(mk.get(k), dict) else {} if "mixin" in k: + mems = [str(m) for m in (cfg.get("llm_nos") or [])] out.append({"id": i, "varName": k, "kind": "mixin", "name": "", - "members": members, "active": i == active}) + "members": mems, "active": i == active}) else: name = self._base_display_name(k, cfg) out.append({"id": i, "varName": k, "kind": "native", "name": name, "model": cfg.get("model", ""), "group": "native" if "native" in k else "std", - "inMixin": name in members, "active": i == active}) + "inMixin": name in all_mixin_members, "active": i == active}) return out def add_to_mixin(self, profile_id: int) -> dict: diff --git a/ga.py b/ga.py index f017ff62..bd2e4ab0 100644 --- a/ga.py +++ b/ga.py @@ -566,7 +566,7 @@ class GenericAgentHandler(BaseHandler): elif turn % 7 == 0: next_prompt += f"\n\n[SYSTEM] Turn {turn}. Call update_working_checkpoint to save key context. Stop ineffective retries; if no progress, switch strategy: 1) Probe physical boundaries 2) **Re-read relevant SOPs**" elif turn % 25 == 0: - next_prompt += f"\n\n[SYSTEM] Turn {turn}. Write checkpoints/key findings/tried approaches to a file for future reference. Avoid losing critical info." + next_prompt += f"\n\n[SYSTEM] Turn {turn}. Write checkpoints/key findings/tried approaches to a **file** for future reference (not only working_checkpoint!). Avoid losing critical info." elif turn % 10 == 0: next_prompt += get_global_memory() if _plan and turn >= 10 and turn % 5 == 0: