DeepSeek Harness 插件:侧栏工作区文件夹分组与会话移动 · Workspace folders and…
30.4/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/25 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add ayachinene285/dsh-session-move该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · browser
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 13 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件发起外部网络请求
查看扫描证据(共 32 处,展示前 25 条)
- 发起网络请求lib/client.js:107
const response = await fetch(API + "?view=folders", { headers: { accept: "application/json" } }); - 发起网络请求lib/client.js:113
const response = await fetch(API, { - 发起网络请求lib/client.js:394
fetch(API + "?sessionId=" + encodeURIComponent(sessionId), { headers: { accept: "application/json" } }) - 发起网络请求lib/client.js:437
fetch(API, { - 发起网络请求lib/client.js:460
fetch(API, { - 读取本地文件lib/engine.js:187
workspace.missing = (await fsp.stat(workspace.path)).isDirectory() !== true; - 读取本地文件lib/engine.js:209
const existed = await fsp.stat(raw).then((value) => value.isDirectory(), () => false); - 写入本地文件lib/engine.js:210
if (!existed) await fsp.mkdir(raw, { recursive: true }); - 读取本地文件lib/engine.js:211
const canonical = await fsp.realpath(raw).catch(() => { - 读取本地文件lib/engine.js:295
const stat = await fsp.stat(target).catch(() => undefined); - 写入本地文件lib/engine.js:304
await fsp.mkdir(target, { recursive: true }); - 读取本地文件lib/engine.js:305
const after = await fsp.stat(target).catch(() => undefined); - 读取本地文件lib/engine.js:321
const real = await fsp.realpath(cwd).catch(() => undefined); - 删除本地文件lib/engine.js:389
await fsp.rm(file, { force: true }); - 写入本地文件lib/engine.js:392
await fsp.mkdir(dirname(file), { recursive: true }); - 写入本地文件lib/engine.js:393
await fsp.writeFile(file, JSON.stringify({ version: 1, items }, null, 2) + "\n", "utf8"); - 写入本地文件lib/engine.js:495
await fsp.mkdir(moved.fromDir, { recursive: true }); - 写入本地文件lib/engine.js:496
await fsp.writeFile(moved.fromFile, moved.original); - 删除本地文件lib/engine.js:497
await fsp.rm(moved.toFile, { force: true }); - 删除本地文件lib/engine.js:498
await fsp.rmdir(moved.toDir).catch(() => {}); - 删除本地文件lib/engine.js:575
await fsp.rm(fromFile); - 删除本地文件lib/engine.js:576
await fsp.rmdir(fromDir).catch(() => {}); - 读取本地文件lib/folders.js:81
return normalize(JSON.parse(await fsp.readFile(storeFile(persistence), "utf8"))); - 写入本地文件lib/folders.js:89
await fsp.mkdir(dirname(file), { recursive: true }); - 写入本地文件lib/folders.js:90
await fsp.writeFile(file, JSON.stringify(state, null, 2) + "\n", "utf8");
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
README
由 DeepSeek 最新模型翻译生成dsh-session-move
DSH 的侧栏只有「工作区(目录)」这一层,也没有把会话挪到别的工作区的接口。这个插件补了这两块:
- 在工作区上面加一层文件夹。纯虚拟的,能嵌套,能放多个工作区,磁盘上不建任何目录;
- 会话可以在工作区之间搬,搬完以后这条会话里跑的东西都在新目录下。
代码分两块。lib/index.js 跑在 DSH 的本地服务进程里,负责读会话文件、改 cwd、开一个本地接口;lib/client.js 是网页里的部分,负责侧栏、菜单和弹窗。
安装
1. clone 或者下载这个仓库到任意目录;
2. 装进 profile:dsh plugin --profile <profile 名> add <插件目录>。桌面版的 profile 由应用自己管理,命令被拒的话,在「插件」页里装,或者手动把 dsh-session-move 加到 profile 的 package.json 里 dsh.profile.bundles 下;
3. 完全退出 DSH 再打开。改插件不是刷新页面就能生效,界面和后台都要重新加载。
用法
会话行右边的「…」里有「移动到工作区 / 文件夹…
展开完整文档(README 剩余 1 节)
dsh-session-move
DSH 的侧栏只有「工作区(目录)」这一层,也没有把会话挪到别的工作区的接口。这个插件补了这两块:
- 在工作区上面加一层文件夹。纯虚拟的,能嵌套,能放多个工作区,磁盘上不建任何目录;
- 会话可以在工作区之间搬,搬完以后这条会话里跑的东西都在新目录下。
代码分两块。lib/index.js 跑在 DSH 的本地服务进程里,负责读会话文件、改 cwd、开一个本地接口;lib/client.js 是网页里的部分,负责侧栏、菜单和弹窗。
安装
1. clone 或者下载这个仓库到任意目录;
2. 装进 profile:dsh plugin --profile <profile 名> add <插件目录>。桌面版的 profile 由应用自己管理,命令被拒的话,在「插件」页里装,或者手动把 dsh-session-move 加到 profile 的 package.json 里 dsh.profile.bundles 下;
3. 完全退出 DSH 再打开。改插件不是刷新页面就能生效,界面和后台都要重新加载。
用法
会话行右边的「…」里有「移动到工作区 / 文件夹…」,弹窗里选目标:
- 选工作区:真的搬过去,会话的工作目录会改成那个目录;
- 在文件夹那一行点「把会话放这里」:只在侧栏归组,工作目录不动;
- 会话已经在某个文件夹里时,弹窗最上面多一行「移出文件夹」,点它回到工作区下面;
- 也可以直接填一个新目录,插件会把它登记成新工作区。
同一条会话可以反复搬。已经在目标工作区、会话正在跑、子代理会话,这几种情况会直接给提示,不会动数据。目标目录不存在时,默认先按同名建一个空目录再搬,弹窗里可以把这个行为关掉。
文件夹分组
侧栏右上角「+」可以新建文件夹,不用选本地目录。文件夹能装文件夹,也能装任意多个工作区;工作区本身不能当父级。
工作区行的「…」里有「移入文件夹…」和「不放入文件夹(顶层)」。文件夹行的「…」里有新建子文件夹、重命名、移入其它文件夹、删除。删除只是解散这个文件夹,里面的东西上移一层。
「+」→「新增工作区(选择本地目录)」还是官方的选目录流程;文件夹的「…」里也有「新建工作区(选目录后放进这里)」,建完自动放进去。
展开状态记在浏览器 localStorage 里,默认展开,点行首的箭头收放。
会话可见性跟官方一致:已归档的会话默认隐藏(工作区「…」→「显示已归档的会话」可以切,这个开关跟官方和归档管理插件共用一份状态),子代理会话不显示,不是当前会话的空会话不显示。没归进任何工作区的会话放在最后「未分组」里。
会话也能直接放进文件夹,只动侧栏分组:会话「…」→ 移动到工作区 / 文件夹… → 在文件夹那一行点「把会话放这里」。放进去之后它只在文件夹下面出现一次,不会再重复出现在所属工作区里;想放回去用「移出文件夹」。
会话移动是怎么做的
DSH 判断一条会话属于哪个工作区,看的是会话自己记录的工作目录:
- 挂载会话的时候,DSH 拿会话文件里的 cwd 跟工作区路径比对,不一致就拒绝;
- 会话文件在磁盘上的位置也由这个 cwd 推出来,位置和记录对不上会被当成坏会话;
- 官方没有提供移动会话的接口。
所以插件分两步做完:
1. 改数据:重写会话文件第一个 zstd 帧里记录的 cwd,把会话目录搬到新 cwd 对应的项目目录下,正文逐字节不动。写完马上自检,失败就回滚。
2. 重新挂载:让 DSH 按磁盘现状重新读一遍这条会话,挂到目标工作区,从旧工作区摘掉,然后马上放掉,不长期占内存。
移动完不需要重启 DSH,也不用手工改 workspace.json,归属由 DSH 自己写。
冷会话和打开着的会话
一条会话只要被打开过(在对话页看过、聊过),DSH 的进程就会一直留着它,并且握着会话文件的写入权,官方没有关掉它的接口。所以:
- 没打开过的:点一下就好,不用重启;
- 打开着但空闲的:这时候改不了文件,插件把这次移动记成待办,下次 DSH 启动时(那时会话都是冷的)自动做完。待办存在 <DSH 数据目录>/storages/session-move-pending.json。重放失败不会把记录删掉,失败原因写进 lastError,下次启动继续试,弹窗顶上也会显示上次为什么没成;
- 有回合在跑的:直接拒绝,等它跑完再搬。
工作区目录不存在时
工作区的目录如果在 DSH 外面被删了或者改了名,DSH 就解析不出会话记录的 cwd,会话会在侧栏掉进「未分组」,工作区的会话数变成 0,往那里搬也只会得到一句「目标目录不存在」。
现在弹窗会把它标出来(行尾写「目录不存在」,选中后下面显示完整路径),并且默认直接修:
- 点「移动」就行,插件先按同名把空目录建出来,再搬会话,然后把归属补上。补归属的时候会顺手让 DSH 重新解析一次 cwd,所以不用重启就能在侧栏看到;
- 不想让它建目录,把弹窗里的「目录不存在时自动新建同名目录」取消掉,那样会直接报错;
- 如果目录只是改了名,别让它建空目录,用下面的「移动到新目录」填真正的路径,会自动登记成新工作区。
重启后重放的待办也按「目录不在就先建」处理。
本地接口
后台只加了一个本地接口,不替换官方任何东西:
| 方法 | 路径 | 说明 |
| GET | /api/dsh-session-move?sessionId=<id> | 工作区列表、这条会话的归属、它的待办移动 |
| POST | /api/dsh-session-move | { action: "move", sessionId, workspaceId 或 targetPath, title?, createMissingDir? } |
写请求只接受本机同源调用,会校验 Origin、Host 和 Sec-Fetch-Site。
配置
package.json 的 dsh.client 指向界面部分的入口,cordis.patch.yml 只有一条 insert,不禁用官方任何入口。
- insert:
- id: dsh-session-move
name: 'dsh-session-move'
开发时踩过的坑
- 改了界面部分也要完整重启 DSH。DSH 会给每个界面模块按文件内容算一个版本号,并且按 immutable 缓存;只刷新页面的话,页面会拿着旧的版本号去取,被后台拒掉,表现可能是「插件加载失败」,严重的时候应用起不来。
- 不要直接读没声明依赖的 ctx.xxx。Cordis 里访问没声明的服务属性会直接抛异常,取可选服务用 ctx.get("xxx")。
- 注册类调用都要自带 try/catch,包括路由、快捷键、槽位注册。界面部分初始化时抛错,DSH 会判定 entry did not activate,弹启动失败并提示禁用第三方插件。
- 同理,插件对外注册的地方都做了兜底,最坏情况只是这个功能不可用,不会连累 DSH 启动。
已知边界
- 移动会改会话的工作目录,之后这条会话里的工具调用都在新目录下跑;历史记录里的旧路径不会改写。
- 有回合在跑的会话不能移动。
- 只处理官方的 JSONL 存储(session-persistence-jsonl,日志格式 v4),别的后端会因为没有 locate() 被拒。
- 已经归档的会话也能移动(归档集合按 id 全局存),但它在侧栏里还是显示为归档。
- 恢复会话时 DSH 会追加一条 session/end-seed 事件,这是官方的恢复标记,不影响历史内容。
卸载
从 profile 的 dsh.profile.bundles 里删掉 dsh-session-move,执行 dsh plugin --profile <name> remove dsh-session-move,然后完整重启 DSH。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
ayachinene285/dsh-session-move
DeepSeek Harness 插件:侧栏工作区文件夹分组与会话移动 · Workspace folders and…
相关插件 · 浏览器
智能体插件框架deepseek-ai/deepseek-harness
DeepSeek Harnessdsh是由 DeepSeek AI 开发的开源 agent harness智能体框架。
★ 270,422已汉化DSH
71.9
多设备 Agent 看板YaoApp/yao
✨ 所有 Agent 和工作区集中管理,覆盖你的每一台设备。任务看板追踪进度,桌面端、移动端、浏览器、API…
★ 8,147已汉化DSH
71.2
可扩展侧边栏工作台omdsh-dev/DSH-better-sidebar
DSH 的双工作台:原生右侧栏 + 自绘底部面板,并把 ctx.betterSidebar 服务开放给所有插件
★ 4,761已汉化DSH
71.1
浏览器自动化桥Tencent/BrowserSkill
你的 Agent。你的浏览器。连接,就能协作。
★ 9,967已汉化DSH
71
AI 小说创作工作台EthanYoQ/AI-Novel-Writer
AI 小说作家 / AI Novel Writer
★ 1,591已汉化DSH
70.7
智能体浏览器引擎platonai/Browser4
DeepSeek Harness 集成
★ 1,175已汉化DSH
70.4
这是你的仓库?认领条目