<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>DeepSeek on Trevor's Blog</title><link>http://hitrevor.com/tags/deepseek/</link><description>Recent content in DeepSeek on Trevor's Blog</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Wed, 04 Nov 2026 22:40:00 +0800</lastBuildDate><atom:link href="http://hitrevor.com/tags/deepseek/index.xml" rel="self" type="application/rss+xml"/><item><title>dsh 0.2.2-rc.1：这次发布改了 0 行代码</title><link>http://hitrevor.com/posts/dsh-022rc/</link><pubDate>Wed, 04 Nov 2026 22:40:00 +0800</pubDate><guid>http://hitrevor.com/posts/dsh-022rc/</guid><description>拆包逐文件比 md5：8 个包 290 个文件，改动只有 8 处，全在 package.json。版本号从 alpha 走到 rc，代码一行没动，但依赖全线升级，插件得跟着抬版本。</description><content:encoded><![CDATA[<p>今天下午五点二十，DeepSeek Harness 发了 0.2.2-rc.1。</p>
<p>从 alpha 转 rc，听着像是个里程碑。我把两个版本都拆开比了一遍，结论是：一个字节都没改。</p>
<h2 id="先说结论">先说结论</h2>
<p><code>0.2.2-rc.1</code> 发布于北京时间 2026 年 11 月 4 日 17:20（<code>2026-11-04T09:20:32Z</code>）。</p>
<p>我拿它和 2026 年 11 月 3 日发布的 <code>0.2.2-alpha.3</code> 做了逐文件 md5 比对，范围是顶层包、六个核心子包、以及底层框架 <code>cordis</code>，一共 290 个文件对齐算了一遍。</p>
<p>结果：每个包里唯一变的文件，都是 <code>package.json</code>。</p>
<p><code>dist</code>、<code>src</code>、<code>locale</code>、<code>README</code> 全部一模一样。这不是「改动很小」，这是零改动。</p>
<h2 id="我怎么比的">我怎么比的</h2>
<p>命令行就三步，没用什么特殊工具：</p>
<p><code>npm pack @deepseek-ai/dsh@0.2.2-alpha.3</code> 和 <code>@0.2.2-rc.1</code> 各拉一份 tarball，解包到两个目录，然后按相对路径逐文件算 md5。</p>
<p>顶层包 20 个文件，六个子包各 30 到 60 个文件，<code>cordis</code> 32 个文件。两边同名文件全部对齐算一遍，只记下哈希不一致的。</p>
<table>
	<thead>
			<tr>
					<th>包</th>
					<th>文件数</th>
					<th>内容变化的文件</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>dsh（顶层）</td>
					<td>20</td>
					<td>1 个，package.json</td>
			</tr>
			<tr>
					<td>dsh-agent-preset</td>
					<td>48</td>
					<td>1 个，package.json</td>
			</tr>
			<tr>
					<td>dsh-plugin-manager</td>
					<td>60</td>
					<td>1 个，package.json</td>
			</tr>
			<tr>
					<td>dsh-web-app</td>
					<td>32</td>
					<td>1 个，package.json</td>
			</tr>
			<tr>
					<td>dsh-client-ui-cordis</td>
					<td>30</td>
					<td>1 个，package.json</td>
			</tr>
			<tr>
					<td>dsh-tool-fs</td>
					<td>34</td>
					<td>1 个，package.json</td>
			</tr>
			<tr>
					<td>dsh-tool-cordis</td>
					<td>34</td>
					<td>1 个，package.json</td>
			</tr>
			<tr>
					<td>cordis</td>
					<td>32</td>
					<td>1 个，package.json</td>
			</tr>
	</tbody>
