← 返回列表
需源码安装
让 DeepSeek Harness 的 工作区Workspace 按「最近使用」排序的宿主Host插件。
暂不能直接安装(需源码编译或环境不满足):仓库 package.json 标记 private,未发布到 npm,需从源码安装。 · 最近上游提交 2026/9/19 · 已提供中文文档
让 DeepSeek Harness 的 **工作区(Workspace)** 按「最近使用」排序的宿主(Host)插件。 侧边栏自带的「排序方式:手动排序 / 最近更新」只作用于**会话**;工作区分组的顺序永远是 Host 注册表的持久顺序。本插件让最近有活动的那个工作区排到最前面。
综合分
30.4
GitHub 分
30.4
用户评分
—
★ Stars
1
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add karottc/dsh-plugin-workspace-sorted仓库 package.json 标记 private,未发布到 npm,需从源码安装,改用 GitHub 源安装
信任档位:已验证本站已于 1 天前真实安装成功
- 是什么
- dsh 原生插件 · market
- 装得上吗
- 本站已真实安装成功(非静态推断)
- 安全吗
- 本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
- 还在维护吗
- 活跃:最近一次提交在 6 天前
档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →
🟢实装验证通过· 2026/9/24
由本站实装验证器在真实 dsh 环境安装成功,非静态推断。
数据截至 2026/9/23(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查需源码安装
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包dsh-plugin-workspace-sorted(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
仓库 package.json 标记 private,未发布到 npm,需从源码安装
验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/23 21:24:37
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
由 DeepSeek 最新模型翻译生成dsh-plugin-workspace-sorted 让 DeepSeek Harness 的 工作区(Workspace) 按「最近使用」排序的宿主(Host)插件。 侧边栏自带的「排序方式:手动排序 / 最近更新」只作用于会话;工作区分组的顺序永远是 Host 注册表的持久顺序。本插件让最近有活动的那个工作区排到最前面。 为什么需要它 三条来自 DSH 0.1.5-rc.2 源码的事实决定了实现方式: 1. @deepseek-ai/dsh-client-ui-workspace 的 deriveGroups() 接收 real workspaces in stable Host order——工作区分组顺序就是 ctx.workspaceRegistry.list() 的顺序,与会话排序选项无关。 2. Host 侧只有 workspaceRegistry.insertBefore(id, beforeId?) 能改变这个顺序 (ctx.workspaceController.insertBefore 是它的 Remote 封装),而新建工作区只是 prepend,会话活动从不重排工作区。 3. 浏览器端没有可用的排序扩展点:ui-workspace 的 /client 只导出 apply/inject 与类型,WorkspaceBrowser 组件是包内私有的,workspaces 这个 root hook 也已被它占用。要加 UI 选项只能整体替换 sidebar.workspaces 席位(约 2800 行 UI)。 因此唯一受支持的接缝是 Host 注册表本身,本插件就驱动它。 排序语义 与客户端为「新会话」挑选最近活跃工作区的逻辑(ui-workspace 的 recentWorkspace())完全一致: - 工作区的活跃时间 = 其成员会话中最大的活跃时间; - 没有任何成员会话时,回退到工作区自己的 createdAt; - 排序为活跃时间降序,同分保持当前注册表位置(不会来回抖动)。 Host 侧一条会话的活跃时间是 max(header.createdAt, sessionListMetadata.lastPromptAt)——也就是侧边栏会话行上 显示的那个相对时间。所以「最近使用」看的是用户真正发过 prompt 的时间, 而不是任何一次后台事件。 数据来源: | 来源 | 作用 | | --- | --- | | ctx.sessionController.list()(可选服务,经 ctx.inject 等待就绪) | 启动时播种,保证刚装好的首次启动就是正确顺序 | | session/created | 在该工作区新建会话 = 使用了它 | | session/event 且 type === 'user/message' 且 source.kind === 'user' | 用户真正发 prompt | 事件只记录会话级时间戳,归属到哪个工作区是在 debounce 之后、 reconcile 时通过 workspace.sessionIds 惰性解析的——因为 attachSession() 是在会话发布之后才执行的。 安装与激活 插件包是两层结构,两者缺一不可,且激活行只能声明在其中一个层里。 1) 安装 本包以源码仓库形式分发(未发布到 npm registry)。克隆到本机后,在本包所在 目录执行: git clone dsh-plugin-workspace-sorted cd dsh-plugin-workspace-sorted dsh plugin --profile web add link:. dsh plugin 在转发给 pnpm 之前会把 link:. 解析成该目录的绝对路径,因此 README 与包本身都不需要、也不应该写死任何本机路径——这份文档可以直接给别人用。 也支持让 dsh 直接从 git 安装(本包没有 prepare 构建步骤,所以不会被 pnpm 的构建白名单挡住): dsh plugin --profile web add github:/ 2) 激活 在 profile 自己的 ~/.dsh/profiles/web/cordis.patch.yml 里声明这一行: - insert: - id: workspace-sorted name: dsh-plugin-workspace-sorted config: enabled: true debounceMs: 1500 countSessionCreation: true includeSubagents: false verbose: false 为什么激活行不放在包的 patch 里 loader 会拒绝一份 id 重复的组合结果: TypeError: duplicate loader entry id: workspace-sorted (cordis-plugin-loader, EntryTree.update) 这个 reject 发生在 Include 的初始化里,会直接让整个 profile 启动失败。 applyEntryPatches() 的 insert 只是 data.push(...insert),不做去重, 所以同一 id 在两个层各 insert 一次必炸。 于是形成一条硬约束: | 激活行放在哪 | 下次重启 | 不重启热加载 | | --- | --- | --- | | 包的 cordis.patch.yml | ✅ | ❌ bundle 列表是启动时读的 | | profile 的 cordis.patch.yml | ✅ | ✅ patchReload: live 会重放这一层 | 本插件选择了后者:包的 cordis.patch.yml 故意是 [],激活行由 profile 层声明。 这样改一行就能热加载/热卸载,且下次重启仍然只有一份 id。 (如果更想要「装完即生效、必须重启」的自包含形态,把那一行搬回包的 cordis.patch.yml 即可——但两层不能同时声明。) 配置 patch 会替换整份 config,所以要保留的键必须全部重写: - id: workspace-sorted config: enabled: true # 总开关;false = 完全交回手动拖拽 debounceMs: 1500 # 活动合并窗口(50–60000) countSessionCreation: true # 新建会话是否算「使用了该工作区」 includeSubagents: false # 侧边栏隐藏的 subagent 会话是否参与 verbose: false # 每次实际重排写一条 info 日志 日志走 ctx.logger(DSH 官方约定)。默认的 dsh web 组合只把日志写进 Cordis 内存缓冲区,终端不打印;只有在组合里注册了 logger exporter (ctx.logger.exporter(...))时才会看到这些行。 验证 在本包所在目录下执行: node --test # 20 个用例 node tools/preview.mjs # 只读 dry-run:当前顺序 vs 目标顺序 vs 计划移动数 dsh --profile web --dump-config | grep -c '^- id: workspace-sorted$' # 必须是 1 tools/preview.mjs 读取真实的 ~/.dsh/storages/workspace.json 与 session_projcache/,跑的是插件里同一份纯函数,不写任何东西。 已完成的实测记录 - 单元 / 框架层(20/20 通过):排序算法、插件生命周期,以及两个跑在真实 Cordis 上的集成用例——在真实 root context 上挂载插件、解析 inject、 通过真实事件总线 emit 触发重排,以及 ctx.inject(['sessionController']) 在服务后于插件提供时仍能触发启动播种。 - 真机端到端:在隔离的 DSH_HOME(建在用户目录下而非系统临时目录—— macOS 的临时目录是一条符号链接,会让 HMR 的路径匹配失效)里启动真实 dsh web,预置一份故意写反的注册表 ['older','newer'],然后 在宿主运行中把激活行追加进 profile patch。观察到的宿主日志: [spy info] workspace-sorted: Workspace order will follow most-recent activity [spy info] workspace-sorted: startup seed took 0 Workspace timestamp(s) from 0 Session(s) [spy info] workspace-sorted: reordered 1 Workspace row(s) -> bbbb… > aaaa… 随后 workspace.json 落盘顺序变为 ['newer','older']。这同时证明了 热加载激活、真实宿主内加载、以及真实的持久重排三条链路。 - 重启安全:dsh --profile web --dump-config 中 ^- id: workspace-sorted$ 计数为 1,即两个 patch 层没有重复 id。 设计约束 - 零运行时依赖:lib/index.js 不 import 任何包,只与传入的 Cordis context 交互,因此作为 profile bundle 层加载时不存在自身模块解析问题。 - 尽力而为、绝不伤主流程:两个事件监听器各自吞掉自己的异常—— session/created 是同步派发的,在那里抛异常会否决会话创建。 - 空闲零写入:推导顺序与当前注册表顺序一致时直接返回,不调用 insertBefore。所以「一直待在一个工作区里」不会反复写盘,安装瞬间 也不会产生任何写盘(本机首次 dry-run 就是「计划移动 0 次」)。 - 拖拽会被覆盖:这是「按最近使用排序」的必然代价。enabled: false 或卸载插件即可恢复纯手动排序。 卸载 / 回滚 1. 删掉 profile patch 里的那一行(热卸载,立即生效); 2. 可选:dsh plugin --profile web remove dsh-plugin-workspace-sorted。 两种方式都不会删除任何工作区、目录或会话;唯一被改动的持久数据是注册表里的 工作区顺序,而顺序本来就可以手动拖拽。