From 9630c1ece7f2ad7f6686ba13998803df8419f3d2 Mon Sep 17 00:00:00 2001 From: zizi Date: Wed, 24 Jun 2026 08:52:29 +0000 Subject: [PATCH] =?UTF-8?q?fix(tier2):=20=E6=9C=8D=E5=8A=A1=E6=80=81?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E8=AE=BE=20BYPASS=20=E6=9D=83=E9=99=90(?= =?UTF-8?q?=E4=BF=AE=E5=B7=A5=E5=85=B7=E8=B0=83=E7=94=A8=E5=8D=A1=E6=AD=BB?= =?UTF-8?q?=20ASK)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit toolkit 抠取修好后,agent 能调工具了,但每个 chat run 抛「Agent is waiting for 1 tool calls... but received no event」(agent/_agent.py:931):tier2 九工具默认 check_permissions 返回 ASK (_adapters.py:99),服务态无人确认 → 工具调用进 ToolCallState.ASKING 等永不来的确认事件 → 生成零产出(workdir 只有 play-spec.json,九工具一个没执行)。 CLI 线靠 studio.py 的 _bypass_state()(AgentState permission=BYPASS)解决;服务态此前没设。 修:bootstrap 建 session 后 PATCH /sessions/{id} permission_mode=bypass (app/_router/_session.py:334 更新 AgentState.permission_context.mode;PermissionMode.BYPASS="bypass"), start_new_game / iterate_existing_project 都设;resume_session 复用同 session 自动继承。加 _patch helper。 Co-Authored-By: Claude Opus 4.8 (1M context) --- tier2/gen-worker/service/bootstrap.py | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tier2/gen-worker/service/bootstrap.py b/tier2/gen-worker/service/bootstrap.py index b0c7fbfe..a125fda2 100644 --- a/tier2/gen-worker/service/bootstrap.py +++ b/tier2/gen-worker/service/bootstrap.py @@ -105,6 +105,31 @@ async def _post(client: Any, base: str, path: str, json_body: dict, *, user_head return resp.json() +async def _patch(client: Any, base: str, path: str, json_body: dict, *, user_header: str) -> dict: + """打一个 PATCH 到运行中的 Agent Service(部分更新),返回 JSON;非 2xx 抛(带可追溯日志)。""" + headers = {"X-User-Id": user_header} if user_header else {} + resp = await client.patch(f"{base}{path}", json=json_body, headers=headers, timeout=30.0) + if resp.status_code >= 300: + print(f"[tier2-bootstrap] PATCH {path} -> {resp.status_code}: {resp.text[:300]}", flush=True) + resp.raise_for_status() + return resp.json() + + +async def _set_permission_bypass(client: Any, base: str, session_id: str, *, user_header: str) -> None: + """把会话权限设为 BYPASS(沙箱无人值守档)——服务态等价 CLI studio.py 的 _bypass_state()。 + + 为什么必须设(2026-06-24 实证):tier2 九工具的 FunctionTool 默认 check_permissions 返回 ASK + (_adapters.py:99),服务态没有人确认。不设 BYPASS,agent 第一次调工具(scaffold_init)就进 + ToolCallState.ASKING、等一个永远不来的确认事件,chat run 抛「Agent is waiting for 1 tool calls... + but received no event」(agent/_agent.py:931)→ 服务态生成零产出。PATCH /sessions/{id} 把 + AgentState.permission_context.mode 设成 "bypass"(app/_router/_session.py:334-343 的更新路径; + PermissionMode.BYPASS 值="bypass"),跳过 ASK,与 CLI 单写口径一致(均运行在受控生成沙箱)。 + """ + await _patch(client, base, f"/sessions/{session_id}", + {"permission_mode": "bypass"}, user_header=user_header) + print(f"[tier2-bootstrap] 会话 {session_id} 权限已设 BYPASS(跳过工具 ASK,无人值守自治)。", flush=True) + + async def start_new_game( base_url: str, brief: str, @@ -169,6 +194,8 @@ async def start_new_game( } session = await _post(http, base_url, "/sessions/", session_body, user_header=user_id) session_id = session.get("session_id") or session.get("id") + # 设会话权限 = BYPASS:tier2 九工具默认 ASK,服务态无人确认,不设则首个工具调用即卡死(实证)。 + await _set_permission_bypass(http, base_url, session_id, user_header=user_id) # ④ 发 kick 触发首轮 chat run(fire-and-forget;事件从 SSE 收)。input 为 UserMsg 形状。 chat_body = { @@ -260,6 +287,8 @@ async def iterate_existing_project( } session = await _post(http, base_url, "/sessions/", session_body, user_header=user_id) session_id = session.get("session_id") or session.get("id") + # 设会话权限 = BYPASS:tier2 九工具默认 ASK,服务态无人确认,不设则首个工具调用即卡死(实证)。 + await _set_permission_bypass(http, base_url, session_id, user_header=user_id) # 迭代指令:先 scaffold_init 起手(已存在文件不覆盖),再按 iterate_instruction 改/加,跑门到绿 finish。 text = (