Files
session-delete/README.md
T
pyh f4e107782a ci: make a repeated release a no-op and drop the misleading diagnostics
Gitea does not implement the npm whoami endpoint and npm refuses to read an auth token back, so both lines only produced error-looking output. The run now checks the registry first and skips publishing a version that already exists, which also makes a manual re-run safe.
2026-09-30 11:28:57 +08:00

127 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# dsh-session-delete
DeepSeek Harness 插件:**彻底删除会话**,外加在 设置 → 通用设置 里**清理孤儿临时文件**。
DeepSeek Harness 原本只能归档会话,归档只是从列表里移开、日志仍然留在磁盘上;这个插件补齐了真正不可逆的删除。
## 功能
### 1. 删除会话
入口:
- 会话行 "..." 菜单 → **删除会话**(同一行的悬停快捷按钮也接管为删除,原"归档会话"按钮的位置)
- 两处入口都会弹出确认弹窗(复刻系统 Modal 的样式与键盘行为:Esc 关闭、Tab 焦点圈定、打开时焦点进入、关闭后焦点归位)
删除时一并处理:
| 对象 | 处理方式 |
| --- | --- |
| 会话日志目录 | 整个目录删除,只保留 `session.lock`(POSIX 语义下该锁文件随会话存活,删除它没有意义且可能影响锁语义) |
| 子智能体会话 | 按 `parentSession` 递归收集,连同各自的日志与溢出文件一起删除 |
| 工具输出溢出文件(spill) | 删除该会话(含子会话)对应的 spill 目录 |
| 工作区登记项 | 解除与该会话的绑定(detach)、取消置顶、取消归档 |
| 客户端列表 | 广播 `api-session/removed`,列表行立即消失 |
有意**不**处理的部分:
- **附件对象**(`$DSH_HOME/attachments/v1/objects`):按内容 sha256 寻址,同一份内容可能被多个会话共享,而 harness 里没有任何引用计数;跟着一个会话删除会破坏别的会话。要做只能实现"引用检查式清扫"(先扫剩余会话日志确认无人引用才删)。
- **投影缓存**(`$DSH_HOME/storages/session_projcache`):由日志派生的缓存,读取时带生命周期身份校验,永远不会串到别的会话;投影缓存服务本身也没有提供删除接口。
### 2. 清理临时文件(设置 → 通用设置)
只清理**孤儿**,判定规则偏保守:
1. 目录名必须精确等于 `session-<sha256(会话 id) 前 12 位十六进制>`——这是 spill 后端唯一会生成的形状;
2. 该名字不能属于任何已知会话(存量会话与内存中正在运行的会话都算);
3. 只在 spill 的 root 内操作(后端当前 root + `%TEMP%\dsh-spill*`);
4. 符号链接一律跳过不跟随,单项失败只记警告。
结果是幂等的,可以反复点击。
## 行为与边界
- **仍在运行的会话无法被插件从内存里移除**:它会先被归档并停止,日志与溢出文件在**下次启动 DeepSeek Harness 时**删除(界面会明确提示"已先停止并归档…");在此之前取消归档就会取消这次删除。
- 删除**不可恢复**,但**不是安全擦除**:按普通文件删除处理,底层介质上可能有残留。
- 工作区里的代码文件不受影响。
- 溢出文件被删除后,如果某个 fork 的日志里仍保留着指向它的路径文本,那些路径会失效——这与"父会话数据被删除"是同一件事。
## 安装
这是一个 DeepSeek Harness **bundle** 包(普通 Node 包 + `cordis.patch.yml`),由 Harness 的插件管理机制安装,而不是单独运行的程序:
- `package.json` 声明 `dsh.bundle.patch`(bundle 补丁)与 `dsh.client`(web 平台客户端半)
- `cordis.patch.yml` 把 `@dsh-plugin/session-delete` 插进 profile
- 安装后 profile 的依赖是 `link:<本目录绝对路径>`(本地目录安装)或注册表/git 解析出的版本,并在 `node_modules` 下建立链接
> 包名在三个地方必须完全一致:`package.json` 的 `name`、`cordis.patch.yml` 里 `name:`、以及 `client.js` 顶部 `__ModuleLoader__.load({ id })`。Cordis 是按 `name` 在 profile 的 `node_modules` 里解析模块的。
### 安装方式
在 DeepSeek Harness 的 **插件 → 添加插件** 里,以下三种都可用:
| 方式 | 输入 |
| --- | --- |
| 本地目录 | 本仓库在本机的绝对路径(`D:\DeepSeek Harness Plugins\dsh-session-delete`),适合边改边用 |
| Git 仓库地址 | `https://gitea.iwake.top/dsh-plugin/session-delete.git#v1.0.0`(`#` 后可跟标签或提交) |
| npm 源 | 安装源选「自定义地址」填 `https://gitea.iwake.top/api/packages/dsh-plugin/npm/`,包名填 `@dsh-plugin/session-delete` |
用 npm 源或私有源时,凭据放在本机 `~/.npmrc`(客户端提示里也是这么说的):
```bash
npm config set @dsh-plugin:registry=https://gitea.iwake.top/api/packages/dsh-plugin/npm/
npm config set //gitea.iwake.top/api/packages/dsh-plugin/npm/:_authToken=<带 package 权限的 token>
```
公开的 git 地址不需要凭据。安装或升级后:**宿主半需要重启客户端**,只改浏览器半时刷新页面即可。
### 发布到 Gitea 的 npm 仓库
仓库自带工作流 [`.gitea/workflows/publish.yml`](.gitea/workflows/publish.yml):推送 `v*` 标签(或在 Actions 页面手动 Run workflow)就会把该版本发布到 `https://gitea.iwake.top/api/packages/dsh-plugin/npm/`。工作流会校验标签与 `package.json` 的版本一致,不一致直接失败。
```bash
git tag -a v1.0.1 -m "v1.0.1" && git push origin v1.0.1
```
发布凭据按顺序取:仓库 secret `NPM_TOKEN`(带 `package` 写权限的个人访问令牌)→ 没有则退回 Gitea 内置任务令牌 `${{ secrets.GITEA_TOKEN }}`(工作流已声明 `permissions: packages: write`)。
前提与排查:
- 实例启用了 Actions 并注册了 runner(`runs-on: ubuntu-latest` 要与 runner 的标签一致);
- 若组织把 Actions 令牌上限设成只读,或任务令牌对包命名空间没有写权限,发布步骤会很快失败:配置 `NPM_TOKEN` 即可,工作流会自动改用它;
- 已发布的版本会在发布前被检测到并**跳过**,所以手动重跑同一个版本是安全的(不会失败,也不再重复上传);
- 真失败时看 `Publish` 步骤日志:`registry =` 那行确认注册表地址,`npm error code` 给出原因(`E401/E403` = 令牌无效或权限不足)。注意 Gitea 的 npm 注册表**不实现** `/-/whoami`,`npm whoami` 返回 404 属正常现象;`npm config get ...:_authToken` 也必然报 protected,因为 npm 禁止读回令牌。
手工发布等价于:
```bash
npm config set @dsh-plugin:registry=https://gitea.iwake.top/api/packages/dsh-plugin/npm/
npm config set //gitea.iwake.top/api/packages/dsh-plugin/npm/:_authToken=<TOKEN>
npm publish # registry 已写在 package.json 的 publishConfig 里,无需再传 --registry
```
同一版本不能重复发布:改内容要同时提升 `package.json` 的 `version`。
## 结构
```
index.js 宿主半:删除流程、溢出文件清理、两条已认证路由、启动补删
client.js 浏览器半:菜单行、行悬停按钮 + 气泡、确认弹窗、设置行
cordis.patch.yml bundle 补丁
locale/*.json 插件管理页显示的标题与描述
icon.svg 插件图标
```
## 兼容性
为 DeepSeek Harness **0.2.0-rc.2** 编写。
浏览器半**不 import 任何 Harness 客户端包**(上游规范要求如此:这些包随时可能变化,且渲染抛错会让整个插槽条目变空白),而是复刻 `dsh-client-ui-primitives` 的 markup、CSS 声明、图标 path 数据与键盘行为,只保留 `--dsw-*` 主题 token 引用。如果上游改动这些内部结构,界面细节可能失配(例如不再弹出气泡),但不会导致插件加载失败或崩溃。
删除逻辑只依赖稳定的服务契约:`sessionPersistence`、`sessionQuery`、`workspaceRegistry`、`sessions`、`agents`、`connection.fetch`,以及 spill 后端的目录规则(`<root>/session-<sha256(id)[:12]>/…`)。
## License
MIT