dsh-agency-market
把 agency-agents 中的 273 个专业智能体装进 DeepSeek Harness,类似 workbuddy 中的专家
- Stars
- 0
- Language
- JavaScript
- Created
- Sep 1, 2026
- Updated
- Sep 1, 2026
Introduction
dsh-agency-market 是社区维护的 DeepSeek Harness(DSH)插件,不是 DeepSeek 官方产品。 273 位专家人格全部导入自开源项目 agency-agents(MIT)。
它是什么
一个装在 DSH Web 里的「专家」市场:浏览专家卡片,一键把专家安装为用户级 agent preset。装好的专家有两种用法——新建会话时选预设直接开聊;或在任意已有会话里让模型召唤(market_experts / summon_market_expert 两个模型工具),随时换专家。
设置 → 专家市场 → 挑一张卡片 → 安装 ─┬→ 新建会话选预设 → 与专家开聊
├→ 任意会话里让模型召唤(market_experts / summon_market_expert)
└→ 输入框「召唤专家」按钮 / @ 菜单 → 生成召唤指令草稿(不自动发送)
主会话始终保留任务上下文、判断与最终答复;被召唤的专家子代理只提供专业视角,且不能再召唤其他专家(防递归)。
特性
- 市场页(设置 → 专家市场):registry 式名录——全宽搜索、领域分类 chips、超大领域的二级分组 tab、已装过滤、行内移除确认、骨架加载,卡片中英文双语,搜索跨语言命中。
- 一键安装:安装即走 roster 认可的预设编写路径(复制底座 → 改写元数据 → 换 persona → 挂载校验),绝不写部署自带的 preset;卸载只删用户级条目。
- 会话中途召唤:
market_experts()列出可召唤专家,summon_market_expert(expert, task)把一个自包含任务委派给专家——一次性子代理带着完整专家人格跑完任务并返回答复,同一会话可以给不同任务换不同专家。 - 三个召唤入口:模型自己调工具、输入框「召唤专家」按钮、
@菜单触发源;后两者只起草指令草稿,不自动发送。 - 273 位专家 × 18 个领域:学术、设计、工程、财务、游戏开发、GIS、医疗、营销、付费媒体、产品、项目管理、研究、销售、安全、空间计算、专业垂直、支持、测试。
- 零构建、零运行时依赖、不执行任何安装脚本:纯 ESM JavaScript + JSON 数据,
node scripts/smoke.mjs一条命令离线自检。
前置条件
- 一套可用的 DeepSeek Harness Web 安装,
dsh命令可用(Node.js 22+;dsh不在 PATH 时可用npx --yes @deepseek-ai/dsh代替)。 - 示例均使用
webprofile,按需替换为目标 profile。
安装
方式一:让另一个 agent 帮你装
本插件运行在 DeepSeek Harness Web 里。把下面这句话粘给 DSH(或 Codex、WorkBuddy 等会装 npm 包的 agent),让它替你装进本地 web profile:
从源码安装 DSH 插件 https://github.com/pbwheel/dsh-agency-market 到我的 web profile:clone 该仓库,进入目录运行 dsh plugin --profile web add .,然后运行 dsh --profile web --dump-config 确认 dsh-agency-market 已挂载,并提醒我重启 DSH Web 和强刷浏览器。
方式二:从源码安装(调试或未发布改动)
git clone https://github.com/pbwheel/dsh-agency-market.git
cd dsh-agency-market
dsh plugin --profile web add .
dsh --profile web --dump-config
dsh plugin ... add 会读取包元数据与 cordis.patch.yml,把 host 半边接入组合层(dsh.profile.bundles 自动登记,无需手改)。配置输出里应能看到 dsh-agency-market。
然后重启 dsh web(bundles 列表只在启动时读)并强刷浏览器。本插件无构建步骤、无运行时依赖、不执行任何安装脚本,克隆目录就是插件源码目录,不要只拷贝 src。
安装排障
- 市场页 404 / 只有客户端按钮不工作:确认
~/.dsh/profiles/web/package.json的dsh.profile.bundles数组里有"dsh-agency-market",改完重启dsh web(bundles 只在启动时加载);客户端半边由 loader 自动扫描,刷新页面即可。 @菜单里没有「专家市场」分组:package.json的dsh.client.inject组合变更由 loader 在启动时扫描,重启dsh web即可(按钮与市场页不受影响,判空降级不报错)。
使用
1. 挑专家安装
打开 设置 → 专家市场:按分类浏览或搜索(中英文关键词均可命中),点卡片安装。已装行盖 ✓ 印章,行内确认即可移除。
2. 新会话直接开聊(preset 模式)
新建会话时,预设选择器里选该专家(expert-<id>,显示专家名与简介),即可以专家人格开一场会话。
3. 任意会话中途召唤(tool 模式)
在任意进行中的会话里,直接让模型召唤,或点输入框左侧的「召唤专家」按钮 / 输入 @ 选专家——按钮与 @ 只把指令写进草稿,不会自动发送:
召唤专家「Code Reviewer」(engineering-code-reviewer)处理以下任务:
审查当前工作区的改动,按严重程度列出可复现的问题。
模型侧的两个工具:
market_experts(category?)—— 列出当前可召唤(= 已安装)的专家:id、名称、描述、分类;不知道精确 id 时先调它。summon_market_expert(expert, task)—— 把一个自包含任务委派给某专家;expert支持 id(推荐)或名称(含中文名,模糊匹配,歧义时报候选列表),task需完整自包含、上限 8000 Unicode 码点。调用等待专家跑完并返回答复。
未安装的专家召唤会报错并提示「请先在 设置 → 专家市场 安装」。
一个专家是什么
一个专家 = 一个用户级 agent preset(expert-<id>,装在 ${DSH_HOME:-~/.dsh}/.agent-presets/ 下):
| 卡片字段 | 落到哪里 |
|---|---|
name / description | preset 的 preset.yml(预设选择器里显示的名字与简介;写入的是目录基字段/英文) |
persona | 组合里 dsh-persona 行的 text(专家的系统提示词) |
base | 被复制的底座预设(默认 standard,完整工具链) |
avatar / tags / category | 市场页自己的展示字段(只在目录数据里) |
中文 name / description / 分类名 | 不进专家文件:放在 locale 覆盖层 data/i18n.d/zh.json,仅用于展示(见多语言) |
安装流程(宿主侧,全部走 roster 服务):
agentPresets.copy(base, 'expert-<id>')—— 复制底座预设到用户根;- 改写副本的
preset.yml(名字/简介); - 用锚定替换把副本 persona 行的
text换成专家 persona(锚不中则降级为底座 persona 并在 UI 提示,不会装出坏预设); agentPresets.standingKeyFor(id)真实挂载校验,通过才算装好。
绝不写部署自带的 preset;卸载只删 trust: "user" 的条目。
行为与安全细节
- 变更路由只接受同源 POST、请求体上限 4 KiB、同时只允许一个安装/卸载在进行;安装只是预设复制加两处文件改写,不执行任何构建/安装脚本。
- 防递归:子代理的
toolFilterdeny 掉两个召唤工具名;系统提示词 section 在子会话(header 带parentSession)返回空串,被召唤的专家学不会再召唤。 - 专家子代理以
stopReason !== 'completed'结束时报错(携带 diagnostic 与部分输出),run.dispose()在 finally 里必定执行。 - persona 里
{{model}}/{{cwd}}/{{provider}}是宿主注册的提示词变量,原样透传、不做 sanitize;导入时会把其余完整{{…}}组拆开({{→{ {),未注册变量会让子代理启动失败,因此按字面文本处理。 - 所有副作用(路由、工具、提示词 section、插槽、样式)收集 disposer 统一释放,插件卸载即全部撤销。
目录数据
目录分三层,加载逐文件合并、逐文件隔离:某个文件 JSON 损坏或校验不过(id 不合法 / 缺 persona / id 重复)只跳过该文件并把原因放进 /api/state 返回的 warnings[],不会拖垮整个目录;头文件损坏也一样降级,只有全部不可用时才报错。
| 文件 | 作用 |
|---|---|
data/experts.json | 头文件:version + categories(18 个领域) |
data/experts.d/ | 每位专家一个 JSON,按领域分子目录(273 位 × 18 领域) |
data/subgroups.json | 二级分组覆盖层:超大领域的子分组(见下) |
data/i18n.d/ | locale 覆盖层:展示层翻译(见多语言) |
一位专家的完整定义:
// data/experts.d/engineering/engineering-code-reviewer.json
{
"id": "engineering-code-reviewer", // [a-z0-9-],安装后 preset id 为 expert-engineering-code-reviewer
"name": "Code Reviewer", // 卡片标题 + preset.yml name
"avatar": "👁️", // ← agency-agents frontmatter emoji
"category": "engineering", // 头文件 categories[].id(= 领域)
"tags": ["Engineering", "agency-agents"],
"description": "卡片一句话简介 + preset.yml description",
"base": "standard", // 底座预设,缺省 standard
"persona": "# Code Reviewer Agent\n\nYou are **Code Reviewer**…" // = md 正文
}
二级分组(subgroups):engineering 一个领域装了 59 位专家,单层 tab 挑不动。二级分组刻意做成独立覆盖层而不是写进专家文件——上游 agency-agents 没有分组信息,--replace 重导入会清空重写 experts.d/,而覆盖层与 i18n 一样原样幸存:
// data/subgroups.json
{
"categories": {
"engineering": [
{ "id": "ai-ml", "label": "AI & Machine Learning", // label 为基字段(英文)
"experts": ["engineering-ai-engineer", /* … */] }, // 数组顺序即子 tab 顺序
// …frontend-client / backend-architecture / data-database /
// ops-reliability / cms-platform / practices-quality,共 7 组覆盖全部 59 位
]
}
}
加载分两步、逐条降级:先按形状校验(坏 id / 空 label / 畸形 experts / 重复组跳过并告警),再与目录对账(目录里已不存在的过期 id、挂错分类的 id、被两个组重复认领的专家、成员掉光的空组,逐条跳过并告警)。当前覆盖四个超载领域:engineering(59 × 7 组)、specialized(58 × 6)、marketing(36 × 4)、game-development(21 × 6);其余领域规模小(≤13 位),保持单层。给新领域加二级分组只需照抄该文件 + zh 覆盖层,代码零改动。
重新导入:agency-agents 上游更新后重跑 scripts/import-agency-agents.mjs:
node scripts/import-agency-agents.mjs --replace # --repo <path> 指定仓库位置,--dry-run 只校验
多语言(locale 覆盖层)
页面静态文案走客户端 locale 服务(zh/en 双语字典)。专家名称/描述/领域与二级分组标签的多语言走独立的 locale 覆盖层 data/i18n.d/:每种语言一个 <locale>.json,纯展示元数据叠加在目录之上——experts.d/ 里的专家文件(含 persona)一个字节都不改,--replace 重导入也不会碰覆盖层:
// data/i18n.d/zh.json(en 不需要文件:目录基字段本身就是英文,缺失即回退)
{
"categories": { "engineering": "工程", /* …18 个领域 */ },
"subcategories": { "engineering/ai-ml": "AI 与机器学习", /* …与 subgroups.json 一一对应 */ },
"experts": {
"engineering-frontend-developer": {
"name": "前端开发工程师",
"description": "专注现代 Web 技术、React/Vue/Angular 框架、UI 实现与性能优化的前端专家"
}
// …273 位专家
}
}
生效链路:市场页把当前界面语言作为 ?locale=zh|en 传给宿主(切换语言自动重拉);宿主用覆盖层逐字段覆盖、缺啥回退基字段;召唤侧 market_experts 的输出、专家名称匹配(粘贴中文卡片标题也能解析到)同样吃覆盖层。市场页搜索是跨语言的——API 为每位专家附另一种语言的关键词,zh 界面输入英文照样命中。冒烟测试会强制校验 zh.json 覆盖全部目录专家,重导入新增专家后跑一次即可发现漏译;批量重译可用 scripts/merge-zh-overlay.mjs 合并片段,零星修订直接编辑 zh.json。
架构
浏览器 DSH 宿主进程
────── ───────────
client/client.js src/index.js (host 入口,双 inject)
settings.section「专家市场」 ├─ inject webServer+agentPresets:
名录行/分组/搜索 ──同源 fetch──────→ │ src/routes.js /dsh-agency-market/api/*
│ src/experts.js catalog + 安装/卸载/状态
conversation.input.left ├─ inject tools+subagents+systemPrompt+agentPresets:
「召唤专家」按钮 ──同源 fetch──────→ │ src/summon.js market_experts / summon_market_expert
(菜单选中 → setDraft 草稿) │ + 提示词 section(子会话为空)
inputTriggers「@」触发源 ├─ agentPresets 服务(copy / remove / standingKeyFor)
(candidates → /api/state) └─ subagents 服务(spawn provider,按次 persona)
data/experts.json + data/experts.d/ ~/.dsh/.agent-presets/expert-<id>/
data/subgroups.json + data/i18n.d/<locale>.json(展示层翻译)
- host 半边(
src/):纯 ESM JavaScript,无依赖无构建。三个路由:GET /api/state(目录+已装标记+告警)、POST /api/install、POST /api/uninstall。src/summon.js注册两个模型工具 + 一个提示词 section;工具名为market命名域,避免与其他专家插件(如 dsh-agency-agents 的list_experts/summon_expert)在同 profile 重名。两段 inject 相互独立:市场页不依赖工具 seam,召唤也不依赖 web server。 - client 半边(
client/client.js):手写的 harness 客户端 bundle 格式(window.__ModuleLoader__.load({ id, factory }),唯一 external 是react),注册两个插槽条目——settings.section渲染市场页、conversation.input.left渲染「召唤专家」按钮——并在inputTriggers服务可用时注册一个@触发源(服务不在组合里则判空跳过)。样式走主题 token(--dsw-alias-*等)并带回退,明暗主题自适应,焦点环与prefers-reduced-motion降级齐备;<style data-plugin>标签随插件卸载被 loader 清掉。 - 安装边界:预设编写只发生在宿主
agentPresets服务;路由层只解析请求、调服务、序列化 JSON。
已知边界
- 安装写入
preset.yml的是目录基字段(英文名/描述),预设选择器因此显示英文名;中文译名只出现在市场卡片、召唤菜单与market_experts输出里(按安装时语言写死元数据会随语言切换过期,故刻意不写)。 - 召唤是一次性委派(one-shot subagent):专家答复返回主会话,不保留可续聊的专家子会话——「直开专家会话」是路线图项。
- persona 替换依赖底座组合里 persona 行的锚定形状;底座漂移时降级为底座 persona 并在安装结果里给出 warning(不会装出坏预设)。
路线图
- 远端 registry:catalog 从远端 JSON 拉取,支持市场内更新;
- 直开专家会话:卡片按钮直接开一个可续聊的专家子会话,主会话随时 @ 它;
- 富卡片:使用次数 / 作者 / 版本 / 预览对话示例;卡片排序(热门/最新)。
开发
node scripts/smoke.mjs # 离线冒烟:目录与覆盖层加载 + 安装/卸载/状态 + 召唤工具 + client bundle 加载与注册
无构建、无依赖、无 install 脚本。改完 host(src/)或 package.json 的 dsh.client.inject 后需重启 dsh web 才生效(bundles 与注入组合只在启动时加载);只改客户端半边(client/client.js)刷新页面即可。目录与脚本:
src/index.js—— host 入口(双 inject 编排);src/experts.js—— 目录加载(头文件 + 分文件 + 覆盖层)与安装/卸载/状态;src/routes.js—— 三个同源 HTTP 路由;src/summon.js—— 两个召唤工具 + 提示词 section;client/client.js—— 市场页 + 输入框按钮 +@触发源;scripts/import-agency-agents.mjs—— 从 agency-agents 导入/重导入目录;scripts/merge-zh-overlay.mjs—— 合并 zh 翻译片段;scripts/smoke.mjs—— 离线冒烟。
许可证与致谢
- 本插件的源码与文档以 MIT License 发布(Copyright (c) 2025 pbwheel)。
data/experts.d/下的 273 位专家人格导入自 agency-agents(MIT,Copyright (c) 2025 AgentLand Contributors),许可见data/experts.d/LICENSE;二级分组与中文翻译为本项目新增。