当前位置: 首页 > news >正文

claw-code 源码详细分析:命令宇宙 vs 工具宇宙——`commands` / `tools` 镜像清单如何驱动路由与 shim 执行?

涉及源码src/reference_data/commands_snapshot.jsontools_snapshot.jsonsrc/commands.pysrc/tools.pysrc/execution_registry.pysrc/runtime.pysrc/main.pysrc/models.pyPortingModule)。


1. 「两个宇宙」是什么

在本仓库里,命令宇宙工具宇宙是两套有穷、可版本化的镜像清单,都从 JSON 快照加载为内存中的PortingModule元组:

  • 命令src/reference_data/commands_snapshot.jsonPORTED_COMMANDScommands.py
  • 工具src/reference_data/tools_snapshot.jsonPORTED_TOOLStools.py

快照里每条记录至少包含namesource_hintresponsibility(加载时映射进PortingModulestatus='mirrored'):

# 23:33:src/commands.pydefload_command_snapshot()->tuple[PortingModule,...]:raw_entries=json.loads(SNAPSHOT_PATH.read_text())returntuple(PortingModule(name=entry['name'],responsibility=entry['responsibility'],source_hint=entry['source_hint'],status='mirrored',)forentryinraw_entries)
# 23:34:src/tools.pydefload_tool_snapshot()->tuple[PortingModule,...]:raw_entries=json.loads(SNAPSHOT_PATH.read_text())returntuple(PortingModule(name=entry['name'],responsibility=entry['responsibility'],source_hint=entry['source_hint'],status='mirrored',)forentryinraw_entries)

产品语义上(与具体 IDE/Agent 产品对齐时):命令多对应用户显式/slash、调色板动作、工作流入口;工具多对应模型 function-calling / MCP 暴露给模型的可调用面。claw-code 在路由层用kind: command | tool把两宇宙拆开评分与排序,在执行层用不同 shim 签名(promptvspayload)区分。


2. 清单如何「驱动」——三层流水线

可以把数据流画成:快照 → 全量宇宙 →(可选过滤视图)→ 路由 → 注册表 shim →QueryEnginePort摘要

阶段命令侧工具侧
真相源commands_snapshot.jsontools_snapshot.json
全量常量PORTED_COMMANDSPORTED_TOOLS
过滤视图get_commands(..., include_plugin_commands, include_skill_commands)get_tools(simple_mode, include_mcp, permission_context)
路由输入route_prompt全量PORTED_COMMANDS同上PORTED_TOOLS
精确执行execute_command/MirroredCommandexecute_tool/MirroredTool

关键点路由不看get_tools的权限过滤。即使用户 CLI 里--deny-prefix mcp缩小了「可见工具列表」,默认route_prompt仍会在完整PORTED_TOOLS上匹配(与「模型实际能调用什么」的严格对齐需在上层再收敛,见result/05.md)。


3. 路由:PortRuntime.route_prompt

3.1 分轨收集 + 公平首发 + 余量排序

# 90:107:src/runtime.pydefroute_prompt(self,prompt:str,limit:int=5)->list[RoutedMatch]:tokens={token.lower()fortokeninprompt.replace('/',' ').replace('-',' ').split()iftoken}by_kind={'command':self._collect_matches(tokens,PORTED_COMMANDS,'command'),'tool':self._collect_matches(tokens,PORTED_TOOLS,'tool'),}selected:list[RoutedMatch]=[]forkindin('command','tool'):ifby_kind[kind]:selected.append(by_kind[kind].pop(0))leftovers=sorted([matchformatchesinby_kind.values()formatchinmatches],key=lambdaitem:(-item.score,item.kind,item.name),)selected.extend(leftovers[:max(0,limit-len(selected))])returnselected[:limit]

工程含义

  1. 分词:把/-替换成空格再split,得到小写 token 集合(适合从自然语言 prompt 里「捞」到与name/source_hint重叠的词)。
  2. 双宇宙并行评分:对命令、工具各跑一遍_collect_matches,得到两个已按分数排序的列表。
  3. 各取第一名:先从 command 榜、tool 榜各拿一个最高分(若存在),避免某一宇宙霸占整个limit
  4. 合并余量:剩余候选按分数降序,同分按kindname稳定排序,填满limit

3.2 单条评分:名字 + 路径提示 + 职责描述

# 176:192:src/runtime.pydef_collect_matches(self,tokens:set[str],modules:tuple[PortingModule,...],kind:str)->list[RoutedMatch]:matches:list[RoutedMatch]=[]formoduleinmodules:score=self._score(tokens,module)ifscore>0:matches.append(RoutedMatch(kind=kind,name=module.name,source_hint=module.source_hint,score=score))matches.sort(key=lambdaitem:(-item.score,item.name))returnmatches@staticmethoddef_score(tokens:set[str],module:PortingModule)->int:haystacks=[module.name.lower(),module.source_hint.lower(),module.responsibility.lower()]score=0fortokenintokens:ifany(tokeninhaystackforhaystackinhaystacks):score+=1returnscore

