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.

Bundle Default Workspace — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
B

dsh-bundle-default-workspace

Bundle Default Workspace

A “default workspace” for miscellaneous tasks that don’t need to be separated by project. Configure its directory location, display title, purpose description, and AGENTS.md seed text in settings, and give the agent a default_workspace tool for querying and creating it; also includes reversible work

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

npx -y @deepseek-ai/dsh plugin --profile web add github:OraSkyC/dsh-bundle-default-workspace#dc13b375307e1fad2e83ca1fea5cd2880bebdbc9
READMECompatibilityVersions

Description

A “default workspace” for miscellaneous tasks that don’t need to be separated by project. Configure its directory location, display title, purpose description, and AGENTS.md seed text in settings, and give the agent a default_workspace tool for querying and creating it; also includes reversible workspace clearing/resetting.

Compatibility and provenance

Bundle Default Workspace is published as dsh-bundle-default-workspace and currently resolves to version 0.2.1. 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/8/2026

Versions

0.2.1stable
10/8/2026
0.2.0stable
10/8/2026

Related plugins

Loading related plugins…

Latest
0.2.1
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/8/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

Related plugins

More verified plugins in productivity-workflow.

Acp App@deepseek-ai/dsh-acp-appThe dsh ACP profile bundle: automation-only JSON-RPC stdio and process lifecycle over dsh-baseExperimental Schedule Bundle@deepseek-ai/dsh-experimental-schedule-bundleOptional bundle that adds Schedule, its task page, and time context to the Web compositionAb Ocrdsh-ab-ocr--- description: "The out-of-tree ocr tool: recognizes a scanned PDF or image page by page, merges the pages in order only after the last one, and saves one Markdown document with the heading levels the model decided." kind: "package-reference" ---Deepseek Ipptdeepseek-ipptiPolloWork PPT Studio and its curated slide templates as a native DeepSeek Harness conversation view.

README

默认工作区 · dsh-bundle-default-workspace

一个 DeepSeek Harness(DSH)插件: 给「杂七杂八、不想区分项目」的小事一个固定的落脚点。

临时算个数、随手写段调试脚本、查个资料做点笔记、问一句就完事 —— 这些事不值得为它新建一个工作区, 但随手丢进某个项目目录又很脏。这个插件提供一个默认工作区,自动建好、自动登记、 并在「设置 → 插件」里给你一张配置卡。

English · 简体中文


为什么需要它

DSH 里每个会话都要落在某个工作区。真正做项目时这很自然,但日常里大量的是一次性小事:

  • 新建一个工作区 → 要起名字、选目录、想它属于哪个项目……为了一个 5 分钟的小事,成本太高;
  • 随便塞进手头那个项目 → 项目目录被临时文件污染,过两天自己也忘了哪些是垃圾。

结果就是两种坏情况二选一。这个插件的做法是:承认有一类工作就是「做完就走」的, 给它一个专用的、被明确标记为「不是项目」的地方。

关键是它会往目录里写一份 AGENTS.md,直接告诉智能体这里不是项目 —— 不要搭 src/、tests/、package.json 那套,不要初始化 git 仓库, 保持根目录整洁,用完有价值的迁走、没价值的删掉。这样智能体不会自作主张把草稿区变成一个半成品项目。

特性

  • 一个默认工作区 —— 默认落在 <你的文档目录>/deepseek-harness/default-workspace, 自动创建并登记到 DSH 工作区列表,标题为「默认工作区」。
  • AGENTS.md 种子 —— 创建时写入中文说明。最重要的一条是「顶层目录不要直接放文件」: 明确禁止在顶层创建临时文件、草稿、验证脚本、依赖与构建产物,并给出 _scratch/ / notes/ / scripts/ 这些去处,最后补一句「拿不准就先问」。 这样智能体不会把你唯一的「干净落脚点」也搞乱。 里面还专门说明 _trash/ 是回收站、不要动它——否则智能体看到它会当成该清掉的垃圾。 默认不覆盖你已有的文件。
  • 智能体工具 default_workspace —— 会话里直接问「默认工作区在哪」「建好了没」, 或让它 ensure 一下把目录建出来。
  • 可视化配置 —— 在插件页改目录位置、标题、用途说明、种子文案等,改完立即生效,不用重启。
  • 可恢复的清空 / 重置 —— 用久了想归零,在面板里点一下就行。删除永远不是直接删: 文件和目录先被搬进工作区里的 _trash/<时间戳>/,随时能捞回来。而且要求你逐字输入目录名 才放行 —— 这个动作会一次搬空整个工作区,值得多花三秒。
  • 三级目录回落 —— 自定义父目录 → 系统文档目录 → ~/.dsh/workspaces,探测失败也不会没有着落。
  • 只读面板轮询 —— GET /state 严格无副作用,不会在你不知情时创建目录。
  • 零构建、零运行时依赖 —— 全部是手写纯 JS,只用 node: 内建模块,从 git 装完就能跑。

