DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

popujiang /

popujiang/dsh-turn-scratch

Verified

一款专门用于清理 dsh 每轮产生的多余临时文件的插件

★ 0 Stars0 Forks1 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@394f7e48

dsh-turn-scratch

一款专门用于清理 dsh 每轮产生的多余临时文件的插件。

介绍

是不是还在因为dsh忙完工作后,工作区里到处都是它产生的临时文件而苦恼?

您是否经常感觉到自己不知道这些文件的作用?删除时又怕这些文件会影响你的电脑?

或者是自己还要在每次对话时做出删除临时文件这种重复性动作?

不用担心,dsh-turn-scratch 这款插件能帮你的忙。

安装

dsh plugin --profile desktop add "git+https://github.com/popujiang/dsh-turn-scratch.git#v0.4.0"

“小而美”

插件体积很小,让你放心。

当然,真的是小而美:

很多操作无感完成,默认无需配置,开箱直用!

为什么?因为它是全自动的。

不过想调的话,配置项都在——在 profile 的 cordis.patch.yml 里给 turn-scratch 行加 config: 即可。

但是你怕dsh误删?

早就想好了这一点!

特色

它并不是直接删文件

每轮结束,临时文件全都会先被挪进一个隔离文件夹(不是你电脑里的回收站),再逐个判断:

~/.dsh/turn-scratch/<工作区名-指纹>/<会话>/turn-<轮次>/

它不在你的工作区里。

一个专门保持工作区干净的插件,自己的东西当然也不该堆在工作区 —— 所以隔离区放在用户目录,工作区从头到尾一个多余文件夹都没有。

能确定的,代码直接决定去留。

拿不准的,才交给一次独立的模型调用判断。

真正的删除,只在你手动清空时发生。

在你还什么都没察觉的时候,分类已经发生,连工作区的界面也跟着清爽了起来。

所以最坏的情况其实是文件被隔离开来,而不是被误删

工作和隔离区不在同一块盘,会怎样?

那"挪"就变成了"真的拷一份字节"(Windows 上跨盘改名会直接失败)。

顺序是:复制 → 校验文件数与字节数 → 落库 → 最后才删原件。任何一步崩掉,原件都还在,最坏只是多留一份重复 —— 不会两头落空。

代价是大目录会慢一点。想避开,把 storeRoot 指到和工作区同一块盘就行:

storeRoot: "D:/.dsh-turn-scratch"   # 同盘,搬运恢复成瞬时的改名

干活干到一半,工作区就已经乱了?

上面说的,都是回合结束时的收尾。

可一个长回合干到一半,中间产物其实早就散在工作区里了 —— 等它结束才动手,中间那段时间你还是得对着一堆不认识的文件发呆。

所以插件给 dsh 备了一块暂存区:

~/.dsh/turn-scratch/<工作区名-指纹>/work/

中间产物直接写这儿,工作区从第一秒就是干净的。

那这些文件就不管了?

当然不是。回合结束时,它们会被搬进本轮的隔离文件夹 —— 照样有记录、照样能复核、照样随时能还原。然后暂存区清空,下一轮又是一个干净的工作台。

路径固定不变,不用每轮重新找。

这不是"只扫暂存区"

暂存区是多出来的一路来源,不是替换。

原来的全工作区扫描一条没动:标记过的、本轮新建的、临时命名的目录、孤儿库 —— 照扫不误。哪怕 dsh 一次都没往暂存区写,散在工作区里的东西照样会在回合结束时被收走。

暂存区只是让它从一开始就不用弄脏工作区。

本轮新建的东西,不分工具

暂存区靠的是 dsh 主动往里写。可现实里它经常不写 —— 它直接用 shell 干活。

于是就有最常见的那个场景:作业做完了,交付的 docx 在,但旁边还躺着一堆 build_docx.py、tpl_preview/、pipwork/、read_docx.py…… 这些全是本轮 shell 现场生成的,以前插件对它们完全失明:它只认 write/edit 两个工具产生的文件,shell 写的一概看不见。

现在多了一条路:按创建时间判定,不看是哪个工具建的。

回合结束时扫一遍工作区,凡是「创建于本轮」的文件都收走(sweepNewFiles,默认开),然后把这些文件腾空了的目录一并删掉 —— 文件走了、空壳还在,工作区仍然不算干净。

