dsh-context-actions 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/LICENSE +21 -0
- package/README.md +201 -0
- package/cordis.patch.yml +7 -0
- package/lib/client.js +1004 -0
- package/lib/index.js +1021 -0
- package/package.json +62 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
本项目遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 与 [语义化版本](https://semver.org/lang/zh-CN/)。
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2026-09-15
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- 零依赖单元测试(Node 内置 `node:test`):宿主命令链、参数/配置/路径校验、机械折叠与 llm 回退;浏览器半侧 bundle 契约与设置卡片字段显隐。
|
|
10
|
+
- GitHub Actions:CI(Node 18/20/22 矩阵:语法检查 + 单元测试 + 打包 dry-run)与 Release(`v*` 标签生成 GitHub Release;配置 `NPM_TOKEN` 后同步发布 npm)。
|
|
11
|
+
- 在「上下文已用」面板底部新增「压缩」「交接」两个按钮,并带状态反馈。
|
|
12
|
+
- `/handover`、`/handover --where`、`/handover --write <绝对路径>` 命令;文档默认写入 `<系统临时目录>/dsh-handover`。
|
|
13
|
+
- 两种生成方式:`脚本节选`(默认,零模型调用)与 `模型总结`(整段派生历史一次喂给模型)。
|
|
14
|
+
- 设置页卡片:生成方式、总结模型 provider / model(复用部署已配置的模型目录下拉)、自定义提示词、输出上限;字段跟随生成方式显示,支持一键恢复全部默认。
|
|
15
|
+
- 内置默认交接提示词(固定七段式交接文档结构)。
|
|
16
|
+
- 模型总结失败时自动回退脚本节选,并在文档中注明原因。
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-context-actions contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# dsh-context-actions
|
|
2
|
+
|
|
3
|
+
[](https://github.com/CN-Hang/dsh-context-actions/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/CN-Hang/dsh-context-actions/actions/workflows/release.yml)
|
|
5
|
+
|
|
6
|
+
> **非官方开源插件,与 DeepSeek 官方无关。** MIT License。
|
|
7
|
+
|
|
8
|
+
给 DeepSeek Harness(`dsh`)Web GUI 的「上下文已用」面板加两个按钮。
|
|
9
|
+
|
|
10
|
+
| 按钮 | 行为 |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| **压缩** | 对当前会话执行宿主命令 `/compact`,就地压缩上下文;执行前先探测该会话的 agent 预设是否挂载了压缩后端,没有就给出可操作的提示 |
|
|
13
|
+
| **交接** | 把当前会话的持久日志生成一份交接文档写到系统临时目录(`%TEMP%\dsh-handover\`)。默认「脚本节选」零模型调用、不消耗 token;可在设置页切换为「模型总结」(按所选模型计费),然后新建一个会话并把文档路径发过去让它接着干 |
|
|
14
|
+
|
|
15
|
+
两个按钮都出现在上下文占用面板底部(点 composer 右侧的圆环弹出),并带一行状态反馈。
|
|
16
|
+
|
|
17
|
+
## 安装
|
|
18
|
+
|
|
19
|
+
要求:Node.js ≥ 18,已安装并可使用 `dsh`(在 `dsh 0.1.5-rc.1` 上验证;dsh 升级后若内部结构变化可能需要跟着调整)。
|
|
20
|
+
|
|
21
|
+
从 npm(发布后):
|
|
22
|
+
|
|
23
|
+
```powershell
|
|
24
|
+
dsh plugin --profile web add dsh-context-actions
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
从源码 / 本地目录(把 `<仓库绝对路径>` 换成实际路径,Windows 用正斜杠最稳):
|
|
28
|
+
|
|
29
|
+
```powershell
|
|
30
|
+
dsh plugin --profile web add file:<仓库绝对路径>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
官方 `dsh plugin add` 会自动把依赖写进 profile 的 `dependencies`、同步 `dsh.profile.bundles`,并发现包里的 `dsh.bundle.patch`。
|
|
34
|
+
|
|
35
|
+
安装后:
|
|
36
|
+
|
|
37
|
+
- 宿主半侧(`/handover` 命令)需要 **重启 dsh** 才生效;
|
|
38
|
+
- 浏览器半侧(按钮)**刷新页面**即可(Ctrl/Cmd+R)。
|
|
39
|
+
|
|
40
|
+
验证装配:
|
|
41
|
+
|
|
42
|
+
```powershell
|
|
43
|
+
dsh --profile web --dump-config | Select-String context-actions -Context 1,1
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
期望看到:
|
|
47
|
+
|
|
48
|
+
```yaml
|
|
49
|
+
# == dsh-context-actions
|
|
50
|
+
- id: context-actions
|
|
51
|
+
name: dsh-context-actions
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 使用
|
|
55
|
+
|
|
56
|
+
1. 打开任意会话,点 composer 右侧的上下文圆环,面板底部就是「压缩 / 交接」。
|
|
57
|
+
2. **压缩**:会话的 agent 预设挂载了 `dsh-compaction-basic` + `dsh-command-compact` 时才可用(`standard` / `ptc` / `cordis` 预设都带;`minimal` 预设刻意不带)。结果文本会显示在按钮下方状态行里。
|
|
58
|
+
3. **交接**:
|
|
59
|
+
- 交接文档写入 `<系统临时目录>\dsh-handover\handover-<会话短id>-<时间戳>.md`;
|
|
60
|
+
- 文档内容 = 该会话持久日志的派生历史(元信息表 + 按时间排序的对话与工具记录 + 涉及的文件 + 执行过的命令 + 接手指引),超出体积预算时省略最早的部分;
|
|
61
|
+
- 随后插件新建一个会话(沿用当前工作目录与模型选择),切换过去,并发送首条消息让它先读交接文档。
|
|
62
|
+
|
|
63
|
+
命令行也能直接用:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
/handover 生成交接文档并返回路径
|
|
67
|
+
/handover --where 返回交接目录(不存在则创建)
|
|
68
|
+
/handover --write <绝对路径> 在指定路径生成交接文档(路径必须在交接目录内)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## 在「设置 → 插件」里改(推荐)
|
|
72
|
+
|
|
73
|
+
插件在宿主注册了 settings namespace `dsh-context-actions`,并在浏览器注册了同名卡片,所以在 **设置 → 插件 → 插件配置** 里会出现一张「上下文动作(压缩 / 交接)」卡片:
|
|
74
|
+
|
|
75
|
+
- 卡片里的字段**跟着生成方式显示**:`脚本节选`(默认)时只有「交接文档生成方式」一项;选成 `模型总结` 后,才出现 总结模型 provider、总结模型 model id、**自定义提示词**(整段可编辑的文本框)、输出上限;
|
|
76
|
+
- **自定义提示词默认就显示内置那份**(不再是空白框):直接在上面改,改完即保存;点「恢复全部默认」又回到内置文本;
|
|
77
|
+
- provider / model 是**下拉框**,候选来自本部署**已配置的模型目录**(`session/modelCatalog`):provider 列出所有已配置的 provider(含当前不可用的),选中后 model 才解锁并列出该 provider 的模型;两栏的第一项都是「跟随会话(不固定)」;
|
|
78
|
+
- 目录读不到时会**自动退回手动输入**(不会卡住);已保存但不在目录里的路由显示成「…(已保存但当前不可用)」,不会被清掉;
|
|
79
|
+
- 每项保存即写入用户设置(`settings.yaml` 的 `dsh-context-actions:` 段),**无需重启**:命令每次执行都会重新读取当前值;
|
|
80
|
+
- 被用户改过的字段会标「已覆盖」;底部「恢复全部默认」**一键清空本插件的全部用户设置**(回到组合层/内置默认),没有覆盖时该按钮是灰的;
|
|
81
|
+
- 卡片标题/描述/字段文案随语言(中/英)切换。
|
|
82
|
+
|
|
83
|
+
命令行方式(不改文件、只影响一次调用):`/handover --llm`、`/handover --mechanical`。
|
|
84
|
+
|
|
85
|
+
配置的优先级:**用户设置(设置页)> loader 行的 config(base)> 内置默认值**。所以下面的 YAML 写法仍然有效,只是会被设置页覆盖。
|
|
86
|
+
|
|
87
|
+
其余策略是固定的(刻意不放进卡片):单次总结超时 180s、总结失败自动回退脚本节选并在文档顶部注明、摘要后附一份脚本节选纪要。
|
|
88
|
+
## 生成方式:脚本节选 / 模型总结
|
|
89
|
+
|
|
90
|
+
默认沿用脚本节选(零模型调用)。想固化成**部署默认值**(设置页的 base)时,在 profile 的 `cordis.patch.yml` 里给这一行加 config:
|
|
91
|
+
|
|
92
|
+
```yaml
|
|
93
|
+
- id: context-actions
|
|
94
|
+
config:
|
|
95
|
+
handover:
|
|
96
|
+
mode: llm # mechanical(默认)| llm
|
|
97
|
+
provider: '' # 可选:总结用模型;留空 = 跟随该会话最近一次请求的路由(设置页里是下拉选择)
|
|
98
|
+
model: ''
|
|
99
|
+
prompt: '' # 可选:整段替换发给模型的提示词;留空 = 内置默认
|
|
100
|
+
maxOutputTokens: 2000
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
模型总结(`mode: llm`)怎么工作:
|
|
104
|
+
|
|
105
|
+
- **整段上下文一次发过去**:把该会话的派生历史(用户需求、助手回复、工具调用与结果)整段渲染成文本,**不做单条截断**,加上会话元信息后一次请求发给模型;
|
|
106
|
+
- 只有总量超过「该会话模型上下文窗口 − 输出上限」时,才从**最早**的记录开始省略(必要时再截断最早那一条),并在文档表格里写明「省略最早 N 条」;上下文窗口取自该会话最近一次请求的 `request/context`,拿不到时按 128k 估;
|
|
107
|
+
- 提示词可在设置页整段替换(`prompt`);**默认值就是内置那份**,所以框里直接能看到、直接改。内置默认要求输出固定结构:标题「交接文档:<一句话任务名>」,二级小节为 任务目标 / 当前状态 / 关键决策与约定 / 涉及的文件与命令 / 待办与下一步 / 风险与未解决的问题 / 接手建议,并附带硬性规则(只写事实、原样保留路径命令与错误原文、压缩摘要里的既有事实要带上、长工具输出只取结论、1-2 页、不写开场白);
|
|
108
|
+
- 文档结构:元信息表(含生成方式、总结模型、喂了多少字符、输入/输出 token、耗时)+ `## 交接摘要(模型生成)` + `## 附:对话纪要(脚本节选)` + 文件/命令清单 + 接手指引;
|
|
109
|
+
- 失败(无路由、无适配器、超时、限流、空输出等)自动回退脚本节选,并在文档顶部注明原因;
|
|
110
|
+
- 成本:一次总结按所选模型计费,输入规模就是上面的「整段上下文」(超大窗口模型下通常几万到几十万 token);想省钱就给该会话选小模型、或在设置页把输出上限调小。
|
|
111
|
+
## 关于「压缩」按钮和 agent 预设
|
|
112
|
+
|
|
113
|
+
Web 部署故意把压缩后端交给 **agent 预设**:`minimal` 预设的注释写着 "Context compaction is absent.",所以用它创建的会话里 `/compact` 根本不存在(命令目录里没有它)。此时「压缩」按钮不会瞎执行,而是提示:
|
|
114
|
+
|
|
115
|
+
> 当前 agent 预设未挂载压缩后端(/compact)
|
|
116
|
+
|
|
117
|
+
想让它在 `minimal` 会话里也能用,二选一:
|
|
118
|
+
|
|
119
|
+
1. **换预设**:新建会话时选 `standard`(或 `ptc` / `cordis`)预设;
|
|
120
|
+
2. **把两行开回宿主面**:在 `$DSH_HOME/profiles/web/cordis.patch.yml` 里加(本插件的补丁层之后应用,会覆盖 `dsh-web-app` 的 `disabled: true`):
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
- id: compaction-basic
|
|
124
|
+
disabled: false
|
|
125
|
+
- id: command-compact
|
|
126
|
+
disabled: false
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
注意:`compaction-basic` 的 `auto` 默认是 `true`,所以第 2 种做法会给 **所有** 会话(含 `minimal`)打开自动压缩,这是官方架构里刻意放在预设面的行为,请自行权衡;只想要手动 `/compact` 可以再补 `config: { auto: false }`。
|
|
130
|
+
|
|
131
|
+
## 实现要点
|
|
132
|
+
|
|
133
|
+
- **宿主半侧** `lib/index.js`:Cordis 插件(`inject: ['commands', 'sessions']`),注册 `/handover` 命令。文档内容来自 `ctx.sessions.get(agent.id).deriveMessages()`,即该会话持久日志的派生历史,因此不额外请求模型;写入前校验目标路径必须落在自己的临时目录内。顺带尽力解析 `<DSH_HOME>/sessions/**/<sessionId>/session.*.jsonl*` 原始日志路径写进文档。
|
|
134
|
+
- **浏览器半侧** `lib/client.js`:`window.__ModuleLoader__.load({ id, factory })` 形式的客户端 bundle。`apply(ctx)` 里用 `ctx.inject(['sessions', 'remote', 'remote.commands', 'remote.session'], ...)` 等必需服务(缺服务只会让这个 fiber 挂起,不会拖垮 Web 启动),然后:
|
|
135
|
+
- `MutationObserver` 监听 DOM,用 `button[aria-haspopup="dialog"]` 且 `aria-label` 含百分号的触发器定位上下文面板,把按钮容器插到面板末尾(面板由 `dsh-client-ui-conversation` 内部渲染,没有对外 slot,因此走 DOM 注入);
|
|
136
|
+
- 交接流程:`remote.commands.execute(id, '/handover --where')` 取目录,拼文件名,`--write` 写入,`sessions.create({ cwd })` 建会话,`sessions.open(newId)` 切过去,`beginSubmission() + prompt()` 发送首条消息;
|
|
137
|
+
- 新会话尽力沿用当前会话的模型(`projectionValues.modelSelection` 转 `remote.session.selectModel`)。
|
|
138
|
+
|
|
139
|
+
## 源码结构
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
<仓库根目录>\
|
|
143
|
+
package.json # dsh.bundle.patch + dsh.client(platform: web) + exports["./client"]
|
|
144
|
+
cordis.patch.yml # 向 profile 树 insert 一行:id: context-actions
|
|
145
|
+
lib\index.js # 宿主半侧:/handover 命令 + 交接文档生成
|
|
146
|
+
lib\client.js # 浏览器半侧:面板按钮注入 + 两个动作
|
|
147
|
+
README.md # 使用与开发文档
|
|
148
|
+
CHANGELOG.md # 版本记录
|
|
149
|
+
LICENSE # MIT
|
|
150
|
+
test\ # node:test 单元测试(宿主 + 浏览器半侧)
|
|
151
|
+
.github\workflows\ # CI / Release
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
改动后同步到 profile(`dsh plugin add` 用的是硬链接副本,改同样的文件路径即可就地生效;新增文件需要重跑一次):
|
|
155
|
+
|
|
156
|
+
```powershell
|
|
157
|
+
dsh plugin --profile web add file:<仓库绝对路径>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## 排查
|
|
161
|
+
|
|
162
|
+
| 现象 | 处理 |
|
|
163
|
+
| --- | --- |
|
|
164
|
+
| 面板里没有按钮 | 刷新页面;确认 `dsh --profile web --dump-config` 里有 `context-actions` 行;看浏览器控制台里 `[dsh-context-actions]` 前缀的告警 |
|
|
165
|
+
| 交接报「宿主未注册 /handover 命令」 | 宿主半侧没加载,重启 dsh |
|
|
166
|
+
| 交接报「拒绝写入」 | 目标路径不在 `<系统临时目录>\dsh-handover` 内 |
|
|
167
|
+
| 压缩报「当前 agent 预设未挂载压缩后端」 | 见上一节 |
|
|
168
|
+
| 新建会话的首条消息没送达 | 状态行停在「已新建会话,但首条消息未送达」,会话已建好,手动把文档路径发过去即可 |
|
|
169
|
+
|
|
170
|
+
## 已知取舍
|
|
171
|
+
|
|
172
|
+
- 上下文面板是包内实现:选择器基于 `aria-haspopup=dialog` 加 `aria-label` 含 `%` 加 `role=dialog`,dsh 后续版本若改结构,需要同步调整 `lib/client.js` 里的 `findPanel()`。
|
|
173
|
+
- 交接文档默认是 **机械摘要**(日志的忠实节选):零 token、零延迟、内容可信;代价是没有「人话总结」。
|
|
174
|
+
开 `handover.mode: llm` 后正文改为模型总结(模型看不到你没想到要喂给它的东西,仍受截断与预算约束),附录依旧是脚本节选,便于核对。
|
|
175
|
+
- 「压缩」不做任何绕过预设的 hack,避免改掉部署的自动压缩行为。
|
|
176
|
+
|
|
177
|
+
## 开发与测试
|
|
178
|
+
|
|
179
|
+
```powershell
|
|
180
|
+
npm test # Node 内置 node:test,零依赖
|
|
181
|
+
npm run check # lib/index.js + lib/client.js 语法检查
|
|
182
|
+
npm run pack:dry # 预览 npm 包内容
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
测试分两层:
|
|
186
|
+
|
|
187
|
+
- `test/index.test.js`:用假 ctx/session 驱动真实的 `/handover` 命令链(参数解析、配置回退、路径校验、机械折叠、llm 回退)。
|
|
188
|
+
- `test/client.test.js`:用假 `window`/React 桩加载浏览器 bundle,校验 bundle 契约与「脚本节选 / 模型总结」字段显隐。
|
|
189
|
+
|
|
190
|
+
CI:push / PR 触发 Node 18、20、22 矩阵;推送 `v*` 标签触发 Release workflow —— 生成 GitHub Release,配置 `NPM_TOKEN` secret 后会同时发布到 npm(带 provenance)。
|
|
191
|
+
|
|
192
|
+
## 开源许可
|
|
193
|
+
|
|
194
|
+
MIT License,全文见 [LICENSE](LICENSE)。
|
|
195
|
+
|
|
196
|
+
## 参与贡献
|
|
197
|
+
|
|
198
|
+
- 提交 Issue / PR 前先跑:`npm test`(14 个零依赖单元测试)与 `npm run check`。
|
|
199
|
+
- 改完源码后用 `dsh plugin --profile web add file:<仓库绝对路径>` 重新同步到 profile,再重启 dsh(宿主半侧)并刷新页面(浏览器半侧)验证。
|
|
200
|
+
- 打包预览:`npm pack --dry-run`;正式打包:`npm pack --pack-destination dist`,产物为 `dsh-context-actions-0.1.0.tgz`。
|
|
201
|
+
- 仓库地址:<https://github.com/CN-Hang/dsh-context-actions>;如果你 fork 后发布,请把 `package.json` 里的 `author`、`repository`、`homepage` 换成你自己的信息。
|
package/cordis.patch.yml
ADDED