安装

插件安装后需要重启 DSH 才会加载(安装界面自己也会提示「下次启动后加载」)。

方式一:插件管理器(推荐)

  1. 打开 设置 → 插件

  2. 点右上角 「添加插件」

  3. 在「包名或地址」里填入本仓库地址:

    https://github.com/OraSkyC/dsh-bundle-default-workspace
    
  4. 点「安装」,然后重启 DSH

这个输入框同时接受 npm 包名、GitHub 仓库地址、本地目录路径三种形式。 用 GitHub 地址时,本机需要能直接访问 github.com(不走 npm 镜像源)。

方式二:命令行

dsh plugin --profile desktop add https://github.com/OraSkyC/dsh-bundle-default-workspace

方式三:本地目录(开发用)

如果你已经 clone 到本地,直接把目录链进 profile:

dsh plugin --profile desktop add /path/to/dsh-bundle-default-workspace

Windows 上手动做等价于三步:

  1. 在 %USERPROFILE%\.dsh\profiles\desktop\package.json 的 dependencies 里加 "dsh-bundle-default-workspace": "link:D:/path/to/dsh-bundle-default-workspace"
  2. 在同一个文件的 dsh.profile.bundles 数组里加上 "dsh-bundle-default-workspace"
  3. 建目录链接:mklink /J node_modules\dsh-bundle-default-workspace D:\path\to\dsh-bundle-default-workspace

升级

插件管理器目前不支持自动更新:请先「卸载」,再按上面的步骤安装新版,然后重启。

配置

配置分两层,优先级从低到高:

层位置生效时机
部署默认值本包的 cordis.patch.yml改完需重启 DSH
用户覆盖%USERPROFILE%\.dsh\state\dsh-bundle-default-workspace\settings.json立即生效,无需重启

用户覆盖层是稀疏的:只存你在面板里真正改过的字段。点「恢复默认」是把那个键删掉 (而不是把默认值再写一遍),于是自动回落到部署配置。

键默认说明
enabledtrue关闭后不创建目录、不登记工作区、不提供工具,面板只读。
directoryNamedefault-workspace叶子目录名。与 DSH 内核首用工作区同名,默认配置下直接包装内核行为。只允许字母数字点下划线连字符。
parentDirectory""父目录。留空走下面的自动解析;填绝对路径则直接用它。
documentsDirectory""系统文档目录覆盖,仅在 parentDirectory 为空时生效。留空则自动探测。
title""展示标题。留空由目录名派生(default-workspace → 「默认工作区」)。改标题会调用 workspaceRegistry.setTitle。
description""用途说明,展示在面板与 AGENTS.md。留空用内置文案。
autoCreatetrue首次使用时自动创建目录并登记,不用手动点「确保」。
seedAgentsMdtrue创建时写入 AGENTS.md。
instructions""非空则整篇替换内置种子正文。
overwriteSeedfalse即使 AGENTS.md 已存在也重写。默认关闭以保留你自己的修改。
pollSeconds30面板刷新间隔,夹在 5–600 秒之间。
trashKeep5回收站保留份数,夹在 0–100 之间。超出份数的最旧批次才会被真正删除;0 = 不自动清理。只影响插件自己创建的批次。
allowedHosts[]额外可信主机名(叠加到 localhost / 127.0.0.1 / ::1,不替换)。

目录是怎么定下来的

1. parentDirectory 非空?      → 直接用它                      来源 = config
2. documentsDirectory 非空?   → <它>/deepseek-harness          来源 = documents
3. 自动探测系统文档目录?       → <文档>/deepseek-harness        来源 = documents
4. 都失败                      → ~/.dsh/workspaces/deepseek-harness  来源 = fallback

最终目录 = <父目录> / <directoryName>

