DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Workspace Scaffolds — DSH Plugin for DeepSeek Harness
← Plugins
W

dsh-workspace-scaffolds

Workspace Scaffolds

Associate DSH projects with the scaffolding plugins used by the project: prepare them before starting, add more during work, hibernate unused ones while retaining them on disk, and restore them with the project when used again. ⚠️ Only partially verified; experimental code.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:Eru07734/dsh-workspace-scaffolds#6eaa8a3453a76aeeab8dfd1672f30afec62f69d7
READMECompatibilityVersions

Compatibility and provenance

Workspace Scaffolds is published as dsh-workspace-scaffolds and currently resolves to version 0.1.12. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
10/12/2026

Versions

0.1.12stable
10/12/2026

Related plugins

Loading related plugins…

Latest
0.1.12
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
10/12/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in

Related plugins

More verified plugins in developer-tools.

Web App@deepseek-ai/dsh-web-appThe dsh browser-surface bundle: the web patch layer over dsh-base plus the runtime glue plugin (frontend dist serving, web-surface prompt, bash runtime variables, URL line)Sdk Minimal@deepseek-ai/dsh-sdk-minimalThe standalone minimal SDK profile bundle: JSON-RPC, one DeepSeek adapter, persistent shell, and JSONL sessionsSdk App@deepseek-ai/dsh-sdk-appThe dsh SDK profile bundle: stdio JSON-RPC serving and process lifecycle over dsh-baseExperimental Inspector@deepseek-ai/dsh-experimental-inspectorExperimental cross-realm CDP hub for Host debugging and Client Runtime inspection

README

工程脚手架 · dsh-workspace-scaffolds

✅ 评审 14 项已全部修复 · ALL 14 REVIEW FINDINGS FIXED

一次独立代码评审发现 14 项可复现缺陷(5 项 P1、9 项 P2),我已逐条对照源码确认全部成立,并已全部修复。 修复过程中又发现并修复了 1 项评审之外的缺陷(F15:splitName 静默截断超长路径,产出连自己的读取器都拒绝的归档)。 逐条状态、修法与仍未关闭的残余风险见 docs/review-response-2026-10-12.md。

已在真实 DSH 0.2.0-rc2 隔离实例上验证(D:\dsh-verify-020rc2,独立 home / profile / 端口,不触碰日常工作 profile):

  • 完整工作流:注册工程 → 导入脚手架包 → 关联 → 预览 → 生成文件 → 启用 → 休眠 → 恢复;
  • 插件的安装与热载入(application: "applied",无需重启);
  • 休眠真正在原生侧停用 bundle,恢复后重新启用;休眠不误停用别的工程仍在使用的包;
  • 重启后的状态对账:关联、版本、原生状态与归档保持一致,且对账不会误钉;
  • HTTP 进度:导入运行期间可轮询到中间步骤;
  • 脚手架注册的工具在真实 agent 回合中被提供、被调用,其返回载荷出现在消息记录里;
  • 评审 P1 的现场复核:解绑只释放被移除的那个关联;自动恢复登记共享持有者;
  • 评审 P2(第二批)的现场复核:未满足的声明依赖被拒且 requires 跨重启存活;重复导入不改写归属;部分绑定更新被接受;必需脚手架关闭时 ready=false;
  • 评审 P2(第三批)的现场复核:原生安装失败会让导入失败且不留下包记录(用真实失败的安装造出来,不是 mock);预览之后的冲突零写入。

未验证:浏览器面板的视觉渲染。逻辑与状态有测试覆盖,但真实浏览器里的画面始终没有人眼确认——这一项自始至终未变。

详细证据、缺陷记录与验证方法见 docs/verification.md。

把 DSH 工程(Workspace)与工程使用的脚手架插件关联起来的插件。

  • 开工前:选择工程需要的脚手架,预览并生成初始文件,然后恢复插件。
  • 工作中:随时给工程追加脚手架;新增能力从下一次模型请求开始生效。
  • 不用时:休眠工程,插件被停用并保留在硬盘上;工程文件、安装包和配置都不动。
  • 再次使用时:恢复工程,按记录的版本和关联把插件重新装回运行状态。

