dsh-plugin-om 0.0.21 → 0.0.22
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/README.md +69 -159
- package/dist/client/OmCompactionCard.d.ts +5 -11
- package/dist/client/OmCompactionCard.d.ts.map +1 -1
- package/dist/client/definition.d.ts +17 -19
- package/dist/client/definition.d.ts.map +1 -1
- package/dist/client/format.d.ts +2 -2
- package/dist/client/format.d.ts.map +1 -1
- package/dist/client/index.d.ts +5 -11
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/locales.d.ts +2 -4
- package/dist/client/locales.d.ts.map +1 -1
- package/dist/client.js +17 -26
- package/dist/client.js.map +1 -1
- package/dist/compress.d.ts +15 -47
- package/dist/compress.d.ts.map +1 -1
- package/dist/config.d.ts +12 -21
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +10 -10
- package/dist/constants.d.ts.map +1 -1
- package/dist/embedding.d.ts +19 -36
- package/dist/embedding.d.ts.map +1 -1
- package/dist/index.d.ts +1 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +436 -722
- package/dist/json-schema.d.ts +4 -7
- package/dist/json-schema.d.ts.map +1 -1
- package/dist/log-index.d.ts +19 -12
- package/dist/log-index.d.ts.map +1 -1
- package/dist/logger.d.ts +3 -3
- package/dist/logger.d.ts.map +1 -1
- package/dist/model-download.d.ts +7 -11
- package/dist/model-download.d.ts.map +1 -1
- package/dist/rate-limit.d.ts +9 -14
- package/dist/rate-limit.d.ts.map +1 -1
- package/dist/recall-output.d.ts +37 -0
- package/dist/recall-output.d.ts.map +1 -0
- package/dist/recall.d.ts +7 -17
- package/dist/recall.d.ts.map +1 -1
- package/dist/semantic-recall.d.ts +10 -19
- package/dist/semantic-recall.d.ts.map +1 -1
- package/dist/summarize.d.ts +29 -46
- package/dist/summarize.d.ts.map +1 -1
- package/dist/types.d.ts +22 -35
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +9 -8
- package/dist/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,48 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/dsh-plugin-om)
|
|
4
4
|
|
|
5
|
-
在 DSH 里应用 [Observational Memory](https://mastra.ai/research/observational-memory)
|
|
5
|
+
在 DSH 里应用 [Observational Memory](https://mastra.ai/research/observational-memory) 风格的上下文管理策略:自动把历史消息压缩为摘要,并提供工具回看原始内容。
|
|
6
6
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
### 说明
|
|
7
|
+
## 功能
|
|
10
8
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
9
|
+
- **自动压缩**(仅主会话,`agent/pre-step` 时阻塞串行执行):
|
|
10
|
+
- **观察**:净压力(上下文压力 − 已压缩 `<history>` 块 token 估算合计)≥ `observeThresholdTokens` 时,摘要未压缩消息并追加为新 `<history>` 块,精确替换被压缩的消息区间(旧块保留)
|
|
11
|
+
- **反思**:全部 `<history>` 块 token 合计 ≥ `reflectThresholdTokens` 时,把多个摘要块合并为一条更紧凑的摘要
|
|
12
|
+
- **输出容错**:摘要输出按首个 `<history>` 开标签到最后一个 `</history>` 定位;整块 XML 非法时按条目标签模糊提取并重建为合法块,再校验无 reasoning 与 index 连续
|
|
13
|
+
- **recall 工具**:按完整消息 index 区间回看原始会话(含被压缩内容;命中消息中的图片附件随结果保留)
|
|
14
|
+
- **recall-semantic 工具**:本地嵌入模型(paraphrase-multilingual-MiniLM-L12-v2)按语义检索全部完整消息(只匹配文本,纯图片消息不进候选池)
|
|
15
|
+
- **压缩卡片**:浏览器客户端在消息列表渲染折叠式「已压缩」卡片与「正在压缩上下文(观察/反思)…」提示行
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
## 安装与启用
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
- `$DSH_HOME` 缺省为 `~/.dsh`;*profile* 描述 dsh 进程的启动模式(官方启动命令即名为 `web` 的 profile)
|
|
17
20
|
|
|
18
21
|
```sh
|
|
19
22
|
dsh plugin --profile <profile> add dsh-plugin-om
|
|
20
23
|
```
|
|
21
24
|
|
|
22
|
-
>
|
|
23
|
-
> 插件的依赖 `@huggingface/transformers` 自带原生构建脚本,pnpm 11 默认禁止依赖构建脚本,并会抛出异常。
|
|
24
|
-
> 把 `$DSH_HOME/profiles/<profile>/pnpm-workspace.yaml` 的 `allowBuilds` 改为 `true` 即可
|
|
25
|
-
> 或者使用`dsh plugin --profile <profile> add dsh-plugin-om --allow-build=onnxruntime-node --allow-build=protobufjs --allow-build=sharp`
|
|
26
|
-
|
|
27
|
-
安装完成后,需要重启dsh
|
|
25
|
+
安装完成后重启 dsh;可用 `dsh --profile <profile> --dump-config` 审查配置。
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
> pnpm 11+ 默认禁止依赖构建脚本,安装失败时把 `$DSH_HOME/profiles/<profile>/pnpm-workspace.yaml` 的 `allowBuilds` 改为 `true`,或使用
|
|
28
|
+
> `dsh plugin --profile <profile> add dsh-plugin-om --allow-build=onnxruntime-node --allow-build=protobufjs --allow-build=sharp`
|
|
30
29
|
|
|
31
|
-
|
|
30
|
+
覆盖默认配置:编辑 `$DSH_HOME/profiles/<profile>/cordis.patch.yml`,删除空数组并加入(可热更新):
|
|
32
31
|
|
|
33
32
|
```yaml
|
|
34
33
|
- id: dsh-plugin-om
|
|
35
34
|
config:
|
|
36
|
-
observeThresholdTokens:
|
|
37
|
-
# 其他配置参考下文
|
|
35
|
+
observeThresholdTokens: 35000
|
|
38
36
|
```
|
|
39
37
|
|
|
40
|
-
不需要重启 可以热更新
|
|
41
|
-
|
|
42
38
|
### 开发插件
|
|
43
39
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
在 `cordis.patch.yml` 里加入
|
|
40
|
+
运行 `pnpm dev` 构建(本地嵌入模型运行时自动下载,也可 `pnpm run download:model` 预下载),在 `cordis.patch.yml` 加入(可热重载):
|
|
47
41
|
|
|
48
42
|
```yaml
|
|
49
43
|
- insert:
|
|
@@ -51,152 +45,68 @@ dsh plugin --profile <profile> add dsh-plugin-om
|
|
|
51
45
|
name: file:///<repo>/dist/index.mjs
|
|
52
46
|
```
|
|
53
47
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
### 关于`compaction-basic`
|
|
57
|
-
|
|
58
|
-
dsh的"预设"分为两层,`dsh web`等同于`dsh --profile web`,调用的是"名为web的profile",进程上的预设
|
|
59
|
-
|
|
60
|
-
而`web-profile`里定义了多个"预设agent"`preset-agent` 这里主要说的是`preset-agent`的问题
|
|
61
|
-
|
|
62
|
-
`preset-agent`配置里自带一个`compaction-basic`,会在到达阈值后做简单的摘要,与此插件冲突。
|
|
63
|
-
|
|
64
|
-
由于配置注入的顺序是层级低的覆盖层级高的,所以`cordis.patch.yml`对`compaction-basic`的禁用不会生效。
|
|
65
|
-
|
|
66
|
-
此外,这个插件位于`preset-agent`的定义而非额外的安装,也无法通过`dsh plugin`卸载。
|
|
67
|
-
|
|
68
|
-
解决方案:
|
|
69
|
-
|
|
70
|
-
- 直接改`preset-agent`的定义(不推荐)
|
|
71
|
-
- 定义不含`compaction-basic`的`preset-agent`
|
|
72
|
-
- `compaction-basic`压缩阈值是80%上下文窗口,而OM的观察阈值是绝对 token 数(默认 `observeThresholdTokens`=100000):模型窗口小于该值/0.8(即 12.5 万 tokens)时宿主强制摘要会先于 OM 触发,需要把 `observeThresholdTokens` 调低到窗口的 0.8 以下
|
|
73
|
-
|
|
74
|
-
## 工作原理
|
|
48
|
+
### 与 compaction-basic 的关系
|
|
75
49
|
|
|
76
|
-
|
|
77
|
-
2. 将新生成摘要追加到已有摘要后(每条压缩日志是独立的消息/块,旧块原地保留)
|
|
78
|
-
3. 如果摘要总长到达反思阈值,对其本身进行摘要(把全部 <history> 块拼接合并为一条)
|
|
79
|
-
4. 提供recall/recall-semantic两个tool进行检索
|
|
80
|
-
|
|
81
|
-
观察与反思共用同一套系统提示词(buildHistoryPrompt):输入与输出都是合法的 <history> 块(模型消息 + index 的表达形式),先定义块、要求压缩、再给出数据源(下方 <history> 消息记录)。
|
|
82
|
-
观察压缩按 `observeChunkTokens` 边界把未压缩消息分块(完整消息不跨块,thinking/text/toolcall&result 同块)压缩摘要,最多 `observeChunkParallelism` 块同时进行、其余块排队,各块合并为一个 <history> 块提交;提示词按块位次分档——前块要求简单摘要,最后一块要求「越往后越细」保留细节。任一摘要请求遇 429 限流后,插件全局进入冷却期:后续所有摘要请求在 `rateLimitWaitMs` 内不会发出。
|
|
83
|
-
|
|
84
|
-
### 压缩日志块结构
|
|
85
|
-
|
|
86
|
-
- 观察压缩只精确替换被压缩的新消息区间:旧 <history> 块保留为独立消息,新观察日志作为新块追加在其后(多块并存按序排列),历史不会随压缩次数膨胀;反思合并时才把多个块合并为一条更紧凑的摘要
|
|
87
|
-
- 压缩边界:消息列表中最后一个合法的 <history> 块(source 为插件,plugin 为插件标识 `dsh-plugin-om`;兼容旧日志的宿主 checkpoint 标记 `compact`)之后的消息视为未压缩;其前(含自身)视为已压缩,不重复压缩、不计入观察阈值
|
|
88
|
-
- 观察输入经 `@xmldom/xmldom` 构建为合法 <history> 块(用户消息文本/assistant 文本/reasoning 特殊字符自动转义,图片/文件以注释补充;assistant 文本与 toolcall&result 原样;系统消息——user_message 中 source.kind 非 user 的部分,如宿主注入的上下文——渲染为 <sys type="KIND" index="N"></sys> 空块,内容不进入压缩输入)
|
|
89
|
-
- 输出经 `@xmldom/xmldom` 解析校验:结构合法(标签匹配/闭合/单块)、不含 <reasoning>、index/start/end 连续(与预期覆盖区间一致),失败按 `compressRetryCount` 重试;观察分块时每块独立校验(预期覆盖各自 index 区间,失败按 `compressRetryCount` 重试),各块校验通过后再合并为一个 <history> 块提交
|
|
90
|
-
- 块开标签带 `tip` 属性(对 AI 的提醒:"当前块是历史消息的压缩产物,不要复述");块顶为构成逻辑注释(完整消息定义串 + 条目标签语义),消息正文不再附加前缀句
|
|
91
|
-
- 压缩生命周期:每次摘要调用前先追加 `compaction/start`(载荷带 `phase`:`observe`/观察 或 `reflect`/反思,客户端据此渲染「正在压缩上下文(观察/反思)…」提示行);摘要成功提交 summary + 替换消息 + end,summary 载荷带 `attemptCount`(重试次数;观察分块为各块重试之和,反思为尝试次数 - 1);摘要失败或重试耗尽时追加 `compaction/end(error)` 关闭生命周期(不产生 summary/替换),客户端随之撤回提示行
|
|
92
|
-
|
|
93
|
-
### 压缩卡片(消息列表中的「已压缩」展示)
|
|
94
|
-
|
|
95
|
-
插件自产的替换消息使用插件自身标记(source.plugin = `dsh-plugin-om`);宿主 conversation UI 只识别内置的 `compact` 检查点,因此插件额外注册一个浏览器客户端 bundle(`src/client/`,经 `dsh.client` 声明、exports["./client"] → `dist/client.js`,由 dsh 客户端模块系统按 `/plugins/dsh-plugin-om/client.js` 加载),自行认领压缩生命周期事件与替换检查点,在消息列表渲染折叠式「已压缩」卡片:
|
|
96
|
-
|
|
97
|
-
- 卡片默认折叠,采用与宿主「上下文注入」卡片同款样式:同一 DisclosureRow 外壳组件 + IconBrowseOutline16 图标,行内统计与展开体样式按宿主 ContextInjectionRow 的规则注入(插件 bundle 无法引用宿主编译期哈希的 CSS Module 类名,按宿主 client bundle 的同一机制注入 <style>),视觉一致
|
|
98
|
-
- 标题直接展示紧凑统计「N 条 · X 字符(A tokens)→ Y 字符(B tokens)」,数字按 k/w/M 单位化(≥1k 用 k、≥1w 用 w、≥1M 用 M,如 8.6k/3.5w/1.2M):压缩前字符数来自插件扩展 shadowedCharCount,压缩前 token 来自 shadowedTokenCount,压缩后字符数为摘要文本长度,压缩后 token 在客户端按 4 字符 ≈ 1 token 估算(与服务端 estimateTextTokens 同一启发式);旧会话载荷缺少 shadowedCharCount 时回落为「已压缩 N 条历史记录(约 M tokens)」
|
|
99
|
-
- 点击展开显示压缩摘要文本,按代码块样式呈现(缩小字号、代码背景与等宽字体、保留换行)
|
|
100
|
-
- summary 事件落在当前加载窗口之外时卡片不可展开(不显示空内容)
|
|
101
|
-
- 卡片只认领插件自产的检查点(source.plugin = `dsh-plugin-om`);宿主 `compact` 检查点仍由宿主自己渲染,不会出现双卡片
|
|
102
|
-
- 压缩进行中(`compaction/start` 已到、summary/检查点未到):渲染不可展开的「正在压缩上下文(观察/反思)…」提示行,按 start 载荷的 `phase` 区分文案(旧会话无 phase 时回落通用文案);压缩失败收到 `compaction/end` 时以 hidden 可见性撤回提示行
|
|
103
|
-
- summary 载荷带 `attemptCount`(重试次数)时,重试次数 > 0 在标题统计行追加「重试 N 次」(无重试不显示;旧载荷无 attemptCount 时不显示)
|
|
104
|
-
- 平台模块(react / cordis / ui-primitives / ui-slots 等)走宿主冻结模块表(保持 external),其余依赖内联进 bundle
|
|
105
|
-
|
|
106
|
-
### 注意
|
|
107
|
-
|
|
108
|
-
- 未压缩消息的 token 统计排除系统消息(user_message 中 source.kind 非 user 的部分,如宿主注入的上下文;宿主注入的提醒不计入观察阈值的触发量)
|
|
109
|
-
- recall 不截断,建议保留 `tool-result-pruner`
|
|
110
|
-
- recall-semantic 使用本地多语言嵌入模型(paraphrase-multilingual-MiniLM-L12-v2),
|
|
111
|
-
|
|
112
|
-
### 依赖策略
|
|
113
|
-
|
|
114
|
-
- dsh宿主提供的依赖,直接复用即可,如 cordis / dsh-tools / zod 等
|
|
115
|
-
- `@xmldom/xmldom` 用于 <history> 块的 XML 构建(输入转义)与解析校验(输出结构合法性),经 tsdown `deps.alwaysBundle` 打包进 dist 产物
|
|
116
|
-
- 浏览器客户端 bundle(`src/client/` → `dist/client.js`)复用宿主冻结模块表:react / cordis / @deepseek-ai/dsh-client-ui-primitives / dsh-client-ui-slots 等平台种子与 runtime/client 豁免保持 external,其余依赖内联;相关 @deepseek-ai/dsh-client-* 仅作 devDependencies(类型与构建期使用)
|
|
117
|
-
- 向量模型模型二进制:量化 ONNX 约 113MB,启用语义召回时下载,位置`$DSH_HOME/plugin-data/dsh-plugin-om/models/<id>/onnx/model_quantized.onnx`。下载失败可以设置`HF_ENDPOINT=https://hf-mirror.com`
|
|
50
|
+
preset-agent 自带 `compaction-basic` 压缩,也会压缩上下文,其压缩阈值为 80% 上下文窗口,一般会先用om进行压缩。
|
|
118
51
|
|
|
119
52
|
## 插件配置项
|
|
120
53
|
|
|
121
|
-
| 键
|
|
122
|
-
|
|
|
123
|
-
| `observeThresholdTokens` | `
|
|
124
|
-
| `reflectThresholdTokens` | `
|
|
125
|
-
| `compressMaxTokens`
|
|
126
|
-
| `
|
|
127
|
-
| `
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
130
|
-
| `
|
|
131
|
-
| `
|
|
132
|
-
| `
|
|
133
|
-
| `
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
| `semanticRecallEnabled` | `true` | 是否注册 `recall-semantic` 工具(`false` 时禁用,不注册、不触发模型下载) |
|
|
137
|
-
|
|
138
|
-
> 不建议将观察阈值设置得过高:越早 OM 收益越高,且当前的机制需要模型对消息计数,过多的消息会导致历史混乱
|
|
139
|
-
|
|
140
|
-
### 关于配置项变更的说明
|
|
141
|
-
|
|
142
|
-
配置键 `omEnabled` 替代了原 `summaryMode`:现在只能通过 `omEnabled` 开启或关闭 OM。
|
|
143
|
-
|
|
144
|
-
现在消息调用会固定新开会话,而取消了fork主会话的链路。fork 方式虽然能复用前缀缓存,但需要模型自行对消息计数,会导致严重的索引异常。
|
|
54
|
+
| 键 | 默认 | 含义 |
|
|
55
|
+
| --- | --- | --- |
|
|
56
|
+
| `observeThresholdTokens` | `35000` | 观察阈值(tokens):净压力 ≥ 该值时触发观察压缩 |
|
|
57
|
+
| `reflectThresholdTokens` | `40000` | 反思阈值(tokens):全部 `<history>` 块 token 合计 ≥ 该值时触发合并 |
|
|
58
|
+
| `compressMaxTokens` | `5000` | 单次摘要生成上限 |
|
|
59
|
+
| `rateLimitWaitMs` | `60000` | 遇 429 限流后下一次摘要请求前的等待毫秒数(全局冷却期;`0` 不限流) |
|
|
60
|
+
| `tailMessageCount` | `5` | 尾部保留的不压缩消息条数 |
|
|
61
|
+
| `compressRetryCount` | `5` | 摘要失败后的最大重试次数(不含首次) |
|
|
62
|
+
| `modelDir` | 共享目录 | recall-semantic 嵌入模型目录(默认 `$DSH_HOME/plugin-data/dsh-plugin-om/models/<id>`,onnx 缺失且启用语义召回时运行时自动下载) |
|
|
63
|
+
| `omEnabled` | `true` | 是否启用自动压缩(`false` 时关闭,recall 工具不受影响) |
|
|
64
|
+
| `debug` | dev | 步骤级日志开关(缺省按 `NODE_ENV !== 'production'` 判定;失败日志始终输出) |
|
|
65
|
+
| `recallEnabled` | `true` | 是否注册 `recall` 工具 |
|
|
66
|
+
| `semanticRecallEnabled` | `true` | 是否注册 `recall-semantic` 工具(`false` 时不注册、不触发模型下载) |
|
|
67
|
+
|
|
68
|
+
> 不建议把观察阈值设置得过高:越早压缩收益越高,且机制依赖模型对消息计数,过多消息会导致历史混乱。
|
|
145
69
|
|
|
146
70
|
## npm 命令
|
|
147
71
|
|
|
148
|
-
| 命令
|
|
149
|
-
|
|
|
150
|
-
| `pnpm check`
|
|
151
|
-
| `pnpm typecheck`
|
|
152
|
-
| `pnpm lint` / `pnpm format` | 代码检查 / 格式化
|
|
153
|
-
| `pnpm test`
|
|
154
|
-
| `pnpm run download:model`
|
|
155
|
-
| `pnpm build`
|
|
156
|
-
| `pnpm
|
|
157
|
-
| `pnpm run release` | 先跑 check(typecheck+lint+test+build),再 CHANGELOG 归档 + 版本号更新 + 打 tag 推送 |
|
|
72
|
+
| 命令 | 作用 |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| `pnpm check` | typecheck + lint + test + build |
|
|
75
|
+
| `pnpm typecheck` | TypeScript 类型检查 |
|
|
76
|
+
| `pnpm lint` / `pnpm format` | 代码检查 / 格式化 |
|
|
77
|
+
| `pnpm test` | vitest 单元测试 |
|
|
78
|
+
| `pnpm run download:model` | 手动预下载嵌入模型(已存在跳过,`--force` 重下) |
|
|
79
|
+
| `pnpm build` / `pnpm dev` | 构建 / 自动打包 |
|
|
80
|
+
| `pnpm run release` | check → CHANGELOG 归档 → 版本号更新 → 打 tag 推送 |
|
|
158
81
|
|
|
159
|
-
##
|
|
82
|
+
## 文件地图
|
|
160
83
|
|
|
161
84
|
```
|
|
162
|
-
cordis.patch.yml
|
|
85
|
+
cordis.patch.yml # bundle patch:dsh plugin add 后作为组合层插入插件行
|
|
163
86
|
src/
|
|
164
|
-
├── index.ts #
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
├──
|
|
179
|
-
|
|
180
|
-
├──
|
|
181
|
-
├──
|
|
182
|
-
├──
|
|
183
|
-
├──
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
├── semantic-recall.ts # recall-semantic 工具(query 语义检索 + 区间限定 + 回退全量 + 匹配说明)
|
|
189
|
-
└── compress.ts # 两级自动压缩(测量 / mid-turn 区间计算 / 配对平衡回退 / source 标记判定摘要消息 / 观察分块经 runWithConcurrency 有界并发池逐块压缩 + 合并 mergeChunkReports / compaction/* 生命周期事件:start 在摘要调用前追加并带 phase,失败补 end(error) + 替换消息 source 插件标识)
|
|
190
|
-
src/client/
|
|
191
|
-
├── index.ts # 浏览器客户端入口(exports["./client"] → dist/client.js):注入 slots/conversationEvents/locale,注册卡片定义与渲染器
|
|
192
|
-
├── definition.ts # 压缩卡片业务定义:认领插件生命周期事件与替换检查点(source.plugin = dsh-plugin-om),聚合摘要卡片节点;start→压缩中提示行(running+phase)、end→hidden 撤回、summary→卡片(retryCount)
|
|
193
|
-
├── OmCompactionCard.tsx # 与宿主「上下文注入」同款的折叠卡片渲染器(统计标题 + 代码块样式 summary 展开)
|
|
194
|
-
└── locales.ts # om-compaction 命名空间字典(zh/en)与 LocaleNamespaceMap 声明合并
|
|
195
|
-
models/
|
|
196
|
-
└── paraphrase-multilingual-MiniLM-L12-v2/ # 嵌入模型目录(小文件随包分发;onnx 二进制不随包分发、由运行时按需下载到跨版本共享目录,不进 git)
|
|
197
|
-
scripts/ # release-archive.mjs(CHANGELOG 归档)/ download-model.mjs(开发手动预下载 CLI)
|
|
198
|
-
tests/ # vitest 单元测试(服务端 src 各模块 + tests/client/ 客户端卡片定义)
|
|
199
|
-
.dsh/skills/ # 项目级 skill(feature-defect-workflow:需求/缺陷完成工作流)
|
|
87
|
+
├── index.ts # 打包入口:注册 recall 工具 + 接线 pre-step 自动压缩
|
|
88
|
+
├── config.ts # 配置默认值与宽松合并(未知键忽略、非法值回退默认)
|
|
89
|
+
├── constants.ts # 共享常量(插件标识 / history 标签 / 完整消息定义)
|
|
90
|
+
├── types.ts # type-only:宿主类型再导出 + 领域类型
|
|
91
|
+
├── utils.ts # 零依赖工具函数(文本渲染 / 主会话判定 / 路由解析)
|
|
92
|
+
├── logger.ts # 插件日志门面(step 按 debug 开关过滤)
|
|
93
|
+
├── rate-limit.ts # 全局 429 限流冷却门(进程级共享状态)
|
|
94
|
+
├── log-index.ts # 完整消息索引与渲染(recall 与摘要共用同一套编号)
|
|
95
|
+
├── recall.ts # recall 工具:按完整消息 index 区间回看
|
|
96
|
+
├── recall-output.ts # recall 输出契约:{ text, images } 与 render 投影
|
|
97
|
+
├── semantic-recall.ts # recall-semantic 工具:本地嵌入语义检索
|
|
98
|
+
├── embedding.ts # 本地 ONNX 嵌入(懒加载 / 批量 / 运行时按需下载编排)
|
|
99
|
+
├── model-download.ts # 模型下载原语(URL / 跳过判定 / 原子落盘)
|
|
100
|
+
├── summarize.ts # 共享压缩提示词 + <history> 块渲染与输出校验 + 摘要调用
|
|
101
|
+
├── compress.ts # 两级自动压缩(观察/反思)与 compaction 生命周期事件
|
|
102
|
+
└── client/ # 浏览器客户端 bundle(压缩卡片)
|
|
103
|
+
├── index.ts # 客户端入口:注册卡片定义与渲染器
|
|
104
|
+
├── definition.ts # 压缩卡片业务定义(认领生命周期事件与替换检查点)
|
|
105
|
+
├── OmCompactionCard.tsx # 折叠卡片渲染器(统计标题 + summary 展开)
|
|
106
|
+
├── format.ts # 统计数字紧凑格式化(k/w/M)
|
|
107
|
+
└── locales.ts # om-compaction 文案字典(zh/en)
|
|
108
|
+
models/ # 嵌入模型目录(小文件随包分发;onnx 运行时按需下载,不进 git)
|
|
109
|
+
scripts/ # release-archive.mjs(CHANGELOG 归档)/ download-model.mjs(预下载 CLI)
|
|
110
|
+
tests/ # vitest 单元测试(服务端各模块 + tests/client/ 客户端卡片)
|
|
200
111
|
```
|
|
201
112
|
|
|
202
|
-
## TODO
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* 的样式是编译期哈希的 CSS Module,插件 bundle 无法引用其类名,故按宿主 client
|
|
7
|
-
* bundle 的同一机制(注入 <style>)注册逐字一致的规则,保证视觉同款。
|
|
8
|
-
*
|
|
9
|
-
* 压缩检查点遮蔽的是模型可见表层,人类转录中的历史仍在其上方;卡片只报告
|
|
10
|
-
* 模型从何处起不再看到那段历史。summary 来自检查点引用的 compaction/summary
|
|
11
|
-
* 事件;窗口裁剪把该事件留在窗外时,行不可展开而不是显示空内容。
|
|
2
|
+
* 压缩卡片渲染器:与宿主「上下文注入」卡片同款的折叠行。
|
|
3
|
+
* 复用平台原语 DisclosureRow;行内统计与展开体样式按宿主 ContextInjectionRow 的规则
|
|
4
|
+
* 注入 <style>(宿主该卡片样式是编译期哈希的 CSS Module,插件 bundle 无法引用其类名)。
|
|
5
|
+
* 卡片报告模型从何处起不再看到那段历史;summary 留在加载窗口外时行不可展开。
|
|
12
6
|
*/
|
|
13
7
|
import type { ChatNode } from '@deepseek-ai/dsh-client-ui-conversation/client';
|
|
14
8
|
import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
|
|
@@ -17,6 +11,6 @@ export interface OmCompactionCardProps {
|
|
|
17
11
|
readonly node: ChatNode<'om-compaction'>;
|
|
18
12
|
readonly t: TranslateNS<'om-compaction'>;
|
|
19
13
|
}
|
|
20
|
-
/** 折叠式压缩卡片(统计标题行 + 代码块样式 summary
|
|
14
|
+
/** 折叠式压缩卡片(统计标题行 + 代码块样式 summary 展开)。 */
|
|
21
15
|
export declare const OmCompactionCard: import("react").MemoExoticComponent<({ node, t }: OmCompactionCardProps) => import("react").JSX.Element>;
|
|
22
16
|
//# sourceMappingURL=OmCompactionCard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OmCompactionCard.d.ts","sourceRoot":"","sources":["../../src/client/OmCompactionCard.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"OmCompactionCard.d.ts","sourceRoot":"","sources":["../../src/client/OmCompactionCard.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAE/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAKpE,0EAA0E;AAC1E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IACzC,QAAQ,CAAC,CAAC,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC;CAC1C;AAgCD,yCAAyC;AACzC,eAAO,MAAM,gBAAgB,oDAA+C,qBAAqB,iCAsF/F,CAAC"}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* PLUGIN_LABEL('dsh-plugin-om'),由本定义认领。生命周期事件(compaction/start
|
|
8
|
-
* |summary|end)同时会被宿主的 compactionDefinition 匹配,但宿主没有检查点证据
|
|
9
|
-
* 时不产出节点(buildViewNode 返回 null),因此双方共存无视觉冲突。
|
|
2
|
+
* 压缩卡片业务定义:认领插件自产的压缩生命周期事件(compaction/start|summary|end)
|
|
3
|
+
* 与替换检查点(source.plugin = 'dsh-plugin-om'),聚合出可渲染的摘要卡片节点。
|
|
4
|
+
* 导出 COMPACTION_CARD_KIND / OmCompactionChatData / checkpointCompactionId /
|
|
5
|
+
* omCompactionDefinition。宿主的 'compact' 检查点由宿主自己渲染,本定义不认领
|
|
6
|
+
* (双方共存无视觉冲突:宿主无检查点证据时不产出节点)。
|
|
10
7
|
*/
|
|
11
8
|
import type { ConversationMatch, ConversationNodeDefinition } from '@deepseek-ai/dsh-client-runtime/client';
|
|
12
9
|
import type { SessionEvent } from '@deepseek-ai/dsh-session/types';
|
|
@@ -18,11 +15,11 @@ declare module '@deepseek-ai/dsh-client-ui-conversation/client' {
|
|
|
18
15
|
'om-compaction': OmCompactionChatData;
|
|
19
16
|
}
|
|
20
17
|
}
|
|
21
|
-
/**
|
|
18
|
+
/** 压缩卡片载荷:摘要文本与遮蔽统计。 */
|
|
22
19
|
export interface OmCompactionChatData {
|
|
23
|
-
/** 压缩进行中(
|
|
20
|
+
/** 压缩进行中(start 已到、checkpoint/end 未到):渲染为「正在压缩上下文…」提示行。 */
|
|
24
21
|
readonly running: boolean;
|
|
25
|
-
/** 压缩 pass(观察/反思;来自 start
|
|
22
|
+
/** 压缩 pass(观察/反思;来自 start 事件载荷扩展,缺失或非运行态为 null)。 */
|
|
26
23
|
readonly phase: 'observe' | 'reflect' | null;
|
|
27
24
|
/** compaction/summary 的文本摘要;窗口裁剪把该事件留在窗外时为 null(卡片不可展开)。 */
|
|
28
25
|
readonly summary: string | null;
|
|
@@ -32,13 +29,13 @@ export interface OmCompactionChatData {
|
|
|
32
29
|
readonly shadowedItemCount: number | null;
|
|
33
30
|
/** 遮蔽的 token 数,summary 事件缺失或载荷非法时为 null。 */
|
|
34
31
|
readonly shadowedTokenCount: number | null;
|
|
35
|
-
/**
|
|
32
|
+
/** 压缩前的字符数,载荷缺失或非法时为 null。 */
|
|
36
33
|
readonly shadowedCharCount: number | null;
|
|
37
34
|
/** 压缩后的字符数(摘要文本长度),summary 不可用或非法时为 null。 */
|
|
38
35
|
readonly summaryCharCount: number | null;
|
|
39
|
-
/** 压缩后的估算 token 数(4 字符 ≈ 1 token
|
|
36
|
+
/** 压缩后的估算 token 数(4 字符 ≈ 1 token),summary 不可用或非法时为 null。 */
|
|
40
37
|
readonly summaryTokenCount: number | null;
|
|
41
|
-
/**
|
|
38
|
+
/** 摘要调用重试次数,载荷缺失或非法时为 null。 */
|
|
42
39
|
readonly retryCount: number | null;
|
|
43
40
|
}
|
|
44
41
|
/** 压缩生命周期关联状态:summary / checkpoint / end 事件证据。 */
|
|
@@ -49,14 +46,15 @@ interface OmCompactionState {
|
|
|
49
46
|
readonly end?: ConversationMatch;
|
|
50
47
|
}
|
|
51
48
|
/**
|
|
52
|
-
* 从压缩替换检查点(user/message + replace surface + source.plugin
|
|
53
|
-
*
|
|
54
|
-
* 避免同一压缩出现两张卡片。
|
|
49
|
+
* 从压缩替换检查点(user/message + replace surface + source.plugin 为本插件)读取
|
|
50
|
+
* 关联 compactionId;其余事件返回 undefined。
|
|
55
51
|
*/
|
|
56
52
|
export declare function checkpointCompactionId(event: SessionEvent): string | undefined;
|
|
57
53
|
/**
|
|
58
|
-
* 插件压缩生命周期定义:compaction/start 开启上下文,summary / 替换检查点 /
|
|
59
|
-
*
|
|
54
|
+
* 插件压缩生命周期定义:compaction/start 开启上下文,summary / 替换检查点 / end
|
|
55
|
+
* 作为 update 折叠证据。有检查点时产出摘要卡片;无检查点的 end 以 hidden 撤回
|
|
56
|
+
* 进行中提示行(已物化节点以 hidden visibility 保留同一 key);仅 start 时渲染
|
|
57
|
+
* 「正在压缩上下文…」提示行。
|
|
60
58
|
*/
|
|
61
59
|
export declare const omCompactionDefinition: ConversationNodeDefinition<OmCompactionState>;
|
|
62
60
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/client/definition.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/client/definition.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,iBAAiB,EAEjB,0BAA0B,EAC3B,MAAM,wCAAwC,CAAC;AAGhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAInE,uCAAuC;AACvC,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AAEpD,OAAO,QAAQ,gDAAgD,CAAC;IAC9D,UAAU,eAAe;QACvB,sCAAsC;QACtC,eAAe,EAAE,oBAAoB,CAAC;KACvC;CACF;AAED,wBAAwB;AACxB,MAAM,WAAW,oBAAoB;IACnC,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC;IAC7C,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gDAAgD;IAChD,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,0CAA0C;IAC1C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,4CAA4C;IAC5C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,8BAA8B;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,6CAA6C;IAC7C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,4DAA4D;IAC5D,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,+BAA+B;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,kDAAkD;AAClD,UAAU,iBAAiB;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;IACxC,oEAAoE;IACpE,QAAQ,CAAC,GAAG,CAAC,EAAE,iBAAiB,CAAC;CAClC;AAgBD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAe9E;AAwGD;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,0BAA0B,CAAC,iBAAiB,CAsDhF,CAAC"}
|
package/dist/client/format.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* 压缩卡片统计行的紧凑数字格式化。导出 formatCompactCount。
|
|
3
|
+
* <1k 原样;≥1k 用 k;≥1w(万)用 w;≥1M 用 M;保留 1 位小数并去掉末尾 .0。
|
|
4
4
|
*/
|
|
5
5
|
export declare function formatCompactCount(value: number): string;
|
|
6
6
|
//# sourceMappingURL=format.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/client/format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/client/format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CASxD"}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* bundle 自行注册一条 conversation 业务定义 + keyed 渲染器,认领插件的压缩
|
|
7
|
-
* 生命周期事件与替换检查点,在消息列表渲染「已压缩」卡片。
|
|
2
|
+
* 浏览器客户端入口(exports["./client"] → dist/client.js):注册压缩卡片的
|
|
3
|
+
* locale 字典、conversation 业务定义与 keyed 渲染器。宿主 conversation UI 只识别
|
|
4
|
+
* 内置 'compact' 检查点,插件自产的压缩检查点(source.plugin = 'dsh-plugin-om')
|
|
5
|
+
* 由本 bundle 认领并在消息列表渲染「已压缩」卡片。
|
|
8
6
|
*/
|
|
9
7
|
import type { Context } from '@deepseek-ai/cordis';
|
|
10
8
|
/** Required services: 聊天节点槽、会话事件注册表与 locale 服务。 */
|
|
11
9
|
export declare const inject: string[];
|
|
12
|
-
/**
|
|
13
|
-
* Client plugin body: 注册压缩卡片的业务定义与 keyed 渲染器。
|
|
14
|
-
* 注册挂在 effect 包装器上,插件卸载时随之移除。
|
|
15
|
-
* @param ctx - client root context.
|
|
16
|
-
*/
|
|
10
|
+
/** Client plugin body: 注册压缩卡片的业务定义与 keyed 渲染器(随插件卸载移除)。 */
|
|
17
11
|
export declare function apply(ctx: Context): void;
|
|
18
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAWnD,mDAAmD;AACnD,eAAO,MAAM,MAAM,UAA4C,CAAC;AAEhE,2DAA2D;AAC3D,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAexC"}
|
package/dist/client/locales.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `om-compaction` namespace
|
|
3
|
-
*
|
|
4
|
-
* 与宿主 conversation 命名空间分离(独立 NS),插件卡片走自己的 keyed 渲染器,
|
|
5
|
-
* 文案键不与对话插件的键冲突。
|
|
2
|
+
* `om-compaction` namespace 字典:插件压缩卡片的界面文案(zh/en)。
|
|
3
|
+
* 导出 NS / zh / en;zh 为键集事实源,en 键集与 zh 一致。
|
|
6
4
|
*/
|
|
7
5
|
/** Dictionary namespace owned by this plugin. */
|
|
8
6
|
export declare const NS = "om-compaction";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../src/client/locales.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../src/client/locales.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,iDAAiD;AACjD,eAAO,MAAM,EAAE,kBAAkB,CAAC;AAElC,mEAAmE;AACnE,eAAO,MAAM,EAAE;;;;;;;;;;CAWL,CAAC;AAEX,qCAAqC;AACrC,eAAO,MAAM,EAAE,EAAE,MAAM,CAAC,MAAM,OAAO,EAAE,EAAE,MAAM,CAW9C,CAAC;AAEF,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,mDAAmD;QACnD,eAAe,EAAE,MAAM,OAAO,EAAE,CAAC;KAClC;CACF"}
|
package/dist/client.js
CHANGED
|
@@ -13,17 +13,16 @@ window.__ModuleLoader__.load({
|
|
|
13
13
|
const COMPACTION_CARD_KIND = "om-compaction";
|
|
14
14
|
/**
|
|
15
15
|
* replace-surface 判定:surfaceOp 为 { op: 'replace' } 对象(与宿主 runtime 的
|
|
16
|
-
* isReplacementSurfaceEvent
|
|
17
|
-
*
|
|
16
|
+
* isReplacementSurfaceEvent 同义;宿主该助手位于浏览器 bundle,node 端测试无法求值,
|
|
17
|
+
* 故本地实现同一形状检查)。
|
|
18
18
|
*/
|
|
19
19
|
function isReplacementSurface(event) {
|
|
20
20
|
const surfaceOp = event.surfaceOp;
|
|
21
21
|
return typeof surfaceOp === "object" && surfaceOp !== null && surfaceOp.op === "replace";
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
|
-
* 从压缩替换检查点(user/message + replace surface + source.plugin
|
|
25
|
-
*
|
|
26
|
-
* 避免同一压缩出现两张卡片。
|
|
24
|
+
* 从压缩替换检查点(user/message + replace surface + source.plugin 为本插件)读取
|
|
25
|
+
* 关联 compactionId;其余事件返回 undefined。
|
|
27
26
|
*/
|
|
28
27
|
function checkpointCompactionId(event) {
|
|
29
28
|
if (event.type !== "user/message" || !isReplacementSurface(event)) return void 0;
|
|
@@ -62,9 +61,8 @@ window.__ModuleLoader__.load({
|
|
|
62
61
|
retryCount
|
|
63
62
|
};
|
|
64
63
|
}
|
|
65
|
-
/** 压缩进行中提示行的载荷(统计未就绪,全部为 null
|
|
64
|
+
/** 压缩进行中提示行的载荷(统计未就绪,全部为 null)。 */
|
|
66
65
|
function runningData(start) {
|
|
67
|
-
/** start 事件载荷(phase 为插件扩展;非法值回退 null)。 */
|
|
68
66
|
const data = start?.event.data;
|
|
69
67
|
return {
|
|
70
68
|
running: true,
|
|
@@ -104,8 +102,10 @@ window.__ModuleLoader__.load({
|
|
|
104
102
|
};
|
|
105
103
|
}
|
|
106
104
|
/**
|
|
107
|
-
* 插件压缩生命周期定义:compaction/start 开启上下文,summary / 替换检查点 /
|
|
108
|
-
*
|
|
105
|
+
* 插件压缩生命周期定义:compaction/start 开启上下文,summary / 替换检查点 / end
|
|
106
|
+
* 作为 update 折叠证据。有检查点时产出摘要卡片;无检查点的 end 以 hidden 撤回
|
|
107
|
+
* 进行中提示行(已物化节点以 hidden visibility 保留同一 key);仅 start 时渲染
|
|
108
|
+
* 「正在压缩上下文…」提示行。
|
|
109
109
|
*/
|
|
110
110
|
const omCompactionDefinition = {
|
|
111
111
|
kind: COMPACTION_CARD_KIND,
|
|
@@ -159,10 +159,8 @@ window.__ModuleLoader__.load({
|
|
|
159
159
|
//#endregion
|
|
160
160
|
//#region src/client/locales.ts
|
|
161
161
|
/**
|
|
162
|
-
* `om-compaction` namespace
|
|
163
|
-
*
|
|
164
|
-
* 与宿主 conversation 命名空间分离(独立 NS),插件卡片走自己的 keyed 渲染器,
|
|
165
|
-
* 文案键不与对话插件的键冲突。
|
|
162
|
+
* `om-compaction` namespace 字典:插件压缩卡片的界面文案(zh/en)。
|
|
163
|
+
* 导出 NS / zh / en;zh 为键集事实源,en 键集与 zh 一致。
|
|
166
164
|
*/
|
|
167
165
|
/** Dictionary namespace owned by this plugin. */
|
|
168
166
|
const NS = "om-compaction";
|
|
@@ -193,11 +191,10 @@ window.__ModuleLoader__.load({
|
|
|
193
191
|
//#endregion
|
|
194
192
|
//#region src/client/format.ts
|
|
195
193
|
/**
|
|
196
|
-
*
|
|
197
|
-
*
|
|
194
|
+
* 压缩卡片统计行的紧凑数字格式化。导出 formatCompactCount。
|
|
195
|
+
* <1k 原样;≥1k 用 k;≥1w(万)用 w;≥1M 用 M;保留 1 位小数并去掉末尾 .0。
|
|
198
196
|
*/
|
|
199
197
|
function formatCompactCount(value) {
|
|
200
|
-
/** 保留 1 位小数并去掉末尾 .0。 */
|
|
201
198
|
const trim = (n) => {
|
|
202
199
|
const text = String(Math.round(n * 10) / 10);
|
|
203
200
|
return text.endsWith(".0") ? text.slice(0, -2) : text;
|
|
@@ -226,19 +223,18 @@ window.__ModuleLoader__.load({
|
|
|
226
223
|
.${css.summary}{min-width:0;color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;flex:auto;font-size:14px;line-height:24px;overflow:hidden}
|
|
227
224
|
.${css.body}{box-sizing:border-box;background:var(--dsw-alias-markdown-code-block);width:calc(100% - 22px);max-height:141px;color:var(--dsw-alias-label-tertiary);font:400 11px/16px var(--ds-font-family-code);border:none;border-radius:8px;margin:4px 0 0 22px;padding:10px 16px 12px 12px;overflow:auto}
|
|
228
225
|
`;
|
|
229
|
-
/**
|
|
226
|
+
/** 注册卡片样式(无 document 的环境如 node 测试直接跳过)。 */
|
|
230
227
|
if (typeof document !== "undefined" && document.querySelector("style[data-dsh-plugin-om-card]") === null) {
|
|
231
228
|
const tag = document.createElement("style");
|
|
232
229
|
tag.dataset.dshPluginOmCard = "true";
|
|
233
230
|
tag.textContent = cardCss;
|
|
234
231
|
document.head.appendChild(tag);
|
|
235
232
|
}
|
|
236
|
-
/** 折叠式压缩卡片(统计标题行 + 代码块样式 summary
|
|
233
|
+
/** 折叠式压缩卡片(统计标题行 + 代码块样式 summary 展开)。 */
|
|
237
234
|
const OmCompactionCard = (0, react.memo)(function OmCompactionCard({ node, t }) {
|
|
238
235
|
const [expanded, setExpanded] = (0, react.useState)(false);
|
|
239
236
|
const { data } = node;
|
|
240
237
|
if (data.running) {
|
|
241
|
-
/** 提示行文案(按 phase 区分观察/反思;缺失回退通用文案)。 */
|
|
242
238
|
const runningLabel = data.phase === "observe" ? t("compaction.running.observe") : data.phase === "reflect" ? t("compaction.running.reflect") : t("compaction.running");
|
|
243
239
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
244
240
|
style: styles.row,
|
|
@@ -254,7 +250,6 @@ window.__ModuleLoader__.load({
|
|
|
254
250
|
}
|
|
255
251
|
const expandable = data.summary !== null;
|
|
256
252
|
const open = expandable && expanded;
|
|
257
|
-
/** 统计行文案(数字按 k/w/M 单位化;重试次数仅在有重试时追加;retryCount 缺失视为未重试)。 */
|
|
258
253
|
const stats = data.shadowedItemCount !== null && data.shadowedCharCount !== null && data.shadowedTokenCount !== null && data.summaryCharCount !== null && data.summaryTokenCount !== null ? t("compaction.stats", {
|
|
259
254
|
items: formatCompactCount(data.shadowedItemCount),
|
|
260
255
|
beforeChars: formatCompactCount(data.shadowedCharCount),
|
|
@@ -298,7 +293,7 @@ window.__ModuleLoader__.load({
|
|
|
298
293
|
});
|
|
299
294
|
const styles = {
|
|
300
295
|
row: {},
|
|
301
|
-
/** 摘要为 <history>
|
|
296
|
+
/** 摘要为 <history> 文本,保留换行。 */
|
|
302
297
|
body: { whiteSpace: "pre-wrap" }
|
|
303
298
|
};
|
|
304
299
|
//#endregion
|
|
@@ -309,11 +304,7 @@ window.__ModuleLoader__.load({
|
|
|
309
304
|
"conversationEvents",
|
|
310
305
|
"locale"
|
|
311
306
|
];
|
|
312
|
-
/**
|
|
313
|
-
* Client plugin body: 注册压缩卡片的业务定义与 keyed 渲染器。
|
|
314
|
-
* 注册挂在 effect 包装器上,插件卸载时随之移除。
|
|
315
|
-
* @param ctx - client root context.
|
|
316
|
-
*/
|
|
307
|
+
/** Client plugin body: 注册压缩卡片的业务定义与 keyed 渲染器(随插件卸载移除)。 */
|
|
317
308
|
function apply(ctx) {
|
|
318
309
|
ctx.effect(() => ctx.locale.register(NS, {
|
|
319
310
|
zh,
|