探测方式与 DSH 内核保持一致:Windows 走 [Environment]::GetFolderPath、 macOS 走 osascript、Linux 走 xdg-user-dir,带 10 秒超时。

当前用的是哪一种来源会显示在面板上 —— 「我的工作区到底建哪去了」是最常问的问题。

智能体工具

注册一个 default_workspace 工具:

action行为
status(默认)目录、是否存在、是否已登记、标题与会话数、AGENTS.md 状态。只读。
ensure创建目录、登记为工作区、写入 AGENTS.md。幂等。
path只返回目录路径与来源。
describe返回用途说明(面板里配的文字)。

工具描述里明确写了:要换目录请让用户去设置里改 parentDirectory,不要在工具里擅自改 —— 避免智能体在没有人类知情的情况下把工作区挪走。

工具描述里也写明了:清空 / 重置只有用户能在面板里操作,刻意不提供工具入口。 理由同上,而且更严重 —— 这两个动作会一次搬空整个工作区。

清空与重置

用久了这里会堆满跑完就没用的草稿。面板最后一个区块「清理与重置」(默认收起)提供两个操作:

操作搬走什么留下什么
清空工作区顶层的全部内容与子目录AGENTS.md、_trash/
重置工作区内容以及 AGENTS.md搬完后按当前设置重新生成 AGENTS.md,并确认工作区登记仍有效

「重置」是真正意义上的恢复初始化:做完之后目录里的状态和你第一次用这个插件时一模一样。

删除是可恢复的

两个操作都不直接删除任何东西。实现上是对每个顶层条目做一次 rename, 把它们搬进工作区里的回收站:

<工作区>/
├── AGENTS.md
└── _trash/
    ├── 20261009-010132-341/      ← 一次操作的批次
    │   ├── tmp.txt
    │   ├── _scratch/
    │   └── notes/
    └── 20261008-231500-123/

想找回什么,直接从 _trash/<批次>/ 里拿回去就行;确认不要了,把批次目录删掉即可。 「当前内容」那一行会告诉你待清理的条目数与体积,「回收站」那一行告诉你已经攒了几批。

两层护栏

  1. 打字确认。确认面板会列出将被搬走的条目,并要求你逐字输入工作区目录名 (默认就是 default-workspace)才让点确认。按钮在输入正确之前是禁用的。 没有用「确定 / 取消」弹窗,因为它挡不住手滑,而输入框能 —— 而且它逼你确认自己清的是哪一个目录, 毕竟目录名和父目录都是可以改的。
  2. _trash 永远不动。「清空」保留它,「重置」也排除它。如果 reset 把回收站也当成待清理内容, 它就会试图把 _trash 搬进 _trash/<批次>/_trash —— 自己搬自己。这个 bug 真实存在过, 被测试逮住(Windows 上直接 EPERM)。

回收站不会无限长大

trashKeep(默认 5)决定保留几批。超出份数后,最旧的批次才被真正删除。

自动清理的边界是目录名必须严格匹配 YYYYMMDD-HHmmss-SSS。也就是说它只删得掉 插件自己创建的批次;你自己往 _trash 里放的东西 —— 哪怕恰好叫 trash、backup 或 2026 —— 永远不会被自动清理碰到。名字受这个格式约束就不含路径分隔符, 拼出来的路径也不可能逃出 _trash。

HTTP 端点

面板用,全部只对本机回环开放(localhost / 127.0.0.1 / ::1)以及 allowedHosts 白名单; 来源不匹配一律 403。只校验 Host 头 —— 这些端点跑在宿主自己的回环 webserver 上, 跨源请求到不了这里,Host 是这条链上唯一可信的入口。

方法路径说明
GET/api/dsh-bundle-default-workspace/state状态快照。严格无副作用。
POST/api/dsh-bundle-default-workspace/settingsbody { "field": "<key>", "value": <v|null> };null = 删除覆盖、回落部署默认值。
POST/api/dsh-bundle-default-workspace/ensure创建 / 登记 / 播种。幂等。
POST/api/dsh-bundle-default-workspace/clearbody { "confirm": "<目录名>" }。{"dryRun": true} 只预演。
POST/api/dsh-bundle-default-workspace/reset同上,但连 AGENTS.md 一起搬走并重新生成。

