games-development-ai/cheap-worker/ws_builtin_tools_patch.py
lili c372837762
Some checks failed
contract-gates / contract-gates (push) Has been cancelled
docs-gate / docs-gate (push) Has been cancelled
feat(deps): 升级 AgentScope 2.0.2→2.0.3(代码+文档,创始人 2026-07-06 拍板)
不为某个新特性,而是没道理把底座停在带并行 tool-result 缺陷的补丁版;2.0.3
是同线相邻补丁版,升级面窄、收益确定。承 tech-decisions §11-13「护城河进洋葱、
框架件谨慎审计」线。

代码:两 worker requirements 钉 2.0.3+溯源注;4 个 cheap-worker patch 的版本
guard 更 2.0.3——主控逐一源码核实 2.0.3 锚点仍成立:compress_context@_agent.py:259
未漂移 / _parse_stream_response@_openai_chat/_model.py:297·index 分桶:417 未漂移 /
list_tools@_local_workspace.py:660 / get_toolkit 装配点迁 _chat.py:354(patch 替
绑定名不依赖行号);patch 头 pin 声明同步 2.0.3+复核标记,根因 2.0.2 期实证保留。

文档:current-truth 面扫除(agentscope-2.0-facts 改掉一处「2.0.3 是笔误」错陈述+
行号漂移开源码更新 594→622/136→162/33→42/857→884/875→902、tech-decisions §15
升级决策散文、运行时 SoT 当前选型句、活代码注释、tier2 README 死链修);留痕层
(plans/HANDOFF/patch 根因分析/ADR 历史核验句)按两层纪律不动。

兼容三证:源码逐处 diff(RedisMessageBus/OpenAI formatter 零变化、Anthropic
formatter 仅并行 tool-result bug 修、ModelCallEndEvent 无变化、MiddlewareBase
加性 get_middleware_key)/ cheap 393+tier2 140+patch 20 测试全绿 / dev 两 venv
升级后 3 服务健康。收敛真跑:cheap 便宜档 ReAct 全链路 356 trace 零升级异常+
真出游戏过九门 9/9;tier2 Anthropic 工具循环跑满 40 轮写 15 文件 gen.log/trace
零升级异常(decision=fix 属 tier2 生成质量、非升级回归)。

2.0.3 新增原生 ReplyBudgetControlMiddleware(历史反复核验 2.0.2 不存在的类)/
tool 级洋葱/RAG/mem0,列而不迁(自建 ¥ 两段式 fail-closed 硬闸是护城河,原生
token 软控替不了),follow-up 见 §15。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 02:06:14 -07:00

56 lines
3.6 KiB
Python

"""ws_builtin_tools_patch.py — 便宜档 Service 关 workspace 内建工具(Bash/Edit/Glob/Grep/Read/Write)。
【坐实根因(2026-07-04 cutover S2 生产实证)】agentscope 2.0.2 Service 路 build_toolkit
(app/_service/_toolkit.py:107)把 workspace.list_tools() 的六内建(workspace/_local_workspace.py
:670-679 硬编码,无配置开关)无条件并入 agent 工具面,再拼 extra_agent_tools(便宜档六工具)。后果两条:
① 写边界击穿:便宜档护城河 = 六工具白名单(write 越界拒 + basename L1_FIXED 拒,I1 fail-closed),
内建 Write/Edit/Bash 不走白名单、可写工作区任意路径(Bash 甚至可越 workdir 触仓外)——白名单被旁路;
② 失败噪声/死圈:内建 Bash cwd=Service 工作区(非 repo 根),M3 惯性用相对路径 `ls game-runtime/...`
连败(80009 四连败触旧版退化签名 stuck 熔断 ¥2.6 作废;80011 复现同款失败指纹,签名富化打印抓获)。
CLI 路(cheap_run)从来只有六工具;Service 归并(配置控制面阶段一②)带进了这个面,per-task review
未抓到,live 工具失败观测抓获——「跨路径封口」教训再 +1(tech-decisions §12 同款)。
【修法】cheap Service 进程内 monkeypatch LocalWorkspace.list_tools → 返回 []。作用域正确性:本进程
(cheap_service_app)只跑便宜档 agent,进程内全局补丁 = 恰好全体便宜档 agent;tier2 服务是独立进程,
不受影响。skills/MCP 装载(list_skills / MCP 发现)不动;Planning/Team/Schedule 工具面收窄另评
(工单 h;其成本风险已有 ¥ 两段式硬地板兜上界)。
【钉 agentscope==2.0.3;2026-07-06 自 2.0.2 升级复核】运行时 monkeypatch,绝不改 venv/site-packages 文件本体。
依赖两个契约,2.0.3 已复核仍成立:① _toolkit.py 的 get_toolkit 仍以 `workspace.list_tools()` 为内建来源
(_toolkit.py:112);② LocalWorkspace.list_tools 仍为 async 无参方法、返六内建(_local_workspace.py:660)。
test_ws_builtin_tools_patch 全绿。上方根因是 2.0.2 期 cutover 的生产实证,原样保留。此后再升级仍按此复核
上述两点并重跑该单测(版本漂移时 apply 响亮 warning、但仍应用——不应用等于开着白名单旁路)。
"""
from __future__ import annotations
def apply_ws_builtin_tools_patch() -> None:
"""把 LocalWorkspace.list_tools 换成恒返回空表(便宜档 Service 进程专用,幂等)。"""
import agentscope # noqa: PLC0415
from agentscope.workspace import LocalWorkspace # noqa: PLC0415
ver = getattr(agentscope, "__version__", "?")
if ver != "2.0.3":
# 版本漂移:响亮告警但仍应用(不应用 = 内建 Bash/Write 旁路写白名单,比契约漂移更危险)。
print(
f"[ws-builtin-patch] WARNING: agentscope 版本 {ver} != 钉住的 2.0.3,"
"list_tools 契约可能已变,升级复核未做——补丁仍应用,请尽快复核。",
flush=True,
)
if getattr(LocalWorkspace.list_tools, "_cheap_ws_patched", False):
return # 幂等:重复 apply 不再包一层
async def _no_builtin_tools(self): # noqa: ANN001 —— 与 2.0.3 原签名一致(async 无参)
# 便宜档:内建工具全关(写边界只认六工具白名单;根因与作用域见模块头注释)。
return []
_no_builtin_tools._cheap_ws_patched = True # type: ignore[attr-defined]
LocalWorkspace.list_tools = _no_builtin_tools
print(
"[ws-builtin-patch] 已关 workspace 内建工具(Bash/Edit/Glob/Grep/Read/Write)——"
"便宜档写边界只认六工具白名单(钉 2.0.3,升级必须复核)。",
flush=True,
)