From 0465471ef4d793abcb32ab214dac7bb9d2408c66 Mon Sep 17 00:00:00 2001 From: lili Date: Mon, 29 Jun 2026 04:26:14 -0700 Subject: [PATCH] =?UTF-8?q?fix(cheap-worker):=20=E7=9C=9F=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=20gameId=20int=E2=86=92str=20=E5=BD=92=E4=B8=80?= =?UTF-8?q?=E5=8C=96(=E6=B2=BB=E4=BE=BF=E5=AE=9C=E6=A1=A3=E7=BB=8F?= =?UTF-8?q?=E7=9C=9F=E5=90=8E=E7=AB=AF=E5=85=A8=E5=A4=B1=E8=B4=A5=E7=9A=84?= =?UTF-8?q?=E9=98=BB=E6=96=AD=20bug)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A11 受计费真后端 e2e(mini-desktop 隔离实例)抓到的阻断性 seam bug: 后端 gameId 是 Java Long → JSON number → Python int;worker 直传 cheap_run 的 subprocess shell-out(scaffold/build/stage/smoke/play 要求 str)→ TypeError(expected str, not int) → scaffold 失败 → 静默归 llm_error → 便宜档经真后端 generate/modify 全部失败。 本机单测用 str gameId 没暴露;真后端 Java int gameId 才触发(e2e 的价值)。 修:_default_run_fn / _process_modify_job / _process_regenerate_job 三处 job 消费边界 归一 game_id=str(...)(str("x")=no-op,既有零影响)。e2e 重跑后全链路成功。 Co-Authored-By: Claude Opus 4.8 (1M context) --- cheap-worker/worker_service.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cheap-worker/worker_service.py b/cheap-worker/worker_service.py index d56fb622..5b627842 100644 --- a/cheap-worker/worker_service.py +++ b/cheap-worker/worker_service.py @@ -138,6 +138,9 @@ def _default_run_fn(job: dict): import cheap_studio game_id = job.get("gameId") or job.get("job_id") + # 真后端来的 gameId 是 Java Long → JSON 数字 → Python int;cheap_run 的 subprocess shell-out(scaffold/build/stage/smoke/play) + # 与路径段都要求 str,int 会抛 TypeError(expected str, not int) → 生成静默判 llm_error。此处在 job 消费边界统一归一为 str。 + game_id = str(game_id) if game_id is not None else None brief = job.get("brief") or "" summary = asyncio.run(cheap_studio.run_studio(game_id, brief)) return summary, cheap_run.game_dir(game_id) @@ -257,6 +260,9 @@ def _process_modify_job(state: WorkerState, job: dict, modify: dict) -> dict: trace_id = job.get("traceId") or job.get("job_id") mode = modify.get("mode") game_id = job.get("gameId") or job.get("job_id") + # 真后端来的 gameId 是 Java Long → JSON 数字 → Python int;cheap_run 的 subprocess shell-out(scaffold/build/stage/smoke/play) + # 与路径段都要求 str,int 会抛 TypeError(expected str, not int) → 生成静默判 llm_error。此处在 job 消费边界统一归一为 str。 + game_id = str(game_id) if game_id is not None else None # A11 M4:模块重生成(改玩法)分流——有界单文件重写 game-logic.js,复用 cheap_studio resume + 三层校验。 if mode == "regenerate-module": @@ -346,6 +352,9 @@ def _process_regenerate_job(state: WorkerState, job: dict, modify: dict) -> dict """ trace_id = job.get("traceId") or job.get("job_id") game_id = job.get("gameId") or job.get("job_id") + # 真后端来的 gameId 是 Java Long → JSON 数字 → Python int;cheap_run 的 subprocess shell-out(scaffold/build/stage/smoke/play) + # 与路径段都要求 str,int 会抛 TypeError(expected str, not int) → 生成静默判 llm_error。此处在 job 消费边界统一归一为 str。 + game_id = str(game_id) if game_id is not None else None import cheap_run