📄 一句话概括
实测 ptc-runtime 的实现包叫 dsh-ptc-runtime-node——能力是一个 id,实现是一个包;换运行时实现,能力名一个字都不用改。
📝 本节和前面几节的关系
7.3 讲 PTC 的分层设计。先看第一层:连【执行一段代码】这件事本身,都是可替换的能力。
一、id 与包名,各说各的话
配置里写的是 - id: ptc-runtime,下一行跟 name: '@deepseek-ai/dsh-ptc-runtime-node'。
- 前者是能力——谁都可以实现。
- 后者是当前选中的实现——后缀
-node就在告诉你它跑在 Node.js 上。
二、别的能力也这样
sandbox→dsh-sandbox-local(本地实现)。jobs→dsh-jobs-local(本地实现)。tool-subagent→ 一个包配四份 config,用provider字段选实现。
接缝要么露在包名后缀上,要么露在 config 字段上——两种都算把话说明白了。
三、这一层为什么必须分开
- 分开了,换实现不动能力名:调用方与模型的工具表都不用改。
- 分开了,实现可以多份并存:subagent 就是四份并存、按需启用。
- 分开了,实现的细节不外泄:能力只承诺【能执行代码】,跑在哪个引擎上是用它的人不必知道的事。
四、动手验证
实验 B:把 tool-subagent 的 provider 从 spawn 换成 fork,接口名 subagent 不动。
实跑结果:实质只改 1 行,0 警告(详见 7.3.4)。
五、动手 Demo:能力是一个 id,实现是一个包
几对【能力 → 实现】,看接缝露在哪儿:
pairs = [("ptc-runtime", "dsh-ptc-runtime-node"),
("sandbox", "dsh-sandbox-local"),
("jobs", "dsh-jobs-local")]
for c, i in pairs:
print(" %-14s -> %s" % (c, i))
print()
print(" 接缝: 包名后缀 (-node / -local) 或 provider 字段")
实跑输出:
--------------------------------------------------------------------
能力是一个 id,实现是一个包
--------------------------------------------------------------------
实测几对【能力 → 实现】,看包名怎么暴露接缝:
能力(配置里的 id) 默认实现(包名) 接缝露在哪
-----------------------------------------------------------------------
ptc-runtime dsh-ptc-runtime-node 包名后缀 -node
sandbox dsh-sandbox-local 包名后缀 -local
jobs dsh-jobs-local 包名后缀 -local
tool-subagent dsh-tool-subagent provider 字段(4 种)
hmr dsh-hmr 整包替换
-----------------------------------------------------------------------
ptc-runtime 这条尤其典型:**代码执行能力**由 `-node` 实现。
换一个 runtime 实现,能力 id 一个字都不用改。
能力名稳定,实现名可换——这是可替换性的最低要求。 包名后缀是最省事的接缝标记:一眼看出当前用的是哪份实现。 subagent 那种【同包 + provider 字段】是另一种形态,7.4.1 展开。
30 秒实验
- 在配置树里找出 ptc-runtime 这一行的 id 与 name。
- 再找两对 id 与 name 不一样的能力,写下它们的接缝在哪。
- 想想你自己写的代码里,有没有【能力与实现糊在一起】的地方。
常见误区
- 错误:ptc-runtime 就是一段执行代码的代码。——纠正:它只是一个能力 id——真正干活的是
dsh-ptc-runtime-node这个包。 - 错误:换实现要改调用方的代码。——纠正:能力名不变,调用方不用动——这正是分层的意义。
- 错误:实现只有一份,接缝是摆设。——纠正:subagent 实测四份并存——接缝是真在用的。
自测三问(点开对答案)
1. ptc-runtime 的实现包叫什么? —— `@deepseek-ai/dsh-ptc-runtime-node`——后缀 `-node` 标出实现。 2. 接缝一般露在哪两处? —— **包名后缀**(-node/-local)或 **config 字段**(provider)。 3. 能力与实现分开,换来什么? —— **换实现不动能力名**、实现可多份并存、实现细节不外泄。- ☐ 下一节(7.3.2 PTC 压缩的是确定性控制流,不是依赖语义理解的决策)
相关笔记
- Creative:让 Runtime 本身也成为可操作对象 —— 换实现这件事的极端形态
- Effect 与 Coeffect:插件增加什么,又需要什么 —— 声明式接缝的另一面
- 观察 composition 的【差分】 —— 从差分里看实现
- 🐳 DeepSeek Harness · 索引