工作台开发规范
版本:2026-10-27 · 以官网版本为准,DSH Desktop 内附文档副本供离线取用。
官方地址:https://dshdesktop.com/workbench/docs/development/
Markdown 原文(供 Agent 读取):https://dshdesktop.com/workbench/docs/development.md
六步速览:https://dshdesktop.com/workbench/docs/quickstart/ (Markdown 原文)。
本文是开发工作台时由 AI 直接执行的规范。只在本地开发、自己使用时,满足本文即可:按第 3 节写好包,装到本机 DSH Desktop,按第 8 节自测通过,就可以正常使用,不需要公开代码,也不需要上传到任何地方。
如果之后想把工作台上架到工作台市场,再阅读《工作台市场验收规范》:https://dshdesktop.com/workbench/docs/market-acceptance/ 。仓库公开、发布、简介、截图和收录 PR 的要求都在那一份里,本文不涉及。
工作台是一种 DSH 插件。它首先必须是一个合格的 DSH 插件包,能被 dsh plugin add 安装、被 Harness 加载;在此基础上,再向 Desktop 注册业务面板,并遵守工作台与会话、工作区的交互规则。
规则分三级:必须(不满足就不能安装或加载)、建议(强烈推荐,不满足会影响体验或以后上架)、可选。
1. 执行原则
规范获取顺序:开始开发前必须实际获取并阅读全文上述官网 Markdown,记录获取地址和文档版本;不能只凭已有知识或内置文档声称已读。只有在线获取失败时才可使用内置离线副本,并报告失败原因、离线来源和版本。离线副本是打包快照,不保证最新,不得默默替代在线规范。最新规范与当前运行版本冲突时,说明能力差异和受阻步骤,不得用旧规范覆盖在线规范。
面向用户的沟通:需求引导、布局建议、确认选项以及安装和完成状态都使用业务语言,例如“整页展示业务内容,需要时再打开 AI 对话”或“边对话边查看辅助资料”。不要要求普通用户确认 customFrame、register()、repository、dshHomePath、reconcileLocalProviders 等代码字段、内部身份或占位仓库地址,也不要大段呈现内部实现后让用户选择。技术字段由 Agent 在开发执行时按本规范处理;缺少发布身份不能阻断已明确的本地开发,不得捏造真实仓库。确实需要用户提供信息时,只询问影响业务或安装的实际问题,例如“要保存在哪个文件夹?”;用户主动询问技术细节时再简短解释。完成汇报先说明能做什么、哪些操作已实测和哪些仍待验证,修改文件与技术检查作为简短附录,最后按下方要求提示用户如何开始使用。
每次完成工作台开发后,最终回复必须以醒目的「接下来怎么用」三点提示收尾,放在所有修改说明、自测结果、文件链接和技术附录之后;不能只在开头提醒,也不能在这三点之后追加内容:
- 开发结果:用工作台实际名称说明已完成的开发和安装状态。只有确实完成开发并安装后才能说“已开发好并安装到本机”;未完成或安装失败时如实说明卡在哪里,不得声称已加载或全部验收通过。
- 如何重启:安装成功且需要重启时,请用户等当前任务结束后,点击顶部提示中的「立即重启」,或使用菜单「Harness → 重启 Harness」;通常只需重启 Harness,无需退出 DSH Desktop。只有重启 Harness 后仍未正常加载且排查确认需要时,才建议完整退出并重新打开 DSH Desktop。不得自行关闭或重启用户正在使用的应用;无需重启或安装未完成时如实说明,不把重启当作安装失败的解决办法。
- 去哪里打开:重启后,展开左侧栏,在左上角「工作台」右侧的当前名称/切换区域,选择刚制作的工作台(写出实际名称)。若没看到,进入「工作台市场 → 已安装」查找带「本地」标识的条目并检查运行状态,加载或启用成功后再切换。用户可以直接试用;如需继续验收,也可以回到原对话说「重启好了」,不必返回对话才能使用。安装未完成时明确此入口仍待安装和加载后确认。
需求确认(先于写代码):用渐进对话了解本次要做的工作台,每次只问一个会影响下一步的必要问题。先复用当前请求及已确认的上下文,不重复询问已提供的信息。名称未知时,先问“这个工作台想叫什么名字?”;可以使用暂定名,名称不应成为开工的阻碍。随后按已有信息补问目标使用者、主要功能或业务场景,不使用固定问卷,也不把多个问题塞进一次提问。用户不清楚核心流程时,根据回答提出一个最小流程建议,请用户确认或调整,不要求用户独立填全需求表。业务目标和最小实现范围已足够明确并经用户确认后即可开始,不必补齐每个形式字段。通用“开发指令”、目录名、已有代码或依赖不能自行当作开发意图。在业务意图或实现范围仍不清楚时,等待当前问题的回答;可以只读检查目录、版本、脚本和宿主能力,不创建或修改业务代码、界面或包文件,也不构建、打包、安装或投稿。
需求明确后,从项目读取名称、作者、版本、说明和测试命令,只询问无法查明且会影响实现的必要信息。开发请求本身不代表授权公开代码、商业数据或凭证。
开发前必须检查:
- 确认项目根目录、已有代码、未提交修改、包管理器、脚本和目标 Desktop 版本;不要覆盖别人的修改。
- 确认目标平台与架构,区分 JS/TS 包、外部程序和原生依赖。缺少宿主或工具链时明确说明,不能只凭构建通过就说能运行。
一页执行流程
- 确认需求:复用已确认的信息,每次只补问一个必要问题;名称可以暂定,流程可以先建议再确认。业务目标及最小范围足够清楚后开始,不要求填全表。通用指令或目录本身不算确认。
- 检查项目:确定项目根目录,运行
pwd、git status --short(若是 Git 仓库),查看已有代码、包管理器、未提交改动和目标 Desktop 版本;保留无关改动。 - 确定最小业务流程与布局:写下入口、主要动作、完成状态及失败恢复;按第 4 节明确选择标准分栏或
customFrame、首次无会话时的入口,再决定所需宿主能力。 - 实现:按第 3 节建立插件包和注册;第 4–7 节按责任及实际使用的能力落实。
- 包校验:运行
pnpm pack,检查 tarball 内package.json、声明的入口和cordis.patch.yml,检查大小和敏感文件。 - 本机安装实测:按 3.6 探测当前 Desktop 的安装能力、安装该 tarball、完成所需重启,并按第 8 节记录真实 UI 与加载证据。在目标 DSH Desktop 内开发时,按下方“同机重启边界”交给用户手动重启。
模型完成构建和包校验后,直接调用 install_local_workbench({ path: "<本机 .tgz 绝对路径>", replace: false }),内部统一使用 Plugin Manager 的 installBundle,无需用户填写路径或操作安装页面。更新用户已授权修改的同名工作台时传 replace: true。读取 application:applied 时直接核验界面,只有 restart-required 才提示用户重启 Harness;失败、取消和 overridden 不算已生效。
同机重启边界:Agent 不要自行关闭或重启 DSH Desktop、Harness,也不要用 ps、pgrep 等进程探测管理重启;请用户手动重启。用户重启 Harness 后,给用户两条可选路径:① 直接试用:展开左侧栏,点击左上角「工作台」右侧的当前工作台名称/切换区域,选择新工作台;若未显示,进入工作台市场的「已安装」检查条目和运行状态,加载或启用成功后再切换。新本地工作台加载后会自动加入切换菜单,不存在单独的「添加」按钮。② 继续 Agent 验收:回到原开发对话告诉 Agent「重启好了」,由 Agent 按第 8 节继续检查加载、已安装列表、切换入口和真实业务界面。用户可自行试用,不必返回对话;Agent 尚未实测的项目仍标为待验证,安装成功不能表述为全部验收通过。运行在目标应用之外的 Agent 可按正常重启流程操作。
空目录演练:目录为空且用户只粘贴通用“开发指令”或说“做个工作台”时,先复用对话中已有的信息。名称未知就只问“这个工作台想叫什么名字?”,并允许暂定名;下一轮再按回答补问一个最影响开发的业务问题,例如“它主要想帮你完成什么事?”。若用户已经说明用途,则跳过这类提问,根据现有信息建议最小流程并确认。可以只读检查目录与 Desktop 能力;业务目标及范围足够明确前,不创建包文件、业务代码或页面,也不构建、安装或投稿。不要把名称答复当作完整的业务需求。
2. 工作台是什么
一个工作台包同时是:
- 一个 npm 包:有
name、version,可以从本地目录或.tgz文件安装,上架后也可以从 npm 或 GitHub 安装。 - 一个 DSH 插件(bundle):
package.json声明dsh.bundle.patch,由cordis.patch.yml把服务端入口插入 Harness 的插件树。 - 一个 Desktop 工作台:客户端通过
desktopWorkbenches.register()注册业务面板。本地包省略repository时,Desktop 从真实调用方客户端 npm 包名派生稳定的本地身份;已有有效仓库身份仍保留。
同一个工作台有以下标识,职责不同,不能混用:
| 标识 | 在哪里 | 用途 |
|---|---|---|
| npm 包名 | package.json 的 name | 安装、依赖解析、cordis.patch.yml 的 name: |
| 插件条目 id | cordis.patch.yml 中 insert 行的 id | Harness 插件树中定位这一行 |
| 本地工作台身份 | 宿主根据真实客户端 npm 包名自动生成 | local:<npm 包名>,例如 local:my-workbench-package 或 local:@scope/name;侧栏入口和会话归属共用 |
| 仓库工作台身份 | 有效的 GitHub repository URL、市场条目 id 及既有归属记录 | 小写 owner/repository;已有身份保持兼容,市场卡片、侧栏入口和会话归属共用 |
| 兼容用旧 ID | 老包 register({ id })、旧目录 workbenchId | 仅迁移旧数据时使用;新包和新投稿都不填写 |
本地开发、安装和使用不需要 GitHub 账号、仓库 URL、创建仓库或上传代码,不得填写虚构或占位仓库。宿主使用真实客户端包来源,作者不要手工填写本地 ID。升级版本或移动项目目录不会改变本地身份;修改 npm 包名会生成新身份。日后上架不会自动迁移本地会话,也不会静默覆盖本地身份;必须明确设计并确认迁移,本规范不提供自动本地到市场迁移。
Desktop 将 GitHub owner 和 repo 规范化为小写,例如 https://github.com/Owner/Repo 对应 owner/repo。仓库改名或转移会改变工作台身份,需按迁移规则处理原有会话,不能仅改 URL。旧版 wb-owner-repo 只作为兼容映射,不是新包的注册 ID。
3. 包格式
3.1 目录结构
一个包只放一个工作台。典型结构:
package.json # npm 与 DSH 插件声明
cordis.patch.yml # 把服务端入口插入插件树
dsh/index.js # 服务端入口(exports["."])
lib/client.js # 已构建的客户端入口(exports["./client"])
README.md LICENSE
3.2 package.json
| 字段 | 级别 | 要求 |
|---|---|---|
name、version | 必须 | 普通 npm 字段,version 为完整 SemVer(如 1.2.0) |
"type": "module" | 建议 | 所有官方示例都使用 ES 模块 |
main 与 exports["."] | 必须 | 指向服务端入口,cordis.patch.yml 导入的就是它 |
dsh.bundle.patch | 必须 | 例如 "dsh": { "bundle": { "patch": "./cordis.patch.yml" } },路径相对包根目录。没有它,包只会被当作普通依赖安装,不会激活任何插件层 |
dsh.client.platform | 必须 | 固定为 "web",否则客户端模块不会被加载 |
dsh.client.inject | 必须 | 字符串数组,必须包含 dsh-desktop-workbenches,保证工作台服务先于你的客户端加载;用到其他客户端包时一并列出。这里只决定加载顺序,不是 Cordis 服务注入 |
exports["./client"] | 必须 | 声明了 dsh.client 就必须导出已构建的客户端文件,否则启动时报错 |
dsh.client.external | 可选 | 客户端需要 require 共享基线以外的模块(包括子路径)时列出;不能列自己 |
exports["./package.json"]、exports["./cordis.patch.yml"] | 建议 | 与官方包保持一致 |
files | 建议 | 必须把 cordis.patch.yml、服务端入口和构建产物包含进去 |
peerDependencies | 建议 | 官方 @deepseek-ai/* 包(如 @deepseek-ai/cordis、@deepseek-ai/dsh-client-connection)写在 peerDependencies,不要写在 dependencies,避免装进第二份宿主代码。版本范围要显式包含预发布分支,例如 ">=0.1.5-rc.2 <0.2.0-0",否则预发布版的 Harness 会被排除,安装时报 ERESOLVE |
@deepseek-ai/schemastery | 建议 | 服务端 Config 使用它定义;它是运行时依赖 |
license、author、description | 建议 | 真实填写 |
不要依赖未文档化的 dsh 字段(例如 dsh.client.inline),它们会被静默忽略。
3.3 cordis.patch.yml
文件是一个 YAML 数组。工作台通常只需要一条 insert:
- insert:
- id: my-workbench # 插件条目 id
name: my-workbench-package # 必须写 npm 包名,Node 才能解析到安装的代码
config:
root: !!js dshHomePath('my-workbench') # 可选:业务数据目录
- 必须:
name写包名,不写相对路径或绝对路径。 - 空文件或只有注释的文件会导致启动失败;不需要任何行时写
[]。 !!js表达式在启动时求值,可用dshHomePath()得到 DSH 数据目录下的路径。- 覆盖已有条目时,patch 会整体替换该行的
config,不会合并,需要保留的键要全部写上。工作台不应覆盖 Desktop 或其他插件的条目。
3.4 服务端入口
import Schema from '@deepseek-ai/schemastery'
export const name = 'my-workbench'
export const inject = ['connection']
export const Config = Schema.object({ root: Schema.string().required() })
export function apply(ctx, config) {
// 注册本工作台自己的本机接口,例如 /api/my-workbench/...
}
Config必须是 Schemastery schema,不能直接导出普通对象。- 本机接口放在自己的路径前缀下(如
/api/<工作台 id>/),不能占用 Desktop 或其他插件的路径。 - 需要判断会话归属时,注入内部只读服务
desktopWorkbenchOwnership并调用await read();不要从可见面板、旧预设或私有设置推断归属。 - 业务数据写在配置的数据目录或作者文档说明的位置;卸载工作台时不得删除用户数据。
3.5 客户端入口
客户端文件必须是已构建好的单文件模块,通过模块加载器注册:
window.__ModuleLoader__.load({
id: 'my-workbench-package',
factory: (require) => {
const React = require('react')
function BusinessPanel({ service, entry }) { /* 业务面板 */ }
function apply(ctx) {
ctx.effect(() => ctx.desktopWorkbenches.register({
title: '我的工作台',
description: '说明它解决什么问题'
}, BusinessPanel))
}
return { apply, inject: ['desktopWorkbenches'] }
}
})
require只能拿到共享基线(React、Cordis 等)、已加载的插件和dsh.client.external中列出的模块。其他依赖要在构建时打进客户端文件。register()必须提供title和业务组件;本地开发默认省略repository,由宿主从真实客户端 npm 包名生成local:<npm 包名>。新包不要填写register({ id })。有效的既有仓库归属仍使用owner/repo,来源冲突不能回退为另一个身份;旧包的id仅用于兼容迁移。- 仅在准备市场投稿并具备真实仓库时,另加
repository: 'https://github.com/your-org/your-workbench';它不是本地安装前置条件。不要因缺少repository跳过register()。 - 注册失败时,工作台管理显示包名、失败阶段和原因,控制台同时输出 warning;修复并重新加载成功后清除对应诊断。若客户端尚未执行或缺少依赖,仍须调查对应加载阶段,不能仅凭没有入口归因为身份失败。
workbench.json和投稿 YAML 的workbenchId不是新工作台的必填协议;运行时包名必须与window.__ModuleLoader__.load({ id })对应。- 可选注册字段:
description、panelTitle、icon、audience、requirements、layout(businessSide为left或right,businessWidth在 0.25–0.7 之间)、customFrame(布尔值,见第 4 节)、headerLayout(第 4 节)、initialization。 - 注册返回的函数用于注销,要交给
ctx.effect管理。
3.6 构建与本地安装
- 客户端文件必须是构建好的单文件,Desktop 不会替你构建。
- 先探测能力:记录 Desktop 版本、平台和架构,确认当前会话能发现
install_local_workbench工具。不能从文档发布日期推断旧版本已具备该工具。 - 模型完成构建和包校验后,直接调用
install_local_workbench({ path: "<本机 .tgz 绝对路径>", replace: false }),内部统一使用 Plugin Manager 的installBundle,无需用户填写路径或操作安装页面。更新用户已授权修改的同名工作台时传replace: true。读取application:applied时直接核验界面,只有restart-required才提示用户重启 Harness;失败、取消和 overridden 不算已生效。 - 工具遵循宿主插件管理权限:已具备完整权限时直接执行,否则走宿主现有审批。被拒绝时不得用 CLI 绕过。安装脚本审批仅使用
pendingBuilds返回的包名,并在明确授权后传approvedBuilds。仅旧版本没有该工具时,检查实际dsh plugin --help,可按其支持的方式使用dsh plugin add安装,并分别验证安装、所需重启和实际加载;不要调用不存在的 HTTP 安装接口。 - 工具与 CLI 均不可用或安装失败时,交付已校验的
.tgz,记录失败原因和未实测项,不声称加载成功。 - 需要运行安装或构建脚本时(pnpm 10 默认阻止),要明确知道每个脚本做什么,再单独授权。
4. 界面边界
工作台是一种面向具体工作场景的插件。本规范约束工作台、会话、工作区的关联关系和切换行为,不规定统一的业务面板设计。
工作台作者或用户可以定义业务面板的布局、内容、工具栏和业务操作。接入已有工作台时,优先复用原有界面和业务绑定流程,不要求加入统一顶部工具栏、会话下拉框、业务区折叠按钮或“通用聊天”按钮。
4.1 先按主任务选择布局
向用户建议时说:“建议先整页展示业务内容,需要时再打开 AI 对话;如果你的主要工作是和 AI 讨论,也可以边对话边查看辅助资料。”只确认这两种体验的取舍;下方 API 与布局参数由 Agent 实现,不作为用户确认项。
不要把常驻会话区当作所有工作台的默认产品设计。先向用户确认主任务;需求不明确时,在业务整页与对话分栏之间给出建议和取舍,再选择布局。技术上未声明 customFrame 仍使用标准分栏,但开发时应主动选择,而不是沿用这个默认值。
- 业务整页 + 按需会话(
customFrame: true):内容审核、装修管理、报表、看板或宽表格等以业务操作为主的工作台,优先建议先展示可用的业务首页。会话入口的位置和形式按业务需要决定,不要求每个工作台默认提供常驻入口或占据一块聊天区。只有用户主动选择 AI 协助时,才创建或恢复工作台会话并显示会话区;关闭后回到业务视图。需要原生会话时,把宿主传入的conversation节点放到合适的位置,不自行复制聊天界面。此模式不显示宿主通用无会话引导;工作台自行设计首次进入和无会话业务状态。不要在首次进入时自动创建会话来填充界面。 - 标准分栏:适用于对话本身是主任务,业务内容是状态、工具、资料等紧凑的伴随面板的场景。默认左侧是宿主原生会话,右侧业务面板占主内容区的 36%。可在
register()的layout中指定businessSide: 'left' | 'right'和businessWidth: 0.25–0.7;这是业务区所占比例,不保证业务组件的每一列都有足够空间。没有绑定到当前工作台的会话时,宿主会在会话区显示可选的 AI 协助引导;业务面板仍须可用,用户无需先创建会话即可完成可独立进行的业务操作。不要仅靠调大businessWidth把报表塞进分栏,导致另一侧引导或会话被挤压。
无论选择哪种布局,都要按业务内容容器的实际宽度设计响应式布局;整窗媒体查询不能代表侧栏展开、分栏及嵌入后的可用宽度。可用容器查询或测量业务根容器,在空间不足时让多列内容重新排布、折叠次要信息或允许有界滚动;长中文标题、英文标识、数字和操作按钮均应保持可读可用,避免单字竖排、按钮裁切和整页横向溢出。
市场、工作台切换和设置等公共入口由 DSH 保留,业务面板不得遮挡。使用 customFrame(见 3.5)的工作台必须限制在宿主分配的主内容区域内:根容器应按正常 flex 布局填满该区域;内部使用绝对定位、窗口最大化或拖拽换位时,都不得越过宿主容器的定位与裁剪边界,也不得覆盖 Desktop 左侧会话栏。原生会话由宿主提供的 conversation 节点放进业务布局,不能再创建一套聊天界面。原生会话能力与模式切换沿用 Desktop 的规则。
顶部布局:默认与紧凑
register() 的 headerLayout 可选值为 'default'(省略时默认)和 'compact';其他值注册失败。侧栏展开时保持工作台原布局,不新增空白行;宿主将既有顶部区域(--dsh-frame-top-clearance,通常 48px)中的非交互部分设置为拖动区域,并按实际控件矩形排除按钮、输入、菜单、iframe 与自定义 data-dsh-no-drag 区域。默认模式仅在 macOS 非全屏且侧栏收起时预留独立系统控件行,业务内容从该行下方开始,不依赖内部 <header> 的层级。Windows 使用独立标题栏;全屏时不额外占用此行。旧工作台不声明时采用默认模式。宿主不推断第一个 <header> 是工具栏,也不清除工作台自身的标题内边距。
紧凑模式可用于任何 customFrame: true 工作台,或 layout.businessSide: 'left' 的标准分栏工作台(无需设置 embedded):
ctx.desktopWorkbenches.register({
title: '业务工具',
customFrame: true, headerLayout: 'compact'
}, BusinessPanel)
// BusinessPanel 渲染的同一文档中,唯一一行工具栏:
React.createElement('header', { 'data-dsh-workbench-toolbar': '' },
React.createElement('span', null, '业务工具'),
React.createElement('button', { onClick: refresh }, '刷新'))
普通左侧分栏仍保留侧边与底部的业务间距;仅有效紧凑模式取消顶部间距,工具栏以 sticky 保持在顶部,正文可滚动。工具栏祖先必须覆盖正文高度,不得另加顶部 margin/padding 或独立滚动容器。
标记工具栏必须位于面板顶部、占满宿主可用宽度,可嵌套在容器中。普通左侧分栏的右侧会话使用既有顶部空白作为拖动区域,不新增独立行;customFrame 的工具栏必须跨整个自定义框架宽度,不能仅覆盖业务子栏,右侧空白的拖动由这条全宽工具栏提供。宿主仅为这一行设置最低高度和左侧控件避让,空白可拖动;按钮、链接、表单控件及标准交互 role 排除拖动。自定义交互区、展开菜单和弹层加 data-dsh-no-drag。宿主内部标记 data-dsh-compact-toolbar 和 data-dsh-compact-valid 不得由工作台设置。不要自行重复系统控件 padding 或 drag/no-drag 整体覆盖规则。
标记缺失或不唯一、右侧分栏不满足共享位置条件时,安全回退默认系统控件行。iframe 内部 DOM 不属于此协议;包含 iframe 的工作台可将唯一工具栏放在同一文档的外部容器,不能标记整个 iframe 来充当可拖动顶栏。工具栏按业务容器宽度重排;长标题缩略、次要描述放在下一行或正文,按钮不得压成不可用尺寸。
验收两种模式:侧栏展开/收起、窄容器、中英文长标题、全屏进入/退出,确认无双重留白或控件遮挡;点击按钮、编辑输入、打开菜单和键盘焦点正常;实际拖动空白移动窗口。DOM/CSS 校验不能替代原生窗口拖动验收。
旧工作台迁移与兼容边界
这是显式选择协议:宿主不能同时保证任意旧 DOM 不被系统控件遮挡,并自动保留所有旧紧凑布局。未迁移工作台仍可加载,采用默认安全布局;仅 macOS 非全屏且侧栏收起时默认布局增加独立控件行;侧栏展开保持原布局。
| 当前工作台 | 迁移操作 | 迁移前行为 |
|---|---|---|
| 标题与介绍等默认业务布局 | 可保持不声明;核对并移除工作台自行添加的系统控件避让,保留正常业务 padding | 展开保留原布局;收起使用独立系统控件行 |
| 希望共享顶栏的 customFrame 或左侧分栏 | 在注册信息声明 headerLayout: 'compact',在同一文档标记唯一的 data-dsh-workbench-toolbar,移除重复的控件避让 | 展开保留原布局;收起使用独立系统控件行,不猜测工具栏 |
| 工具栏在 iframe 中、右侧分栏或多个标记 | 将单一工具栏移到支持的同一文档位置,或保持默认布局 | 安全回退默认布局 |
迁移只通过公开注册字段和工具栏标记,不使用工作台名称白名单或语义 header 自动识别。外部工作台的维护者须自行发布迁移版本;宿主升级不修改已安装的外部包。普通左侧分栏仅在有效紧凑声明下取消宿主的顶部 18px 间距,默认模式和工作台自身的 header padding 保持原值。
5. 工作台、会话与工作区
- 一个工作台可以关联多个会话,每个会话最多归属一个工作台。
- 工作区是 DSH Desktop 的项目资料环境;每个会话如绑定工作区,最多绑定一个工作区。同一工作区内的不同会话可以属于不同工作台。
- 一个工作台可以处理多个工作区,不同工作台也可以使用同一个工作区。
- 工作台内部的档案、业务项目不等同于 DSH 工作区,不要求重复绑定。例如,玄学档案和选址项目继续使用各自原有的创建、选择流程。DSH 工作区目录是用户资料位置,不因打开或创建业务项目而自动归属某个工作台。
6. 未绑定会话时的使用
打开工作台后,即使没有会话或工作区,也应立即显示业务面板。浏览、创建、选择业务档案或项目,不得以已有原生会话或工作区为前提。
仅当用户执行向 Agent 发起请求、写入会话草稿等依赖会话的操作时,才检查当前会话是否属于该工作台。尚未绑定时,在该操作处引导创建或打开会话,不阻断其他业务功能。
工作台内部应提供“在此工作区新建工作台会话”或“选择资料位置并开始工作台会话”等明确动作。业务项目本身不需要文件系统时可以先创建业务记录;一旦需要保存文件或创建 DSH 工作区,必须先调用宿主目录选择器,由用户选择已有目录或在系统选择器中明确新建目录。工作台不得在默认位置、用户主目录、当前仓库或其他推测路径中静默创建文件夹。确认位置后再创建工作区和会话、登记归属、保存业务关联并填入开场草稿;取消时不得留下目录、空项目、工作区、会话或绑定。已有业务资料只能恢复用户此前确认的位置;位置不存在时重新选择,不得自动创建同名目录。失败时保留可重试状态,不得默默改用无关工作区。
先选择业务档案或项目,再创建第一条会话时,应保留当前业务选择。打开已有会话时,优先恢复该会话已有的业务映射,不被其他会话最近选择覆盖。
接入已有工作台时保留原有的项目创建引导和独立业务流程。用户无需先手工新建会话;工作台通过 Desktop 接口发起创建或恢复,由宿主校验并登记归属。开场草稿保留用户已输入的内容并由用户发送;创建失败或延迟时保留草稿供重试。自动执行的业务流程必须在正确归属的会话中运行,不能与开场草稿混用,也不能由隐藏工作台触发误发送。
7. 模式入口与切换
宿主在侧栏顶部提供单一模式切换器:按钮只显示当前模式,展开后可在“原生会话”和已添加工作台之间切换;“工作台管理”入口常驻最右侧。工作台不得复制、遮挡或替换这些公共入口。切换模式只改变前台展示和会话筛选,不执行卸载重装,也不停止后台任务。
“原生会话”和各工作台是平行模式,当前模式决定可见会话和新建归属:
- 工作台模式:只显示当前工作台的会话。“新建会话”或切换工作区时,只能打开当前 owner 的会话;目标工作区没有时创建新的 owner 会话,并在显示前持久化归属和最近会话。不得复用、收编或改绑普通会话及其他工作台会话。
- 原生会话模式:只显示未绑定会话。“新建会话”或切换工作区时,只能打开未绑定会话;目标工作区没有时创建一条。不得根据同一工作区中的工作台会话推断或切换工作台。
显式打开未绑定会话时切换到“原生会话”;显式打开已绑定且 owner 可用的会话时切换到对应工作台。owner 已移除、卸载或不可用时按普通会话处理,不自动唤起或重装。异步创建期间如果用户继续导航、切换模式或移除 owner,不得把界面拉回旧模式、覆盖后续选择或绑定到失效 owner。
切换模式不得自动收起或展开左侧会话栏;侧栏状态由用户控制并在模式间保持。工作台会话标题前显示所属工作台的小图标,普通会话不显示;图标只表示归属,并提供可访问名称或提示。折叠态与展开态中的按钮、菜单、选中态和焦点轮廓都不得裁切、重叠或溢出。
首次进入工作台可以显示首页、空会话状态或按工作台约定初始化会话,但业务面板不能依赖会话初始化完成。后续进入恢复该工作台最近会话。导航和切换不得删除会话、业务资料、项目文件、收藏或笔记。
8. 本地自测清单
验证省略 repository 的本地包(包括 scoped npm 包名):安装加载后出现带「本地」标识的条目和切换入口,业务面板可打开;重载或版本更新后身份及会话归属稳定。另验证注册失败时工作台管理显示包名、阶段和原因,修复重载后诊断消失。模块 HTTP 200、导入成功和测试通过均不能替代真实 UI 验收。
开发完成后按责任逐项确认。“宿主负责”是对当前 Desktop 能力的观察和问题反馈,插件作者不得为此复制宿主界面;标为“仅使用该能力时适用”的项,不使用时记“不适用”及原因。全部适用项有证据通过,才能称为本机自测通过。
包与加载
- 插件负责:第 3 节全部“必须”项通过。运行
pnpm pack,用tar -tzf <产物.tgz>核对package.json、服务端和客户端入口、cordis.patch.yml;从该产物安装,而非只从源码启动。 - 插件负责:按 3.6 安装并完成所需重启;若 Agent 在目标 DSH Desktop 内运行,由用户点击顶部提示中的「立即重启」,或使用菜单「Harness → 重启 Harness」,用户选择继续 Agent 验收并确认重启后再实测;自行试用不要求返回对话。
dsh --profile web --dump-config中找到本包插件层,在 Desktop 工作台市场的“已安装”找到条目,再从左侧入口打开业务面板。分别记录配置、列表和真实界面证据;重启前这些加载与界面项目保持待验证。
第 4 节:界面边界
- 插件负责:打开业务面板,缩放窗口并切换原生会话/工作台,确认面板不遮挡侧栏、市场和管理入口;键盘可到达业务操作。
- 插件负责:分别在首次进入且无工作台会话、打开已关联会话时,检查业务入口与会话相关操作。标准分栏要检查宿主通用引导与业务面板并列时的阅读和操作;
customFrame要检查自己提供的首次使用和无会话入口。 - 插件负责:在侧栏展开、收起及较窄窗口下,用真实长度的中英文标题、标识、数字和按钮检查业务区;不得出现单字竖排、关键控件裁切或整页横向溢出。按业务容器宽度验证多列内容的重排,而非只按整窗宽度判断。
- 仅使用该能力时适用,插件负责:若使用
customFrame,缩窄窗口并操作布局、弹层和拖拽,确认都在宿主主内容区域内;使用原生会话时确认宿主提供的conversation节点可用。
第 5–6 节:工作区与会话
- 仅使用该能力时适用,插件负责:业务流程需要创建文件或工作区时,从业务入口触发宿主目录选择器;取消后核对没有新目录、空项目或绑定,确认后核对文件只在所选位置。原目录丢失时验证重新选择和失败恢复。
- 仅使用该能力时适用,插件负责:业务操作要给 Agent 发送或写会话草稿时,先在无会话状态打开面板,确认非会话功能可用;发起依赖会话的操作时创建/恢复本工作台会话,草稿由用户发送,切换已有会话后恢复其业务选择。
- 宿主负责,插件配合核验:在同一工作区分别创建原生会话和两个工作台会话;从侧栏逐个打开,核对各会话只属于一个 owner,项目资料不因模式切换被搬移。
第 7 节:模式切换与保留
- 宿主负责:用侧栏顶部模式切换器在“原生会话”和各工作台间切换,核对只显示对应会话,工作台图标、管理入口、焦点和折叠状态正确;切换工作区、新建会话后再核对归属。异常时记录 Desktop 版本和复现步骤,不能由插件私自改写宿主状态。
- 宿主负责,插件配合核验:关闭重开、卸载后检查已有会话、项目文件、草稿、笔记和收藏仍在原位置;安装/卸载动作与数据保留分别记录。
- 插件负责:记录 Desktop 版本、操作系统、架构、包版本、执行的 UI 路径及未验证项;无法安装时按第 9 节交付,不能勾选安装后的项目。
9. 失败时如何交付
最终必须列出真实结果和证据:修改的文件、包版本、本机安装与自测结果、未验证的项目。缺哪一项就写哪一项,不虚构成功。缺少工具链、安装失败或宿主接口不可用时,保留已完成的代码,说明原因和下一步。
参考
- DSH 插件打包与发布:deepseek-harness 仓库
docs/user/develop/basic/publish.md、config.md;包清单类型@deepseek-ai/dsh-package-manifest;客户端模块加载@deepseek-ai/dsh-client-modules。 - 上架到工作台市场:《工作台市场验收规范》:https://dshdesktop.com/workbench/docs/market-acceptance/ 。