四个豁免,保证不碰你真正要的东西:

  • 交付物扩展名(createdKeepExtensions):.docx .doc .pdf .pptx .ppt .xlsx .xls .odt .odp .ods .epub .zip .7z .rar .tar .gz .mp4 .mov .mp3 .wav;
  • 你本轮原话里点过名的路径或文件名;
  • .git/、node_modules/、__pycache__/、.venv/ 等保护目录;
  • 早就存在、只是被改过的文件 —— 只看创建时间,改旧文件永远不会被收。

还有一条比豁免更要紧的前置条件:复核得真的会跑。收走从来不是终点 —— 清单会交给复核模型看一遍,谁其实是你要的东西就摆回来;这类条目模型没表态时默认方向是还原,不是留着。所以只要复核落不了地(aiReview 关着,或者 aiReview.provider/model 没配、settings 里也没有默认模型),这条路整条不启用:本轮新建的文件原地不动,日志里说明原因。想让它在无复核时硬跑,写 sweepNewFiles: "force"(后果自负:没人往回捞)。

sweepNewFiles: false          # 关掉「本轮新建全收」,回到只看工具与临时命名
createdKeepExtensions: [".docx", ".pdf"]   # 想多保几种类型就自己加
createdSkipDirs: ["node_modules", ".git"]  # 扫描永不进入的目录名

扫描本身有上限(createdMaxEntries,默认两万条;深 6 层),大工作区也不会把回合收尾拖死。

收走的文件,直接进系统回收站(recycleRemoved,默认开着)

隔离库只有 agent 看得见。为了让你也看得见,每轮收走的文件会按原位置交给系统回收站:打开资源管理器、右键「还原」,就回到它原来的地方。回收站接手之后,隔离库里那份随即删掉 —— 反正不是永久删除,没必要在两个地方各留一份:既省盘,也不会让人分不清该去哪儿找。

  • 只对文件生效。整棵目录搬回原位再送回收站太贵,而且回收站按目录还原容易撞名,目录条目继续留在隔离库(日志和 scratch_status 里仍看得到,scratch_restore 也能捞)。
  • 送过回收站的文件,scratch_restore 会直接告诉你「已交系统回收站,去资源管理器还原」,不再含糊地报「源缺失」。
  • 送之前先跑一遍探针(recyclePreflight,默认开着):被降权的进程里 SendToRecycleBin 会不报错地退化成永久删除,所以「没报错 + 文件不见了」不算数,只有「回收站里真出现了这个名字」才算。
  • 后端不可用、探针没过、副本没造出来 —— 任何一步失败都只是「你没看见」,文件仍在隔离库兜底,工作区保持「文件不见了」的原样,不会多丢一个。
  • 为过路副本临时造出来的空目录,送完就清掉,不留下空壳。
recycleRemoved: false    # 关掉:文件只留在隔离库,回收站里看不到
recyclePreflight: false  # 不跑探针(不推荐:权限不足时会退化成永久删除)

关掉会怎样?

workDir: ""

回到原来的样子:

  • 暂存区不再创建,scratch_workdir 会明确回你一句"未启用"
  • dsh 写哪儿由它自己决定(通常就是工作区)
  • 全工作区扫描照旧,回合结束该收的还是收

所以关掉的只是"提前变干净"这条路 —— 收尾那套一点没少。

让"最后一步"进系统回收站(可选)

scratch_purge 是本插件唯一不可逆的操作:真删。想给这一步再套一层系统级撤销:

purgeToRecycleBin: true

开了之后 purge 不再 rm,而是把整个桶交给操作系统回收站,用户还能自己从回收站捞回来。

后端按这个顺序找:

  1. 显式指定的助手程序(trashHelper: C:\tools\genie-trash\win32-x64.exe)—— 给了它就只用它,起不来就整批拒绝,不会退到别的后端;
  2. 系统现成的:Windows 用 powershell 调 Microsoft.VisualBasic.FileIO 的 SendToRecycleBin,macOS 用 /usr/bin/trash(macOS 15+)或 osascript + Finder,Linux 用 gio trash / trash-put;
  3. 都没有(比如 Linux 上没装任何 trash 工具)就回 refused,一个桶都不动。

