🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

子代理模型透视 mirelconstantin/dsh-subagents-model

DeepSeek Harnessv0.1.1
mirelconstantin18 天前有提交已提供中文文档扫描:含敏感能力

DeepSeek Harness 的模型可见性:标题栏标签显示每个会话用的模型和推理强度,子代理下拉菜单标出哪个子代理走自己的路由,侧边栏悬停卡片展示每段对话做了什么。

31.5/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/14 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查有告警:npm 同名包「dsh-subagent-model」归属 loonylabs-dev/dsh-subagent-model,装到的可能不是本插件。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add mirelconstantin/dsh-subagents-model
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · browser
装得上吗
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 18 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

npm 同名包「dsh-subagent-model」归属 loonylabs-dev/dsh-subagent-model,装到的可能不是本插件

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-subagent-model @ 0.1.1
✓Node 引擎要求 >=20 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/13 09:39:19

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件
查看扫描证据(共 1 处,展示前 1 条)
  • 读取本地文件
    src/model.js:96
    const source = readFileSync(new URL('./client.model.js', import.meta.url), 'utf8')
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-app-boot
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 显示会话模型与推理强度
  • 标注子代理独立路由
  • 悬停卡片展示对话内容

README

由 DeepSeek 最新模型翻译生成
dsh-subagents-model 看清 DeepSeek Harness 会话真正跑在哪个模型上。顶部栏的标签会写明当前打开的对话用的是哪个模型、推理强度多少——子代理的对话也一样;输入框下方 composer dock 里的标签,则显示整轮运行委派给了哪些模型;侧边栏悬停卡片会说明每个对话实际做了什么。它只做加法:harness 自带的子代理下拉菜单原样保留,一点没动。 安装 在 GUI 里,把下面这行粘进 Add plugin: dsh-subagents-model 或者在终端里执行: dsh plugin add dsh-subagents-model 不需要构建步骤,也完全没有依赖。每个入口都以源码形式提交:Host 读取 src/client.js,原样发给页面,所以 pnpm 从来不用跑任何东西,也不会要求你把某个构建加入白名单。 别的什么都不用做。 安装器自己完成组装——它读取本包的 cordis.patch.yml,挂上 Loader 行,再把包加进 dsh.profile.bundles (dsh-plugin-manager/lib/index.js:247-265)。
展开完整文档(README 剩余 1 节)
dsh-subagents-model

看清 DeepSeek Harness 会话真正跑在哪个模型上。顶部栏的标签会写明当前打开的对话用的是哪个模型、推理强度多少——子代理的对话也一样;输入框下方 composer dock 里的标签,则显示整轮运行委派给了哪些模型;侧边栏悬停卡片会说明每个对话实际做了什么。它只做加法:harness 自带的子代理下拉菜单原样保留,一点没动。

安装

在 GUI 里,把下面这行粘进 Add plugin:

dsh-subagents-model

或者在终端里执行:

dsh plugin add dsh-subagents-model

不需要构建步骤,也完全没有依赖。每个入口都以源码形式提交:Host 读取 src/client.js,原样发给页面,所以 pnpm 从来不用跑任何东西,也不会要求你把某个构建加入白名单。

别的什么都不用做。 安装器自己完成组装——它读取本包的 cordis.patch.yml,挂上 Loader 行,再把包加进 dsh.profile.bundles (dsh-plugin-manager/lib/index.js:247-265)。不要手动往配置档的 cordis.patch.yml 里加行,也不要手动把包写进 package.json:同一个包出现第二份定义会让组装失败,还会把整个 web shell 一起拖下水(dsh-client-modules/lib/index.js:871-877)。

之后重启配置档。只要对话发过请求,顶部栏标签就会出现;底部栏标签只在某轮运行至少委派过一个子代理后才出现,因为一轮没有子代理的运行没什么可说的。

@deepseek-ai/dsh-app-boot 上的 peer 范围(>=0.2.0-rc.2 <0.3.0)是运行时唯一会检查的兼容字段(dsh-app-boot/lib/index.js:289-301):插件的范围不满足正在运行的运行时,启动时就会被跳过,并给出警告指明不匹配之处。

其他安装方式

| 方式 | 命令 |
| npm,默认 | dsh plugin add dsh-subagents-model |
| 锁定版本 | dsh plugin add dsh-subagents-model@1.2.1 |
| 锁定 commit | dsh plugin add github:mirelconstantin/dsh-subagents-model#<sha> |
| Tarball | dsh plugin add ./dsh-subagents-model-1.2.1.tgz |
| 本地 checkout | dsh plugin add /absolute/path/to/dsh-subagents-model |
file: 或本地路径安装会对包目录做硬链接,所以编辑器替换文件会断开链接,配置档就会悄悄保留旧内容。改完本地安装后,删掉 profiles/<profile>/node_modules/dsh-subagents-model 再重新安装。

