dsh-plugin-om 0.0.17 → 0.0.19
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 +7 -4
- package/dist/client/OmCompactionCard.d.ts.map +1 -1
- package/dist/client/definition.d.ts +9 -1
- package/dist/client/definition.d.ts.map +1 -1
- package/dist/client/locales.d.ts +4 -0
- package/dist/client/locales.d.ts.map +1 -1
- package/dist/client.js +81 -13
- package/dist/client.js.map +1 -1
- package/dist/compress.d.ts.map +1 -1
- package/dist/index.mjs +58 -23
- package/dist/summarize.d.ts +2 -0
- package/dist/summarize.d.ts.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -87,6 +87,7 @@ dsh的"预设"分为两层,`dsh web`等同于`dsh --profile web`,调用的
|
|
|
87
87
|
- 观察输入经 `@xmldom/xmldom` 构建为合法 <history> 块(用户消息文本/assistant 文本/reasoning 特殊字符自动转义,图片/文件以注释补充;assistant 文本与 toolcall&result 原样;系统消息——user_message 中 source.kind 非 user 的部分,如宿主注入的上下文——渲染为 <sys type="KIND" index="N"></sys> 空块,内容不进入压缩输入)
|
|
88
88
|
- 输出经 `@xmldom/xmldom` 解析校验:结构合法(标签匹配/闭合/单块)、不含 <reasoning>、index/start/end 连续(与预期覆盖区间一致),失败按 `compressRetryCount` 重试
|
|
89
89
|
- 块开标签带 `tip` 属性(对 AI 的提醒:"当前块是历史消息的压缩产物,不要复述");块顶为构成逻辑注释(完整消息定义串 + 条目标签语义),消息正文不再附加前缀句
|
|
90
|
+
- 压缩生命周期:每次摘要调用前先追加 `compaction/start`(载荷带 `phase`:`observe`/观察 或 `reflect`/反思,客户端据此渲染「正在压缩上下文(观察/反思)…」提示行);摘要成功提交 summary + 替换消息 + end,summary 载荷带 `attemptCount`(第几次尝试成功);摘要失败或重试耗尽时追加 `compaction/end(error)` 关闭生命周期(不产生 summary/替换),客户端随之撤回提示行
|
|
90
91
|
|
|
91
92
|
### 压缩卡片(消息列表中的「已压缩」展示)
|
|
92
93
|
|
|
@@ -97,6 +98,8 @@ dsh的"预设"分为两层,`dsh web`等同于`dsh --profile web`,调用的
|
|
|
97
98
|
- 点击展开显示压缩摘要文本,按代码块样式呈现(缩小字号、代码背景与等宽字体、保留换行)
|
|
98
99
|
- summary 事件落在当前加载窗口之外时卡片不可展开(不显示空内容)
|
|
99
100
|
- 卡片只认领插件自产的检查点(source.plugin = `dsh-plugin-om`);宿主 `compact` 检查点仍由宿主自己渲染,不会出现双卡片
|
|
101
|
+
- 压缩进行中(`compaction/start` 已到、summary/检查点未到):渲染不可展开的「正在压缩上下文(观察/反思)…」提示行,按 start 载荷的 `phase` 区分文案(旧会话无 phase 时回落通用文案);压缩失败收到 `compaction/end` 时以 hidden 可见性撤回提示行
|
|
102
|
+
- summary 载荷带 `attemptCount`(第几次尝试成功)时,重试次数 > 0 在标题统计行追加「重试 N 次」(首次成功不显示;旧载荷无 attemptCount 时不显示)
|
|
100
103
|
- 平台模块(react / cordis / ui-primitives / ui-slots 等)走宿主冻结模块表(保持 external),其余依赖内联进 bundle
|
|
101
104
|
|
|
102
105
|
### 注意
|
|
@@ -166,7 +169,7 @@ src/
|
|
|
166
169
|
│ └─ ctx.on('agent/pre-step') → compress.ts # maybeCompress:两级压缩阻塞串行(先反思后观察;turn 中间即可触发)
|
|
167
170
|
│ ├─ reflectPass → summarize.ts # 全部 <history> 块总长 ≥ 窗口 × historyMergeRatio:多块拼接 + 共享提示词合并整个块区段
|
|
168
171
|
│ ├─ observePass → summarize.ts # 未压缩消息 ≥ 窗口 × thresholdRatio:渲染 <history> 输入 → 观察日志 → 追加 + 替换
|
|
169
|
-
│ └─ 提交 → compress.ts # compaction/start → summary → 替换消息(source 插件标识 + compactionId) → end;usage 归入主会话
|
|
172
|
+
│ └─ 提交 → compress.ts # compaction/start(摘要调用前,载荷 phase) → summary(attemptCount) → 替换消息(source 插件标识 + compactionId) → end;失败补 end(error);usage 归入主会话
|
|
170
173
|
├── constants.ts # 共享常量(PLUGIN_LABEL / HISTORY_TAG / HISTORY_TIP / COMPLETE_MESSAGE_DEFINITION / COMPACT_CHECKPOINT_PLUGIN)
|
|
171
174
|
├── types.ts # type-only:宿主类型再导出 + 领域类型(MessageNode / MessageIndex)
|
|
172
175
|
├── config.ts # 配置默认值 / 宽松合并(缺省、null、空串回退默认值;未知键忽略、非法值回退默认;数值键/布尔键/omEnabled/modelDir)
|
|
@@ -174,13 +177,13 @@ src/
|
|
|
174
177
|
├── log-index.ts # 完整消息索引(index 定位 user/sys/assistant/具有result的toolcall;user_message 按 source.kind 分类:kind:user 为用户消息、其余为系统消息;本插件自产压缩日志消息不占位;未闭合 tool-call 不占位;recall 与摘要共用)
|
|
175
178
|
├── embedding.ts # 本地 ONNX 嵌入(@huggingface/transformers + 本地模型;共享目录解析 / 小文件补齐 / 运行时按需下载编排 / 懒加载 / 批量 / cosine)
|
|
176
179
|
├── model-download.ts # 模型下载原语(modelSourceUrl / needsDownload / 原子落盘 / 开始结束日志与失败镜像建议;运行时与 dev CLI 共用)
|
|
177
|
-
├── summarize.ts # 共享提示词 buildHistoryPrompt(观察/反思同一套)+ renderMessages(@xmldom/xmldom 构建 <history> 块输入:用户消息原样、系统消息渲染为 <sys> 空块、自动转义)+ 直连 ctx.llm.stream() 摘要(new 方式:指令作 system、输入为渲染消息;extractSummaryLog 提取校验:XML 结构合法 / 无 reasoning / index 连续 / 覆盖区间;重试与流式 usage
|
|
180
|
+
├── summarize.ts # 共享提示词 buildHistoryPrompt(观察/反思同一套)+ renderMessages(@xmldom/xmldom 构建 <history> 块输入:用户消息原样、系统消息渲染为 <sys> 空块、自动转义)+ 直连 ctx.llm.stream() 摘要(new 方式:指令作 system、输入为渲染消息;extractSummaryLog 提取校验:XML 结构合法 / 无 reasoning / index 连续 / 覆盖区间;重试与流式 usage 归入主会话;成功返回 attemptCount 供卡片展示重试次数)
|
|
178
181
|
├── recall.ts # recall 工具
|
|
179
182
|
├── semantic-recall.ts # recall-semantic 工具(query 语义检索 + 区间限定 + 回退全量 + 匹配说明)
|
|
180
|
-
└── compress.ts # 两级自动压缩(测量 / mid-turn 区间计算 / 配对平衡回退 / source 标记判定摘要消息 / compaction/*
|
|
183
|
+
└── compress.ts # 两级自动压缩(测量 / mid-turn 区间计算 / 配对平衡回退 / source 标记判定摘要消息 / compaction/* 生命周期事件:start 在摘要调用前追加并带 phase,失败补 end(error) + 替换消息 source 插件标识)
|
|
181
184
|
src/client/
|
|
182
185
|
├── index.ts # 浏览器客户端入口(exports["./client"] → dist/client.js):注入 slots/conversationEvents/locale,注册卡片定义与渲染器
|
|
183
|
-
├── definition.ts # 压缩卡片业务定义:认领插件生命周期事件与替换检查点(source.plugin = dsh-plugin-om
|
|
186
|
+
├── definition.ts # 压缩卡片业务定义:认领插件生命周期事件与替换检查点(source.plugin = dsh-plugin-om),聚合摘要卡片节点;start→压缩中提示行(running+phase)、end→hidden 撤回、summary→卡片(retryCount)
|
|
184
187
|
├── OmCompactionCard.tsx # 与宿主「上下文注入」同款的折叠卡片渲染器(统计标题 + 代码块样式 summary 展开)
|
|
185
188
|
└── locales.ts # om-compaction 命名空间字典(zh/en)与 LocaleNamespaceMap 声明合并
|
|
186
189
|
models/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OmCompactionCard.d.ts","sourceRoot":"","sources":["../../src/client/OmCompactionCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAE/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAIpE,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,oDAAoD;AACpD,eAAO,MAAM,gBAAgB,oDAA+C,qBAAqB,
|
|
1
|
+
{"version":3,"file":"OmCompactionCard.d.ts","sourceRoot":"","sources":["../../src/client/OmCompactionCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAE/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAIpE,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,oDAAoD;AACpD,eAAO,MAAM,gBAAgB,oDAA+C,qBAAqB,iCA+F/F,CAAC"}
|
|
@@ -20,6 +20,10 @@ declare module '@deepseek-ai/dsh-client-ui-conversation/client' {
|
|
|
20
20
|
}
|
|
21
21
|
/** 压缩卡片载荷:摘要文本与遮蔽统计(seq/time 由节点本体提供,不重复存放)。 */
|
|
22
22
|
export interface OmCompactionChatData {
|
|
23
|
+
/** 压缩进行中(compaction/start 已到、checkpoint/end 未到):渲染为「正在压缩上下文…」提示行。 */
|
|
24
|
+
readonly running: boolean;
|
|
25
|
+
/** 压缩 pass(观察/反思;来自 start 事件载荷的插件扩展,缺失或非运行态为 null)。 */
|
|
26
|
+
readonly phase: 'observe' | 'reflect' | null;
|
|
23
27
|
/** compaction/summary 的文本摘要;窗口裁剪把该事件留在窗外时为 null(卡片不可展开)。 */
|
|
24
28
|
readonly summary: string | null;
|
|
25
29
|
/** 已载入的 compaction/summary 事件 seq,窗外时为 null。 */
|
|
@@ -34,11 +38,15 @@ export interface OmCompactionChatData {
|
|
|
34
38
|
readonly summaryCharCount: number | null;
|
|
35
39
|
/** 压缩后的估算 token 数(4 字符 ≈ 1 token,与服务端 estimateTextTokens 同一启发式),summary 不可用或非法时为 null。 */
|
|
36
40
|
readonly summaryTokenCount: number | null;
|
|
41
|
+
/** 摘要调用重试次数(= 载荷 attemptCount - 1;载荷缺失或非法时为 null)。 */
|
|
42
|
+
readonly retryCount: number | null;
|
|
37
43
|
}
|
|
38
|
-
/** 压缩生命周期关联状态:summary / checkpoint 事件证据。 */
|
|
44
|
+
/** 压缩生命周期关联状态:summary / checkpoint / end 事件证据。 */
|
|
39
45
|
interface OmCompactionState {
|
|
40
46
|
readonly summary?: ConversationMatch;
|
|
41
47
|
readonly checkpoint?: ConversationMatch;
|
|
48
|
+
/** compaction/end(成功与失败都会到达;无 checkpoint 的 end 表示压缩失败,撤回进行中提示行)。 */
|
|
49
|
+
readonly end?: ConversationMatch;
|
|
42
50
|
}
|
|
43
51
|
/**
|
|
44
52
|
* 从压缩替换检查点(user/message + replace surface + source.plugin 为本插件)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/client/definition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;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,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,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,2CAA2C;IAC3C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,6CAA6C;IAC7C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,0FAA0F;IAC1F,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/client/definition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;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,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,uDAAuD;IACvD,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,2CAA2C;IAC3C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,6CAA6C;IAC7C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,0FAA0F;IAC1F,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,sDAAsD;IACtD,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;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAe9E;AA0GD;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,0BAA0B,CAAC,iBAAiB,CAuDhF,CAAC"}
|
package/dist/client/locales.d.ts
CHANGED
|
@@ -13,6 +13,10 @@ export declare const zh: {
|
|
|
13
13
|
readonly 'compaction.stats': "压缩前 {items} 条消息 · {beforeChars} 字符(约 {beforeTokens} tokens)→ 压缩后 {afterChars} 字符(约 {afterTokens} tokens)";
|
|
14
14
|
readonly 'compaction.expand': "点击查看压缩摘要";
|
|
15
15
|
readonly 'compaction.unavailable': "压缩摘要不可用";
|
|
16
|
+
readonly 'compaction.running': "正在压缩上下文…";
|
|
17
|
+
readonly 'compaction.running.observe': "正在压缩上下文(观察)…";
|
|
18
|
+
readonly 'compaction.running.reflect': "正在压缩上下文(反思)…";
|
|
19
|
+
readonly 'compaction.retries': "重试 {count} 次";
|
|
16
20
|
};
|
|
17
21
|
/** English dictionary(键集与 zh 一致)。 */
|
|
18
22
|
export declare const en: Record<keyof typeof zh, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../src/client/locales.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,iDAAiD;AACjD,eAAO,MAAM,EAAE,kBAAkB,CAAC;AAElC,mEAAmE;AACnE,eAAO,MAAM,EAAE
|
|
1
|
+
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../src/client/locales.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;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
|
@@ -37,6 +37,7 @@ window.__ModuleLoader__.load({
|
|
|
37
37
|
let shadowedItemCount = null;
|
|
38
38
|
let shadowedTokenCount = null;
|
|
39
39
|
let shadowedCharCount = null;
|
|
40
|
+
let retryCount = null;
|
|
40
41
|
if (summaryMatch?.event.type === "compaction/summary") {
|
|
41
42
|
const data = summaryMatch.event.data;
|
|
42
43
|
if (Array.isArray(data.summary)) {
|
|
@@ -46,28 +47,51 @@ window.__ModuleLoader__.load({
|
|
|
46
47
|
shadowedItemCount = Array.isArray(data.shadowedSeqs) && data.shadowedSeqs.every((seq) => Number.isSafeInteger(seq) && seq >= 0) ? data.shadowedSeqs.length : null;
|
|
47
48
|
shadowedTokenCount = Number.isSafeInteger(data.shadowedTokenCount) && data.shadowedTokenCount >= 0 ? data.shadowedTokenCount : null;
|
|
48
49
|
shadowedCharCount = data.shadowedCharCount !== void 0 && Number.isSafeInteger(data.shadowedCharCount) && data.shadowedCharCount >= 0 ? data.shadowedCharCount : null;
|
|
50
|
+
retryCount = data.attemptCount !== void 0 && Number.isSafeInteger(data.attemptCount) && data.attemptCount >= 1 ? data.attemptCount - 1 : null;
|
|
49
51
|
}
|
|
50
52
|
return {
|
|
53
|
+
running: false,
|
|
54
|
+
phase: null,
|
|
51
55
|
summary,
|
|
52
56
|
summaryEventSeq: summaryMatch?.event.seq ?? null,
|
|
53
57
|
shadowedItemCount,
|
|
54
58
|
shadowedTokenCount,
|
|
55
59
|
shadowedCharCount,
|
|
56
60
|
summaryCharCount: summary === null ? null : summary.length,
|
|
57
|
-
summaryTokenCount: summary === null ? null : Math.ceil(summary.length / 4)
|
|
61
|
+
summaryTokenCount: summary === null ? null : Math.ceil(summary.length / 4),
|
|
62
|
+
retryCount
|
|
58
63
|
};
|
|
59
64
|
}
|
|
60
|
-
/**
|
|
65
|
+
/** 压缩进行中提示行的载荷(统计未就绪,全部为 null;phase 取自 start 事件载荷扩展,缺失回退 null)。 */
|
|
66
|
+
function runningData(start) {
|
|
67
|
+
/** start 事件载荷(phase 为插件扩展;非法值回退 null)。 */
|
|
68
|
+
const data = start?.event.data;
|
|
69
|
+
return {
|
|
70
|
+
running: true,
|
|
71
|
+
phase: data?.phase === "observe" || data?.phase === "reflect" ? data.phase : null,
|
|
72
|
+
summary: null,
|
|
73
|
+
summaryEventSeq: null,
|
|
74
|
+
shadowedItemCount: null,
|
|
75
|
+
shadowedTokenCount: null,
|
|
76
|
+
shadowedCharCount: null,
|
|
77
|
+
summaryCharCount: null,
|
|
78
|
+
summaryTokenCount: null,
|
|
79
|
+
retryCount: null
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/** 窗口只载入部分事件时的回落证据扫描(summary / 检查点 / end 各自独立)。 */
|
|
61
83
|
function fallbackState(context) {
|
|
62
84
|
const summary = context.matches.find((match) => match.event.type === "compaction/summary");
|
|
63
85
|
const checkpoint = context.matches.find((match) => checkpointCompactionId(match.event) !== void 0);
|
|
86
|
+
const end = context.matches.find((match) => match.event.type === "compaction/end");
|
|
64
87
|
return {
|
|
65
88
|
...summary === void 0 ? {} : { summary },
|
|
66
|
-
...checkpoint === void 0 ? {} : { checkpoint }
|
|
89
|
+
...checkpoint === void 0 ? {} : { checkpoint },
|
|
90
|
+
...end === void 0 ? {} : { end }
|
|
67
91
|
};
|
|
68
92
|
}
|
|
69
93
|
/** 构建最终 Chat 目标节点(与 ui-conversation 的 chatNode 助手同构)。 */
|
|
70
|
-
function chatNode(context, kind, anchorSeq, data) {
|
|
94
|
+
function chatNode(context, kind, anchorSeq, data, visibility = "visible") {
|
|
71
95
|
return {
|
|
72
96
|
key: context.key,
|
|
73
97
|
kind,
|
|
@@ -75,7 +99,7 @@ window.__ModuleLoader__.load({
|
|
|
75
99
|
target: "chat",
|
|
76
100
|
anchorSeq,
|
|
77
101
|
location: context.start?.location ?? context.matches[0]?.location ?? { kind: "unresolved" },
|
|
78
|
-
visibility
|
|
102
|
+
visibility,
|
|
79
103
|
data
|
|
80
104
|
};
|
|
81
105
|
}
|
|
@@ -108,6 +132,10 @@ window.__ModuleLoader__.load({
|
|
|
108
132
|
...context.state,
|
|
109
133
|
summary: match
|
|
110
134
|
};
|
|
135
|
+
if (match.event.type === "compaction/end") return {
|
|
136
|
+
...context.state,
|
|
137
|
+
end: match
|
|
138
|
+
};
|
|
111
139
|
if (checkpointCompactionId(match.event) !== void 0) return {
|
|
112
140
|
...context.state,
|
|
113
141
|
checkpoint: match
|
|
@@ -116,9 +144,16 @@ window.__ModuleLoader__.load({
|
|
|
116
144
|
},
|
|
117
145
|
buildViewNode: (context) => {
|
|
118
146
|
const state = context.state ?? fallbackState(context);
|
|
119
|
-
if (state.checkpoint
|
|
120
|
-
|
|
121
|
-
|
|
147
|
+
if (state.checkpoint !== void 0) {
|
|
148
|
+
const data = compactSummaryData(state.summary);
|
|
149
|
+
return chatNode(context, COMPACTION_CARD_KIND, state.checkpoint.event.seq, data);
|
|
150
|
+
}
|
|
151
|
+
if (state.end !== void 0) {
|
|
152
|
+
const anchorSeq = context.start?.event.seq ?? state.end.event.seq;
|
|
153
|
+
return chatNode(context, COMPACTION_CARD_KIND, anchorSeq, runningData(context.start), "hidden");
|
|
154
|
+
}
|
|
155
|
+
if (context.start !== void 0) return chatNode(context, COMPACTION_CARD_KIND, context.start.event.seq, runningData(context.start));
|
|
156
|
+
return null;
|
|
122
157
|
}
|
|
123
158
|
};
|
|
124
159
|
//#endregion
|
|
@@ -137,7 +172,11 @@ window.__ModuleLoader__.load({
|
|
|
137
172
|
"compaction.completed": "已压缩 {items} 条历史记录(约 {tokens} tokens)",
|
|
138
173
|
"compaction.stats": "压缩前 {items} 条消息 · {beforeChars} 字符(约 {beforeTokens} tokens)→ 压缩后 {afterChars} 字符(约 {afterTokens} tokens)",
|
|
139
174
|
"compaction.expand": "点击查看压缩摘要",
|
|
140
|
-
"compaction.unavailable": "压缩摘要不可用"
|
|
175
|
+
"compaction.unavailable": "压缩摘要不可用",
|
|
176
|
+
"compaction.running": "正在压缩上下文…",
|
|
177
|
+
"compaction.running.observe": "正在压缩上下文(观察)…",
|
|
178
|
+
"compaction.running.reflect": "正在压缩上下文(反思)…",
|
|
179
|
+
"compaction.retries": "重试 {count} 次"
|
|
141
180
|
};
|
|
142
181
|
/** English dictionary(键集与 zh 一致)。 */
|
|
143
182
|
const en = {
|
|
@@ -145,7 +184,11 @@ window.__ModuleLoader__.load({
|
|
|
145
184
|
"compaction.completed": "Compacted {items} messages (~{tokens} tokens)",
|
|
146
185
|
"compaction.stats": "{items} messages · {beforeChars} chars (~{beforeTokens} tokens) before → {afterChars} chars (~{afterTokens} tokens) after",
|
|
147
186
|
"compaction.expand": "Click to view summary",
|
|
148
|
-
"compaction.unavailable": "Summary unavailable"
|
|
187
|
+
"compaction.unavailable": "Summary unavailable",
|
|
188
|
+
"compaction.running": "Compressing context…",
|
|
189
|
+
"compaction.running.observe": "Compressing context (observation)…",
|
|
190
|
+
"compaction.running.reflect": "Compressing context (reflection)…",
|
|
191
|
+
"compaction.retries": "Retried {count} times"
|
|
149
192
|
};
|
|
150
193
|
//#endregion
|
|
151
194
|
//#region src/client/OmCompactionCard.tsx
|
|
@@ -177,8 +220,32 @@ window.__ModuleLoader__.load({
|
|
|
177
220
|
const OmCompactionCard = (0, react.memo)(function OmCompactionCard({ node, t }) {
|
|
178
221
|
const [expanded, setExpanded] = (0, react.useState)(false);
|
|
179
222
|
const { data } = node;
|
|
223
|
+
if (data.running) {
|
|
224
|
+
/** 提示行文案(按 phase 区分观察/反思;缺失回退通用文案)。 */
|
|
225
|
+
const runningLabel = data.phase === "observe" ? t("compaction.running.observe") : data.phase === "reflect" ? t("compaction.running.reflect") : t("compaction.running");
|
|
226
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
227
|
+
style: styles.row,
|
|
228
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
|
|
229
|
+
className: css.root,
|
|
230
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutline16, { size: 14 }),
|
|
231
|
+
title: t("compaction"),
|
|
232
|
+
open: false,
|
|
233
|
+
expandable: false,
|
|
234
|
+
onToggle: () => {},
|
|
235
|
+
collapsedContent: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
236
|
+
className: css.sep,
|
|
237
|
+
"aria-hidden": true
|
|
238
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
239
|
+
className: css.summary,
|
|
240
|
+
"data-om-compaction-running": true,
|
|
241
|
+
children: runningLabel
|
|
242
|
+
})] })
|
|
243
|
+
})
|
|
244
|
+
});
|
|
245
|
+
}
|
|
180
246
|
const expandable = data.summary !== null;
|
|
181
247
|
const open = expandable && expanded;
|
|
248
|
+
/** 统计行文案(重试次数仅在有重试时追加;retryCount 缺失视为未重试)。 */
|
|
182
249
|
const stats = data.shadowedItemCount !== null && data.shadowedCharCount !== null && data.shadowedTokenCount !== null && data.summaryCharCount !== null && data.summaryTokenCount !== null ? t("compaction.stats", {
|
|
183
250
|
items: data.shadowedItemCount,
|
|
184
251
|
beforeChars: data.shadowedCharCount,
|
|
@@ -189,6 +256,7 @@ window.__ModuleLoader__.load({
|
|
|
189
256
|
items: data.shadowedItemCount,
|
|
190
257
|
tokens: data.shadowedTokenCount
|
|
191
258
|
}) : expandable ? t("compaction.expand") : t("compaction.unavailable");
|
|
259
|
+
const retry = data.retryCount !== null && data.retryCount > 0 ? ` \u00b7 ${t("compaction.retries", { count: data.retryCount })}` : "";
|
|
192
260
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
193
261
|
style: styles.row,
|
|
194
262
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
|
|
@@ -199,10 +267,10 @@ window.__ModuleLoader__.load({
|
|
|
199
267
|
collapsedContent: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
200
268
|
className: css.sep,
|
|
201
269
|
"aria-hidden": true
|
|
202
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
270
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
203
271
|
className: css.summary,
|
|
204
272
|
"data-om-compaction-summary": true,
|
|
205
|
-
children: stats
|
|
273
|
+
children: [stats, retry]
|
|
206
274
|
})] }),
|
|
207
275
|
keepContentWhenOpen: true,
|
|
208
276
|
expandable,
|
|
@@ -220,7 +288,7 @@ window.__ModuleLoader__.load({
|
|
|
220
288
|
});
|
|
221
289
|
});
|
|
222
290
|
const styles = {
|
|
223
|
-
row: {
|
|
291
|
+
row: {},
|
|
224
292
|
/** 摘要为 <history> 文本,保留换行(宿主 body 的白色空间由内容形态各自处理)。 */
|
|
225
293
|
body: { whiteSpace: "pre-wrap" }
|
|
226
294
|
};
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["memo","useState","DisclosureRow","IconBrowseOutline16"],"sources":["../src/constants.ts","../src/client/definition.ts","../src/client/locales.ts","../src/client/OmCompactionCard.tsx","../src/client/index.ts"],"sourcesContent":["/**\n * 共享常量:集中定义插件级魔法字符串与事件名,避免散落各模块。\n */\n\n/** 插件标识:压缩消息 source.plugin 取值(注入压缩日志的来源标记)与日志前缀。 */\nexport const PLUGIN_LABEL = 'dsh-plugin-om';\n\n/** 压缩日志标签名:<history>...</history> 包裹观察/反思日志块(输入与输出均为合法 history 块)。 */\nexport const HISTORY_TAG = 'history';\n\n/** 压缩日志块开标签上的 tip 属性(对 AI 的提醒:本块是历史压缩产物,不要复述)。 */\nexport const HISTORY_TIP = '当前块是历史消息的压缩产物,不要复述';\n\n/**\n * 「完整消息」定义(提示词 / recall 工具描述 / 块顶注释共用同一字符串)。\n * 完整消息是摘要日志与 recall 共用的定位单位;首条 index 为 0,按会话顺序递增、全局稳定。\n * 用户消息指 user_message 中 source.kind 为 user 的部分;其余部分(宿主注入的上下文等)\n * 为系统消息,同样是一条完整消息。\n */\nexport const COMPLETE_MESSAGE_DEFINITION =\n '`完整消息`被定义为`用户消息`,`系统消息`,`模型输出文本`和`具有result的toolcall`的集合。首条`完整消息`的index是0,后续的index递增。';\n\n/** 判定 user/message 的 source 是否为本插件自产(压缩日志机制消息;含兼容旧宿主 checkpoint 标记 'compact')。这类消息不占完整消息 index。 */\nexport function isPluginOwnedSource(\n source: { kind?: string; plugin?: string } | undefined,\n): boolean {\n if (source?.kind !== 'plugin') return false;\n return source.plugin === PLUGIN_LABEL || source.plugin === COMPACT_CHECKPOINT_PLUGIN;\n}\n\n/** 旧日志压缩消息的宿主 checkpoint 标记 plugin 名(dsh-compaction-basic 的 COMPACT_CHECKPOINT_MARKER.plugin;历史兼容识别用)。 */\nexport const COMPACT_CHECKPOINT_PLUGIN = 'compact';\n","/**\n * 压缩卡片业务定义:认领插件自产的压缩生命周期事件与替换检查点,\n * 聚合出可渲染的摘要卡片节点。\n *\n * 宿主 conversation 客户端仅识别 source.plugin === 'compact' 的压缩检查点\n * (ui-conversation 的 compactionDefinition),插件自产的检查点标记为\n * PLUGIN_LABEL('dsh-plugin-om'),由本定义认领。生命周期事件(compaction/start\n * |summary|end)同时会被宿主的 compactionDefinition 匹配,但宿主没有检查点证据\n * 时不产出节点(buildViewNode 返回 null),因此双方共存无视觉冲突。\n */\n\nimport type {\n ConversationMatch,\n ConversationNodeContext,\n ConversationNodeDefinition,\n} from '@deepseek-ai/dsh-client-runtime/client';\nimport type { ChatNode, ChatNodeDataMap } from '@deepseek-ai/dsh-client-ui-conversation/client';\nimport type {} from '@deepseek-ai/dsh-compaction/types';\nimport type { SessionEvent } from '@deepseek-ai/dsh-session/types';\nimport { PLUGIN_LABEL } from '../constants.ts';\nimport type { CompactionSummaryPayload } from '../types.ts';\n\n/** 压缩卡片渲染器分发键(合并进 ChatNodeDataMap)。 */\nexport const COMPACTION_CARD_KIND = 'om-compaction';\n\ndeclare module '@deepseek-ai/dsh-client-ui-conversation/client' {\n interface ChatNodeDataMap {\n /** dsh-plugin-om 压缩替换检查点渲染的摘要卡片数据。 */\n 'om-compaction': OmCompactionChatData;\n }\n}\n\n/** 压缩卡片载荷:摘要文本与遮蔽统计(seq/time 由节点本体提供,不重复存放)。 */\nexport interface OmCompactionChatData {\n /** compaction/summary 的文本摘要;窗口裁剪把该事件留在窗外时为 null(卡片不可展开)。 */\n readonly summary: string | null;\n /** 已载入的 compaction/summary 事件 seq,窗外时为 null。 */\n readonly summaryEventSeq: number | null;\n /** 被遮蔽的表层节点数,summary 事件缺失或载荷非法时为 null。 */\n readonly shadowedItemCount: number | null;\n /** 遮蔽的 token 数,summary 事件缺失或载荷非法时为 null。 */\n readonly shadowedTokenCount: number | null;\n /** 压缩前的字符数(被压缩内容文本长度合计),载荷缺失或非法时为 null。 */\n readonly shadowedCharCount: number | null;\n /** 压缩后的字符数(摘要文本长度),summary 不可用或非法时为 null。 */\n readonly summaryCharCount: number | null;\n /** 压缩后的估算 token 数(4 字符 ≈ 1 token,与服务端 estimateTextTokens 同一启发式),summary 不可用或非法时为 null。 */\n readonly summaryTokenCount: number | null;\n}\n\n/** 压缩生命周期关联状态:summary / checkpoint 事件证据。 */\ninterface OmCompactionState {\n readonly summary?: ConversationMatch;\n readonly checkpoint?: ConversationMatch;\n}\n\n/**\n * replace-surface 判定:surfaceOp 为 { op: 'replace' } 对象(与宿主 runtime 的\n * isReplacementSurfaceEvent 同义)。宿主该助手位于浏览器 bundle 内\n * (window.__ModuleLoader__ 闭包),node 端测试无法求值,故本地实现同一形状检查。\n */\nfunction isReplacementSurface(event: SessionEvent): boolean {\n const surfaceOp = (event as { surfaceOp?: unknown }).surfaceOp;\n return (\n typeof surfaceOp === 'object' &&\n surfaceOp !== null &&\n (surfaceOp as { op?: unknown }).op === 'replace'\n );\n}\n\n/**\n * 从压缩替换检查点(user/message + replace surface + source.plugin 为本插件)\n * 读取关联 identity。宿主的 'compact' 检查点由宿主自己渲染,本插件不认领,\n * 避免同一压缩出现两张卡片。\n */\nexport function checkpointCompactionId(event: SessionEvent): string | undefined {\n if (event.type !== 'user/message' || !isReplacementSurface(event)) return undefined;\n const data = event.data as unknown as {\n source?: { kind?: unknown; plugin?: unknown; compactionId?: unknown };\n };\n const source = data.source;\n if (\n source === undefined ||\n source.kind !== 'plugin' ||\n source.plugin !== PLUGIN_LABEL ||\n typeof source.compactionId !== 'string'\n ) {\n return undefined;\n }\n return source.compactionId;\n}\n\n/** 从 compaction/summary 载荷提取摘要文本与遮蔽统计(载荷非法时各字段回落 null)。 */\nfunction compactSummaryData(summaryMatch: ConversationMatch | undefined): OmCompactionChatData {\n let summary: string | null = null;\n let shadowedItemCount: number | null = null;\n let shadowedTokenCount: number | null = null;\n let shadowedCharCount: number | null = null;\n if (summaryMatch?.event.type === 'compaction/summary') {\n // 宿主载荷类型是 union 且不含插件扩展字段,读取处收窄为插件扩展类型\n const data = summaryMatch.event.data as CompactionSummaryPayload;\n if (Array.isArray(data.summary)) {\n const text = data.summary.map((block) => (block.type === 'text' ? block.text : '')).join('');\n summary = text.trim() === '' ? null : text;\n }\n shadowedItemCount =\n Array.isArray(data.shadowedSeqs) &&\n data.shadowedSeqs.every((seq) => Number.isSafeInteger(seq) && seq >= 0)\n ? data.shadowedSeqs.length\n : null;\n shadowedTokenCount =\n Number.isSafeInteger(data.shadowedTokenCount) && data.shadowedTokenCount >= 0\n ? data.shadowedTokenCount\n : null;\n shadowedCharCount =\n data.shadowedCharCount !== undefined &&\n Number.isSafeInteger(data.shadowedCharCount) &&\n data.shadowedCharCount >= 0\n ? data.shadowedCharCount\n : null;\n }\n return {\n summary,\n summaryEventSeq: summaryMatch?.event.seq ?? null,\n shadowedItemCount,\n shadowedTokenCount,\n shadowedCharCount,\n summaryCharCount: summary === null ? null : summary.length,\n summaryTokenCount: summary === null ? null : Math.ceil(summary.length / 4),\n };\n}\n\n/** 窗口只载入检查点(生命周期事件在窗外)时的回落证据扫描。 */\nfunction fallbackState(context: ConversationNodeContext<OmCompactionState>): OmCompactionState {\n const summary = context.matches.find((match) => match.event.type === 'compaction/summary');\n const checkpoint = context.matches.find(\n (match) => checkpointCompactionId(match.event) !== undefined,\n );\n return {\n ...(summary === undefined ? {} : { summary }),\n ...(checkpoint === undefined ? {} : { checkpoint }),\n };\n}\n\n/** 构建最终 Chat 目标节点(与 ui-conversation 的 chatNode 助手同构)。 */\nfunction chatNode<Kind extends keyof ChatNodeDataMap & string>(\n context: ConversationNodeContext,\n kind: Kind,\n anchorSeq: number,\n data: ChatNodeDataMap[Kind],\n): ChatNode<Kind> {\n return {\n key: context.key,\n kind,\n id: context.id,\n target: 'chat',\n anchorSeq,\n location: context.start?.location ?? context.matches[0]?.location ?? { kind: 'unresolved' },\n visibility: 'visible',\n data,\n };\n}\n\n/**\n * 插件压缩生命周期定义:compaction/start 开启上下文,summary / 替换检查点 /\n * end 作为 update 折叠证据;仅在存在替换检查点时产出卡片节点。\n */\nexport const omCompactionDefinition: ConversationNodeDefinition<OmCompactionState> = {\n kind: COMPACTION_CARD_KIND,\n target: 'chat',\n match: (event) => {\n const compactionId = checkpointCompactionId(event);\n if (compactionId !== undefined) return { id: compactionId, role: 'update' };\n if (\n event.type === 'compaction/start' ||\n event.type === 'compaction/summary' ||\n event.type === 'compaction/end'\n ) {\n const id: unknown = event.data.compactionId;\n if (typeof id !== 'string' || id === '') return null;\n return { id, role: event.type === 'compaction/start' ? 'start' : 'update' };\n }\n return null;\n },\n start: () => ({}),\n update: (context, match) => {\n if (match.event.type === 'compaction/summary') return { ...context.state, summary: match };\n if (checkpointCompactionId(match.event) !== undefined)\n return { ...context.state, checkpoint: match };\n return context.state;\n },\n buildViewNode: (context) => {\n const state = context.state ?? fallbackState(context);\n if (state.checkpoint === undefined) return null;\n const data = compactSummaryData(state.summary);\n return chatNode(context, COMPACTION_CARD_KIND, state.checkpoint.event.seq, data);\n },\n};\n","/**\n * `om-compaction` namespace dictionaries: 插件压缩卡片的界面文案。\n *\n * 与宿主 conversation 命名空间分离(独立 NS),插件卡片走自己的 keyed 渲染器,\n * 文案键不与对话插件的键冲突。\n */\n\n/** Dictionary namespace owned by this plugin. */\nexport const NS = 'om-compaction';\n\n/** Simplified Chinese dictionary (the key-set source of truth). */\nexport const zh = {\n compaction: '上下文已压缩',\n 'compaction.completed': '已压缩 {items} 条历史记录(约 {tokens} tokens)',\n 'compaction.stats':\n '压缩前 {items} 条消息 · {beforeChars} 字符(约 {beforeTokens} tokens)→ 压缩后 {afterChars} 字符(约 {afterTokens} tokens)',\n 'compaction.expand': '点击查看压缩摘要',\n 'compaction.unavailable': '压缩摘要不可用',\n} as const;\n\n/** English dictionary(键集与 zh 一致)。 */\nexport const en: Record<keyof typeof zh, string> = {\n compaction: 'Context compacted',\n 'compaction.completed': 'Compacted {items} messages (~{tokens} tokens)',\n 'compaction.stats':\n '{items} messages · {beforeChars} chars (~{beforeTokens} tokens) before → {afterChars} chars (~{afterTokens} tokens) after',\n 'compaction.expand': 'Click to view summary',\n 'compaction.unavailable': 'Summary unavailable',\n};\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Compaction card copy owned by dsh-plugin-om. */\n 'om-compaction': keyof typeof zh;\n }\n}\n","/**\n * dsh-plugin-om 压缩卡片渲染器:与宿主「上下文注入」卡片同款的折叠行。\n *\n * 复用平台原语 DisclosureRow(宿主 ContextInjectionRow 用的同一外壳组件);行内\n * 统计与展开体样式按宿主 ContextInjectionRow.module.css 的规则注入——宿主该卡片\n * 的样式是编译期哈希的 CSS Module,插件 bundle 无法引用其类名,故按宿主 client\n * bundle 的同一机制(注入 <style>)注册逐字一致的规则,保证视觉同款。\n *\n * 压缩检查点遮蔽的是模型可见表层,人类转录中的历史仍在其上方;卡片只报告\n * 模型从何处起不再看到那段历史。summary 来自检查点引用的 compaction/summary\n * 事件;窗口裁剪把该事件留在窗外时,行不可展开而不是显示空内容。\n */\n\nimport type { ChatNode } from '@deepseek-ai/dsh-client-ui-conversation/client';\nimport { DisclosureRow, IconBrowseOutline16 } from '@deepseek-ai/dsh-client-ui-primitives';\nimport type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';\nimport type { CSSProperties } from 'react';\nimport { memo, useState } from 'react';\n\n/** Keyed renderer props: 装配好的卡片节点 + 绑定 `om-compaction` 命名空间的 locale 座。 */\nexport interface OmCompactionCardProps {\n readonly node: ChatNode<'om-compaction'>;\n readonly t: TranslateNS<'om-compaction'>;\n}\n\n/** 卡片样式类名(与宿主 ContextInjectionRow.module.css 同款规则,见下方注册)。 */\nconst css = {\n root: 'om-compaction-root',\n chevron: 'om-compaction-chevron',\n sep: 'om-compaction-sep',\n summary: 'om-compaction-summary',\n body: 'om-compaction-body',\n} as const;\n\n/** 宿主 ContextInjectionRow.module.css 的规则(逐字一致,仅类名按插件前缀)。 */\nconst cardCss = `\n.${css.root}{min-width:0}\n.${css.root}[data-open]{padding-bottom:4px}\n.${css.chevron}{color:var(--dsw-alias-label-secondary)}\n.${css.sep}{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}\n.${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}\n.${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}\n`;\n\n/** 注册卡片样式(与宿主 client bundle 同机制;无 document 的环境如 node 测试直接跳过)。 */\nif (\n typeof document !== 'undefined' &&\n document.querySelector('style[data-dsh-plugin-om-card]') === null\n) {\n const tag = document.createElement('style');\n tag.dataset.dshPluginOmCard = 'true';\n tag.textContent = cardCss;\n document.head.appendChild(tag);\n}\n\n/** 折叠式压缩卡片(统计标题行 + 代码块样式 summary 展开,同「上下文注入」卡片)。 */\nexport const OmCompactionCard = memo(function OmCompactionCard({ node, t }: OmCompactionCardProps) {\n const [expanded, setExpanded] = useState(false);\n const { data } = node;\n const expandable = data.summary !== null;\n const open = expandable && expanded;\n const stats =\n data.shadowedItemCount !== null &&\n data.shadowedCharCount !== null &&\n data.shadowedTokenCount !== null &&\n data.summaryCharCount !== null &&\n data.summaryTokenCount !== null\n ? t('compaction.stats', {\n items: data.shadowedItemCount,\n beforeChars: data.shadowedCharCount,\n beforeTokens: data.shadowedTokenCount,\n afterChars: data.summaryCharCount,\n afterTokens: data.summaryTokenCount,\n })\n : data.shadowedItemCount !== null && data.shadowedTokenCount !== null\n ? t('compaction.completed', {\n items: data.shadowedItemCount,\n tokens: data.shadowedTokenCount,\n })\n : expandable\n ? t('compaction.expand')\n : t('compaction.unavailable');\n return (\n <div style={styles.row}>\n <DisclosureRow\n className={css.root}\n icon={<IconBrowseOutline16 size={14} />}\n chevronClassName={css.chevron}\n title={t('compaction')}\n collapsedContent={\n <>\n <span className={css.sep} aria-hidden />\n <span className={css.summary} data-om-compaction-summary>\n {stats}\n </span>\n </>\n }\n keepContentWhenOpen\n expandable={expandable}\n expandOnRowClick\n open={open}\n onToggle={() => {\n setExpanded((value) => !value);\n }}\n >\n {data.summary !== null && (\n <div className={css.body} style={styles.body}>\n {data.summary}\n </div>\n )}\n </DisclosureRow>\n </div>\n );\n});\n\nconst styles: Record<string, CSSProperties> = {\n row: { padding: '2px 12px' },\n /** 摘要为 <history> 文本,保留换行(宿主 body 的白色空间由内容形态各自处理)。 */\n body: { whiteSpace: 'pre-wrap' },\n};\n","/**\n * dsh-plugin-om 浏览器客户端贡献:压缩卡片。\n *\n * 服务端压缩替换消息继续使用插件自身的检查点标记(source.plugin =\n * 'dsh-plugin-om');宿主 conversation UI 只识别内置的 'compact' 标记,因此本\n * bundle 自行注册一条 conversation 业务定义 + keyed 渲染器,认领插件的压缩\n * 生命周期事件与替换检查点,在消息列表渲染「已压缩」卡片。\n */\nimport type { Context } from '@deepseek-ai/cordis';\n// Type-only: 拉取 locale 插件的 Context 合并(ctx.locale)。\nimport type {} from '@deepseek-ai/dsh-client-locale/client';\n// Type-only: 拉取 runtime 的 Context 合并(ctx.conversationEvents)。\nimport type {} from '@deepseek-ai/dsh-client-runtime/client';\n// Type-only: 'conversation.chat.node' 的 SlotMap 行与 ChatNodeDataMap 声明合并\n// (均由 ui-conversation 声明),注册调用才得以类型化。\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client';\nimport { omCompactionDefinition } from './definition.ts';\nimport { en, NS, zh } from './locales.ts';\nimport { OmCompactionCard } from './OmCompactionCard.tsx';\n\n/** Required services: 聊天节点槽、会话事件注册表与 locale 服务。 */\nexport const inject = ['slots', 'conversationEvents', 'locale'];\n\n/**\n * Client plugin body: 注册压缩卡片的业务定义与 keyed 渲染器。\n * 注册挂在 effect 包装器上,插件卸载时随之移除。\n * @param ctx - client root context.\n */\nexport function apply(ctx: Context): void {\n ctx.effect(\n () => ctx.locale.register(NS, { zh, en }),\n 'dsh-plugin-om: compaction card dictionaries',\n );\n ctx.effect(\n () => ctx.conversationEvents.register(omCompactionDefinition),\n 'dsh-plugin-om: compaction definition',\n );\n ctx.slots.inject('conversation.chat.node', () =>\n ctx.slots.register(\n { name: 'conversation.chat.node', key: 'om-compaction', locale: NS },\n OmCompactionCard,\n ),\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["memo","useState","DisclosureRow","IconBrowseOutline16"],"sources":["../src/constants.ts","../src/client/definition.ts","../src/client/locales.ts","../src/client/OmCompactionCard.tsx","../src/client/index.ts"],"sourcesContent":["/**\n * 共享常量:集中定义插件级魔法字符串与事件名,避免散落各模块。\n */\n\n/** 插件标识:压缩消息 source.plugin 取值(注入压缩日志的来源标记)与日志前缀。 */\nexport const PLUGIN_LABEL = 'dsh-plugin-om';\n\n/** 压缩日志标签名:<history>...</history> 包裹观察/反思日志块(输入与输出均为合法 history 块)。 */\nexport const HISTORY_TAG = 'history';\n\n/** 压缩日志块开标签上的 tip 属性(对 AI 的提醒:本块是历史压缩产物,不要复述)。 */\nexport const HISTORY_TIP = '当前块是历史消息的压缩产物,不要复述';\n\n/**\n * 「完整消息」定义(提示词 / recall 工具描述 / 块顶注释共用同一字符串)。\n * 完整消息是摘要日志与 recall 共用的定位单位;首条 index 为 0,按会话顺序递增、全局稳定。\n * 用户消息指 user_message 中 source.kind 为 user 的部分;其余部分(宿主注入的上下文等)\n * 为系统消息,同样是一条完整消息。\n */\nexport const COMPLETE_MESSAGE_DEFINITION =\n '`完整消息`被定义为`用户消息`,`系统消息`,`模型输出文本`和`具有result的toolcall`的集合。首条`完整消息`的index是0,后续的index递增。';\n\n/** 判定 user/message 的 source 是否为本插件自产(压缩日志机制消息;含兼容旧宿主 checkpoint 标记 'compact')。这类消息不占完整消息 index。 */\nexport function isPluginOwnedSource(\n source: { kind?: string; plugin?: string } | undefined,\n): boolean {\n if (source?.kind !== 'plugin') return false;\n return source.plugin === PLUGIN_LABEL || source.plugin === COMPACT_CHECKPOINT_PLUGIN;\n}\n\n/** 旧日志压缩消息的宿主 checkpoint 标记 plugin 名(dsh-compaction-basic 的 COMPACT_CHECKPOINT_MARKER.plugin;历史兼容识别用)。 */\nexport const COMPACT_CHECKPOINT_PLUGIN = 'compact';\n","/**\n * 压缩卡片业务定义:认领插件自产的压缩生命周期事件与替换检查点,\n * 聚合出可渲染的摘要卡片节点。\n *\n * 宿主 conversation 客户端仅识别 source.plugin === 'compact' 的压缩检查点\n * (ui-conversation 的 compactionDefinition),插件自产的检查点标记为\n * PLUGIN_LABEL('dsh-plugin-om'),由本定义认领。生命周期事件(compaction/start\n * |summary|end)同时会被宿主的 compactionDefinition 匹配,但宿主没有检查点证据\n * 时不产出节点(buildViewNode 返回 null),因此双方共存无视觉冲突。\n */\n\nimport type {\n ConversationMatch,\n ConversationNodeContext,\n ConversationNodeDefinition,\n} from '@deepseek-ai/dsh-client-runtime/client';\nimport type { ChatNode, ChatNodeDataMap } from '@deepseek-ai/dsh-client-ui-conversation/client';\nimport type {} from '@deepseek-ai/dsh-compaction/types';\nimport type { SessionEvent } from '@deepseek-ai/dsh-session/types';\nimport { PLUGIN_LABEL } from '../constants.ts';\nimport type { CompactionSummaryPayload } from '../types.ts';\n\n/** 压缩卡片渲染器分发键(合并进 ChatNodeDataMap)。 */\nexport const COMPACTION_CARD_KIND = 'om-compaction';\n\ndeclare module '@deepseek-ai/dsh-client-ui-conversation/client' {\n interface ChatNodeDataMap {\n /** dsh-plugin-om 压缩替换检查点渲染的摘要卡片数据。 */\n 'om-compaction': OmCompactionChatData;\n }\n}\n\n/** 压缩卡片载荷:摘要文本与遮蔽统计(seq/time 由节点本体提供,不重复存放)。 */\nexport interface OmCompactionChatData {\n /** 压缩进行中(compaction/start 已到、checkpoint/end 未到):渲染为「正在压缩上下文…」提示行。 */\n readonly running: boolean;\n /** 压缩 pass(观察/反思;来自 start 事件载荷的插件扩展,缺失或非运行态为 null)。 */\n readonly phase: 'observe' | 'reflect' | null;\n /** compaction/summary 的文本摘要;窗口裁剪把该事件留在窗外时为 null(卡片不可展开)。 */\n readonly summary: string | null;\n /** 已载入的 compaction/summary 事件 seq,窗外时为 null。 */\n readonly summaryEventSeq: number | null;\n /** 被遮蔽的表层节点数,summary 事件缺失或载荷非法时为 null。 */\n readonly shadowedItemCount: number | null;\n /** 遮蔽的 token 数,summary 事件缺失或载荷非法时为 null。 */\n readonly shadowedTokenCount: number | null;\n /** 压缩前的字符数(被压缩内容文本长度合计),载荷缺失或非法时为 null。 */\n readonly shadowedCharCount: number | null;\n /** 压缩后的字符数(摘要文本长度),summary 不可用或非法时为 null。 */\n readonly summaryCharCount: number | null;\n /** 压缩后的估算 token 数(4 字符 ≈ 1 token,与服务端 estimateTextTokens 同一启发式),summary 不可用或非法时为 null。 */\n readonly summaryTokenCount: number | null;\n /** 摘要调用重试次数(= 载荷 attemptCount - 1;载荷缺失或非法时为 null)。 */\n readonly retryCount: number | null;\n}\n\n/** 压缩生命周期关联状态:summary / checkpoint / end 事件证据。 */\ninterface OmCompactionState {\n readonly summary?: ConversationMatch;\n readonly checkpoint?: ConversationMatch;\n /** compaction/end(成功与失败都会到达;无 checkpoint 的 end 表示压缩失败,撤回进行中提示行)。 */\n readonly end?: ConversationMatch;\n}\n\n/**\n * replace-surface 判定:surfaceOp 为 { op: 'replace' } 对象(与宿主 runtime 的\n * isReplacementSurfaceEvent 同义)。宿主该助手位于浏览器 bundle 内\n * (window.__ModuleLoader__ 闭包),node 端测试无法求值,故本地实现同一形状检查。\n */\nfunction isReplacementSurface(event: SessionEvent): boolean {\n const surfaceOp = (event as { surfaceOp?: unknown }).surfaceOp;\n return (\n typeof surfaceOp === 'object' &&\n surfaceOp !== null &&\n (surfaceOp as { op?: unknown }).op === 'replace'\n );\n}\n\n/**\n * 从压缩替换检查点(user/message + replace surface + source.plugin 为本插件)\n * 读取关联 identity。宿主的 'compact' 检查点由宿主自己渲染,本插件不认领,\n * 避免同一压缩出现两张卡片。\n */\nexport function checkpointCompactionId(event: SessionEvent): string | undefined {\n if (event.type !== 'user/message' || !isReplacementSurface(event)) return undefined;\n const data = event.data as unknown as {\n source?: { kind?: unknown; plugin?: unknown; compactionId?: unknown };\n };\n const source = data.source;\n if (\n source === undefined ||\n source.kind !== 'plugin' ||\n source.plugin !== PLUGIN_LABEL ||\n typeof source.compactionId !== 'string'\n ) {\n return undefined;\n }\n return source.compactionId;\n}\n\n/** 从 compaction/summary 载荷提取摘要文本与遮蔽统计(载荷非法时各字段回落 null)。 */\nfunction compactSummaryData(summaryMatch: ConversationMatch | undefined): OmCompactionChatData {\n let summary: string | null = null;\n let shadowedItemCount: number | null = null;\n let shadowedTokenCount: number | null = null;\n let shadowedCharCount: number | null = null;\n let retryCount: number | null = null;\n if (summaryMatch?.event.type === 'compaction/summary') {\n // 宿主载荷类型是 union 且不含插件扩展字段,读取处收窄为插件扩展类型\n const data = summaryMatch.event.data as CompactionSummaryPayload;\n if (Array.isArray(data.summary)) {\n const text = data.summary.map((block) => (block.type === 'text' ? block.text : '')).join('');\n summary = text.trim() === '' ? null : text;\n }\n shadowedItemCount =\n Array.isArray(data.shadowedSeqs) &&\n data.shadowedSeqs.every((seq) => Number.isSafeInteger(seq) && seq >= 0)\n ? data.shadowedSeqs.length\n : null;\n shadowedTokenCount =\n Number.isSafeInteger(data.shadowedTokenCount) && data.shadowedTokenCount >= 0\n ? data.shadowedTokenCount\n : null;\n shadowedCharCount =\n data.shadowedCharCount !== undefined &&\n Number.isSafeInteger(data.shadowedCharCount) &&\n data.shadowedCharCount >= 0\n ? data.shadowedCharCount\n : null;\n retryCount =\n data.attemptCount !== undefined &&\n Number.isSafeInteger(data.attemptCount) &&\n data.attemptCount >= 1\n ? data.attemptCount - 1\n : null;\n }\n return {\n running: false,\n phase: null,\n summary,\n summaryEventSeq: summaryMatch?.event.seq ?? null,\n shadowedItemCount,\n shadowedTokenCount,\n shadowedCharCount,\n summaryCharCount: summary === null ? null : summary.length,\n summaryTokenCount: summary === null ? null : Math.ceil(summary.length / 4),\n retryCount,\n };\n}\n\n/** 压缩进行中提示行的载荷(统计未就绪,全部为 null;phase 取自 start 事件载荷扩展,缺失回退 null)。 */\nfunction runningData(start: ConversationMatch | undefined): OmCompactionChatData {\n /** start 事件载荷(phase 为插件扩展;非法值回退 null)。 */\n const data = start?.event.data as { phase?: unknown } | undefined;\n /** 合法 phase(观察/反思)。 */\n const phase = data?.phase === 'observe' || data?.phase === 'reflect' ? data.phase : null;\n return {\n running: true,\n phase,\n summary: null,\n summaryEventSeq: null,\n shadowedItemCount: null,\n shadowedTokenCount: null,\n shadowedCharCount: null,\n summaryCharCount: null,\n summaryTokenCount: null,\n retryCount: null,\n };\n}\n\n/** 窗口只载入部分事件时的回落证据扫描(summary / 检查点 / end 各自独立)。 */\nfunction fallbackState(context: ConversationNodeContext<OmCompactionState>): OmCompactionState {\n const summary = context.matches.find((match) => match.event.type === 'compaction/summary');\n const checkpoint = context.matches.find(\n (match) => checkpointCompactionId(match.event) !== undefined,\n );\n const end = context.matches.find((match) => match.event.type === 'compaction/end');\n return {\n ...(summary === undefined ? {} : { summary }),\n ...(checkpoint === undefined ? {} : { checkpoint }),\n ...(end === undefined ? {} : { end }),\n };\n}\n\n/** 构建最终 Chat 目标节点(与 ui-conversation 的 chatNode 助手同构)。 */\nfunction chatNode<Kind extends keyof ChatNodeDataMap & string>(\n context: ConversationNodeContext,\n kind: Kind,\n anchorSeq: number,\n data: ChatNodeDataMap[Kind],\n visibility: 'visible' | 'hidden' = 'visible',\n): ChatNode<Kind> {\n return {\n key: context.key,\n kind,\n id: context.id,\n target: 'chat',\n anchorSeq,\n location: context.start?.location ?? context.matches[0]?.location ?? { kind: 'unresolved' },\n visibility,\n data,\n };\n}\n\n/**\n * 插件压缩生命周期定义:compaction/start 开启上下文,summary / 替换检查点 /\n * end 作为 update 折叠证据;仅在存在替换检查点时产出卡片节点。\n */\nexport const omCompactionDefinition: ConversationNodeDefinition<OmCompactionState> = {\n kind: COMPACTION_CARD_KIND,\n target: 'chat',\n match: (event) => {\n const compactionId = checkpointCompactionId(event);\n if (compactionId !== undefined) return { id: compactionId, role: 'update' };\n if (\n event.type === 'compaction/start' ||\n event.type === 'compaction/summary' ||\n event.type === 'compaction/end'\n ) {\n const id: unknown = event.data.compactionId;\n if (typeof id !== 'string' || id === '') return null;\n return { id, role: event.type === 'compaction/start' ? 'start' : 'update' };\n }\n return null;\n },\n start: () => ({}),\n update: (context, match) => {\n if (match.event.type === 'compaction/summary') return { ...context.state, summary: match };\n if (match.event.type === 'compaction/end') return { ...context.state, end: match };\n if (checkpointCompactionId(match.event) !== undefined)\n return { ...context.state, checkpoint: match };\n return context.state;\n },\n buildViewNode: (context) => {\n const state = context.state ?? fallbackState(context);\n // 替换检查点已到达 → 压缩完成,渲染摘要卡片(摘要统计就绪)\n if (state.checkpoint !== undefined) {\n const data = compactSummaryData(state.summary);\n return chatNode(context, COMPACTION_CARD_KIND, state.checkpoint.event.seq, data);\n }\n // end 已到达但无检查点 → 压缩失败/中止:撤回进行中提示行——\n // 已物化节点不能撤回,以 hidden visibility 保留同一 key(聊天视图按可见节点过滤,行从消息流消失)\n if (state.end !== undefined) {\n const anchorSeq = context.start?.event.seq ?? state.end.event.seq;\n return chatNode(\n context,\n COMPACTION_CARD_KIND,\n anchorSeq,\n runningData(context.start),\n 'hidden',\n );\n }\n // start 已到、checkpoint/end 未到 → 压缩进行中,渲染「正在压缩上下文…」提示行\n if (context.start !== undefined) {\n return chatNode(\n context,\n COMPACTION_CARD_KIND,\n context.start.event.seq,\n runningData(context.start),\n );\n }\n return null;\n },\n};\n","/**\n * `om-compaction` namespace dictionaries: 插件压缩卡片的界面文案。\n *\n * 与宿主 conversation 命名空间分离(独立 NS),插件卡片走自己的 keyed 渲染器,\n * 文案键不与对话插件的键冲突。\n */\n\n/** Dictionary namespace owned by this plugin. */\nexport const NS = 'om-compaction';\n\n/** Simplified Chinese dictionary (the key-set source of truth). */\nexport const zh = {\n compaction: '上下文已压缩',\n 'compaction.completed': '已压缩 {items} 条历史记录(约 {tokens} tokens)',\n 'compaction.stats':\n '压缩前 {items} 条消息 · {beforeChars} 字符(约 {beforeTokens} tokens)→ 压缩后 {afterChars} 字符(约 {afterTokens} tokens)',\n 'compaction.expand': '点击查看压缩摘要',\n 'compaction.unavailable': '压缩摘要不可用',\n 'compaction.running': '正在压缩上下文…',\n 'compaction.running.observe': '正在压缩上下文(观察)…',\n 'compaction.running.reflect': '正在压缩上下文(反思)…',\n 'compaction.retries': '重试 {count} 次',\n} as const;\n\n/** English dictionary(键集与 zh 一致)。 */\nexport const en: Record<keyof typeof zh, string> = {\n compaction: 'Context compacted',\n 'compaction.completed': 'Compacted {items} messages (~{tokens} tokens)',\n 'compaction.stats':\n '{items} messages · {beforeChars} chars (~{beforeTokens} tokens) before → {afterChars} chars (~{afterTokens} tokens) after',\n 'compaction.expand': 'Click to view summary',\n 'compaction.unavailable': 'Summary unavailable',\n 'compaction.running': 'Compressing context…',\n 'compaction.running.observe': 'Compressing context (observation)…',\n 'compaction.running.reflect': 'Compressing context (reflection)…',\n 'compaction.retries': 'Retried {count} times',\n};\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Compaction card copy owned by dsh-plugin-om. */\n 'om-compaction': keyof typeof zh;\n }\n}\n","/**\n * dsh-plugin-om 压缩卡片渲染器:与宿主「上下文注入」卡片同款的折叠行。\n *\n * 复用平台原语 DisclosureRow(宿主 ContextInjectionRow 用的同一外壳组件);行内\n * 统计与展开体样式按宿主 ContextInjectionRow.module.css 的规则注入——宿主该卡片\n * 的样式是编译期哈希的 CSS Module,插件 bundle 无法引用其类名,故按宿主 client\n * bundle 的同一机制(注入 <style>)注册逐字一致的规则,保证视觉同款。\n *\n * 压缩检查点遮蔽的是模型可见表层,人类转录中的历史仍在其上方;卡片只报告\n * 模型从何处起不再看到那段历史。summary 来自检查点引用的 compaction/summary\n * 事件;窗口裁剪把该事件留在窗外时,行不可展开而不是显示空内容。\n */\n\nimport type { ChatNode } from '@deepseek-ai/dsh-client-ui-conversation/client';\nimport { DisclosureRow, IconBrowseOutline16 } from '@deepseek-ai/dsh-client-ui-primitives';\nimport type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';\nimport type { CSSProperties } from 'react';\nimport { memo, useState } from 'react';\n\n/** Keyed renderer props: 装配好的卡片节点 + 绑定 `om-compaction` 命名空间的 locale 座。 */\nexport interface OmCompactionCardProps {\n readonly node: ChatNode<'om-compaction'>;\n readonly t: TranslateNS<'om-compaction'>;\n}\n\n/** 卡片样式类名(与宿主 ContextInjectionRow.module.css 同款规则,见下方注册)。 */\nconst css = {\n root: 'om-compaction-root',\n chevron: 'om-compaction-chevron',\n sep: 'om-compaction-sep',\n summary: 'om-compaction-summary',\n body: 'om-compaction-body',\n} as const;\n\n/** 宿主 ContextInjectionRow.module.css 的规则(逐字一致,仅类名按插件前缀)。 */\nconst cardCss = `\n.${css.root}{min-width:0}\n.${css.root}[data-open]{padding-bottom:4px}\n.${css.chevron}{color:var(--dsw-alias-label-secondary)}\n.${css.sep}{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}\n.${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}\n.${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}\n`;\n\n/** 注册卡片样式(与宿主 client bundle 同机制;无 document 的环境如 node 测试直接跳过)。 */\nif (\n typeof document !== 'undefined' &&\n document.querySelector('style[data-dsh-plugin-om-card]') === null\n) {\n const tag = document.createElement('style');\n tag.dataset.dshPluginOmCard = 'true';\n tag.textContent = cardCss;\n document.head.appendChild(tag);\n}\n\n/** 折叠式压缩卡片(统计标题行 + 代码块样式 summary 展开,同「上下文注入」卡片)。 */\nexport const OmCompactionCard = memo(function OmCompactionCard({ node, t }: OmCompactionCardProps) {\n const [expanded, setExpanded] = useState(false);\n const { data } = node;\n // 压缩进行中:start 已到、checkpoint/end 未到 → 不可展开的「正在压缩上下文…」提示行\n if (data.running) {\n /** 提示行文案(按 phase 区分观察/反思;缺失回退通用文案)。 */\n const runningLabel =\n data.phase === 'observe'\n ? t('compaction.running.observe')\n : data.phase === 'reflect'\n ? t('compaction.running.reflect')\n : t('compaction.running');\n return (\n <div style={styles.row}>\n <DisclosureRow\n className={css.root}\n icon={<IconBrowseOutline16 size={14} />}\n title={t('compaction')}\n open={false}\n expandable={false}\n onToggle={() => {\n /* 进行中提示行不可展开 */\n }}\n collapsedContent={\n <>\n <span className={css.sep} aria-hidden />\n <span className={css.summary} data-om-compaction-running>\n {runningLabel}\n </span>\n </>\n }\n />\n </div>\n );\n }\n const expandable = data.summary !== null;\n const open = expandable && expanded;\n /** 统计行文案(重试次数仅在有重试时追加;retryCount 缺失视为未重试)。 */\n const stats =\n data.shadowedItemCount !== null &&\n data.shadowedCharCount !== null &&\n data.shadowedTokenCount !== null &&\n data.summaryCharCount !== null &&\n data.summaryTokenCount !== null\n ? t('compaction.stats', {\n items: data.shadowedItemCount,\n beforeChars: data.shadowedCharCount,\n beforeTokens: data.shadowedTokenCount,\n afterChars: data.summaryCharCount,\n afterTokens: data.summaryTokenCount,\n })\n : data.shadowedItemCount !== null && data.shadowedTokenCount !== null\n ? t('compaction.completed', {\n items: data.shadowedItemCount,\n tokens: data.shadowedTokenCount,\n })\n : expandable\n ? t('compaction.expand')\n : t('compaction.unavailable');\n const retry =\n data.retryCount !== null && data.retryCount > 0\n ? ` \\u00b7 ${t('compaction.retries', { count: data.retryCount })}`\n : '';\n return (\n <div style={styles.row}>\n <DisclosureRow\n className={css.root}\n icon={<IconBrowseOutline16 size={14} />}\n chevronClassName={css.chevron}\n title={t('compaction')}\n collapsedContent={\n <>\n <span className={css.sep} aria-hidden />\n <span className={css.summary} data-om-compaction-summary>\n {stats}\n {retry}\n </span>\n </>\n }\n keepContentWhenOpen\n expandable={expandable}\n expandOnRowClick\n open={open}\n onToggle={() => {\n setExpanded((value) => !value);\n }}\n >\n {data.summary !== null && (\n <div className={css.body} style={styles.body}>\n {data.summary}\n </div>\n )}\n </DisclosureRow>\n </div>\n );\n});\n\nconst styles: Record<string, CSSProperties> = {\n row: {},\n /** 摘要为 <history> 文本,保留换行(宿主 body 的白色空间由内容形态各自处理)。 */\n body: { whiteSpace: 'pre-wrap' },\n};\n","/**\n * dsh-plugin-om 浏览器客户端贡献:压缩卡片。\n *\n * 服务端压缩替换消息继续使用插件自身的检查点标记(source.plugin =\n * 'dsh-plugin-om');宿主 conversation UI 只识别内置的 'compact' 标记,因此本\n * bundle 自行注册一条 conversation 业务定义 + keyed 渲染器,认领插件的压缩\n * 生命周期事件与替换检查点,在消息列表渲染「已压缩」卡片。\n */\nimport type { Context } from '@deepseek-ai/cordis';\n// Type-only: 拉取 locale 插件的 Context 合并(ctx.locale)。\nimport type {} from '@deepseek-ai/dsh-client-locale/client';\n// Type-only: 拉取 runtime 的 Context 合并(ctx.conversationEvents)。\nimport type {} from '@deepseek-ai/dsh-client-runtime/client';\n// Type-only: 'conversation.chat.node' 的 SlotMap 行与 ChatNodeDataMap 声明合并\n// (均由 ui-conversation 声明),注册调用才得以类型化。\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client';\nimport { omCompactionDefinition } from './definition.ts';\nimport { en, NS, zh } from './locales.ts';\nimport { OmCompactionCard } from './OmCompactionCard.tsx';\n\n/** Required services: 聊天节点槽、会话事件注册表与 locale 服务。 */\nexport const inject = ['slots', 'conversationEvents', 'locale'];\n\n/**\n * Client plugin body: 注册压缩卡片的业务定义与 keyed 渲染器。\n * 注册挂在 effect 包装器上,插件卸载时随之移除。\n * @param ctx - client root context.\n */\nexport function apply(ctx: Context): void {\n ctx.effect(\n () => ctx.locale.register(NS, { zh, en }),\n 'dsh-plugin-om: compaction card dictionaries',\n );\n ctx.effect(\n () => ctx.conversationEvents.register(omCompactionDefinition),\n 'dsh-plugin-om: compaction definition',\n );\n ctx.slots.inject('conversation.chat.node', () =>\n ctx.slots.register(\n { name: 'conversation.chat.node', key: 'om-compaction', locale: NS },\n OmCompactionCard,\n ),\n );\n}\n"],"mappings":"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"}
|
package/dist/compress.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../src/compress.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../src/compress.ts"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EACV,KAAK,EAIL,OAAO,EACP,YAAY,EACZ,OAAO,EAIR,MAAM,YAAY,CAAC;AACpB,OAAO,EAAgB,KAAK,YAAY,EAAqC,MAAM,YAAY,CAAC;AAEhG,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvD;AAoDD,+DAA+D;AAC/D,MAAM,MAAM,cAAc,GAAG;IAAE,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,CAAC;AAE3E;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAyBzF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAc1E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,CA8BpE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG;IAChD,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7C,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC,CAaA;AA8GD;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC9B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CA8Hf;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC9B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAwJf;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC9B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAwCf"}
|
package/dist/index.mjs
CHANGED
|
@@ -7661,7 +7661,7 @@ function parseHistoryBlock(xml) {
|
|
|
7661
7661
|
for (let i = 0; i < children.length; i += 1) {
|
|
7662
7662
|
/** 当前子节点(跳过文本与注释)。 */
|
|
7663
7663
|
const node = children[i];
|
|
7664
|
-
if (
|
|
7664
|
+
if (node?.nodeType !== 1) continue;
|
|
7665
7665
|
/** 子元素(节点类型收窄)。 */
|
|
7666
7666
|
const el = node;
|
|
7667
7667
|
/** 元素标签名。 */
|
|
@@ -7841,6 +7841,7 @@ async function runSummarySubagent(ctx, agent, instruction, contextText, maxToken
|
|
|
7841
7841
|
logger.step(`摘要调用成功(第 ${attempt}/${maxAttempts} 次,输出 ${text.length} 字符` + (usage === void 0 ? "" : `,input ${String(usage.inputTokens ?? "?")} / output ${String(usage.outputTokens ?? "?")} tokens`) + ")");
|
|
7842
7842
|
return {
|
|
7843
7843
|
text,
|
|
7844
|
+
attemptCount: attempt,
|
|
7844
7845
|
...usage === void 0 ? {} : { usage }
|
|
7845
7846
|
};
|
|
7846
7847
|
} catch (error) {
|
|
@@ -7874,8 +7875,9 @@ async function runSummarySubagent(ctx, agent, instruction, contextText, maxToken
|
|
|
7874
7875
|
* 替换 <history> 消息 → compaction/end),使消息记录(聊天视图压缩卡片)与轨迹视图
|
|
7875
7876
|
* 可见;compaction/summary 同时承担影子价格认领(shadowedTokenCount),不再单独发
|
|
7876
7877
|
* compaction/prune。替换消息的 source 使用插件标识(plugin: 'dsh-plugin-om' +
|
|
7877
|
-
* compactionId),UI 据此关联 summary
|
|
7878
|
-
*
|
|
7878
|
+
* compactionId),UI 据此关联 summary 与替换消息。compaction/start 在摘要调用前追加
|
|
7879
|
+
* (UI 压缩中提示行的开启标记,载荷带 phase 区分观察/反思);摘要失败/无输出或提交
|
|
7880
|
+
* 失败时追加 compaction/end(error) 结束生命周期(失败不产生替换消息)。
|
|
7879
7881
|
*
|
|
7880
7882
|
* 观察区间:pre-step 触发时日志 call-result 完备,区间不再受 turn/end 封顶——压缩边界 →
|
|
7881
7883
|
* 表层长度-1-tailCount(尾部保留 config.tailMessageCount 条不压缩),当前 turn 中已
|
|
@@ -8058,15 +8060,21 @@ function newCompactionId() {
|
|
|
8058
8060
|
return uuid();
|
|
8059
8061
|
}
|
|
8060
8062
|
/** 追加 compaction/start(log-only:仅标记生命周期开始,不进入表层),返回事件 seq。 */
|
|
8061
|
-
function appendCompactionStart(session, lifecycle) {
|
|
8062
|
-
|
|
8063
|
+
function appendCompactionStart(session, lifecycle, phase) {
|
|
8064
|
+
/** start 事件载荷(宿主类型 + 插件扩展 phase;宿主 append 不做 schema 剥离,扩展字段原样持久化)。 */
|
|
8065
|
+
const payload = {
|
|
8066
|
+
compactionId: lifecycle.compactionId,
|
|
8067
|
+
turn: lifecycle.turn,
|
|
8068
|
+
phase
|
|
8069
|
+
};
|
|
8070
|
+
return session.append("compaction/start", payload).seq;
|
|
8063
8071
|
}
|
|
8064
8072
|
/**
|
|
8065
8073
|
* 追加 compaction/summary(log-only,承担影子价格认领:紧随其后的替换消息消费 claim)。
|
|
8066
8074
|
* summary 为完整合并后的 <history> 内文;usage 由摘要调用提取(无则省略)。
|
|
8067
8075
|
*/
|
|
8068
8076
|
function appendCompactionSummary(session, data) {
|
|
8069
|
-
/** summary 事件载荷(宿主类型 + 插件扩展 shadowedCharCount;宿主 append 不做 schema 剥离,扩展字段原样持久化)。 */
|
|
8077
|
+
/** summary 事件载荷(宿主类型 + 插件扩展 shadowedCharCount/attemptCount;宿主 append 不做 schema 剥离,扩展字段原样持久化)。 */
|
|
8070
8078
|
const payload = {
|
|
8071
8079
|
compactionId: data.lifecycle.compactionId,
|
|
8072
8080
|
summary: [{
|
|
@@ -8080,6 +8088,7 @@ function appendCompactionSummary(session, data) {
|
|
|
8080
8088
|
provider: data.provider,
|
|
8081
8089
|
model: data.model,
|
|
8082
8090
|
maxTokens: data.maxTokens,
|
|
8091
|
+
attemptCount: data.attemptCount,
|
|
8083
8092
|
...data.usage === void 0 ? {} : { usage: data.usage }
|
|
8084
8093
|
};
|
|
8085
8094
|
return session.append("compaction/summary", payload).seq;
|
|
@@ -8157,6 +8166,20 @@ async function reflectPass(ctx, agent, config, window, target, signal) {
|
|
|
8157
8166
|
const contextText = blocks.map((block) => block.text).join("\n");
|
|
8158
8167
|
/** 反思输出应覆盖输入块引用的全部 index(解析输入条目取最大 end;无条目则只校验起点)。 */
|
|
8159
8168
|
const expectedEnd = reflectExpectedEnd(contextText);
|
|
8169
|
+
/** 本次压缩生命周期(compactionId + 当前轮次;start 在摘要调用前开启,UI 压缩中提示)。 */
|
|
8170
|
+
const lifecycle = {
|
|
8171
|
+
compactionId: newCompactionId(),
|
|
8172
|
+
turn: openTurnOf(session)
|
|
8173
|
+
};
|
|
8174
|
+
try {
|
|
8175
|
+
logger.step("反思:追加 compaction/start(摘要调用前开启压缩中提示)");
|
|
8176
|
+
appendCompactionStart(session, lifecycle, "reflect");
|
|
8177
|
+
} catch (error) {
|
|
8178
|
+
/** 启动失败信息(统一字符串)。 */
|
|
8179
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
8180
|
+
logger.warn(`反思压缩启动失败: ${message}`);
|
|
8181
|
+
return;
|
|
8182
|
+
}
|
|
8160
8183
|
/** 反思摘要结果(null 表示失败/跳过)。 */
|
|
8161
8184
|
const summaryResult = await runSummarySubagent(ctx, agent, instruction, contextText, config.compressMaxTokens, target, config.debug, signal, {
|
|
8162
8185
|
maxAttempts: config.compressRetryCount + 1,
|
|
@@ -8166,19 +8189,15 @@ async function reflectPass(ctx, agent, config, window, target, signal) {
|
|
|
8166
8189
|
}
|
|
8167
8190
|
});
|
|
8168
8191
|
if (summaryResult === null || summaryResult.text.trim().length === 0) {
|
|
8169
|
-
logger.step("
|
|
8192
|
+
logger.step("反思:摘要调用失败/无输出,追加 compaction/end(error)");
|
|
8193
|
+
try {
|
|
8194
|
+
appendCompactionEnd(session, lifecycle, "摘要调用失败/无输出");
|
|
8195
|
+
} catch {}
|
|
8170
8196
|
return;
|
|
8171
8197
|
}
|
|
8172
8198
|
/** 反思摘要文本。 */
|
|
8173
8199
|
const report = summaryResult.text;
|
|
8174
|
-
/** 本次压缩生命周期(compactionId + 当前轮次;摘要成功后才写入日志)。 */
|
|
8175
|
-
const lifecycle = {
|
|
8176
|
-
compactionId: newCompactionId(),
|
|
8177
|
-
turn: openTurnOf(session)
|
|
8178
|
-
};
|
|
8179
8200
|
try {
|
|
8180
|
-
logger.step("反思提交:追加 compaction/start");
|
|
8181
|
-
appendCompactionStart(session, lifecycle);
|
|
8182
8201
|
logger.step("反思提交:追加 compaction/summary(影子价格认领)");
|
|
8183
8202
|
/** compaction/summary 事件 seq(承担影子价格认领,紧随其后的替换消息消费)。 */
|
|
8184
8203
|
const summarySeq = appendCompactionSummary(session, {
|
|
@@ -8194,6 +8213,7 @@ async function reflectPass(ctx, agent, config, window, target, signal) {
|
|
|
8194
8213
|
provider: target.provider,
|
|
8195
8214
|
model: target.model,
|
|
8196
8215
|
maxTokens: config.compressMaxTokens,
|
|
8216
|
+
attemptCount: summaryResult.attemptCount,
|
|
8197
8217
|
...summaryResult.usage === void 0 ? {} : { usage: summaryResult.usage }
|
|
8198
8218
|
});
|
|
8199
8219
|
logger.step("反思提交:替换整个 <history> 块区段为合并摘要");
|
|
@@ -8262,8 +8282,26 @@ async function observePass(ctx, agent, config, window, tailCount, target, signal
|
|
|
8262
8282
|
const startIndex = inRangeCms[0]?.index ?? 0;
|
|
8263
8283
|
const endIndex = inRangeCms[inRangeCms.length - 1]?.index ?? startIndex;
|
|
8264
8284
|
logger.step(`观察:保留旧块 ${blocks.length} 条,替换新消息 [${replaceSeqs[0]}..${range.end}](${replaceSeqs.length} 条),尾部保留 ${tailCount} 条(不压缩、不进日志),新消息 index ${startIndex}..${endIndex}`);
|
|
8285
|
+
/** 共享提示词(观察/反思同一套)。 */
|
|
8286
|
+
const instruction = buildHistoryPrompt();
|
|
8287
|
+
/** 渲染输入:本次要压缩的完整消息(合法 <history> 块,含绝对 index;不含尾部;系统消息渲染为 <sys> 空块,本插件自产消息不占位)。 */
|
|
8288
|
+
const contextText = renderMessages(session, replaceSeqs);
|
|
8289
|
+
/** 本次压缩生命周期(compactionId + 当前轮次;start 在摘要调用前开启,UI 压缩中提示)。 */
|
|
8290
|
+
const lifecycle = {
|
|
8291
|
+
compactionId: newCompactionId(),
|
|
8292
|
+
turn: openTurnOf(session)
|
|
8293
|
+
};
|
|
8294
|
+
try {
|
|
8295
|
+
logger.step("观察:追加 compaction/start(摘要调用前开启压缩中提示)");
|
|
8296
|
+
appendCompactionStart(session, lifecycle, "observe");
|
|
8297
|
+
} catch (error) {
|
|
8298
|
+
/** 启动失败信息(统一字符串)。 */
|
|
8299
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
8300
|
+
logger.warn(`观察压缩启动失败: ${message}`);
|
|
8301
|
+
return;
|
|
8302
|
+
}
|
|
8265
8303
|
/** 观察摘要结果(null 表示失败/跳过)。 */
|
|
8266
|
-
const summaryResult = await runSummarySubagent(ctx, agent,
|
|
8304
|
+
const summaryResult = await runSummarySubagent(ctx, agent, instruction, contextText, config.compressMaxTokens, target, config.debug, signal, {
|
|
8267
8305
|
maxAttempts: config.compressRetryCount + 1,
|
|
8268
8306
|
expected: {
|
|
8269
8307
|
start: startIndex,
|
|
@@ -8271,7 +8309,10 @@ async function observePass(ctx, agent, config, window, tailCount, target, signal
|
|
|
8271
8309
|
}
|
|
8272
8310
|
});
|
|
8273
8311
|
if (summaryResult === null || summaryResult.text.trim().length === 0) {
|
|
8274
|
-
logger.step("
|
|
8312
|
+
logger.step("观察:摘要调用失败/无输出,追加 compaction/end(error)");
|
|
8313
|
+
try {
|
|
8314
|
+
appendCompactionEnd(session, lifecycle, "摘要调用失败/无输出");
|
|
8315
|
+
} catch {}
|
|
8275
8316
|
return;
|
|
8276
8317
|
}
|
|
8277
8318
|
/** 观察摘要文本(独立新块;旧块保留,不再合并)。 */
|
|
@@ -8292,14 +8333,7 @@ async function observePass(ctx, agent, config, window, tailCount, target, signal
|
|
|
8292
8333
|
const message = event ? session.deriveEventMessage(event) : null;
|
|
8293
8334
|
return total + (message ? textCharCount(message) : 0);
|
|
8294
8335
|
}, 0);
|
|
8295
|
-
/** 本次压缩生命周期(compactionId + 当前轮次;摘要成功后才写入日志)。 */
|
|
8296
|
-
const lifecycle = {
|
|
8297
|
-
compactionId: newCompactionId(),
|
|
8298
|
-
turn: openTurnOf(session)
|
|
8299
|
-
};
|
|
8300
8336
|
try {
|
|
8301
|
-
logger.step("观察提交:追加 compaction/start");
|
|
8302
|
-
appendCompactionStart(session, lifecycle);
|
|
8303
8337
|
logger.step("观察提交:追加 compaction/summary(影子价格认领)");
|
|
8304
8338
|
/** compaction/summary 事件 seq(承担影子价格认领,紧随其后的替换消息消费)。 */
|
|
8305
8339
|
const summarySeq = appendCompactionSummary(session, {
|
|
@@ -8315,6 +8349,7 @@ async function observePass(ctx, agent, config, window, tailCount, target, signal
|
|
|
8315
8349
|
provider: target.provider,
|
|
8316
8350
|
model: target.model,
|
|
8317
8351
|
maxTokens: config.compressMaxTokens,
|
|
8352
|
+
attemptCount: summaryResult.attemptCount,
|
|
8318
8353
|
...summaryResult.usage === void 0 ? {} : { usage: summaryResult.usage }
|
|
8319
8354
|
});
|
|
8320
8355
|
logger.step("观察提交:替换被压缩新消息区间为 <history>(旧块保留)");
|
package/dist/summarize.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ export declare function renderMessages(session: Session, seqs: readonly number[]
|
|
|
35
35
|
export type SummarySubagentResult = {
|
|
36
36
|
text: string;
|
|
37
37
|
usage?: TokenUsage;
|
|
38
|
+
/** 成功时的尝试次数(1 起;1=首次即成功,>1 表示重试后成功;UI 重试次数 = 该值 - 1)。 */
|
|
39
|
+
attemptCount: number;
|
|
38
40
|
};
|
|
39
41
|
/** 日志最小有效长度:<history> 中间内容小于该长度视为不合法(C 段校验)。 */
|
|
40
42
|
export declare const MIN_HISTORY_LENGTH = 10;
|
package/dist/summarize.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summarize.d.ts","sourceRoot":"","sources":["../src/summarize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAaH,OAAO,KAAK,EAAE,KAAK,EAAmB,OAAO,EAAE,OAAO,EAAE,UAAU,EAAe,MAAM,YAAY,CAAC;AACpG,OAAO,EAAE,KAAK,YAAY,EAAQ,MAAM,YAAY,CAAC;AAErD;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAsC3C;AA0CD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAqEhF;AAED,yEAAyE;AACzE,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"summarize.d.ts","sourceRoot":"","sources":["../src/summarize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAaH,OAAO,KAAK,EAAE,KAAK,EAAmB,OAAO,EAAE,OAAO,EAAE,UAAU,EAAe,MAAM,YAAY,CAAC;AACpG,OAAO,EAAE,KAAK,YAAY,EAAQ,MAAM,YAAY,CAAC;AAErD;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAsC3C;AA0CD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAqEhF;AAED,yEAAyE;AACzE,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AA8EF,gDAAgD;AAChD,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,0DAA0D;AAC1D,eAAO,MAAM,mBAAmB,yrBAA6K,CAAC;AAE9M,4CAA4C;AAC5C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,KAAK,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAoFF;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAYrE;AACD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,iBAAiB,EAAE,GAC3B;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAuBvC;AAED,sCAAsC;AACtC,MAAM,MAAM,sBAAsB,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,sBAAsB,GAAG,MAAM,GAAG,IAAI,CAiC/F;AACD,iFAAiF;AACjF,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAK/C;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,OAAO,EACd,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,sBAAsB,CAAA;CAAE,GACpE,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CA+EvC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -73,5 +73,16 @@ export type CompleteMessage = {
|
|
|
73
73
|
export type CompactionSummaryPayload = SessionEventMap['compaction/summary'] & {
|
|
74
74
|
/** 被压缩内容的字符数(压缩前文本长度合计;UI 标题统计用),旧载荷可能缺失。 */
|
|
75
75
|
shadowedCharCount?: number;
|
|
76
|
+
/** 摘要调用成功时的尝试次数(1 起;重试次数 = attemptCount - 1,UI 展示用),旧载荷可能缺失。 */
|
|
77
|
+
attemptCount?: number;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* 插件扩展的 compaction/start 载荷:宿主类型 + phase(压缩 pass)。
|
|
81
|
+
* 宿主 append 不做 schema 剥离,扩展字段原样持久化;客户端读取时按可选处理,
|
|
82
|
+
* 缺失(旧版本会话)回落通用压缩中文案。
|
|
83
|
+
*/
|
|
84
|
+
export type CompactionStartPayload = SessionEventMap['compaction/start'] & {
|
|
85
|
+
/** 压缩 pass(观察/反思;UI 压缩中提示行区分文案)。 */
|
|
86
|
+
phase: 'observe' | 'reflect';
|
|
76
87
|
};
|
|
77
88
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACvF,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACnG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7E,gDAAgD;AAChD,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;GAGG;AACH,YAAY,EACV,KAAK,EACL,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,MAAM,EACN,OAAO,EACP,OAAO,EACP,YAAY,EACZ,eAAe,EACf,cAAc,EACd,WAAW,EACX,oBAAoB,EACpB,YAAY,EACZ,UAAU,EACV,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,WAAW,GACZ,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,mBAAmB;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,IAAI,EAAE,cAAc,GAAG,mBAAmB,GAAG,aAAa,CAAC;CAC5D,CAAC;AAEF,yDAAyD;AACzD,MAAM,MAAM,YAAY,GAAG;IACzB,oBAAoB;IACpB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,kCAAkC;IAClC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3B,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,WAAW,GAAG,UAAU,CAAC;IAChD,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,wBAAwB,GAAG,eAAe,CAAC,oBAAoB,CAAC,GAAG;IAC7E,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACvF,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACnG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7E,gDAAgD;AAChD,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;GAGG;AACH,YAAY,EACV,KAAK,EACL,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,MAAM,EACN,OAAO,EACP,OAAO,EACP,YAAY,EACZ,eAAe,EACf,cAAc,EACd,WAAW,EACX,oBAAoB,EACpB,YAAY,EACZ,UAAU,EACV,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,WAAW,GACZ,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,mBAAmB;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,IAAI,EAAE,cAAc,GAAG,mBAAmB,GAAG,aAAa,CAAC;CAC5D,CAAC;AAEF,yDAAyD;AACzD,MAAM,MAAM,YAAY,GAAG;IACzB,oBAAoB;IACpB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,kCAAkC;IAClC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3B,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,WAAW,GAAG,UAAU,CAAC;IAChD,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,wBAAwB,GAAG,eAAe,CAAC,oBAAoB,CAAC,GAAG;IAC7E,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG,eAAe,CAAC,kBAAkB,CAAC,GAAG;IACzE,oCAAoC;IACpC,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;CAC9B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-om",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.mjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"build": "tsdown && tsc -p tsconfig.build.json",
|
|
56
56
|
"download:model": "node scripts/download-model.mjs",
|
|
57
57
|
"check": "pnpm run typecheck && pnpm run lint && pnpm run test && pnpm run build",
|
|
58
|
-
"release": "pnpm check &&
|
|
58
|
+
"release": "pnpm check && npm version patch && node scripts/release-archive.mjs && git push && git push --tags",
|
|
59
59
|
"typecheck": "tsc --noEmit",
|
|
60
60
|
"test": "vitest run",
|
|
61
61
|
"build:types": "tsc -p tsconfig.build.json",
|