这条路和 WorkBuddy 的 genie-trash 是同一个做法:自带/调用一个「把东西搬进回收站」的助手进程,而不是依赖 Electron(DSH Desktop 把整个 profile 放在 ELECTRON_RUN_AS_NODE=1 的子进程里跑,那里 import("electron") 拿到的是个路径字符串,shell.trashItem 根本不在)。

探针预检(purgePreflight,默认开着)

purgeToRecycleBin: true 之后,scratch_purge 不会一上来就动你的桶:它先在系统临时区造一个探针小文件(dsh-scratch-preflight-<时间>-<随机>.tmp),用与桶完全相同的后端送走它,然后去回收站里找这个文件名:

  • 找到了 → 后端在当前权限下可信,继续处理真实桶;
  • 被删掉了、但回收站里没有它 → 这个后端已经退化成永久删除,整批拒绝(回 refused),一个桶都不动;
  • 枚举不出回收站(COM 不可用等)→ 同样按不可信处理,拒绝;
  • 探针还躺在磁盘上 → 后端没真正搬运,拒绝。

为什么值得多这一跳:「调用没报错 + 文件确实没了」并不等于「东西进了回收站」——被降权的进程里 SendToRecycleBin 恰好就是这个样子,而那是永久删除。只有"回收站里出现了同名条目"才算证据。

确认过这台机器、这个权限下回收站确实可用之后,可以 purgePreflight: false 跳过这次往返(代价是每批 purge 多一次枚举回收站的开销 —— 一个探针文件加一次目录列表而已)。

三条刻意的取舍:

  • 拿不到回收站后端就拒绝执行:保留全部桶,回一句 refused。绝不悄悄退回真删 —— 那等于在用户以为有系统撤销的时候永久删除。
  • purge 之前先用探针确认回收站真的可用(purgePreflight,默认开):确认不了就整批拒绝。
  • 后端返回成功也要复查桶是否真的离开磁盘,没离开算失败(和跨盘搬运同一条纪律)。
  • 助手进程起不来(缺可执行文件、被沙箱拦住 spawn EPERM)同样算失败:桶留下,报错里说清楚原因,绝不 rm 兜底。

⚠️ 别在被降权的沙箱里用这条路:低完整性令牌写不进 C:\$Recycle.Bin,SendToRecycleBin 会静默退化成永久删除(调用不报错、文件也没了,但回收站里一项都没有 —— 已实测)。插件自己的工具跑在宿主子进程里(正常完整性),所以能用;但如果你把插件塞进别的沙箱执行环境,默认开着的探针预检会替你拦下这种环境(它拒绝执行,就说明这条路在这台机器上不可信)。

注意回收站会被系统自动清空(按卷容量上限、存储感知的"超过 N 天自动删除"),所以它只配当最后一步的兜底,不能当存储根 —— 隔离库仍然是唯一真相来源。

包含的工具及其作用

工具 作用
scratch_status 看现在扣着什么、已还原什么
scratch_restore 手动把一个文件捞回工作区
scratch_purge 清空隔离区(真删;开了 purgeToRecycleBin 则是送进系统回收站)
scratch_mark 告诉 dsh 某个文件是一次性脚手架,可以收走
scratch_workdir 拿到一个暂存区路径,中间产物写那儿,不弄脏工作区

安全

默认只隔离,不删除。

scratch_purge 是唯一的例外,而它是显式人工操作(要求 confirm: true)。想连这一步都不留死角,就打开 purgeToRecycleBin:真删改成送进系统回收站,拿不到回收站、或者探针预检(purgePreflight,默认开)验证不出回收站真的可用,就整批拒绝执行。

跨盘搬运时确实要移除原件,但那是在副本校验通过之后才做的,顺序保证任何时候崩溃原件都还在。

拿不准的会被还回工作区,不会误删。

模型只能还原、不能删除,最后文件的生杀大权在你手里。

三套测试共 189 项断言全绿。最坏的情况是文件被隔离,随时可还原,请放心食用。

其他

插件如果有任何问题,希望大家能多多反馈。 未来想增加UI界面方便操作,不过现在你直接与dsh对话就可以删除。

—/ 5

No ratings yet

Verified DSH bundle

Commit 394f7e4867eb

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout