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

技能工坊增强版 samir2015dzh/dsh-skill-studio-plus

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

每轮自动沉淀技能并语义合并去重,无需人工干预

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

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
dsh 原生插件 · market
暂无时间戳·判据 →
装得上吗[实装验证]—
本站尚未做安装检查
暂无时间戳·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/05·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 11 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

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

验证判据与等级说明 →

可信度证据

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

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

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 68 处,展示前 58 条)
  • 写入本地文件
    lib/index.js:72
    await mkdir(dirname(PENDING_REMEMBER_FILE()), { recursive: true });
  • 写入本地文件
    lib/index.js:73
    await writeFile(PENDING_REMEMBER_FILE(), JSON.stringify({ text, at: Date.now() }), "utf8");
  • 读取本地文件
    lib/index.js:81
    const raw = await readFile(PENDING_REMEMBER_FILE(), "utf8");
  • 写入本地文件
    lib/index.js:82
    await writeFile(PENDING_REMEMBER_FILE(), "{}", "utf8");
  • 读取本地文件
    lib/index.js:331
    const parsed = JSON.parse(await readFile(REGISTRY_CACHE_FILE(), "utf8"));
  • 写入本地文件
    lib/index.js:347
    await mkdir(dirname(REGISTRY_CACHE_FILE()), { recursive: true });
  • 写入本地文件
    lib/index.js:348
    await writeFile(REGISTRY_CACHE_FILE(), JSON.stringify({ at: Date.now(), summaries }), "utf8");
  • 写入本地文件
    lib/index.js:415
    await writeFile(skill.path, args.content, "utf8");
  • 读取本地文件
    lib/index.js:443
    const raw = await readFile(skill.path, "utf8");
  • 读取本地文件
    lib/index.js:1670
    const pkg = JSON.parse(await readFile(`${profileDir}/package.json`, "utf8"));
  • 发起网络请求
    lib/client.js:33
    response = await fetch(path, init);
  • 写入剪贴板
    lib/client.js:663
    await navigator.clipboard.writeText(String(value ?? ""));
  • 读取本地文件
    lib/scanner.js:214
    await stat(join(current, ".git"));
  • 读取本地文件
    lib/scanner.js:267
    const info = await stat(path);
  • 读取本地文件
    lib/scanner.js:276
    const info = await stat(path);
  • 读取本地文件
    lib/scanner.js:285
    const entries = await readdir(path, { withFileTypes: true });
  • 读取本地文件
    lib/scanner.js:340
    text = await readFile(candidate.path, "utf8");
  • 读取本地文件
    lib/trash.js:25
    await stat(p);
  • 写入本地文件
    lib/trash.js:35
    await rename(from, to);
  • 删除本地文件递归
    lib/trash.js:39
    await rm(from, { recursive: true, force: true });
  • 读取本地文件
    lib/trash.js:48
    dirs = await readdir(root, { withFileTypes: true });
  • 读取本地文件
    lib/trash.js:58
    const parsed = JSON.parse(await readFile(join(base, "manifest.json"), "utf8"));
  • 写入本地文件
    lib/trash.js:88
    await mkdir(root, { recursive: true });
  • 写入本地文件
    lib/trash.js:92
    await mkdir(batch, { recursive: true });
  • 写入本地文件
    lib/trash.js:95
    await writeFile(
  • 读取本地文件
    lib/trash.js:108
    const parsed = JSON.parse(await readFile(join(batch, "manifest.json"), "utf8"));
  • 删除本地文件递归
    lib/trash.js:127
    if (remaining.length === 0) await rm(batch, { recursive: true, force: true });
  • 写入本地文件
    lib/trash.js:128
    else await writeFile(join(batch, "manifest.json"), JSON.stringify(remaining, null, 2), "utf8");
  • 读取本地文件
    lib/trash.js:137
    const parsed = JSON.parse(await readFile(join(batch, "manifest.json"), "utf8"));
  • 删除本地文件递归
    lib/trash.js:143
    await rm(batch, { recursive: true, force: true });
  • 删除本地文件递归
    lib/trash.js:148
    await rm(item.to ?? join(batch, item.name), { recursive: true, force: true });
  • 删除本地文件递归
    lib/trash.js:150
    if (remaining.length === 0) await rm(batch, { recursive: true, force: true });
  • 写入本地文件
    lib/trash.js:151
    else await writeFile(join(batch, "manifest.json"), JSON.stringify(remaining, null, 2), "utf8");
  • 读取本地文件
    lib/profile-mcp.js:186
    text = await readFile(patchPath, "utf8");
  • 读取本地文件
    lib/profile-mcp.js:258
    text = await readFile(patchPath, "utf8");
  • 写入本地文件
    lib/profile-mcp.js:265
    await writeFile(patchPath, result.text, "utf8");
  • 读取本地文件
    lib/mcp.js:112
    raw = await readFile(storePath(), "utf8");
  • 写入本地文件
    lib/mcp.js:138
    await mkdir(storeDir(), { recursive: true });
  • 写入本地文件
    lib/mcp.js:139
    await writeFile(storePath(), JSON.stringify(body, null, 2) + "\n", "utf8");
  • 读取本地文件
    lib/mcp.js:914
    const info = await stat(storePath());
  • 读取本地文件
    lib/extractor.js:59
    if (existsSync(candidate)) return candidate;
  • 读取本地文件
    lib/extractor.js:166
    return parse(JSON.parse(await readFile(configPath(), "utf8")));
  • 写入本地文件
    lib/extractor.js:172
    await mkdir(dirname(configPath()), { recursive: true });
  • 写入本地文件
    lib/extractor.js:174
    await writeFile(tmp, JSON.stringify(cfg, null, 2), { mode: 0o600 });
  • 写入本地文件
    lib/extractor.js:175
    await rename(tmp, configPath());
  • 读取本地文件
    lib/extractor.js:209
    entries = await readdir(dir, { withFileTypes: true });
  • 读取本地文件
    lib/extractor.js:230
    : await readFile(file, "utf8");
  • 读取本地文件
    lib/extractor.js:296
    st = await stat(f);
  • 写入本地文件
    lib/extractor.js:420
    await writeFile(join(dirname(configPath()), "last-llm-raw.txt"), text, "utf8");
  • 发起网络请求
    lib/extractor.js:429
    const res = await fetch(`${base}/chat/completions`, {
  • 读取本地文件
    lib/extractor.js:566
    const arr = JSON.parse(await readFile(candidatePath(), "utf8"));
  • 写入本地文件
    lib/extractor.js:574
    await mkdir(dirname(candidatePath()), { recursive: true });
  • 写入本地文件
    lib/extractor.js:575
    await writeFile(candidatePath(), JSON.stringify(arr, null, 2), { mode: 0o600 });
  • 执行外部命令来自配置/变量
    lib/mcp-client.js:62
    this.child = spawn(spec.command, Array.isArray(spec.args) ? spec.args : [], {
  • 发起网络请求
    lib/mcp-client.js:144
    const response = await fetch(this.url, {
  • 发起网络请求
    lib/mcp-client.js:231
    const result = await this.request("initialize", {
  • 发起网络请求
    lib/mcp-client.js:295
    const page = await this.request("tools/list", cursor === undefined ? {} : { cursor }, this.connectTimeoutMs);
  • 发起网络请求
    lib/mcp-client.js:303
    return await this.request("tools/call", { name, arguments: args ?? {} });
扫描于 2026/11/5(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-tools@deepseek-ai/cordis@deepseek-ai/dsh-client-connection@deepseek-ai/dsh-client-ui-settings@deepseek-ai/dsh-host-webserver@deepseek-ai/dsh-skill@deepseek-ai/dsh-system-prompt
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DeepSeek Harness 的自改进技能流水线:逐轮判断、自动接受、语义合并、DSH 原生模型

README

由 DeepSeek 最新模型翻译生成
DSH Skill Studio 每轮自动沉淀 · 语义合并去重 · 走 DSH 自己的模型 简体中文 · 功能 · 合并怎么工作 · 安装 · 改动记录 本仓库是 zhengjy01/dsh-skill-studio 的社区 fork,不是 DeepSeek AI 官方产品。上游提供 skill 可视化、编辑与手动提取;本 fork 在其之上补上「无人值守」需要的四件事:每轮判断、自动入库、语义合并、模型跟随 DSH。 功能 在 DSH 里跑着不用管,它会自己判断这一轮学到了什么、该并进哪个 skill、并进去之后会不会重复。 - 每轮自动判断值不值得记:一轮对话结束 3 秒后发一个只要 YES/NO 的小请求(最近 1 个会话的 10 条摘要),判 YES 才跑完整提取。判定最少间隔 90 秒,提取最少间隔 5 分钟。 - 自动入库,不进候选队列:提取出的候选直接写进 ~/.agents/skills,DSH 立刻能加载。写入失败(同名冲突等)才留在队列里等人工处理。 - 语义合并而不是堆新文件:拿新候选跟全部既有 skill 比对,能并进就并进,只有确实是新主题才新建。实测同一类工作流换个措辞后,词面相似度只有 0.07–0.24,所以本地相似度只做粗筛,最终由模型看整份清单裁决。
展开完整文档(README 剩余 1 节)
DSH Skill Studio

每轮自动沉淀 · 语义合并去重 · 走 DSH 自己的模型

简体中文 · 功能 · 合并怎么工作 · 安装 · 改动记录

本仓库是 zhengjy01/dsh-skill-studio 的社区 fork,不是 DeepSeek AI 官方产品。上游提供 skill 可视化、编辑与手动提取;本 fork 在其之上补上「无人值守」需要的四件事:每轮判断、自动入库、语义合并、模型跟随 DSH。

功能

在 DSH 里跑着不用管,它会自己判断这一轮学到了什么、该并进哪个 skill、并进去之后会不会重复。

- 每轮自动判断值不值得记:一轮对话结束 3 秒后发一个只要 YES/NO 的小请求(最近 1 个会话的 10 条摘要),判 YES 才跑完整提取。判定最少间隔 90 秒,提取最少间隔 5 分钟。
- 自动入库,不进候选队列:提取出的候选直接写进 ~/.agents/skills,DSH 立刻能加载。写入失败(同名冲突等)才留在队列里等人工处理。
- 语义合并而不是堆新文件:拿新候选跟全部既有 skill 比对,能并进就并进,只有确实是新主题才新建。实测同一类工作流换个措辞后,词面相似度只有 0.07–0.24,所以本地相似度只做粗筛,最终由模型看整份清单裁决。
- 模型跟随 DSH:面板下拉列出你 DSH 里配置的 provider/model,留空就跟随触发这次提取的会话。插件自己不再存 API key,也不再要求填网关地址。
- 面板看「最近添加」:技能工作台列出最近改动过的 skill(名字 + 描述 + 时间),一眼看到它这两天自己学了什么。
- 写进去的内容是干净的:合并时自动去掉模型重复抄写的章节,切掉 MERGE: 这类协议残渣,拦住比原文短一大截的覆盖。

合并怎么工作

一个候选要过四道闸才会落进库,任何一道认为不该合并,它就会变成新 skill(或按规则丢弃)。

新候选 │ ├─ ① 墓碑:这个名字以前被合并过(扫 ~/.dsh/skill-archive/) │ → 强制并入同类里正文最长的那份;合不进就丢弃,绝不再写一份重复 │ ├─ ② 类别标签:清单写成 "- [decompile] 名字: 描述",模型先看类别再看描述 │ → 类别不同且描述不像,模型自己就不会选它 │ ├─ ③ 本地复核:模型给了 FOLD_INTO,再验一次 │ → 同类直接放行;跨类别要求相似度 ≥ 0.5,否则改判 SAVE │ └─ ④ 合并本身:让模型把新经验并进主 skill 的既有章节 → 结果里重复的章节截断、协议残渣切掉、比原文短 40% 以上则拒绝

类别从名字推导(gui- → gui、decompiled- / java-decompile- → decompile、portable- / offline- → portable ……),CATEGORY_ALIASES 在 lib/extractor.js 里,加一行就能扩。

安装

插件装在 DSH profile 里,用 link: 指向本目录,改代码不用重新发布。

1. clone 到本地任意位置:

git clone <this-repo> D:/dsh-plugins/dsh-skill-studio

2. 在 profile 的 package.json 里登记:

{
"dependencies": { "dsh-skill-studio": "link:D:/dsh-plugins/dsh-skill-studio" },
"dsh": { "profile": { "bundles": ["dsh-skill-studio"] } }
}

3. 建目录联接,让 node_modules 解析到本目录:

New-Item -ItemType Junction
-Path "$env:DSH_PROFILE_DIR\node_modules\dsh-skill-studio"
-Target "D:\dsh-plugins\dsh-skill-studio"

4. 重启 DSH,打开 设置 → Skill 工作台。

配置

配置文件:~/.dsh/dsh-skill-studio/extractor.json(0600 权限)。

{
"enabled": true,
"autoPerTurn": true,
"intervalMinutes": 60,
"windowDays": 7,
"maxCandidatesPerRun": 3,
"autoAccept": true,
"mergeThreshold": 0.2,
"skillLanguage": "auto",
"agentSkillDir": "C:\\Users\\<you>\\.agents\\skills",
"provider": "",
"model": ""
}

| 键 | 作用 |
| autoPerTurn | 每轮结束是否先做 YES/NO 判断 |
| intervalMinutes | 兜底扫描间隔;填 0 = 只靠每轮判断 |
| autoAccept | 直接入库,不走候选队列 |
| mergeThreshold | 本地相似度粗筛阈值(合并判定主要由模型做) |
| skillLanguage | auto / zh / en,代码与命令一律不翻译 |
| provider / model | 留空 = 跟随会话;也可在面板下拉里选 |

llmBaseUrl / llmApiKey / llmModel 三个旧字段仍然兼容,只在 ctx.llm 不可用时作为 HTTP 回退;正常情况留空即可。

提供的工具

| 工具 | 作用 |
| skillmgr_list | 列出所有 skill(含来源、启用状态、分组) |
| skillmgr_get | 读某个 skill 的完整内容 |
| skillmgr_save | 整篇写回 SKILL.md |
| skillmgr_policy | 启用/禁用模型调用与用户调用 |
| skillmgr_extract_run | 立即跑一次提取 |
| skillmgr_extract_status | 看开关、间隔、队列、上次运行时间 |
| skillmgr_extract_config | 改配置 |
| skillmgr_extract_list / _accept / _reject | 处理候选队列(自动入库开启时通常为空) |

HTTP 路由挂在 /api/dsh-skill-studio/*,面板用的就是它们。

调试

每次调模型的原始输出会留在:

~/.dsh/dsh-skill-studio/last-llm-raw.txt

解析报错时先看这个文件 —— 是 JSON 被截断、还是夹了 markdown 围栏、还是模型答非所问,一眼能分辨。

两个回归脚本不碰真实目录:

node scripts/e2e-preview.mjs # 提取→裁决→合并→入库 全链路,6 项断言
node scripts/e2e-tombstone.mjs # 墓碑压制模型裁决(故意让它说 SAVE + KEEP)

与上游的差异

完整清单见 FORK-NOTES.md,共 15 条。要点:

1. 模型调用改走 ctx.llm.prepareCall(),插件不再存密钥
2. 每轮 YES/NO 判断 + 自动入库
3. 语义合并:类别标签、模型裁决、本地复核、墓碑拦截
4. 合并结果去重、去残渣、短正文拦截
5. 面板「最近添加的 skills」+ 模型下拉
6. 提取输出截断抢救、maxTokens 提到 8000

许可

MIT,与上游一致。上游版权归 zhengjy01。
预览分享卡片长什么样 ↓samir2015dzh/dsh-skill-studio-plus
分享 · DeepSeek Harness Hub
samir2015dzh/dsh-skill-studio-plus

每轮自动沉淀技能并语义合并去重,无需人工干预

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部