什么都没出现时

这个插件遇到过的每一种故障都是静默的——没有报错,没有日志,只是少了一个标签——所以按下面的顺序排查:

1. 重启配置档。 打包在启动时组装,不是保存时。
2. 确认它已启用,在 Settings → Plugins 里。
3. 在已安装的副本里跑测试套件。 它不需要 harness,也不需要网络:在包目录里执行 npm test,会打印 89 个单元测试、35 个组装检查,以及一个安装探针——它会打包 tarball,解包到一个临时配置档,然后执行实际发布的字节。哪一层出问题,失败信息就会点名。
4. 头部标签就是诊断工具。 只要路由已解析,它在任何会话里都会渲染,不需要子代理。如果头部标签缺失但底部标签在,问题出在底部栏的会话作用域插槽;如果两个都缺失,说明浏览器那一半根本没加载。

贡献者请看:AGENTS.md 和 RELEASING.md。

它显示什么

| 位置 | 显示内容 | 在哪里 |
| 头部标签 | 活动会话的 model: <id> (effort) | 会话头部,子代理胶囊旁边 |
| 底栏标签 | 本次运行委派了多少子代理,以及它们跑在哪些模型上 | conversation.composer.dock,输入框下方,ContextMeter 旁边 |
| 悬停卡片行 | 模型、effort、已完成工作、活跃时间、token、缓存、上下文窗口、任务、类型 | 侧边栏每个会话的悬停卡片里 |

标签的 tooltip 还会列出模型提供的各档推理 effort,以及哪一档是默认值,数据来自实时模型目录。目录里没列出的模型不会额外添加任何东西:目录只是参考,路由会接受它没有公布的 id,所以目录里缺失从不视为故障。

只有设置了 effort 才会显示——它在模型来源的同一条路由记录里是可选的,没配置的会话保持紧凑。

纯展示。模型、它的工具、它的会话日志都不受影响:不注册任何工具,不发布任何服务,模型能观察到的东西没有任何变化。

它解决的问题

DeepSeek Harness 按模型路由会话,子代理跑的模型可能和父级不同——但页面上没有任何地方说明这一点。由此带来两个后果:

子代理的模型在打开它之前是不可见的。 会话投影到达浏览器有两个位置,它们持有的会话不同。projectionsBySession 只携带投影存储常驻在客户端的会话,而存储是懒创建的(dsh-api-session-controller/lib/index.js:2525)——所以用户从未打开过的子代理就是缺席的。列表行携带相同的值,在
byId[id].projectionValues(:2942、:3521、:3549),由父级的 subagentCatalog 合成而来(:3518-3542),正是它覆盖了「已列出但从未加载」的子项。同时读取这两个来源,才是完整的修复。

继承来的路由无法恢复。 关闭模型选择时——也就是 subagent 的默认状态(dsh-tool-subagent/README.md:47)——每个子项都继承父级的路由(:67),而这条路由在子项自己的日志里根本找不到。插件沿 parentId 向上追溯血缘,直到某个祖先记录了显式路由,于是打开的子代理会给出一个真实模型,并标注 (inherited),而不是什么都不显示。

这个值从哪来

来自 modelSelection 会话投影,harness 已经注册了它,也已经把它送到浏览器:

dsh-api-session-controller/lib/types/model-selection-projection.js
stateSchema : { lastUsed, pending } (routes carry optional reasoningEffort)
wire view : { lastUsed, next } // next = pending ?? lastUsed
registered : lib/index.js:2114 (installModelSelectionProjection)

lastUsed 由每个请求自己的 request/header 配置折叠而来,所以它是会话实际用过的路由,而不是配置时指定的那条。next 在有选择排队时是待定的选择,否则就是 lastUsed,因此读 next 就能回答「这个会话现在用的是哪个模型」,两种状态下都成立。已发布的 Agent Team 行也是同样的读法(dsh-experimental-client-ui-agent-team/lib/client.js:89)。

子代理,实话实说

模型选择默认关闭,所以子代理显示 Inherited from parent 是预期情况,不是 bug——没有任何东西被覆盖。差异来自构造方式:

- 有自己路由的可继续子代理会在描述符里快照 agentProvider / agentModel / agentReasoningEffort(dsh-subagent/lib/types/descriptor.js:38-45),所以它的显式模型能被恢复并完整显示。
- 有自己路由的一次性子代理会刻意省略 agent 路由(:37、:118-126),因为冷恢复不需要它。因此显式选中的一次性模型无法持久化,插件会说 Inherited from parent,而不是去猜。这是持久化格式的限制,不是插件的限制。