/clear 与 /reset 的校验顺序是:来源 → 方法 → JSON body → 插件是否启用 → dryRun → 确认词。 确认词必须与工作区目录名逐字相同,否则 400,并在错误信息里告诉你该输入什么。 插件停用时这两个端点一律拒绝 —— 面板只读,接口也不放行。

工作逻辑

只读与副作用被严格分开

函数行为
describeWorkspace只 resolveByPath 探查,绝不创建任何东西
ensureRegistered命中就复用,否则 mkdir + create,再套用标题
buildState只 stat + 探查,只读
writeSeed已存在且未开启 overwriteSeed → 不写
listClearable只 readdir + lstat 汇总,只读,目录不存在也不创建

所以面板每 30 秒轮询的 GET /state 不会偷偷建目录。要创建只能走 /ensure 或工具的 ensure。

清理为什么用 rename 而不是递归删除

moveToTrash 对每个待清理的顶层条目只做一次 rename,从不递归进入子目录。这样有三个好处:

  • 快。清空一个塞满几千个文件的目录是一次系统调用,不是几千次。
  • 不可能删到工作区外面。删目录树最怕符号链接与 Windows 联接点:递归删除会顺着链接走进 C:\ 或网络盘。而 rename 搬走的是链接本身,目标完全不受影响。 这条不是纸上推导 —— 测试里真的建了一个指向工作区外面的联接点,断言搬完之后 目标目录与其中文件毫发无损。
  • 可恢复。这正是回收站能成立的前提。

配套的体积统计(measureTree)反过来必须递归,所以它用 lstat 而不是 stat (不跟随符号链接),并且有硬上限:最多 2000 个条目、8 层深度,撞到上限就置 truncated 并如实告诉面板「N 项以上」。

这里有个实测才发现的细节:光对子条目查 isSymbolicLink() 不够 —— readdir 会跟随作为根传进来的链接。所以 measureTree 在入口处也检查自己, 根是链接就直接返回 0 个字节、0 个条目。链接自身的元数据大小同样不计入体积: 那不是用户要搬走的内容。

还有一个边界:如果顶层条目超过 5000 个,moveToTrash 拒绝执行并说明原因。 宁可让用户手动整理,也不要出现「搬走了一部分然后报告成功」—— 那种「清空」比不清空更糟。

一个幂等的刷新函数服务三个调用方

apply(ctx, config)
  ├─ new FileStore($DSH_HOME/state/<name>/settings.json)
  ├─ registerRoutes()                 同步,挂上五条路由
  ├─ registerTool()                   异步,拿不到 tools 服务就返回 null
  ├─ void refreshFromSettings()       首轮
  ├─ setInterval(refresh, pollSeconds).unref()
  └─ ctx.effect(() => () => stop())   卸载钩子

refreshFromSettings(wiring)     ← 首轮 / 轮询兜底 / 面板写入后 都走它
  ├─ disposed / refreshing 守卫
  ├─ 读覆盖层 → resolveSettings 重算 → 写回 wiring
  ├─ !enabled || !autoCreate ? 直接返回
  ├─ resolveParent → mkdir
  ├─ ensureRegistered
  └─ writeSeed

那个 refreshing 布尔守卫不是装饰:没有它,用户点「确保工作区」时轮询正好触发, 两条路径会并发 mkdir + create,可能登记出两个工作区。

apply() 永不抛错

拿不到 tools 就不注册工具,拿不到 workspaceRegistry 就只建目录不登记,都只记一条 warn。 理由很实际:插件的挂载失败会连累 DSH 启动,一个可选插件不值得。

但这里有个反直觉的陷阱,也是本插件开发中真实踩过的坑 —— Cordis 的 ctx 是受限代理,访问未声明在 inject 里的属性会抛错,而不是返回 undefined:

cannot get property "webServer" without inject

所以「静默降级」不能写成 ctx.webServer ?? fallback —— 异常在求值那一刻就抛出去了, ?? 根本没机会执行,结果是整个 apply() 失败、插件在面板显示「异常」、三条路由全部 404。

正确做法是区分两类服务:

  • webServer 这类必然存在的服务 → 声明进 inject;
  • tools、workspaceRegistry 这类可选服务 → 用 ctx.get() 包 try 去读。

兼容性

项目要求
DSHweb profile(用到 webServer 与 slots)
Node>= 22.19.0
运行时依赖无(只用 node: 内建模块)
构建步骤无(手写纯 JS,从 git 装完直接可用)

