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

专家中心 Aliboder/dsh-expert-hub

DeepSeek Harness
Aliboder17 天前有提交已提供中文文档扫描:含敏感能力

统一管理专家库,在会话输入框旁一键切换挂载

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

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Aliboder/dsh-expert-hub
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:待复验
是什么
dsh 原生插件 · market
装得上吗
曾在 dsh 0.2.0-rc.2 下真实安装成功,但当前 dsh 已更新至 0.2.1-rc.5,本站尚未在新版下复验
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 17 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 105 处,展示前 71 条)
  • 发起网络请求
    client.js:1222
    return fetch(path, init).then(function (response) {
  • 写入剪贴板
    client.js:4295
    navigator.clipboard.writeText(template).then(markCopied, function () {
  • 读取本地文件
    src/paths.js:108
    start = await realpath(resolve(cwd))
  • 读取本地文件
    src/paths.js:109
    if (!(await stat(start)).isDirectory()) return undefined
  • 读取本地文件
    src/paths.js:116
    await lstat(join(current, '.git'))
  • 读取本地文件
    src/routes.js:205
    const data = await readFile(file.path)
  • 读取本地文件
    src/selections.js:47
    state = normalizeState(JSON.parse(await readFile(stateFile, 'utf8')))
  • 写入本地文件
    src/selections.js:58
    await mkdir(dirname(stateFile), { recursive: true })
  • 写入本地文件
    src/selections.js:60
    await writeFile(tmp, `${JSON.stringify(snapshot, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 })
  • 写入本地文件
    src/selections.js:61
    await rename(tmp, stateFile)
  • 读取本地文件
    src/workbuddy.js:82
    return JSON.parse(normalizeText(await readFile(path, 'utf8')))
  • 读取本地文件
    src/workbuddy.js:91
    return normalizeText(await readFile(path, 'utf8'))
  • 读取本地文件
    src/workbuddy.js:100
    return (await stat(path)).isFile()
  • 读取本地文件
    src/workbuddy.js:110
    entries = await readdir(dir, { withFileTypes: true })
  • 读取本地文件
    src/workbuddy.js:415
    entries = await readdir(root, { withFileTypes: true })
  • 写入本地文件
    src/store.js:73
    await mkdir(paths.expertsRoot, { recursive: true })
  • 读取本地文件
    src/store.js:79
    const parsed = JSON.parse(normalizeText(await readFile(join(dir, MANIFEST), 'utf8')))
  • 读取本地文件
    src/store.js:91
    if ((await stat(join(dir, name))).isFile()) return { path: join(dir, name), ext: `.${name.split('.').pop()}` }
  • 写入本地文件
    src/store.js:104
    await mkdir(join(targetRoot, 'skills'), { recursive: true })
  • 删除本地文件递归
    src/store.js:105
    await rm(target, { recursive: true, force: true })
  • 写入本地文件
    src/store.js:111
    await mkdir(target, { recursive: true })
  • 写入本地文件
    src/store.js:112
    await writeFile(join(target, 'SKILL.md'), `${normalizeText(skill.content)}\n`, {
  • 读取本地文件
    src/store.js:136
    exists = (await stat(dir)).isDirectory()
  • 删除本地文件递归
    src/store.js:149
    await rm(staging, { recursive: true, force: true })
  • 写入本地文件
    src/store.js:150
    await mkdir(staging, { recursive: true })
  • 写入本地文件
    src/store.js:153
    await writeFile(join(staging, 'expert.yml'), serializeExpertYml(meta), { encoding: 'utf8', mode: 0o600 })
  • 删除本地文件递归
    src/store.js:183
    await rm(dir, { recursive: true, force: true })
  • 删除本地文件递归
    src/store.js:187
    await rm(staging, { recursive: true, force: true }).catch(() => {})
  • 删除本地文件递归
    src/store.js:210
    await rm(dir, { recursive: true, force: true })
  • 读取本地文件
    src/store.js:218
    return normalizeText(await readFile(path, 'utf8'))
  • 读取本地文件
    src/store.js:304
    entries = await readdir(paths.expertsRoot, { withFileTypes: true })
  • 读取本地文件
    src/store.js:402
    sourceExists = (await stat(paths.sourceDir)).isDirectory()
  • 读取本地文件
    src/skill-sources.js:69
    return (await stat(path)).isDirectory()
  • 读取本地文件
    src/skill-sources.js:78
    return (await stat(path)).isFile()
  • 读取本地文件
    src/skill-sources.js:164
    entries = await readdir(home, { withFileTypes: true })
  • 读取本地文件
    src/skill-sources.js:186
    entries = await readdir(configDir, { withFileTypes: true })
  • 读取本地文件
    src/skill-sources.js:204
    real = await realpath(dir)
  • 读取本地文件
    src/skill-sources.js:249
    entries = await readdir(root.path, { withFileTypes: true })
  • 写入本地文件
    src/author.js:156
    await writeFile(temp, data, { mode: 0o600, ...options })
  • 写入本地文件
    src/author.js:157
    await rename(temp, filePath)
  • 删除本地文件
    src/author.js:161
    await rm(temp, { force: true }).catch(() => {})
  • 写入本地文件
    src/author.js:178
    await mkdir(dir)
  • 读取本地文件
    src/author.js:192
    entries = await readdir(dir, { withFileTypes: true })
  • 删除本地文件
    src/author.js:200
    await rm(join(dir, entry.name), { force: true }).catch(() => {})
  • 读取本地文件
    src/author.js:258
    await stat(absolute)
  • 写入本地文件
    src/author.js:293
    await writeFile(join(dir, 'expert.yml'), serializeExpertYml(meta), { encoding: 'utf8', mode: 0o600 })
  • 写入本地文件
    src/author.js:294
    await writeFile(join(dir, 'role.md'), `${roleText}\n`, { encoding: 'utf8', mode: 0o600 })
  • 写入本地文件
    src/author.js:296
    await writeFile(join(dir, `avatar${avatar.ext}`), avatar.data, { mode: 0o600 })
  • 删除本地文件递归
    src/author.js:310
    await rm(dir, { recursive: true, force: true }).catch(() => {})
  • 删除本地文件递归
    src/author.js:318
    await rm(dir, { recursive: true, force: true }).catch(() => {})
  • 读取本地文件
    src/author.js:364
    const existing = await readdir(skillsDir, { withFileTypes: true }).catch(() => [])
  • 删除本地文件递归
    src/author.js:368
    await rm(join(skillsDir, entry.name), { recursive: true, force: true })
  • 读取本地文件
    src/author.js:380
    const text = normalizeText(await readFile(file, 'utf8'))
  • 读取本地文件
    src/author.js:420
    info = await stat(source)
  • 删除本地文件递归
    src/author.js:431
    await rm(target, { recursive: true, force: true })
  • 读取本地文件
    src/author.js:439
    const content = await readFile(source, 'utf8')
  • 读取本地文件
    src/fingerprint.js:32
    listed = await readdir(current, { withFileTypes: true })
  • 读取本地文件
    src/fingerprint.js:45
    const info = await stat(path)
  • 写入本地文件
    src/importers.js:316
    await mkdir(base, { recursive: true })
  • 删除本地文件递归
    src/importers.js:326
    await rm(dir, { recursive: true, force: true }).catch(() => {})
  • 删除本地文件递归
    src/importers.js:339
    await rm(dir, { recursive: true, force: true }).catch(() => {})
  • 删除本地文件递归
    src/importers.js:366
    await rm(dir, { recursive: true, force: true }).catch(() => {})
  • 写入本地文件
    src/importers.js:465
    await mkdir(root, { recursive: true })
  • 写入本地文件
    src/importers.js:529
    await mkdir(entry.destination, { recursive: true }).catch((error) => {
  • 写入本地文件
    src/importers.js:570
    await mkdir(dirname(entry.destination), { recursive: true })
  • 写入本地文件
    src/importers.js:571
    await writeFile(entry.destination, content, { mode: 0o600 })
  • 写入本地文件
    src/importers.js:638
    await mkdir(root, { recursive: true })
  • 删除本地文件递归
    src/importers.js:834
    await rm(dir, { recursive: true, force: true }).catch(() => {})
  • 读取本地文件
    src/importers.js:857
    info = await stat(absolute)
  • 读取本地文件
    src/importers.js:887
    const bytes = await readFile(absolute)
  • 删除本地文件递归
    src/importers.js:934
    await rm(dir, { recursive: true, force: true }).catch(() => {})
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DSH 专家中心:WorkBuddy 市场、AI 创建专家、详情即编辑、技能管理、按会话切换

README

由 DeepSeek 最新模型翻译生成
DSH Expert Hub · 专家中心 把 WorkBuddy 专家、自建专家、网上导入的专家统一收进 DSH 的同一个专家库,在设置页里像应用商店一样浏览、导入、编辑,在会话输入框旁一键切换。 这是 DeepSeek Harness(DSH)的社区插件,不是 DeepSeek 官方产品。 它解决什么 旧版 WorkBuddy 专家插件只能「只读扫描 → 逐个安装 → 再去输入框旁选择」,看不到专家详情、不能新建、不能编辑、不能从网上导入。Expert Hub 重新实现了整条链路: | 能力 | 说明 | | WorkBuddy 专家市场 | 读取本机 WorkBuddy 已落盘的专家(.codebuddy-plugin/plugin.json + agents/.md),展示头像、职业、分类、技能,一键导入/更新/全部导入 | | AI 创建专家 | 用自然语言描述你要的专家,AI 先读《DSH 专家创作规范》,再生成 role.md 与必要的技能并写入专家库 | | AI 代为导入 | 把专家链接、网页内容或一段介绍直接发给 AI,由 AI 读取并整理成专家条目后写入;不再需要填网址、找下载链接 | | 对话内管理 | 直接在会话里说「改一下某专家的提示词 / 加个技能 / 从目录导入技能 / 让我用某专家」,由 expert_manage 工具完成 |
展开完整文档(README 剩余 1 节)
DSH Expert Hub · 专家中心

把 WorkBuddy 专家、自建专家、网上导入的专家统一收进 DSH 的同一个专家库,在设置页里像应用商店一样浏览、导入、编辑,在会话输入框旁一键切换。

这是 DeepSeek Harness(DSH)的社区插件,不是 DeepSeek 官方产品。

它解决什么

旧版 WorkBuddy 专家插件只能「只读扫描 → 逐个安装 → 再去输入框旁选择」,看不到专家详情、不能新建、不能编辑、不能从网上导入。Expert Hub 重新实现了整条链路:

| 能力 | 说明 |
| WorkBuddy 专家市场 | 读取本机 WorkBuddy 已落盘的专家(.codebuddy-plugin/plugin.json + agents/.md),展示头像、职业、分类、技能,一键导入/更新/全部导入 |
| AI 创建专家 | 用自然语言描述你要的专家,AI 先读《DSH 专家创作规范》,再生成 role.md 与必要的技能并写入专家库 |
| AI 代为导入 | 把专家链接、网页内容或一段介绍直接发给 AI,由 AI 读取并整理成专家条目后写入;不再需要填网址、找下载链接 |
| 对话内管理 | 直接在会话里说「改一下某专家的提示词 / 加个技能 / 从目录导入技能 / 让我用某专家」,由 expert_manage 工具完成 |
| 详情即编辑 | 卡片只有「详情」一个入口;打开后头像、名称、职业、role.md、技能在同一页面编辑,点「保存修改」生效 |
| 迁移专家 | 详情页可把全局专家整体迁移到某个项目,或把项目专家迁回全局;也可在对话里让 agent 调用 expert_manage 的 migrate 完成 |
| 项目级 / 全局专家 | 全局专家在 ~/.dsh/experts;项目专家在 <项目根>/.dsh/experts(随仓库走)。项目页顶部从 DSH 已登记工作区中选择,失效目录禁用;已安装页可按「全部 / 全局 / 项目」筛选,卡片带范围徽章;会话胶囊里也分组展示 |
| 技能管理 | 技能卡片式列表,可新增/编辑/删除,也可从本机技能目录一键导入 |
| 删除与回收站 | 卡片可直接删除(软删除到回收站);回收站可恢复或永久删除 |
| 会话内切换 | 输入框旁的专家胶囊:头像 + 搜索 + 当前标记,按 2 列网格分组展示全局/项目专家,选中即挂载「角色提示词 + 全部 skills」;「不用专家」随时退出 |
| 选择可恢复 | 选择按会话持久化,DSH 重启或会话恢复后自动重新挂载 |
| 实时刷新 | 专家库或 WorkBuddy 来源变化时,打开的下拉/页面通过 SSE 自动更新 |

界面

| 专家中心(设置 → 专家中心) | WorkBuddy 市场 |
| 已安装 | 市场 |

| 专家档案(详情 + 编辑合并) | 会话输入框旁的专家胶囊 |
| 专家档案 | 胶囊 |

安装

桌面端(推荐):侧栏 插件 → 添加插件,输入 npm 包名 dsh-expert-hub,安装后重启桌面 App。

终端:

dsh plugin --profile web add dsh-expert-hub

也可以从源码目录安装(开发调试):

dsh plugin --profile web add D:\SystemFiles\Documents\Project\DSH\plugins\dsh-expert-hub

安装后重启宿主(bundles 只在启动时读取),浏览器强刷。

使用

专家中心(设置 → 专家中心)

- 已安装:专家卡片墙,支持搜索、分类筛选、排序;每张卡片可直接「详情」或「删除」(删除前二次确认,删除是软删除,移入回收站)。详情与编辑合并成「专家档案」页:头像、名称、职业、role.md 和技能都在一个页面里改,点「保存修改」生效;技能可增删改或从目录导入。
- 回收站:列出软删除的专家,可「恢复」或「永久删除」(永久删除需二次确认,删除后不可恢复)。
- WorkBuddy 市场:本机 WorkBuddy 里已「召唤」的专家。首次使用需在 WorkBuddy 专家中心点击「召唤」,专家落盘到 ~/.workbuddy/plugins/marketplaces/experts/plugins 后这里就能看到。
支持单个导入、批量导入、发现源更新后的「更新」。
- AI 添加:页面只保留「让 AI 帮我创建专家」一条路——描述需求,AI 按《DSH 专家创作规范》生成 role.md 与必要的技能并写入;不再有手动填表或本机路径导入。

AI 创建专家(推荐)

在任意会话里直接用自然语言描述即可:

创建一个「周报助手」:帮我整理零散工作记录,输出 Markdown 周报表格,语气简洁,再加一个“周报检查清单”技能。

AI 会先调用 expert_manage({action:'guide'}) 读取创作规范(身份 / 工作流程 / 输出格式 / 质量检查 / 边界;技能只在确有可复用流程时创建),再调用 expert_manage({action:'create'}) 写入;需要的话可以用 activate:true 立即在当前会话启用。

AI 代为导入(外部来源)

不需要再走「填网址 → 下载 → 解压 → 导入」的流程。在任意会话里直接把来源发给 AI 即可:

帮我导入这个专家:https://example.com/some-expert

把下面这段专家介绍整理成一位专家并导入: AI 的处理流程:

1. 读取:网页正文用 web_fetch 读取;专家压缩包、本机目录、单个 .md 交给插件读取;
2. 整理:归一成一位专家的完整条目——中文显示名、职业/称号、role.md 角色提示词(必要时附技能正文);
3. 写入:调用 expert_import({expert:{…}}) 写入 ~/.dsh/experts/<id>/,并给出来源记录;
4. 选用(可选):用户说「导入并直接用」时传 activate: true,立刻在当前会话启用。

来源里有多位专家时,AI 会先问你要导入哪几位,再逐个写入;已有的同名专家不会被覆盖,会自动改用 -2 后缀。

对话内管理专家

除了设置页,也可以直接让智能体改专家: text 列出专家库里有哪些专家看看「电脑管家」的角色提示词把「电脑管家」的职业改成“硬件工程师”,角色提示词里加上二手配件避坑给「像素君」加一个技能:设计评审清单,内容是……
从 D:\skills\my-skill 导入技能到「像素君」让我用「码小序」

对应模型工具 expert_manage,支持 list / get / create / update / add_skill / remove_skill / import_skill / use。
删除专家仍只在设置页操作,避免对话里误删。

需要用项目级专家时,让 AI 带 library="project",例如: text 给这个项目建一个「本仓库代码评审」专家,用项目级把当前项目的「接口约定」专家角色提示词补上错误码规范

项目根目录优先使用 DSH 工作区注册表里当前会话所属的 workspace;找不到时退回「最近的包含 .git 的祖先目录」,再退回当前工作目录。项目专家存于 <项目根>/.dsh/experts;全局专家仍存于 ~/.dsh/experts。
项目页顶部可以从所有已登记工作区里切换查看,目录失效的工作区会禁用。

会话内切换

输入框左侧的专家胶囊会显示当前专家头像与名字(未选择时显示「专家」)。点开后:

- 搜索已安装专家,点选即切换,当前专家带 ✓;
- 「不用专家」移除当前会话的专家角色与 skills;
- 切换不会打断正在进行的回复,在下一个模型请求前生效。

命令行同样可用: text /expert 列出专家库 /expert <id> 切换当前会话专家 /expert off 取消 /expert info <id> 查看专家详情

数据与格式

专家库固定在 ~/.dsh/experts/<id>/($DSH_HOME 优先): text <id>/ ├─ expert.yml # 元数据(schema 1,中文优先,含来源/分类/快捷提示词) ├─ role.md # 角色提示词正文 ├─ skills/<name>/SKILL.md# 0..N 个技能,资源文件随目录复制 ├─ avatar.png # 可选 └─ .expert-source.json # 导入来源 + 内容指纹(仅导入的专家有)

兼容旧版 dsh-workbuddy-expert 导出的专家文件夹(expert.yml 只有 id/display_name/description/order 也能识别)。插件自己的会话选择记录与临时文件在 ~/.dsh/expert-hub/。

安全边界

- 专家只贡献提示词与技能文本:scripts/、.mcp.json、agent.cordis.yml 等可执行内容一律不导入、不执行;
- 导入的 Markdown 会做 CRLF/BOM 归一与 {{...}} 模板消毒,避免破坏宿主提示词插值;
- 专家库写入全部限制在 ~/.dsh/experts 内,ID 只允许 [a-z0-9-],删除前校验目录归属;
- HTTP 接口仅监听 loopback、只接受同源 POST、请求体有上限、响应 no-store;
- 压缩包读取拒绝内网/回环地址,zip 解压防目录穿越,跳过符号链接与可执行位文件;
- 删除专家是软删除:移到 ~/.dsh/expert-hub/trash/,误删可从该目录恢复;
- AI 导入写入的专家同样是纯提示词与技能文本:模型只负责整理,来源里的「指令」不会被当作插件行为执行;导入不会自动启用,除非用户明确要求 activate。

配置

默认 WorkBuddy 来源目录写死在 bundle patch 里,需要改时编辑 cordis.patch.yml 的 config.sourcePath(支持 ~),重启宿主生效: yaml
- id: expert-hub
name: dsh-expert-hub
config:
sourcePath: ~/.workbuddy/plugins/marketplaces/experts/plugins

开发 sh
npm test # test/run.mjs:format / store / switch / importers / author / tools
npm run check # node --check 两个入口

| 模块 | 职责 |
| index.js | 装配:paths / selections / switcher / routes / tools / 生命周期事件 |
| src/workbuddy.js | WorkBuddy 源目录扫描(富元数据 → 专家草稿) |
| src/store.js | 专家库读写、指纹、卡片、详情、导入安装 |
| src/compose.js | 智能体作用域内挂载角色段 + skills |
| src/switch.js | 串行切换事务、回滚、选择恢复 |
| src/selections.js | 会话选择 sidecar |
| src/importers.js | 压缩包 / 本机目录读取、zip/tar.gz 安全解压 |
| src/tools.js | 模型工具 expert_import(AI 整理导入)+ expert_manage(对话内查看/修改专家与技能) |
| src/author.js | 新建 / 编辑(含 skills)/ 从目录导入技能 / 回收站恢复 |
| src/routes.js | /expert-hub/ 路由与 SSE |
| client.js | 设置页 + 会话胶囊(浏览器端) |
| docs/CONTRACT.md | Host/Client 接口契约 |

许可证

MIT
预览分享卡片长什么样 ↓Aliboder/dsh-expert-hub
分享 · DeepSeek Harness Hub
Aliboder/dsh-expert-hub

统一管理专家库,在会话输入框旁一键切换挂载

这是你的仓库?认领条目

回到顶部