目录

  • 核心概念
  • 安装
  • 使用流程
  • 面板说明
  • agent 工具
  • HTTP 接口
  • 数据与状态
  • 能力边界
  • 验证
  • 脚手架包格式

核心概念

术语含义
工程DSH 原生 workspaceRegistry 中的 Workspace,用原生 workspaceId 标识
脚手架包声明了 dsh.bundle 的原生 DSH 插件包,可以另外携带文件模板
关联把某个精确版本的包记入工程清单;关联本身不加载任何东西
准备 / 恢复通过原生插件管理器启用插件能力;不生成模板文件
生成依据模板向工程写入新文件;必须单独执行,永不覆盖已有文件
休眠释放工程对插件的占用;没有其他工程需要时才真正停用,磁盘文件全部保留
解除关联从工程清单移除记录;已生成的文件保留
全局常驻标记某个包始终启用,任何工程休眠都不会关闭它

租约(lease)是推导出来的,不是存下来的。 一个工程持有某个包的租约,当且仅当它处于「使用中」且该关联处于启用状态。这样就不会出现「存的租约和实际关联不一致」这类问题。

安装

本插件是一个原生 DSH bundle。开发目录没有第三方依赖,Host 代码和浏览器代码都是普通 JavaScript。

# 在 DSH 中通过插件管理器安装本目录或发行包
dsh plugin add /absolute/path/to/dsh-workspace-scaffolds
# 或安装打包好的发行包
dsh plugin add ./dsh-workspace-scaffolds-0.1.9.tgz

安装后需要为本插件启用 bundle(默认 cordis.patch.yml 已声明)。面板出现在 插件页 → 本插件卡片,使用 plugins.bundle.config 插槽。

使用流程

1. 注册工程

在面板「注册工程」中填写项目目录的绝对路径。插件会在原生工程注册表中登记它,并建立自己的管理记录——此时不关联任何脚手架、不启用任何插件、不写任何文件。

已注册的目录再次注册不会报错,也不会产生第二个工程:原生注册表按路径去重,插件会接管既有的那个,并保留它已有的关联。

2. 导入脚手架包

在面板「导入脚手架包」中填写绝对路径,可以是:

  • 一个包含 package.json(且声明了 dsh.bundle)的目录;
  • 一个 .tgz 包。

导入会依次完成:校验原生 bundle 声明 → 校验可选的 scaffold.json → 打包并计算 SHA-256 → 存入本地归档 → 通过原生插件管理器安装但不启用。

3. 关联到工程

在「已关联脚手架」区域选择包并点击「添加到该工程」。关联只写配置,不加载插件、不写工程文件。

4. 生成初始文件(可选)

对声明了模板的包点击「生成预览」:

  • 预览会列出每个目标文件的 create / identical / conflict 状态;
  • 预览阶段发现任何 conflict 时整批阻止,此时不会写入任何文件;
  • 确认后点击「生成文件」。已存在且内容相同的文件被跳过,内容不同的文件不会被覆盖。
  • 应用前会再次检查全部目标:预览之后才出现的冲突(文件被他人改写、目标变成目录)同样整批中止,一个文件都不会写入。
  • 写入过程中若发生 I/O 失败,会回滚本次已创建的文件与目录——只删空目录,且只删内容摘要仍是本次写入的那些,避免误删用户在窗口期内的改动。若回滚自身失败(例如文件被别的进程占用),错误详情会如实报告 rolledBack / leftBehind / partial,不会假装干净。进程被硬杀或断电时不存在回滚路径,会留下部分文件。

5. 恢复工程

点击「恢复」。所有必需的包都会依次启用;失败时不会把工程标成「已就绪」,并且会回滚本次新启用、且没有其他工程需要的包。

6. 休眠