peerDependencies 只声明了 @deepseek-ai/cordis,且用范围而非精确版本:

"peerDependencies": { "@deepseek-ai/cordis": ">=4.0.0 <5.0.0" }

两个刻意的选择:

  1. 不静态 import 任何 @deepseek-ai/* 包。宿主半侧只用 node: 内建模块; 浏览器半侧的 React 由 loader 在运行时交进来(loaderRequire("react"))。 这样插件不会因为 DSH 内部包路径变动而挂掉。
  2. peer 版本用范围。DSH 的 peer 兼容性检查只针对 @deepseek-ai/dsh 和 @deepseek-ai/dsh-* 前缀的包;@deepseek-ai/cordis 不在其列。但写精确版本仍然危险 —— 会因为 peer 版本不匹配被插件管理器直接拒绝安装。

开发

node --check lib/index.js     # 语法检查
node --check client.js

node test-e2e.mjs             # 宿主半侧(64 项断言组)
node test-client.mjs          # 浏览器半侧(42 项断言组)

npm test                     # 两个都跑

两个测试各用一个独立的 DSH_HOME 临时目录,跑完自动清理,不会碰你的真实配置。

⚠️ 改完代码必须重启 DSH

光刷新页面是不够的。 客户端 bundle 由宿主在激活时读进内存 (@deepseek-ai/dsh-client-modules 的 initialBundleSnapshot → readFileSync), 之后一直发那份快照;revision 也由那一次的 mtimeMs / ctimeMs / size 算出。

决定要不要重新扫描的 sourceKey 只由 baseUrl + loaderName 组成,不含任何文件元数据, 所以宿主见它没变就直接返回,既不重新 stat 也不重读文件。 加上 cache-control 是 public, max-age=31536000, immutable,刷新只会命中旧 URL。

判断新构建有没有真的生效:面板标题右边有一颗版本号小标(如 v0.1.2)。 版本号由 lib/index.js 在加载时从 package.json 读出,不会漂移。

目录结构

dsh-bundle-default-workspace/
├── package.json         # 清单:dsh.bundle.patch / dsh.client.inject / peerDependencies
├── cordis.patch.yml     # 部署默认值(补丁层)
├── lib/index.js         # 宿主半侧:配置、目录解析、FileStore、路由、工具、轮询
├── client.js            # 浏览器半侧:设置卡(React 由 loader 注入)
├── icon.svg
├── locale/zh.json       # meta.title / meta.description
├── locale/en.json
├── README.md            # 本文件
├── README.en.md         # 英文版
├── CHANGELOG.md
├── LICENSE
├── test-e2e.mjs         # 宿主半侧测试
└── test-client.mjs      # 浏览器半侧测试

常见问题

面板显示「读取失败:HTTP 404」,插件状态是「异常」 宿主半侧的 apply() 挂了,路由没注册上。最常见的原因是 lib/index.js 的 inject 漏声明了 webServer(见上面「apply() 永不抛错」一节)。

建到别的地方去了 看面板「父目录来源」那一行。要固定下来,就在面板里把 parentDirectory 填成绝对路径。

改了设置没反应 面板里的改动是立即生效的(走状态覆盖层)。但改 cordis.patch.yml 需要重启 DSH。

改了 client.js / lib/index.js 没反应 必须重启 DSH,刷新页面无效(见上面「改完代码必须重启 DSH」)。

AGENTS.md 被覆盖了 默认不会。检查是不是打开了 overwriteSeed。

清空之后文件去哪了 在工作区里的 _trash/<时间戳>/ 下,原样保留。面板「清理与重置」区块的「回收站」那一行会显示 批次数与最新批次名,照着路径去找就行。

_trash 会不会被自动删掉 只有符合 YYYYMMDD-HHmmss-SSS 命名、且超出 trashKeep 份数的最旧批次会被删。 你自己放进 _trash 的任何东西都不会被碰。

能不能让智能体帮我清空工作区 不能,这是刻意的。这个动作一次搬空整个工作区,只留了面板入口,并且要求逐字输入目录名。 智能体只能告诉你「去面板的清理与重置区块操作」。

和 DSH 内核自带的默认工作区冲突吗 不冲突。directoryName 默认就叫 default-workspace,与内核首用工作区同路径, 插件会通过 resolveByPath 复用它而不是另建一个。

许可证

MIT