🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

工作区整理器 dream-fish69/dsh-session-workspace-organizer

DeepSeek Harness
dream-fish6911 天前有提交已提供中文文档扫描:含敏感能力

迁移工作区目录并让每个会话拥有独立输出文件夹

30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/24 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dream-fish69/dsh-session-workspace-organizer
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
dsh 原生插件 · other
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
数据截至 2026/10/25·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/03·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 11 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 108 处,展示前 56 条)
  • 写入本地文件
    index.js:187
    await rename(sourceFile, targetFile)
  • 删除本地文件
    index.js:194
    await rm(sourceFile, { force: true })
  • 读取本地文件
    index.js:223
    for (const name of readdirSync(join(home, 'profiles'))) {
  • 读取本地文件
    index.js:225
    if (existsSync(join(candidate, 'node_modules', 'dsh-session-workspace-organizer', 'package.json'))) {
  • 读取本地文件
    index.js:354
    resolved.push(await realpath(path))
  • 读取本地文件
    index.js:374
    canonical = await realpath(path)
  • 写入本地文件
    index.js:399
    void mkdir(dirname(pendingPath), { recursive: true })
  • 写入本地文件
    index.js:400
    .then(() => writeFile(join(dirname(pendingPath), 'version.json'), JSON.stringify({ version: '2-strict-retry', loadedAt: new Date().toISOString() }), '
  • 读取本地文件
    index.js:425
    const parsed = JSON.parse(await readFile(pendingPath, 'utf8'))
  • 写入本地文件
    index.js:438
    await mkdir(dirname(pendingPath), { recursive: true })
  • 写入本地文件
    index.js:440
    await writeFile(temp, JSON.stringify(entries, null, 2), 'utf8')
  • 写入本地文件
    index.js:441
    await rename(temp, pendingPath)
  • 删除本地文件递归
    index.js:772
    await rm(path, { recursive: true, force: true, maxRetries: 2, retryDelay: 150 })
  • 读取本地文件
    index.js:834
    const canonicalParent = await realpath(targetParent)
  • 删除本地文件递归
    index.js:1053
    await rm(relocated.backup, { recursive: true, force: true })
  • 删除本地文件
    index.js:1062
    await rmdir(oldProjectDir)
  • 删除本地文件递归
    index.js:1132
    try { await rm(dir, { recursive: true, force: true }) } catch (cleanupError) {
  • 删除本地文件递归
    index.js:1313
    await rm(relocation.backup, { recursive: true, force: true, maxRetries: 2, retryDelay: 150 })
  • 发起网络请求
    client.js:1596
    const response = await fetch('/workspace-organizer/restart', {
  • 发起网络请求
    client.js:1626
    const probe = await fetch('/workspace-organizer/restart', { method: 'GET', cache: 'no-store' })
  • 执行外部命令固定命令
    lib/restart.js:181
    const out = execFileSync('powershell', query, { encoding: 'utf8', timeout: 4000, windowsHide: true })
  • 读取本地文件
    lib/restart.js:334
    const names = (await readdir(dir)).filter((name) => /^restart-.*\.(?:out|err)\.log$/u.test(name))
  • 读取本地文件
    lib/restart.js:338
    return { name, at: (await fstat(join(dir, name))).mtimeMs }
  • 删除本地文件
    lib/restart.js:345
    await Promise.all(entries.slice(20).map((entry) => rm(join(dir, entry.name), { force: true })))
  • 写入本地文件
    lib/restart.js:359
    await mkdir(dir, { recursive: true })
  • 写入本地文件
    lib/restart.js:367
    await writeFile(script, helperSource(spec, shellPid, process.pid, port, logs), 'utf8')
  • 执行外部命令来自配置/变量
    lib/restart.js:376
    const child = spawn(process.execPath, [script], {
  • 读取本地文件
    lib/fs-ops.js:100
    await lstat(path)
  • 写入本地文件
    lib/fs-ops.js:119
    await mkdir(target)
  • 读取本地文件
    lib/fs-ops.js:151
    const children = await readdir(directory, { withFileTypes: true })
  • 读取本地文件
    lib/fs-ops.js:156
    const info = await lstat(absolute)
  • 读取本地文件
    lib/fs-ops.js:158
    entries.push({ rel, type: 'link', link: await readlink(absolute) })
  • 读取本地文件
    lib/fs-ops.js:162
    const canonical = await realpath(absolute)
  • 读取本地文件
    lib/fs-ops.js:174
    entry.hash = createHash('sha256').update(await readFile(absolute)).digest('hex')
  • 删除本地文件递归
    lib/fs-ops.js:224
    await rm(destination, { recursive: true, force: true }).catch(() => {})
  • 写入本地文件
    lib/fs-ops.js:278
    await mkdir(join(destination, relPath), { recursive: true })
  • 写入本地文件
    lib/fs-ops.js:300
    await mkdir(targetDirectory, { recursive: true })
  • 删除本地文件递归
    lib/fs-ops.js:307
    await rm(source, { recursive: true, force: true })
  • 删除本地文件递归
    lib/fs-ops.js:335
    await rm(newPath, { recursive: true, force: true }).catch(() => {})
  • 写入本地文件
    lib/fs-ops.js:353
    await rename(oldPath, newPath)
  • 写入本地文件
    lib/fs-ops.js:365
    await rename(oldPath, backup)
  • 删除本地文件递归
    lib/fs-ops.js:367
    await rm(newPath, { recursive: true, force: true }).catch(() => {})
  • 写入本地文件
    lib/fs-ops.js:381
    if (await pathExists(newPath)) await rename(newPath, oldPath)
  • 删除本地文件递归
    lib/fs-ops.js:387
    if (info.isDirectory()) await rm(oldPath, { recursive: true, force: true })
  • 删除本地文件递归
    lib/fs-ops.js:392
    await rm(newPath, { recursive: true, force: true }).catch(() => {})
  • 读取本地文件
    lib/session-logs.js:105
    entries = await readdir(sessionDir, { withFileTypes: true })
  • 读取本地文件
    lib/session-logs.js:173
    const info = await stat(file)
  • 读取本地文件
    lib/session-logs.js:177
    const bytes = await readFile(file)
  • 读取本地文件
    lib/session-logs.js:225
    const bytes = await readFile(token.file)
  • 读取本地文件
    lib/session-logs.js:245
    entries = await readdir(projectDir, { withFileTypes: true })
  • 写入本地文件
    lib/session-logs.js:281
    await writeFile(temp, data)
  • 写入本地文件
    lib/session-logs.js:282
    await rename(temp, file)
  • 写入本地文件
    lib/session-logs.js:292
    await mkdir(destinationProject, { recursive: true })
  • 写入本地文件
    lib/session-logs.js:294
    await rename(source, destination)
  • 写入本地文件
    lib/session-logs.js:307
    await mkdir(destinationProject, { recursive: true })
  • 读取本地文件
    lib/session-logs.js:325
    const info = await stat(file)
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

把 DeepSeek Harness 工作区文件夹迁移到新路径,同时改写会话日志里的 cwd,并让每个新会话在 sessions/ 下拥有自己的输出文件夹。

README

由 DeepSeek 最新模型翻译生成
dsh-session-workspace-organizer DeepSeek Harness(DSH)插件:把工作区文件夹迁移到新位置,让每个新会话在 sessions/ 下拥有自己的输出目录,并可从顶栏整进程重启应用。 DSH 把每个会话绑定到一个工作区目录,同一个工作区的所有会话共用这个目录——于是不同对话产生的脚本、日志、下载、截图全堆在一处。本插件在 DSH 自己的模型上补四件事,不修改 DSH 源码: 1. 迁移工作区——把文件夹搬到别的路径或别的磁盘,会话跟着走:每个会话日志 header 里的 cwd 改写到新路径,会话照常可用,并继续归在新工作区下。 2. 每个会话一个输出目录——新建或恢复会话时自动得到 <工作区>/sessions/<YYYY-MM-DD>_<会话标题>/;插件通过会话级系统提示告诉模型把新产物放这里;在工作区根目录新建文件时 write 会先弹确认。 3. 会话管理——把未运行的会话移到别的工作区,或删除会话(带预览),可选连同它创建的文件一起删。 4. 顶栏重启——结束并重启整个 DSH 进程,带确认对话框、忙时守卫和进度层,而不是一个卡死的页面。 已在 Windows + DSH Desktop 0.2.1-rc.2 上验证。Host 端只用 Node 内置模块,客户端是手写的 CommonJS bundle,没有构建步骤。
展开完整文档(README 剩余 1 节)
dsh-session-workspace-organizer

DeepSeek Harness(DSH)插件:把工作区文件夹迁移到新位置,让每个新会话在 sessions/ 下拥有自己的输出目录,并可从顶栏整进程重启应用。

DSH 把每个会话绑定到一个工作区目录,同一个工作区的所有会话共用这个目录——于是不同对话产生的脚本、日志、下载、截图全堆在一处。本插件在 DSH 自己的模型上补四件事,不修改 DSH 源码:

1. 迁移工作区——把文件夹搬到别的路径或别的磁盘,会话跟着走:每个会话日志 header 里的 cwd 改写到新路径,会话照常可用,并继续归在新工作区下。
2. 每个会话一个输出目录——新建或恢复会话时自动得到 <工作区>/sessions/<YYYY-MM-DD>_<会话标题>/;插件通过会话级系统提示告诉模型把新产物放这里;在工作区根目录新建文件时 write 会先弹确认。
3. 会话管理——把未运行的会话移到别的工作区,或删除会话(带预览),可选连同它创建的文件一起删。
4. 顶栏重启——结束并重启整个 DSH 进程,带确认对话框、忙时守卫和进度层,而不是一个卡死的页面。

已在 Windows + DSH Desktop 0.2.1-rc.2 上验证。Host 端只用 Node 内置模块,客户端是手写的 CommonJS bundle,没有构建步骤。

安装

从 npm(预构建,无需构建授权)
dsh plugin --profile web add dsh-session-workspace-organizer

从 GitHub 源码
dsh plugin --profile web add github:dream-fish69/dsh-session-workspace-organizer

本地开发目录
dsh plugin --profile web add link:/绝对路径

桌面端:在侧栏「插件」页移除旧条目,再输入包名或 github:dream-fish69/dsh-session-workspace-organizer 安装。安装或升级后要重启 DSH——Host 半边只在启动时加载。

卸载:

dsh plugin --profile web remove dsh-session-workspace-organizer

卸载不会动 sessions/ 里的目录和文件。

界面在哪

设置 → 工作区(英文界面为 Settings → Workspaces)。

移动位置

选择任意已注册工作区,点「移动位置…」,选择目标父文件夹并填写新文件夹名。插件执行严格迁移:

- 整个目录(含 sessions/)移到新路径,旧路径被删除,不保留 junction / 符号链接;
- 所有 header cwd 等于旧路径的会话日志都会被改写:zstd 第一帧是 header,只替换其中的 cwd,后续事件帧逐字节保留;随后把日志目录从 --旧cwd-- 搬到 --新cwd--;
- 用新路径重建工作区注册并挂回会话;当前进程因缓存挂不上的会话写入 pending-attach.json,重启 DSH 后由插件自动归位;
- 跨磁盘移动先复制并逐文件校验,校验通过前不动源目录,失败自动回滚;
- 旧目录被占用(Windows EBUSY/EPERM/EACCES,例如 DSH 自己还持有句柄)时自动降级为复制迁移:复制并校验、改写副本日志、切换注册表,旧目录能删就删,删不掉会给出具体原因。

硬性前提:要移动的工作区不能有运行中的会话——会话日志是追加写的,运行中的写句柄不能安全改写。请先切到另一个工作区的会话再执行移动。若仍有会话在跑,弹窗会列出它们(标题 + id),可选「是」:先取消这些会话正在进行的任务、等它们停稳,再按复制方式处理并继续;但承载这次操作的会话本身若就在目标工作区,只能换地方操作。

如果旧路径正是 DSH 的启动目录,插件会临时切换进程工作目录和沙箱回退根,但桌面快捷方式/启动项仍需你手动改成新路径。

整理结构

只在缺失时创建 sessions/ 和 sessions/README.md。勾选「同时移动散件」后,根目录的普通文件会移进 sessions/<日期>_整理/;点开头的隐藏文件、README.md、AGENTS.md 和常见项目清单保持不动。

会话

- 移动到工作区…——把未运行的会话(单个或批量)移到另一个工作区:会话日志、它的 sessions/ 专属目录及其中全部文件、以及它通过 write/edit 在 sessions/ 之外写进源工作区的文件都会一起移动。
- 无法确定去向的文件(单个移动)——移动前点「预览无法确定去向的文件」:计划会列出没有 marker 的历史会话目录、相对路径文件(写入时 cwd 不确定)、源工作区外文件、目标同名冲突,以及可选的项目目录。每条选择 目标会话目录、目标工作区根目录、自定义目录… 或 取消迁移此条(默认)。已知文件自动迁移,取消的留在原位置。
- 历史目录/项目——可选填「旧会话文件夹」「项目目录」明确合并/移动。冲突文件不覆盖目标,保留为 <文件名>.<旧目录名><扩展名>,例如 verify.COT中文翻译插件.md。
- 删除——永久删除未运行的会话,删除前有预览,列出将被删除的日志、会话目录和外部文件。只有勾选「同时删除它写过的文件」时才删除 sessions/ 之外的文件,且只处理该会话源工作区内的文件。
- 批量移动仍按已知去向执行;无法确定去向的条目会报告并留在原位置。需要逐条选择去向时用单个移动。

每个会话一个目录

只要新会话或恢复的会话其 cwd 属于某个已注册工作区:

- 创建 <工作区>/sessions/<YYYY-MM-DD>_<标题>/;会话标题变化时目录自动改名(保留日期前缀,重名加 -2);
- 目录里的 .dsh-session 记录 sessionId、workspacePath、createdAt,用于恢复会话时找回原目录,请勿删除;
- 该会话的作用域系统提示会告知模型:本会话新建的脚本、日志、下载、截图、临时数据、一次性产物都放这个目录,已有项目代码在原位置修改;
- 在工作区根目录用 write 新建文件会弹确认;已存在的文件与常见清单(README.md、AGENTS.md、package.json、各类 lockfile、Makefile、Dockerfile 等)不拦。

顶栏重启

顶栏的重启按钮结束并重启整个应用,让缓存的服务、插件和模块全部从磁盘重新加载——和刷新页面不是一回事。

- 先问再做:点击后弹出确认框,说明整个应用会关闭再启动、进行中的工作会被打断。Esc、点遮罩、取消都能关掉,误点不会直接断会话。
- 保护进行中的工作:有会话正在生成、有排队中的轮次或后台任务时,确认按钮变成红色的「仍要重启」且不再是默认动作;{"force": true} 可在服务端越过该守卫,格式不正确的请求永远不算 force。
- 有进度,不是卡死:全屏进度层(双环 spinner + 不确定进度条 + 状态行)直接画在 document.body 上,所以 React 树被拆掉也不会消失;重启失败会转成红色状态并写明错误与恢复办法,而不是一直转圈。
- 不弹原生错误框:DSH Desktop 把 Host 子进程的任何退出都当致命错误并弹系统对话框(渲染层盖不住)。所以助手先结束 Electron 主进程,让 Host 沿自己的 IPC 断开路径收尾,等进程树消失后再拉起应用,并验证新进程确实活着。
- 重启日志只保留最近 20 组;被强杀的 JSONL 写在下次打开时自动修复,退出不会写坏会话日志。

GET /workspace-organizer/restart 会报告当前能否重启(mode、revision、lastError),有活干时返回 409 + busy: true。

配置

在 profile 的 cordis.patch.yml 里按行 id 覆盖:

- id: workspace-organizer
config:
sessionFolders: true # 是否自动创建会话输出目录 guardRootWrites: true # 根目录新建文件时是否弹确认 sessionsDirName: sessions # 会话目录的父目录名 maxTitleChars: 40 # 目录名里标题的最大字符数(8-80) sessionsRoot: /path/to/dsh/home/sessions # 仅当 DSH 把日志放在别处

安全说明

- 严格迁移会删除旧目录。它只在预检通过后执行,先写新位置、再改写日志、最后删旧路径,任一步失败会回滚——但设计上没有“两边都留”的模式。想保留旧目录时请用复制迁移(插件自动降级的那条路)。
- 改写会话日志属于离线操作,迁移后请重启 DSH,让会话列表、搜索索引和持久化缓存重新读取新路径。
- 工作区内存在符号链接/联接点时,复制迁移会被拒绝(避免复制出循环或丢链接);同磁盘重命名不受影响。
- 插件安装前就已打开、之后没有重新恢复的会话不会补建目录,下次恢复时才补。
- 所有破坏性命令都要求 check / preview 步骤签发的一次性确认令牌,客户端无法发出“裸删除”。

兼容性与限制

- DSH 0.2.x,需要包含 dsh-base + dsh-web-app 的 Web 或 Desktop profile。
- 占用判断基于 Windows 错误码;其他平台上复制迁移就是常规路径。
- 移动与删除都以命令形式记录在一个打开的会话里,因此必须有会话打开,且该会话不能属于要移动的工作区。
- DSH 侧边栏工作区行的「…」菜单没有扩展槽位,所以入口放在设置里。

实现结构

| 层 | 文件 | 负责 |
| Host | index.js | 注册 workspace-relocate-check / workspace-relocate-strict / workspace-organize / session-relocate-plan / session-relocate / session-relocate-batch / session-delete-preview / session-delete / session-delete-batch;agent/created 建会话目录与作用域提示;session/event 跟随标题改名;tools/pre-execute 拦截根目录写入;提供重启路由 |
| Host | lib/fs-ops.js | 目录移动(同盘 rename / 跨盘复制 + 校验 + 回滚)、名称净化、散件扫描 |
| Host | lib/session-logs.js | 解析 zstd 第一帧 header,只改写 cwd,后续帧原样保留;会话日志目录重定位 |
| Host | lib/restart.js | 整进程重启:先结束 shell(避免原生错误框)、分离式重启助手、存活校验、重启日志限量 |
| Client | client.js | settings.section 页面:移动 / 整理 / 会话三个面板,外加顶栏重启按钮与确认框、进度层;文案取自 locale/*.json |

开发

npm run check # node --check index.js、client.js、lib/ 下三个模块
npm test # node --test tests/(路径安全、复制/合并、header 改写、重启路由)

没有打包器:lib/ 就是源码,client.js 是 DSH 通过 window.__ModuleLoader__ 加载的 bundle。改 Host 需要重启 DSH,改客户端刷新页面即可。

License

MIT
预览分享卡片长什么样 ↓dream-fish69/dsh-session-workspace-organizer
分享 · DeepSeek Harness Hub
dream-fish69/dsh-session-workspace-organizer

迁移工作区目录并让每个会话拥有独立输出文件夹

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部