学习点:路由是子串命中计数,不是 embedding;source_hint含文件路径,用户说MCPreview等词时容易同时命中命令与工具条目,正好检验双轨公平逻辑。

RoutedMatch携带kind,后续执行与QueryEnginePortmatched_commands/matched_tools分拆都依赖它:

# 16:21:src/runtime.py@dataclass(frozen=True)classRoutedMatch:kind:strname:strsource_hint:strscore:int

4. Shim 执行:ExecutionRegistryexecute_*

4.1 注册表 = 全量清单的薄包装

# 47:51:src/execution_registry.pydefbuild_execution_registry()->ExecutionRegistry:returnExecutionRegistry(commands=tuple(MirroredCommand(module.name,module.source_hint)formoduleinPORTED_COMMANDS),tools=tuple(MirroredTool(module.name,module.source_hint)formoduleinPORTED_TOOLS),)

registry.command(name)/registry.tool(name)大小写不敏感查找,与get_command/get_tool一致。

4.2 命令 shim:prompt字符串

# 75:80:src/commands.pydefexecute_command(name:str,prompt:str='')->CommandExecution:module=get_command(name)ifmoduleisNone:returnCommandExecution(name=name,source_hint='',prompt=prompt,handled=False,message=f'Unknown mirrored command:{name}')action=f"Mirrored command '{module.name}' from{module.source_hint}would handle prompt{prompt!r}."returnCommandExecution(name=module.name,source_hint=module.source_hint,prompt=prompt,handled=True,message=action)

4.3 工具 shim:payload字符串

# 81:86:src/tools.pydefexecute_tool(name:str,payload:str='')->ToolExecution:module=get_tool(name)ifmoduleisNone:returnToolExecution(name=name,source_hint='',payload=payload,handled=False,message=f'Unknown mirrored tool:{name}')action=f"Mirrored tool '{module.name}' from{module.source_hint}would handle payload{payload!r}."returnToolExecution(name=module.name,source_hint=module.source_hint,payload=payload,handled=True,message=action)

命名差异是接口层对未来「命令吃自然语言 / 工具吃 JSON payload」的预留;当前bootstrap 里工具也传了用户prompt当 payload

# 119:120:src/runtime.pycommand_execs=tuple(registry.command(match.name).execute(prompt)formatchinmatchesifmatch.kind=='command'andregistry.command(match.name))tool_execs=tuple(registry.tool(match.name).execute(prompt)formatchinmatchesifmatch.kind=='tool'andregistry.tool(match.name))

即:路由后的统一「用户 utterance」先灌进两条执行链,真实现时可再分支解析。


5.bootstrap_session:路由 + shim + 引擎一条链

# 117:133:src/runtime.pymatches=self.route_prompt(prompt,limit=limit)registry=build_execution_registry()command_execs=tuple(registry.command(match.name).execute(prompt)formatchinmatchesifmatch.kind=='command'andregistry.command(match.name))tool_execs=tuple(registry.tool(match.name).execute(prompt)formatchinmatchesifmatch.kind=='tool'andregistry.tool(match.name))denials=tuple(self._infer_permission_denials(matches))stream_events=tuple(engine.stream_submit_message(prompt,matched_commands=tuple(match.nameformatchinmatchesifmatch.kind=='command'),matched_tools=tuple(match.nameformatchinmatchesifmatch.kind=='tool'),denied_tools=denials,))turn_result=engine.submit_message(prompt,matched_commands=tuple(match.nameformatchinmatchesifmatch.kind=='command'),matched_tools=tuple(match.nameformatchinmatchesifmatch.kind=='tool'),denied_tools=denials,)

顺序matches→ 按kind跑 shim → 推断denials→ 把名称元组(不是路径)交给QueryEnginePort
报告RuntimeSession.as_markdown()分别打印Routed Matches、Command Execution、Tool Execution、Stream Events、Turn Result(见runtime.pyas_markdown),便于肉眼核对「路由到了谁 → shim 说了啥 → 引擎摘要里写了啥」


6. CLI:清单自省、路由调试、按名 shim

子命令作用
commands/toolsget_commands/get_tools(可带过滤),列表视图
route <prompt>直接route_prompt,打印kind\tname\tscore\tsource_hint
show-command/show-toolget_command/get_tool按精确名看单条条目
exec-command/exec-tool不经路由,按名执行 shim(失败 exit 1)
# 142:148:src/main.pyifargs.command=='route':matches=PortRuntime().route_prompt(args.prompt,limit=args.limit)ifnotmatches:print('No mirrored command/tool matches found.')return0formatchinmatches:print(f'{match.kind}\t{match.name}\t{match.score}\t{match.source_hint}')
# 200:207:src/main.pyifargs.command=='exec-command':result=execute_command(args.name,args.prompt)print(result.message)return0ifresult.handledelse1ifargs.command=='exec-tool':result=execute_tool(args.name,args.payload)print(result.message)return0ifresult.handledelse1