要给每个子代理固定模型,在 subagent 工具上设置 modelSelectionSettings: true,并在每次调用时传入路由;list_subagent_models 随后可用于发现模型。

三个席位,以及为什么它们都不替换任何东西

每个席位都 ADD 一个带自己 id 的单元格,所以不会挤掉任何已发布的占用者,harness 自己的子代理下拉框也保持原样。这不是审美选择:这个插件的早期版本以 priority: -9998 抢占了 subagent-catalog 表头单元格,为的是在每个子代理行旁边放一个模型标记,因为已发布的 CatalogRows 不渲染任何逐行插槽(dsh-client-ui-subagent/lib/client.js:164-338)。替换那个 cell 意味着要重新实现它整套导航契约——openChild、openChildAside、refreshProjection、树遍历、焦点模型——而重实现里每出一个错,都会让页眉里的内置子代理列表消失。它确实出错了;列表不再出现。

现在按子代理拆分的模型明细改放在底栏 chip 里,那里完全不需要这套机制。scripts/check-plugin.mjs 会断言没有任何东西占用或遮蔽内置 cell,所以这种接管无法悄悄回来。

| slot | 声明方 | 本插件 |
| conversation.session.header.actions | dsh-client-ui-conversation/lib/index.js:18268-18271 | id 'subagent-model'(chip) |
| conversation.composer.dock | dsh-client-ui-conversation/lib/index.js:18329-18332 | id 'subagent-model-dock',order 40(底栏) |
| sidebar.session.row.hover | dsh-client-ui-workspace/lib/index.js:4322-4325 | id 'subagent-model' |

每个位置告诉你什么

chip 显示当前打开会话的有效路由,无论是根会话还是子代理,并在排队的选择尚未被消费时标上 (switching),在来自父级时标上 (inherited)。它的 tooltip 还会补上各后代的模型明细——3× deepseek-chat, 2× deepseek-reasoner——而当某次生成确实拆分了这份明细时,还会给出按生成拆分的同一份明细。这就是与兄弟插件 dsh-subagent-tree 的集成:两项事实都来自对 subagentCatalog 的一次遍历,所以读起来就在一处。

底栏 chip 回答的是整个运行的问题,而不是碰巧打开的那个会话:本次会话委派了多少个子代理,它们跑在哪些模型上。它位于 conversation.composer.dock,即 composer 下方那一行,紧挨内置的 ContextMeter——与兄弟插件 dsh-opencode-router 给它的 proxy chip 用的是同一个 slot、同一种控件形态。对于从未委派过的运行,它什么都不渲染,所以普通会话不会多出任何家具。

hover card 回答的是「这个会话是什么」。每一行都从客户端已持有的投影中读取,且只在其值存在时才出现,所以零值永远不会被读成「什么都没做」:模型与 effort、轮次与步数、活跃时间、生成的 token、委派智能体自己的任务标签,以及决定会话能否继续的模式。

逐轮模型历史——已实现但未挂载

src/client.route-history.js 是逐轮路由历史的完整实现,但没有任何东西加载它:src/client.js 只对 ./client.model.js 调用 require.async。这个文件是惰性的,对 UI 没有任何贡献。它留在包里,是因为它是一份完成且自包含的工作,挂载前只需让它的读取方匹配当前的投影形状。

因此,任何会话显示的路由都来自 modelSelection 仅投影。要做到每轮准确,需要挂载这个 chunk 并加一个 conversation.chat.turnTail 座位;为什么没这么做,见下面的理由。

request/header 是记录每个请求路由的事件。SessionProjectionMap 里没有任何东西会把它发出去,所以 chip 读的是 modelSelection 投影——但事件日志本身未经过滤就到达浏览器,request/header 就在其中(dsh-api-session-controller/lib/client.js:166,流在 :398)。harness 自己的聊天视图本来就是这么读的(dsh-client-ui-chat/lib/client.js:9389-9394)。

所以每轮的真实路由在客户端恢复,Host 不用做任何事:一个 request/header conversation Definition 把事件折叠成按轮次的映射,一个 conversation.chat.turnTail 条目读取它。因为开头的日志帧是快照,插件挂载之前打开的会话仍然能拿到它的历史,而不只是从那一刻起的事件。

reason 决定一轮的路由锚定在哪里。initial、resume 和 series 都会锚定;单独的 change 是系列中途的重新路由,不锚定,除非它带有 startsSeries。reasoningEffort 缺失不等于「关闭」——adapterDefaults.reasoningEffort 意味着由适配器提供,这一行会如实说明,而不是暗示没有 effort。