</table>
<p>没有新增，没有删除。八个包八处改动，全是版本号和依赖范围那一行。</p>
<p><img loading="lazy" src="/images/dsh-022rc/fig1.png"></p>
<h2 id="唯一真正变了的东西">唯一真正变了的东西</h2>
<p>代码没变。但依赖版本号全换了一茬，这是这次发布唯一的实质动作：</p>
<table>
	<thead>
			<tr>
					<th>包</th>
					<th>alpha.3</th>
					<th>rc.1</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>@deepseek-ai/cordis</code></td>
					<td>4.0.6-alpha.2</td>
					<td>4.1.0</td>
			</tr>
			<tr>
					<td><code>cordis-plugin-loader</code></td>
					<td>1.0.7-alpha.2</td>
					<td>1.1.0</td>
			</tr>
			<tr>
					<td><code>cordis-plugin-include</code></td>
					<td>1.0.11-alpha.2</td>
					<td>1.1.0</td>
			</tr>
			<tr>
					<td><code>cordis-plugin-timer</code></td>
					<td>1.1.8-alpha.2</td>
					<td>1.2.0</td>
			</tr>
			<tr>
					<td><code>@deepseek-ai/schemastery</code></td>
					<td>3.18.6-alpha.2</td>
					<td>3.19.0</td>
			</tr>
			<tr>
					<td><code>@deepseek-ai/cosmokit</code></td>
					<td>1.8.7-alpha.2</td>
					<td>1.9.0</td>
			</tr>
	</tbody>