点击「休眠并保留」:

  • 有任务正在执行时,休眠会排队,等环境空闲后自动完成,不会打断正在运行的任务;
  • 其他工程仍在使用的包保持不变,面板会说明保留原因;
  • 标记为「全局常驻」或原本就由外部启用的包不会被关闭;
  • 只调用原生「停用」,不会删除安装、归档或工程文件。

面板说明

面板分为四块:

  1. 导入脚手架包 — 路径输入与导入。
  2. 工程 — 选择工程;显示期望状态、是否就绪、待处理项;提供「恢复」与「休眠并保留」。
  3. 已关联脚手架 — 每个关联的版本、原生状态、归档状态、是否多工程共享;提供生成预览与解除关联。声明了模板变量的包会在行内给出变量输入框。
  4. 本地仓库与已装插件 — 本地仓库中的包、是否已安装、归档是否存在、当前有哪些工程在用它;提供全局常驻开关与删除归档。

所有写操作都携带当前 revision;版本冲突时面板会重新读取状态并提示,不会盲目重放。

面板标题行显示三个标签:配置版本、profile 名称、以及当前运行的构建版本(pluginVersion)。当 profile 声明的构建与内存中运行的不是同一个时,面板会额外显示一行提示和所声明的 spec —— 也就是「更新已写盘,但需要重启才生效」这个状态,不必再靠行为反推。

agent 工具

工具名 workspace_scaffolds,动作与 HTTP 接口一致。默认工程取自当前会话的工作目录(通过原生工程注册表按规范化路径精确匹配,不做前缀猜测)。

读操作:

  • list — 完整状态,包含 revision、工程、关联、包和阻塞项。
  • operation-status — 按 operationId 查询进度与结果。
  • scaffolds — 读取某个包的模板描述。

写操作(必须携带 list 返回的 expectedRevision 与一个新的 UUID operationId):

  • workspace-register — 把一个已存在的目录注册为受管工程(path,可选 title)
  • import、bind、unbind、update-binding、set-pin
  • wake、sleep
  • template-preview、template-apply
  • delete-archive

operationId 与参数一起构成幂等键:同参数重试会返回记录过的结果而不重复执行;同 ID 换参数会被拒绝(operation-id-reused)。

wake 返回 effectiveFrom: "next-model-request" —— 这是准确语义:当前已经发给模型的工具列表不会改变,新增能力在下一次请求生效。

HTTP 接口

GET  /api/workspace-scaffolds/state
GET  /api/workspace-scaffolds/progress            # 只读进度,适合高频轮询
GET  /api/workspace-scaffolds/progress?operationId=<id>
POST /api/workspace-scaffolds/execute

成功:{ "ok": true, "value": ... };失败:{ "ok": false, "code": "...", "details": { ... } }。

请求体上限 1 MiB。配置、版本、模板冲突返回 409,输入错误 400,找不到 404。

进度

import 会真的跑包管理器,wake 要逐个原生启用 bundle;这些请求在完成前如果不返回任何中间信息,调用方就只看到一个卡住的连接。因此耗时的动作会被登记成一条进度记录,可以在它还在跑的时候查询:

// POST /execute  { "action": "import", ..., "background": true }
{ "ok": true, "value": {
    "operationId": "…", "action": "import", "status": "running", "background": true,
    "progress": { "phase": "validate package", "steps": [ /* … */ ] } } }
// GET /progress        (或包含在 GET /state 的 progress 字段里,一次轮询即可)
{ "ok": true, "value": {
    "running": [ {
      "operationId": "…", "action": "import", "status": "running",
      "phase": "install without enabling",
      "steps": [
        { "label": "validate package", "status": "done", "detail": "dsh-scaffold-notes@0.1.0" },
        { "label": "install without enabling", "status": "active" },
        { "label": "record in warehouse", "status": "pending" }
      ] } ],
    "recent": [ /* 最近完成的,保留 20 条 */ ] } }

实际轮询效果(真实输出,install 被注入 1.2s 延迟以便观察):