测试锚点test_route_and_show_entry_cli_runtest_exec_command_and_tool_cli_runtest_execution_registry_runs等把快照非空、路由可命中、shim 有固定子串锁在 CI 里。


7. 镜像数据的「真实形状」与陷阱

7.1 同名多条目

快照里同一name可对应多条(例如多个source_hint指向不同文件):

{"name":"add-dir","source_hint":"commands/add-dir/add-dir.tsx",...},{"name":"add-dir","source_hint":"commands/add-dir/index.ts",...},

get_command/get_tool线性扫描,返回首个大小写匹配项:

# 52:56:src/commands.pydefget_command(name:str)->PortingModule|None:needle=name.lower()formoduleinPORTED_COMMANDS:ifmodule.name.lower()==needle:returnmodule

后果:shim 与show-command展示的source_hint可能只是其中一条;路由里每条快照行仍是独立PortingModule,同名可多次命中、多次出现在不同RoutedMatch(若分数与 limit 允许)。产品化时常需要primary_fqnentry_id消歧。

7.2 工具快照里的「非顶层工具」名

tools_snapshot.json中会出现UIagentMemory等与「用户心智中的工具类名」混在一起的条目,它们来自归档路径镜像。路由仍按 token 子串匹配——这是移植期忠实还原表面,不是最终 UX;成熟产品会在清单层再标callable: bool分层 tool spec


8. 小结

  • 命令宇宙 / 工具宇宙JSON 快照 →PORTED_*→(可选)get_*过滤构成;路由固定吃全量PORTED_*,与列表过滤解耦。
  • 路由在两条宇宙上独立打分、各取榜首、再合并余量,输出带kindRoutedMatch
  • ShimExecutionRegistry统一按名查找;命令prompt语义,工具payload语义,bootstrap 阶段暂用同一用户字符串灌入。
  • CLI提供列表 / 路由 / 精确查看 / 精确执行四条路径,支撑移植期可测试、可调试闭环。
http://www.jsqmd.com/news/591282/

相关文章:

  • Halcon fill_up/fill_up_shape 实战:精准填充工业图像中的复杂孔洞与裂缝
  • GD32F407单片机USART串口485通讯实战:从波形解析到中断收发
  • 2026年姜堰谷歌外贸推广费用分析,靠谱公司推荐 - 工业品牌热点
  • 如何让微信聊天记录成为数字资产?WeChatMsg全解析
  • SEED Labs实战:ROP攻击中如何巧妙利用环境变量获取root权限
  • 3个维度解锁Iverilog:免费硬件仿真工具的终极指南
  • ELK踩坑实录:从日志分析到安全告警,我是如何用Elastic Stack搭建内部SIEM的
  • 组件库版本升级全攻略:从问题诊断到风险控制的系统化迁移指南
  • Web 3D 交互开发实战:10个可直接落地的游戏与交互原型提示词
  • 手把手教学:Qwen2.5-VL-7B-Instruct本地部署,打造你的私人视觉AI助理
  • Pixel Aurora Engine 创意生成与VSCode Codex联动:智能代码辅助实战
  • Using Vulkan -- HLSL in Vulkan
  • B站缓存视频转换与媒体处理全攻略:从本地存储到高效管理
  • Web字体优化与前端性能提升:Fontmin工具全解析
  • 3分钟掌握:让PPT公式排版效率提升10倍的LaTeX插件使用指南
  • 分析1688代运营性价比,能提升自然流量且效果稳定的公司排名 - 工业推荐榜
  • KDD-99数据集实战:基于机器学习的网络入侵检测系统优化
  • ms-swift微调框架实战:10分钟在单卡3090上微调Qwen2.5-7B,新手也能快速上手
  • MATLAB高斯过程回归工具箱:支持多因素单/多输出拟合预测,比神经网络和支持向量机学习速度更...
  • 2种高效方案:Wand-Enhancer工具全功能解锁实战
  • 7个实用技巧:如何在项目中高效应用Plus Jakarta Sans开源字体
  • App-Installer:重新定义你的iOS应用安装体验
  • 微信单向好友困扰?WechatRealFriends一键检测工具助你优化社交关系
  • 诚信通代运营靠谱吗,全国范围内值得推荐的公司有哪些 - myqiye
  • 解决Chrome浏览器中Video标签进度条无法拖动的服务器端配置指南
  • 百考通:AI精准赋能开题报告,让学术研究更高效、更专业
  • ncmdump:让NCM音乐文件重获自由的格式转换工具
  • 突破加密壁垒:ArchivePasswordTestTool让压缩包密码恢复效率提升10倍的秘诀
  • 音频解密工具:打破加密壁垒的本地音乐格式转换解决方案
  • 终极窗口调整指南:如何用WindowResizer突破Windows尺寸限制