DeepSeek Harness Hub
← 返回列表

fan56/dsh-profile-switch

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
未验证

一个 dsh 插件:具名模型配置档案,你可以通过宿主原生的询问用户流程进行交互式切换和配置——一套实现同时适用于…

尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/14 · 已提供中文文档

dsh 插件:通过宿主 ask-user 流程交互式切换命名模型配置(默认模型、思考级别、各子代理模型)——一套实现同时适用于 TUI 和 Web 界面

综合分
30.3
GitHub 分
30.3
用户评分
★ Stars
1
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add fan56/dsh-profile-switch
该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/18(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-agent@deepseek-ai/dsh-commands@deepseek-ai/dsh-llm@deepseek-ai/dsh-user-questions
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-profile-switch

一个 dsh 插件:具名模型配置档案,你可以通过宿主原生的询问用户流程进行交互式切换和配置——一套实现同时适用于 TUI 和 Web 界面,并在无头环境下快速失败并给出指引。

模型配置档案是你整个模型配置的快照:

- 默认模型 + 思考等级(保存的 /model 选择),以及
- 可选的按子代理的模型/思考覆盖。

在不同上下文之间切换(work ↔ personal)只需一条命令,而不用再来一遍 /model 加逐个代理的巡游。

“profile”在 dsh 中有两种不同含义——本插件指的是模型那一类。 dsh 的 profile(~/.dsh/profiles//、dsh --profile )是启动时的插件组合;它在进程运行期间无法更改。本插件所切换的模型配置档案存放在 ~/.dsh/model-profiles.json,在运行时生效,并且作用域限定于绑定它们的 workspace 树。

安装

dsh plugin --profile  add @aiwayds/dsh-profile-switch

该插件以 inject: ['commands', 'userQuestions'] 挂载——两者都是 dsh-base 服务,因此它可以与任何界面和任何插件栈共存。

命令

/profile-switch

一个问题:此 workspace 树绑定到哪个配置档案。回答后会分层应用该配置档案:

1. 实时默认模型——当存在实时选择通道时:在 TUI 上通过 dsh-tui-pi 的选择桥接,在 Web 上通过会话控制器。当前对话会立即在新模型上继续。没有通道时,摘要会说明这一点;该路由仍会在下一个会话中通过树固定生效。
2. 树绑定——将 .dsh-profile 写入当前目录(沿树向上最近的该文件生效,类似 .nvmrc),这样此树中每个新会话都会从该配置档案组装其初始选择。其他树不受影响:切换是 workspace 作用域的,绝不是机器全局的。
3. 子代理覆盖——在应用时不写入任何地方。每个代理的运行时模型/思考在生成时由代理文件 frontmatter 基线 ⊕ 此固定配置档案的覆盖组合而成(每次派发时重新计算,包括续接),这正是让切换完全限定于 workspace 作用域的原因。

该切换有意不写入全局 agent-default-model 设置——那仍然是 /model 的写入职责,而跨越树边界恰恰是配置档案切换绝不能做的事。

当树已绑定时,列表中还会带有 (unbind this tree):移除固定(有保护——手工修饰过的固定文件绝不会被覆盖;插件会拒绝并说明原因)。

/profile-cfg

配置向导——先是一个操作菜单,然后是相应的流程:

| 操作 | 询问内容 |
| --- | --- |
| new | 名称 → 默认模型链 → 按子代理覆盖 |
| edit | 选择一个配置档案 → 重新回答同一链条(问题中显示当前值) |
| save-current | 名称 → 捕获当前实时选择(或部署默认值)→ 可选地为每个已发现的 agent 快照其基线 |
| rename | 选择一个 profile → 新名称 |
| delete | 选择一个 profile → 确认(最后一个剩余的 profile 会被拒绝) |

每一次模型选择都是一条三步收窄链,由独立的 ask-user 问题组成——provider → 该 provider 的 models → 该 model 的 think levels——因为每一步的选项都取决于上一步的答案。这三个列表都从已安装的 llm 适配器实时读取(listProviders / listModels / resolveModelInfo),因此 think levels 正是适配器所提供的——绝不硬编码(llm-deepseek 路由会拒绝 medium;只有适配器知道某个 model 接受什么)。如果某个 provider 没有列出任何内容,则回退到手动输入 model id;如果某个 model 没有可选的 effort,则跳过 think 步骤。

在任何地方取消(Esc / 关闭问题)都会中止向导,且不保存任何内容——存储只在最后写入一次。

Subagent 覆盖(配合 dsh-subagent-registry)

当安装了 dsh-subagent-registry 时,new/edit 向导会在你已发现的 agents(~/.dsh/agents/.md)上增加一个多选,然后对每个选中的 agent 执行相同的 provider → model → think 链——每一步都以 (inherit) 打头。组合语义:

- 已记录的非空值优先于 agent 文件的 frontmatter;
- 空条目(两步都继承)记录一次显式继承;
- profile 中不存在的 agents 从基线组合。

没有该 registry 时,这些覆盖就没有消费者,因此每个 agent 的部分会被跳过并附上一条说明,profile 只保留主默认 model——检测是一个契约成员探测(composeAgentRuntime / readModelProfilesDoc / workspaceProfileName),与 dsh-tui-pi 确立的约定相同。

界面

| | TUI | web | headless |
| --- | --- | --- | --- |
| 问题渲染 | dsh-tui-pi 的 ask-user 停靠面板 | web 编辑器接管 | — |
| 实时默认 model 切换 | 是(tui-pi 桥接) | 是(session 控制器) | 不适用 |
| 树绑定 + 存储 | 是 | 是 | 通过文件 |
| 无应答者行为 | — | — | 快速失败并给出指引 |

在没有 ask-user 应答者的界面上(headless 运行一个任务后即退出),这些命令会快速失败并给出指向非交互路径的指引:直接写入 /.dsh-profile 并编辑 ~/.dsh/model-profiles.json。不会挂起。

存储与文件

- ~/.dsh/model-profiles.json —— 存储(遵循 $DSH_HOME)。带版本
(version: 1),可自愈(损坏/未知的文件会降级为预置的 work / personal / other profiles,绝不抛错),原子
写入(临时同级文件 + 重命名)。此文件是一份共享契约:
dsh-subagent-registry 会读取它(生成时组合),dsh-tui-pi 的
session 引导也会读取它(从 pin 播种新 session)。Schema:

{
"version": 1,
"current": "work",            // 信息性字段,表示最后一次在任何地方应用的值
"profiles": [
{
"name": "work",
"defaultModel": { "provider": "zai-coding-cn", "model": "glm-5.3", "reasoningEffort": "high" },
"agents": {
"workhorse": { "model": "volc-ark-plan/deepseek-v4-flash", "thinking": "high" },
"oldfox": {}              // 空条目 = 显式继承
}
}
]
}

- /.dsh-profile —— 树级固定项:一行,指定 profile 名称;
允许空行和 # 注释。插件在切换时覆盖它,
仅当它解析为恰好一行条目时——手工修饰过的文件会被拒绝并上报,绝不会被覆盖。

与 dsh-tui-pi 的关系

模型 profile 功能从 dsh-tui-pi 迁移到了这里(此前它作为仅限 TUI 的面板存在)。配对关系:

- 配合提供 dshTuiModelSelection 桥接的 dsh-tui-pi 时:
/profile-switch 也会实时切换当前 TUI 会话的默认模型;
- 配合没有该桥接的较旧/较新 tui-pi 时:其他一切照常工作;实时部分降级为
“此树中的下一个会话”,摘要中会说明这一点;
- tui-pi 的 /agents 管理器中的按 agent 编辑入口会以相同的 schema 写入同一个
存储——两个编辑器可以共存;
- 建议在 TUI 上使用 dsh-tui-pi ≥ 2.18.1。 tui-pi 2.16.0–2.18.0
在将面板迁移到这里时,把这些命令名从其永不中止的调度列表中移除了,
因此超过 90 秒的 /profile-cfg 会话会回显一条虚假的
aborted due to timeout(面板本身仍在工作;
2.18.1 恢复了该调度)。在 web/无头界面上不存在此类保护,
任何插件版本都可与任何版本配对。

任何地方都不需要手动配置 profile:dsh plugin add 会协调
bundle 条目,bundle 补丁会挂载插件,命令会在 profile 启动的每个界面上注册。

卸载

dsh plugin --profile  remove @aiwayds/dsh-profile-switch

该插件不拥有任何守护进程,也不持有任何宿主资源,因此卸载后
下次启动即干净完成。你的数据会被有意保留:

- ~/.dsh/model-profiles.json —— 如果你想删除该存储,请删除它;
- /.dsh-profile 固定项 —— 按树删除(rm .dsh-profile);
指向不存在 profile 的固定项不会绑定任何内容。

开发

pnpm install
pnpm build && pnpm check && pnpm test   # 单元测试套件(先构建)
node scripts/smoke-boot.mjs             # 真实宿主启动门禁(需要全局 dsh)
pnpm contract                           # 与注册表的写入↔读取握手
(在没有注册表可解析的地方自动跳过)

契约检查在真实文件上验证了部署后的三仓库形态:
插件的存储写入(固定项 + 按 agent 覆盖)通过注册表的 composeAgentRuntime
组合回来——覆盖优先、显式继承和基线回退均成立,且探测部分确认了 registryDetected()
通过配置文件的同级 node_modules 进行解析,与在实时部署中完全一致。在没有注册表的机器/配置文件上,它会降级为有文档记录的跳过,因此可以在任何地方运行。

scripts/link-dsh-closure.mjs 将 node_modules/@deepseek-ai/ 重新指向全局 dsh CLI 自身的闭包,这样类型检查和测试只会看到一个 cordis。CI 在 Node 22/24 上运行相同的步骤,外加启动冒烟测试,并且每日计划会监视上游 rc/stable 的漂移。

许可证 — MIT。

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群