tick 2
  import  running  phase=install without enabling
      [x] validate package  (dsh-scaffold-notes@0.1.0)
      [x] hash and archive  (8700a0a14de3)
      [x] read scaffold descriptor  (1 template(s))
      [>] install without enabling
      [ ] record in warehouse

要点:

  • background: true 让耗时动作立刻返回 operationId,而不是把连接挂到跑完为止;配合 /progress 轮询即可。适用于 import、wake、sleep、template-apply。
  • 步骤状态为 pending / active / done / failed / skipped;wake 与 sleep 会按包动态追加步骤(每个包一行),因为这些步骤在计划时就已确定但数量取决于关联。
  • 进度只在内存中,刻意不持久化:它描述的是一个活着的进程,重启后读到过期记录比读不到更糟。持久的结果仍在操作日志里(operation-status)。
  • operation-status 对进行中的操作同样可用(读实时进度),不必等它写入操作日志。
  • 面板在动作执行期间轮询 /progress 并逐步渲染,而不是只显示一个转圈。

构建标识

list(以及 GET /state)的返回值里带有三个诊断字段,用来回答「现在到底是哪个构建在跑」:

字段含义
pluginVersion正在内存中运行的构建版本,读自该模块自己的 package.json
profileSpecprofile manifest 为该插件声明的依赖 spec(即「请求的是哪个」),读不到时为 null
restartPending前者与后者不一致,需要重启 DSH 才会生效

pluginVersion 取自运行中的模块自身,而不是 profile 声明——后者恰恰是会在「更新已写盘、进程仍持旧代码」时说谎的那个。

restartPending 是保守启发式:只对 file: / link: 这类把具体产物写进字符串的本地 spec 判定;^0.1.0 这类注册表范围描述的是一个可接受集合,不是另一个构建,因此永不报告为待重启。读不到版本时一律返回 false,不会把「未知」伪装成任何结论。

错误码

invalid-request、workspace-not-found、workspace-unavailable、revision-conflict、operation-id-reused、package-content-conflict、version-conflict、dependency-missing、dependency-cycle、protected-bundle、restart-required、native-overridden、native-operation-failed、template-conflict、preview-expired、preview-stale、path-outside-workspace、archive-in-use、state-corrupt、unsupported-host、not-a-bundle、package-unknown、scaffold-invalid、archive-invalid。

sleep 在有空闲问题时返回 status: "pending-idle" —— 这是正常的异步状态,不是错误。

数据与状态

全部状态位于当前 profile 目录下:

<profileDir>/workspace-scaffolds/
  state.json          权威状态(含 revision、工程、包、预览、操作日志)
  state.json.bak      上一次成功的状态,用于损坏恢复
  archives/<sha>.tgz  内容寻址的脚手架包快照
  operations/         预留的操作目录
  staging/            临时解包目录(用完即删)

规则:

  • 所有写操作串行化,写前校验 revision,写入使用「临时文件 + 原子改名」。
  • state.json 损坏时先从 .bak 恢复;没有可用备份就报错停止,绝不把损坏状态当成空状态。
  • 存储的 schemaVersion 高于本插件支持的版本时只读报错,不做降级。
  • 操作日志保留最近 200 条,用于幂等重放。
  • 预览记录带 10 分钟有效期,template-apply 必须引用预览 ID。

工程目录里只有你显式生成的模板文件;本插件不写隐藏清单、不改 .gitignore。

能力边界