较早的 Route change <from> → <to>, not yet applied 行,是 next 与 lastUsed 之间的不一致,仍然报告一个排队中的切换,还没有任何请求消费它。

如实对待缺失数据

四种状态分开保留,因为把它们合并就会打印出谎言:

| 状态 | chip | 悬停卡片 |
| 已加载,模型已知 | model: deepseek-chat (high) | Model deepseek-chat (high) |
| 已加载,还没有请求 | (无) | Model No model yet |
| 在目录中列出,从未打开 | (无) | Model <model>,或 Inherited from parent |
| 两个存储都不知道它 | (无) | (无) |

文件

| 路径 | 作用 |
| cordis.patch.yml | 恰好一行 Loader —— 锚点 |
| src/index.js | Host 锚点;不发布任何东西 |
| src/model.js | 纯逻辑,以普通 ESM 形式供单元测试套件使用 |
| src/client.js | 浏览器那一半;注册所有座位 |
| src/client.model.js | 同样的纯逻辑,作为浏览器 chunk 供那一半加载 |
| src/client.route-history.js | request/header 折叠和按轮次的路由映射 —— 当前未加载,见上文 |
| locale/{en,ro}.json | 命名空间 dsh-subagents-model 的字典 |
| scripts/unit.mjs | 针对 src/model.js 和 locale 一致性的 node --test 套件 |
| scripts/check-plugin.mjs | manifest、patch、exports、浏览器半部分契约 |

没有构建步骤,没有打包器,没有转译器,也没有已安装的依赖——唯一声明的 peer 是这个插件验证时所用的运行时,DSH 会从安装中解析它。

为什么纯逻辑放在第二个 chunk 里

经典脚本不能 import,但它不必如此:require 这个 factory 拿到手时会带一个 async 方法,用来拉取包内的 chunk (dsh-client-modules/lib/client.js:707-713),而 CLIENT_CHUNK =
/^client\.[A-Za-z0-9][A-Za-z0-9._-]*\.js$/(:169,在 :915-932 处提供服务)就是该文件必须匹配的模式。已经有三个已发布的包用这种方式附带第二个 chunk —— dsh-client-ui-sidebar-terminal 和
dsh-client-ui-sidebar-documentpreview —— 所以这是一种受支持的形态,不是变通做法。

src/model.js 是普通 ESM 模块,浏览器脚本无法访问,因此 src/client.model.js 以自注册 chunk 的形式保存同样的函数,src/client.js 只加载它一次。以前同时发布两者的全部代价就是这份重复;现在它被限制在一个 chunk 内,其导出会对照 src/model.js 检查。

在该 chunk 解析完成之前,每个 seat 都不渲染任何内容,正是这一点避免了拉取失败时把对话头部一起拖垮。代价是 chip 会比同步 import 允许的时间晚一拍出现;页面上没有别的东西等它。

浏览器那一半

有两条加载规则是承重的,两条都在真实页面上实测过,不是假设。完整说明见 src/client.js。

inject 保持为空。 一旦写上 slots,fiber.await() 就会让该行停住,等渲染器提供它,而渲染器又在等这一行旁边的那些 UI 包。两边互相等待,整个启动失败并报 web boot: 1 entry did not activate …,把整个 GUI 拖垮。gate 为空时,apply 会在 slots 存在之前运行,所以 whenService 用 setTimeout 轮询。不要换成 queueMicrotask:微任务轮询会把自己重新排到每个包激活所依赖的宏任务前面,让启动饿死,并复现同样的失败。

ro 被加入语言目录。 en 和 zh 是随包发布的目录语言;ro 不是,而回退链走的是目录,不是已注册的字典 —— 所以只有 ro 字典时它不可达,除非 locale.addLanguage 把这个语言加进去。locale/en.json 和 locale/ro.json 发布同一套键,一旦两者出现偏差,scripts/check-plugin.mjs 就会让构建失败。

验证

node --test scripts/unit.mjs # 84 tests: model logic, cycles, depth grouping, locale parity
node scripts/check-plugin.mjs # 31 checks: manifest, dsh peer range, patch, exports, browser contract

许可

Apache-2.0。见 LICENSE。
预览分享卡片长什么样 ↓mirelconstantin/dsh-subagents-model
分享 · DeepSeek Harness Hub
mirelconstantin/dsh-subagents-model

DeepSeek Harness 的模型可见性:标题栏标签显示每个会话用的模型和推理强度,子代理下拉菜单标出哪个子代理走自己的路由,侧边栏悬停卡片展示每段对话做了什么。

回到顶部