</table>
<p>一句话总结：把整个 cordis 家族的 alpha 后缀去掉，抬成正式版本号。</p>
<p>但这里有个细节值得说。我把 <code>cordis</code> 4.0.6-alpha.2 和 4.1.0 也拆开比了，它的 32 个文件里同样只有 <code>package.json</code> 不同。也就是说连框架层都是原样搬过去的，只换了门牌号。这个比上面那张表更有意思。</p>
<p>那次「版本号从 alpha 变正式」，改动量是零。</p>
<p><img loading="lazy" src="/images/dsh-022rc/fig2.png"></p>
<h2 id="所以这次发布到底图什么">所以这次发布到底图什么</h2>
<p>图一个 tag。</p>
<p>发布之前，<code>latest</code> 指向 <code>0.2.1-rc.5</code>，<code>next</code> 指向 <code>0.2.2-alpha.3</code>。想装最新的得手动写全版本号。</p>
<p>发布之后，<code>latest</code> 和 <code>next</code> 都指向 <code>0.2.2-rc.1</code>。这意味着 <code>npm i -g @deepseek-ai/dsh</code> 不加版本号，默认装的就是它。</p>
<p>对大项目来说这不是小事。alpha 线是「我们自己敢用」的标记，rc 是「你也来试试，接口已经定死了」的标记。改功能是开发，改标记是承诺。这一版做的是后者。</p>
<h2 id="升级花了不到一分钟">升级花了不到一分钟</h2>
<p>全局装一条命令，<code>npm i -g @deepseek-ai/dsh@0.2.2-rc.1</code>，跑完 <code>dsh --version</code> 就是 <code>0.2.2-rc.1</code>。</p>
<p>第二条命令不是升级，是修 profile。这条很多人会漏，我上次就漏了：</p>
<p><code>dsh plugin --profile web add @deepseek-ai/dsh-cua-bundle@0.2.2-rc.1 @deepseek-ai/dsh-experimental-plugin-market-bundle@0.2.2-rc.1 @deepseek-ai/dsh-experimental-client-ui-agent-team@0.2.2-rc.1</code></p>
<p>pnpm 报回来：解析 62 个包，复用 41 个，下载 21 个，新增 22 个，耗时 939 毫秒。</p>
<p>装完我先用 headless 模式冒烟了一次，让它「只回答两个字：收到」。它回了「收到」，说明 profile 能正常启动、模型路由通、没有插件卡在 disable 状态。这一步比看界面快。</p>
<p>为什么要重跑？因为 dsh 的 profile 是一层叠一层的插件堆，全局升了 dsh 之后，profile 里那些还钉在 alpha.3 的插件和主程序版本对不上，启动时会被版本校验直接 disable。</p>
<p>上次升 alpha.3 我只升了全局，结果六行插件被关掉，<code>storage-domain</code> 就在其中。它一挂，工作区、会话列表、定时任务跟着全卡死，网页版直接废掉，最后靠这条命令才救回来。</p>
<p>所以我的顺序固定了：先全局，再 profile，最后验证。少一步就是给自己找麻烦。</p>
<p><img loading="lazy" src="/images/dsh-022rc/fig3.png"></p>
<h2 id="上次没救回来的那个这次回来了">上次没救回来的那个，这次回来了</h2>
<p>上次升级唯一遗留的伤是 <code>ui-agent-team</code>：它版本线特殊，npm 上找不到能和 alpha.3 对齐的包，只能一直禁用着。</p>
<p>这次它有对应版本了。装完之后 <code>profile_ping</code> 报的插件清单里，这三个都在：</p>
<p><code>@deepseek-ai/dsh-experimental-agent-team</code></p>
<p><code>@deepseek-ai/dsh-experimental-client-ui-agent-team</code></p>
<p><code>@deepseek-ai/dsh-experimental-tool-agent-team</code></p>
<p>上一版被禁的 <code>dsh-storage-domain</code> 也在列表里。插件页面上，「Agent teams」那个开关是打开的，新会话的标题栏上还多了一个 Agent team 的标识。</p>
<p>装的时候出了一句提示，我觉得值得原样记下来：<code>@deepseek-ai/dsh-experimental-client-ui-agent-team</code> 没有声明 <code>dsh.bundle</code>，所以它是作为普通依赖装的，不是一个 profile 层。</p>
<p>换句话说它能用，但它在体系里的位置和那些 bundle 不一样。这种话厂商不会写在发布说明里，只在安装输出里闪一句。</p>
<p><img loading="lazy" src="/images/dsh-022rc/fig4.png"></p>
<h2 id="profile-里不全是官方包">profile 里不全是官方包</h2>
<p>顺手看了一眼 profile 的依赖清单，六条：</p>
<p>三个 bundle 现在是 rc.1，<code>agent-team-web-profile</code> 还停在 <code>0.1.6-alpha.2</code>，剩下两条是我自己装的，一个从本地 tgz 装，一个直接从 GitHub 仓库装。</p>
<p>这说明 dsh 的 profile 不是一个封闭的官方套装，是你自己拼的组合。好处是你想加什么加什么，代价是升级时得自己盯：哪些是官方的、哪些钉在某个版本、哪些根本不在官方的版本线上。</p>
<p><code>agent-team-web-profile</code> 就是例子。它是 agent-team 的界面层，版本线和主程序完全独立，主程序到 rc.1 了它还在 alpha.2。这种包不会跟着你升级，它自己走自己的。</p>
<h2 id="顺手验了一遍">顺手验了一遍</h2>
<p>升级完之后我在网页版开了一个新会话，只发一句：调用 profile_ping，把返回的 JSON 原样贴出来。</p>
<p>十秒完成，返回的开头是 <code>&quot;profile&quot;: &quot;web&quot;, &quot;dshVersion&quot;: &quot;0.2.2-rc.1&quot;, &quot;plugins&quot;: [</code> 后面跟着 212 个插件名。</p>
<p>这 212 行就是我这个 profile 现在的真实构成，从 <code>cordis-plugin-timer</code> 一直到我自己写的 <code>dsh-plugin-profile-ping</code>。想确认升级到底有没有生效，看这一个数字比看任何界面都准。</p>
<p>顺带一提，这个查询本身花了 56.3K token，缓存命中 86%，上下文只用了 3%。开销主要在插件清单太长，不在推理。</p>
<p><img loading="lazy" src="/images/dsh-022rc/fig5.png"></p>
<h2 id="一个查版本的经验">一个查版本的经验</h2>
<p>如果你也想追 dsh 的版本，有个坑得避开：子包的 <code>latest</code> 标签是滞后的。</p>
<p>比如 <code>dsh-experimental-client-ui-agent-team</code>，它的 <code>latest</code> 停在 <code>0.1.5-alpha.2</code>，<code>alpha</code> 停在 <code>0.2.2-alpha.3</code>，真正的新版本在 <code>next</code> 里。</p>
<p><code>npm view &lt;包名&gt; dist-tags</code> 三个标签一起看，别只看 <code>latest</code>。主包现在 <code>latest</code> 是对的，子包不是。</p>
<h2 id="我的判断">我的判断</h2>
<p>这类版本值不值得跟？我的答案是跟，但不用急。</p>
<p>代码零变化意味着风险接近零，升不升都不会坏你的环境。真正的收益不在 dsh 本身，而在那些跟着转正的插件：<code>ui-agent-team</code> 这种跨版本线的包，只有在整条线一起转 rc 的时候才会被放出来。</p>
<p>反过来说，如果你手上有个跑得好好的 alpha.3，没有任何插件被禁，那这次不用动。等 0.2.2 正式版出来再一次性跟上，中间这几天不会有新功能给你。</p>
<p>你升级的时候会先看发布说明，还是直接拆包比一遍？</p>
]]></content:encoded></item><item><title>让 dsh 自己给自己写插件，它花了九分钟</title><link>http://hitrevor.com/posts/dsh-creator/</link><pubDate>Tue, 03 Nov 2026 19:40:00 +0800</pubDate><guid>http://hitrevor.com/posts/dsh-creator/</guid><description>我让 dsh 的创造模式写一个插件，它查运行时、读源码、写包、申请安装，九分钟后工具真的出现在插件管理页里，新会话十秒调通。</description><content:encoded><![CDATA[<p>今天热点里那条「DeepSeek 上线创作者模式」，英文媒体写得很玄，说用聊天就能造插件。</p>
<p>我本机天天在用 dsh，跑的是 2026 年 10 月 28 日发的 0.2.2-alpha.2，看到这条的第一反应不是转述，是试一遍。</p>
<p>于是我在自己的 web profile 里开了一个 Creator mode 的会话。给它的需求只有一句话：写一个最小的插件，注册一个叫 profile_ping 的工具，返回当前 profile 名、dsh 版本号、以及这个 profile 里装了哪些插件。</p>
<p>九分钟之后，这个工具躺在插件管理页里，我新开一个会话调它，十秒拿到了结果。</p>
<h2 id="dsh-一共有四种模式">dsh 一共有四种模式</h2>
<p>打开 web 界面，输入框上面有个模式选择器，点开是四条：</p>
<ul>
<li>Standard，写代码、查资料、跑命令，适合大多数任务</li>
<li>PTC，包住 Standard 全部能力，额外适合「批量调工具再筛、去重、统计」这类活</li>
<li>Minimal，只给终端和读图，用来测基础能力</li>
<li>Creator，官方原话是「通过对话定制 dsh，让 agent 写插件加功能或界面，或者把工具和提示词组合成你自己的模式」</li>
</ul>
<p>我这次点的是第四条。</p>
<p><img alt="四种模式，第四种是让它改自己" loading="lazy" src="/images/dsh-creator/fig1.png"></p>
<h2 id="它没有一上来就写代码">它没有一上来就写代码</h2>
<p>这点是我最意外的。</p>
<p>接到需求之后，它先载入了一个叫 cordis-plugin-development 的技能包，然后开始查运行时。</p>
<p>界面右侧的 Trajectory 里能看到它一连串动作。先 inspect providers 看有哪些服务，再 query runtime 问 Service.listService 的方法签名，一遍遍查 pluginManager、profileContext、defineTool 的确切契约。</p>
<p>它甚至去翻了 @deepseek-ai/dsh-app-boot 的源码，来判断「插件里能不能 import 这个包」。它要拿 dsh 版本号，而版本号只能从安装目录的 package.json 里读。</p>
<p>这一步的判断过程我觉得比结果更值钱：它先确认「profile 里装的插件解析不到安装目录的包」，然后改用运行时已经提供的 profileContext，从 installAnchor 那个路径自己去读。</p>
<h2 id="写出来的东西是这个样子">写出来的东西是这个样子</h2>
<p>生成物在会话的工作区里，是个标准的 bundle 包：清单、补丁、入口、两份语言文件、一枚图标，外加一份 README。</p>
<p>package.json 里那句 <code>&quot;dsh&quot;: { &quot;bundle&quot;: { &quot;patch&quot;: &quot;./cordis.patch.yml&quot; } }</code>，就是它跟 dsh 打招呼的方式。补丁文件只有三行，插入一条 id 叫 profile-ping 的行。</p>
<p>index.js 六点九 KB，自己注册工具、定义参数和输出 schema、写 render。中文名字「Profile 探针」是它自己起的。</p>
<p><img alt="它生成的不是一个文件，是一个能装进 profile 的包" loading="lazy" src="/images/dsh-creator/fig3.png"></p>
<h2 id="中间我拒了它一次">中间我拒了它一次</h2>
<p>安装那一步它调的是 plugin_manager 的 install_bundle，界面上弹出一个授权框，写明「这会把改动写进 profile，装进去的 Host 代码在沙箱外面跑」。</p>
<p>我点了 Allow once。</p>
<p>后来它想把打包好的 tgz 从 /tmp 复制到 Documents 下做长期保存，又申请一次授权。这次我点了 Reject，因为这是我准备做完实验就清理的临时东西。</p>
<p>它的反应值得记一笔：它停下了，并且明确说「用户拒绝了这次提权，所以我不该绕开，解释清楚就行」。</p>
<p>这条规矩写在它的技能包里，不是模型的即兴发挥。原文是「不要手写 profile 的 package.json，不要自己在 profile 目录里跑 pnpm，这些事由 install_bundle 做」。</p>
<p><img alt="它自己走完的八十三个步骤" loading="lazy" src="/images/dsh-creator/fig2.png"></p>
<h2 id="跑通了">跑通了</h2>
<p>新开一个会话，我说「直接调用 profile_ping，把返回原文贴出来」。</p>
<p>十秒钟，它贴出来：</p>
<p>返回就三行开头：<code>Profile: web</code>、<code>dsh version: 0.2.2-alpha.2</code>、<code>Plugins (209):</code>。后面跟着两百零九个包名，排在末尾的那个，正是它自己写的。</p>
<p>插件管理页的「已安装」里也多了一行：Profile ping，带图标、带描述、开关是开的。</p>
<p><img alt="左边是调用结果，右边是它出现在插件管理页" loading="lazy" src="/images/dsh-creator/fig4.png"></p>
<h2 id="它的技能包里把规矩写死了">它的技能包里把规矩写死了</h2>
<p>跑完我才去读它载入的那份技能文档，读完明白它为什么这么走。文档里写道，这套流程分五步，第一步就是「先交付能用的版本」。</p>
<p>文档开头就写：先交一个能跑的版本，再谈好不好看。视觉需求如果没说落在哪，默认就是当前这个 Web 界面；不要先做预览页、别做几套设计稿、别写截图脚本。</p>
<p>然后是三条禁止：不要手写 profile 的 package.json，不要在 profile 目录里跑 pnpm，不要在 $DSH_HOME 下面造包。这些活统一交给插件管理器的 install_bundle，手工写一次就要一次审批。</p>
<p>还有一条验证规矩：装完看返回里的 application 字段和 warnings，别看日志、别看进程列表、别看页面是不是起了。</p>
<p>我这次全程没干预它的技术判断，唯一做的就是两次授权点击，一次同意一次拒绝。它在这套规矩里自己走完了。</p>
<h2 id="三个坑我得说清楚">三个坑，我得说清楚</h2>
<p>第一个，它创建的工作区目录名带了反斜杠。dsh 在 macOS 上把路径拼成了 <code>deepseek-harness\creator-lab</code>，那个反斜杠是真的字符，不是转义。结果 ESM 加载这种路径直接报错，插件根本 import 不进来。它自己发现的，改用打包成 tgz 安装绕过去了。</p>
<p>第二个，装完当回合调不到工具。工具列表是这个回合开始时就定死的，新注册的工具下一轮才出现。它在 Trajectory 里连着打转了好几次，自己在思考里写「我可能只能发出静态列表里的工具」，我另开一个会话，才验证成功。</p>
<p>第三个，安装记录里写的是 <code>file:/tmp/dsh-plugin-build/xxx.tgz</code>。也就是说，清了临时目录，这个插件下次就装不上。它想修的正是这一点，被我拒了。真要长期用，得把包放到工作区里，用 install_bundle 指目录安装。</p>
<h2 id="它现在能造什么造不出什么">它现在能造什么，造不出什么</h2>
<p>能造的：工具类插件，往 agent 的工具箱里加一个能力，我这次的 profile_ping 就是；配置类插件，改宿主某个服务的行为；界面类插件，往 Web 界面的插槽里挂一块。技能包里这三类各有模板和参考文档。</p>
<p>造不出的：需要新宿主服务的插件，它自己文档里写着这个插件不是内核，不加服务、不加会话事件类型、不加沙箱后端；还有跨 profile 的改动，一次只能动当前这个 profile。</p>
<p>一个更实际的限制是 token。这次九分钟的活，烧掉 890 万 token，缓存命中 99% 才压住了成本。你要让它干大活，得先想清楚值不值。</p>
<h2 id="我的判断">我的判断</h2>
<p>「用聊天造插件」这个说法容易让人以为它是个生成器：你描述，它吐代码。</p>
<p>不是。它更像一个懂这套框架的工程师：先查运行时有哪些能力，再读源码确认约束，然后照技能包里的流程施工，装的时候申请授权，装完自己验一遍。</p>
<p>真正稀缺的是那套流程本身。技能包里把「先交一个能跑的版本，再谈好看」「视觉需求默认落在当前界面」「安装结果看 application 字段而不是日志」这些规矩都写死了。模型会换，这套规矩不换。</p>
<p>一个能力边界放这儿：它九分钟里烧了 890 万 token，缓存命中 99%。这不是零成本的魔法，是一次真刀真枪的施工。</p>
<p>你手上有哪个工具，是每次都要手动翻一遍配置才知道状态的？那种东西，值得让它给你写一个插件。</p>
]]></content:encoded></item><item><title>DeepSeek Super-agent：五个模块只剩两个</title><link>http://hitrevor.com/posts/dsh-superagent/</link><pubDate>Sun, 01 Nov 2026 10:33:00 +0800</pubDate><guid>http://hitrevor.com/posts/dsh-superagent/</guid><description>官方文章讲了五个模块，我把仓库翻了一遍：真正落地的只有两个，其余靠已有机制兜。显式和隐式的差别，决定了这套架构能走多远。</description><content:encoded><![CDATA[<p>2026 年 10 月 31 日，DeepSeek Harness 团队发了一篇讲 Super-agent 的长文。我没急着转，先把配套仓库拉下来翻了一遍。</p>
<p>文章讲的事很具体：人和 agent 的关系卡在注意力上。一个人顶多同时跟三到五个活跃会话，再多就顾不过来。所以他们想造一个常驻的、自己接活自己干的 agent，让人的角色从「每一步都盯着」退到「偶尔看一眼」。</p>
<p>四个特征：连续、高效、主动、持久。拆成五个模块：双层架构、事件驱动、面向人的交互、存算分离、Watchdog。</p>
<p>我的规矩是，官方说设计，我回代码里看。仓库 <code>deepseek-ai/dsh-superagent-prototype</code> 是当天下午五点半建的，现在两千九百星、两百五十三个 fork。<code>src</code> 下面九十二个 TypeScript 文件，一万两千三百九十行。</p>
<p>先说结论：五个模块，代码里能搜到两个半。</p>
<h2 id="五个模块代码里能搜到几个">五个模块，代码里能搜到几个</h2>
<p>我把文章里那几个专有名词一次性 grep 到 <code>src</code>、<code>docs</code>、<code>prompts</code> 三个目录。命中为零的就是没落地：投机执行、Inline 与 Spill、链式召回、端侧 daemon、Watchdog，全是零。</p>
<p><img alt="五个模块的落地情况" loading="lazy" src="/images/dsh-superagent/fig1.png"></p>
<p>这个落差不是作者藏了什么。README 自己写着：</p>
<blockquote>
<p>We have adapted it for publication, so it is not identical to our internal version&hellip; Some designs discussed in the article are directions for future development and are not implemented in this prototype.</p>
</blockquote>
<p>意思是公开发布做过裁剪，文章里有些东西属于未来方向。真实范围是：盯一个 GitHub 仓库，可选加一个飞书，有人提需求就判断接不接，接了在独立目录里干，干完回原会话答，通常开个 PR。</p>
<p>一句话，它现在是个只认 GitHub 的接单机器人。</p>
<h2 id="骨架是五个部件从收消息到回话一条直线">骨架是五个部件，从收消息到回话一条直线</h2>
<p>业务逻辑压在一个二百七十行的 <code>engine.ts</code> 里，内部拆成五块，依赖单向流动：Intake 收、Evals 判、Tickets 建单、Assignments 干、Replies 回。</p>
<p>Intake 收消息存一次，扇出给订阅这件事的工单。Evals 管评估，合并同一串讨论、算强度、定截止时间。Tickets 管生命周期，Assignments 收执行器回报，Replies 走 outbox 往信道写。</p>
<p>每个调用方只拿到自己那一片接口，收消息的碰不到工单表，执行器改不了策略。这个切法比功能本身更值得抄：它把「谁能改什么」写成了类型，越权在编译期就过不去。</p>
<p><img alt="Engine 的五个部件和两个 preset 的权限边界" loading="lazy" src="/images/dsh-superagent/fig2.png"></p>
<h2 id="router-不是不给-bash是配置里没有写权限">Router 不是「不给 Bash」，是配置里没有写权限</h2>
<p>文章里有个说法容易被读成比喻：Router 层不直接执行任务，连 Bash 都不配。代码里是两个 preset 实现的，Worker 有 subagent、todo、web 搜索、文件读写；Router 把文件写、编辑、subagent、web 全关了。</p>
<p>那个「不配」是真不配。权限面在服务装配那一刻就定死，不是靠提示词嘱咐它别动手。</p>
<h2 id="有三处比文章写得更细">有三处比文章写得更细</h2>
<p>准入矩阵。谁来提需求算数，文章只说两级过滤加名单，代码里是一张四格表：名单内名单外，乘上有没有 @ 它，每格配成显式、推断、忽略三档。</p>
<p>截止时间是活的。一次评估到点不会直接丢，重排两次才记成不可用；计时从候选送进主会话那刻才开始，处理暂停时跟着顺延。</p>
<p>还有插队。执行器最多同时跑三个工单，人在会话里直接插话时可以多用一格。</p>
<p>这三样文章都没展开。写到这个粒度，说明作者真在拿它跑活儿。</p>
<h2 id="装起来不难难的是两个不许弄错的地方">装起来不难，难的是两个不许弄错的地方</h2>
<p>装的部分很快。tmux 起服务，克隆，<code>pnpm install</code> 十八秒，<code>pnpm build</code> 一秒，产出十一个包共六百九十多 KB。然后从 web 模板复制一个 profile，把仓库挂成本地 link，写两行配置：状态目录和面板端口。我用了 3082，不跟日常那个 3080 抢。</p>
<p>起来之后七个部件全 ready，侧栏多出一个入口。到这一步你会以为成了。</p>
<h2 id="第一个坑它必须是另一个账号">第一个坑：它必须是另一个账号</h2>
<p>这东西要求 agent 用一个独立的 GitHub 账号发评论、开 PR，官方部署文档写得直白：agent 写的每句话都会挂在那个名字下面。我第一次授权失败得很典型，浏览器那边点了通过，我这边换 token 时直连 github.com 超时，二十秒的窗口过去，那次授权就作废了。换成走代理重来一遍才成。</p>
<p>连带一个问题：它干活时 <code>git push</code> 也要出网，但服务不能在全局环境挂代理，否则 DeepSeek 的接口会被带偏。我的做法是代理只注入两处，一个 GitHub CLI 包装脚本，一个工作克隆的仓库级 git 配置。</p>
<h2 id="第二个坑全部-ready它却一个字都不说">第二个坑：全部 ready，它却一个字都不说</h2>
<p>这个坑贵得多，而且它一声不吭。</p>
<p>配置填完，面板没有报错，七个部件全绿。我发了个测试请求，到达数加了，评估数一直卡在一。</p>
<p>翻会话记录才看到真话：<code>llm-deepseek: no API key for provider route &quot;deepseek-official&quot;</code>，错误码 <code>MISSING_CREDENTIAL</code>。</p>
<p><img alt="面板显示全部 ready，而 Router 会话里每一轮都在失败" loading="lazy" src="/images/dsh-superagent/fig3.png"></p>
<p>根因是环境。日常那个 dsh 进程从一个 export 过密钥的 shell 里起来，新 profile 是干净环境，密钥只存在那次 export 里，不写文件。</p>
<p>面板看不到，因为这是 Router 内部会话失败，不算组件健康问题。整条链路每环都 ready，只有最中间那次模型调用在静默地死。</p>
<p>修法是加一层启动包装，从密钥该在的地方取出来再注入。代价是以后启停必须走那个包装，直接调官方脚本会把密钥丢掉，然后你又回到「一切正常但什么都不做」。</p>
<h2 id="装完之后我在-issue-里等它回话">装完之后，我在 Issue 里等它回话</h2>
<p>真验收是让它干件小事。我开了条 Issue，只要求回一句已连通、说出 README 第一行的标题，不许改文件不许开 PR。</p>
<p>不到十分钟，它以 <code>dsh-super-agent</code> 的身份回了：</p>
<blockquote>
<p>已连通。
README 第一行标题：<code># ADK for Kotlin + Ktor：KMP 开发者的 AI agent 起手式</code></p>
</blockquote>
<p>回复上面还自带一行免责声明，说这是自动程序写的，不是人。</p>
<p><img alt="Issue #1 里它的回复实录" loading="lazy" src="/images/dsh-superagent/fig4.png"></p>
<p>我回头看它干了什么：给这条讨论建工单，在状态目录下开了独立 worktree，分支名 <code>agent/冒烟测试...</code>，干完在同一个讨论里答话。紧接着它把第二条重复请求判成重复，没再回一遍。</p>
<p>这一步之后我才信它真在跑，而不是看起来在跑。</p>
<h2 id="现在停在观察模式还没敢让它自己开工">现在停在观察模式，还没敢让它自己开工</h2>
<p>四路观察我都打开了：新 Issue、新 PR、新评论、默认分支的 CI。但评估模式还是默认的 observe，意思是它只记「我本来会接」，不动手。理由很简单，两个 preset 都是满权限，以我本人的系统用户跑，能读我整个 home。任何一句进了 GitHub 评论的提示词注入，都能在我机器上执行命令。</p>
<p>所以顺序是：先跑一两天，翻它的判断记录，看有没有把不该接的活接进来。名单里只有我一个人，别人 @ 它不会有反应。</p>
<p>文章里有个数据我印象很深。去掉订阅直通之后，Router 的决定数涨了 30%，token 涨了 37%。作者拿这个说过滤层的价值。</p>
<p>我倒觉得这是全篇最该记住的一句：这类系统真正的成本不在模型跑多快，在它要不要为每件事都动一次脑子。</p>
<p>那么问题来了，一个自己接活、自己判断、权限跟你一样大的 agent，你愿意让它替你收一晚上的 GitHub 通知吗？</p>
<p>还是说，你更想要的只是一个能替你盯着、但每次动手前都要点头的工具？</p>
<p>如果你也在搭这类东西，说说卡在哪一层：安装、权限，还是那句「它到底该不该自己决定」。</p>
]]></content:encoded></item></channel></rss>