这些是已知且有意的限制,请按此预期使用:

  1. 原生插件是全 profile 共享的。 关联到工程不等于运行隔离。本插件用「工程使用记录 + 全局常驻保护」来避免误停用,但一个启用的 bundle 会向该 DSH 环境中的所有会话提供它的能力。
  2. 不做工程级配置隔离,也不支持同一包的多版本并行。 两个工程要求同包不同版本时会明确报 version-conflict,不会替换正在运行的版本。
  3. agent/created 自动恢复只走快路径:只对已安装的包做启用,绝不在创建 agent 时运行包管理器。需要安装时,面板会显示待处理项,由「恢复」显式完成。自动恢复有 15 秒预算;超时会记录并标记为 degraded,不会挂起启动。
  4. 原生侧边栏单纯切换到一个已存在的会话不会触发恢复。 请用面板的「恢复」,或在新建/恢复 agent 时依赖自动恢复。
  5. 休眠时如果环境中有任务在执行会排队,不会打断。
  6. 停用不保证卸载模块内存。 Node 的模块缓存不保证回收,所以本插件只说「停用并保留」,不承诺完全释放内存。
  7. 离线恢复分两级:休眠后再恢复不需要网络;如果包被从 profile 里移除,则只有归档存在、且重新安装成功后才能恢复(第三方依赖是否可离线重装未经验证)。
  8. 模板没有覆盖更新、三方合并或升级迁移。 用户改过的文件永远保留。
  9. 本插件自身被停用时不会去关闭第三方插件(此时宿主服务可能正在释放),只释放自己注册的路由、工具和监听器;下次启动重新对账。

验证

验证分两层,两层都要看:

node --test test/*.test.mjs        # 171 项单元测试(假宿主)

第一层:单元测试(内存假宿主,但执行的是真实的 src/host.js 适配层):

验证了什么没验证什么
171 项 node:test 用例全部通过浏览器面板的真实渲染与交互
Linux(Node 22 / 24)与 Windows 上均通过— 真实环境由第二层覆盖
真实适配层被实际执行(非桩替换):installBundle(..., {enabled:false}) 等契约在测试范围内

第二层:隔离 DSH 0.2.0-rc2 实例上的端到端验证(主流程 + 评审 P1/P2 复核共 66/66、重启对账 9/9、agent 层 12/12):

验证了什么没验证什么
完整工作流:注册 → 导入 → 关联 → 预览 → 生成 → 启用 → 休眠 → 恢复浏览器面板的视觉渲染(布局与样式)
休眠真的在原生侧停用 bundle;恢复真的重新启用与 0.2.0-rc2 以外版本的兼容性
两个工程共享同一 bundle 时,休眠不误停用别人仍在用的包
重启后的状态对账(关联、版本、原生状态、归档一致,且不会误钉)
HTTP 进度可在长操作运行期间轮询到中间步骤
真实 agent 回合中脚手架注册的工具被提供、被调用,且其返回载荷出现在消息记录里

验证环境:独立 home D:\dsh-verify-020rc2、独立 profile verify、独立端口 —— 与日常工作 profile 完全隔离,验证产物也留在隔离区内。

测试覆盖的验收场景与结果见 docs/verification.md。

试用前请自行确认:本插件会在 <profileDir>/workspace-scaffolds/ 下写入状态,并会调用原生插件管理器启用/停用 bundle。请先在非关键 profile 或副本工程上验证。

脚手架包格式

一个可运行的脚手架包就是原生 DSH bundle,可以额外声明模板:

{
  "name": "dsh-scaffold-notes",
  "version": "0.1.0",
  "type": "module",
  "exports": { ".": "./plugin.js" },
  "dsh": { "bundle": { "patch": "./cordis.patch.yml" } },
  "workspaceScaffold": "./scaffold.json"
}

scaffold.json:

{
  "schemaVersion": 1,
  "title": "工程笔记",
  "variables": {
    "projectName": { "type": "string", "required": true, "maxLength": 100 }
  },
  "templates": [
    {
      "id": "notes",
      "files": [
        { "source": "templates/NOTES.md", "target": "docs/NOTES.md", "render": "text" }
      ]
    }
  ]
}
  • render: "text" 只支持 {{variableName}} 替换,不支持表达式、脚本或递归 include。
  • render: "copy" 原样复制二进制资源。
  • 目标是固定的相对路径,必须是相对路径且不能越出工程目录。
  • requires 用于声明依赖其他脚手架包(精确版本),由本插件做依赖排序与环路检测。

examples/ 下有两个可直接导入的示例:dsh-scaffold-notes(只提供模板)与 dsh-scaffold-checks(提供 project_checklist 工具与模板)。

许可

MIT