dsh-plugin-om 0.0.16 → 0.0.17

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 CHANGED
@@ -88,6 +88,17 @@ dsh的"预设"分为两层,`dsh web`等同于`dsh --profile web`,调用的
88
88
  - 输出经 `@xmldom/xmldom` 解析校验:结构合法(标签匹配/闭合/单块)、不含 <reasoning>、index/start/end 连续(与预期覆盖区间一致),失败按 `compressRetryCount` 重试
89
89
  - 块开标签带 `tip` 属性(对 AI 的提醒:"当前块是历史消息的压缩产物,不要复述");块顶为构成逻辑注释(完整消息定义串 + 条目标签语义),消息正文不再附加前缀句
90
90
 
91
+ ### 压缩卡片(消息列表中的「已压缩」展示)
92
+
93
+ 插件自产的替换消息使用插件自身标记(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` 加载),自行认领压缩生命周期事件与替换检查点,在消息列表渲染折叠式「已压缩」卡片:
94
+
95
+ - 卡片默认折叠,采用与宿主「上下文注入」卡片同款样式:同一 DisclosureRow 外壳组件 + IconBrowseOutline16 图标,行内统计与展开体样式按宿主 ContextInjectionRow 的规则注入(插件 bundle 无法引用宿主编译期哈希的 CSS Module 类名,按宿主 client bundle 的同一机制注入 <style>),视觉一致
96
+ - 标题直接展示「压缩前 N 条消息 · X 字符(约 A tokens)→ 压缩后 Y 字符(约 B tokens)」:压缩前字符数来自插件扩展 shadowedCharCount,压缩前 token 来自 shadowedTokenCount,压缩后字符数为摘要文本长度,压缩后 token 在客户端按 4 字符 ≈ 1 token 估算(与服务端 estimateTextTokens 同一启发式);旧会话载荷缺少 shadowedCharCount 时回落为「已压缩 N 条历史记录(约 M tokens)」
97
+ - 点击展开显示压缩摘要文本,按代码块样式呈现(缩小字号、代码背景与等宽字体、保留换行)
98
+ - summary 事件落在当前加载窗口之外时卡片不可展开(不显示空内容)
99
+ - 卡片只认领插件自产的检查点(source.plugin = `dsh-plugin-om`);宿主 `compact` 检查点仍由宿主自己渲染,不会出现双卡片
100
+ - 平台模块(react / cordis / ui-primitives / ui-slots 等)走宿主冻结模块表(保持 external),其余依赖内联进 bundle
101
+
91
102
  ### 注意
92
103
 
93
104
  - 未压缩消息的 token 统计排除系统消息(user_message 中 source.kind 非 user 的部分,如宿主注入的上下文;宿主注入的提醒不计入观察阈值的触发量)
@@ -98,6 +109,7 @@ dsh的"预设"分为两层,`dsh web`等同于`dsh --profile web`,调用的
98
109
 
99
110
  - dsh宿主提供的依赖,直接复用即可,如 cordis / dsh-tools / zod 等
100
111
  - `@xmldom/xmldom` 用于 <history> 块的 XML 构建(输入转义)与解析校验(输出结构合法性),经 tsdown `deps.alwaysBundle` 打包进 dist 产物
112
+ - 浏览器客户端 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(类型与构建期使用)
101
113
  - 向量模型模型二进制:量化 ONNX 约 113MB,启用语义召回时下载,位置`$DSH_HOME/plugin-data/dsh-plugin-om/models/<id>/onnx/model_quantized.onnx`。下载失败可以设置`HF_ENDPOINT=https://hf-mirror.com`
102
114
 
103
115
  ## 插件配置项
@@ -166,10 +178,15 @@ src/
166
178
  ├── recall.ts # recall 工具
167
179
  ├── semantic-recall.ts # recall-semantic 工具(query 语义检索 + 区间限定 + 回退全量 + 匹配说明)
168
180
  └── compress.ts # 两级自动压缩(测量 / mid-turn 区间计算 / 配对平衡回退 / source 标记判定摘要消息 / compaction/* 生命周期事件 + 替换消息 source 插件标识)
181
+ src/client/
182
+ ├── index.ts # 浏览器客户端入口(exports["./client"] → dist/client.js):注入 slots/conversationEvents/locale,注册卡片定义与渲染器
183
+ ├── definition.ts # 压缩卡片业务定义:认领插件生命周期事件与替换检查点(source.plugin = dsh-plugin-om),聚合摘要卡片节点
184
+ ├── OmCompactionCard.tsx # 与宿主「上下文注入」同款的折叠卡片渲染器(统计标题 + 代码块样式 summary 展开)
185
+ └── locales.ts # om-compaction 命名空间字典(zh/en)与 LocaleNamespaceMap 声明合并
169
186
  models/
170
187
  └── paraphrase-multilingual-MiniLM-L12-v2/ # 嵌入模型目录(小文件随包分发;onnx 二进制不随包分发、由运行时按需下载到跨版本共享目录,不进 git)
171
188
  scripts/ # release-archive.mjs(CHANGELOG 归档)/ download-model.mjs(开发手动预下载 CLI)
172
- tests/ # vitest 单元测试(151 例)
189
+ tests/ # vitest 单元测试(服务端 src 各模块 + tests/client/ 客户端卡片定义)
173
190
  .dsh/skills/ # 项目级 skill(feature-defect-workflow:需求/缺陷完成工作流)
174
191
  ```
175
192
 
@@ -0,0 +1,22 @@
1
+ /**
2
+ * dsh-plugin-om 压缩卡片渲染器:与宿主「上下文注入」卡片同款的折叠行。
3
+ *
4
+ * 复用平台原语 DisclosureRow(宿主 ContextInjectionRow 用的同一外壳组件);行内
5
+ * 统计与展开体样式按宿主 ContextInjectionRow.module.css 的规则注入——宿主该卡片
6
+ * 的样式是编译期哈希的 CSS Module,插件 bundle 无法引用其类名,故按宿主 client
7
+ * bundle 的同一机制(注入 <style>)注册逐字一致的规则,保证视觉同款。
8
+ *
9
+ * 压缩检查点遮蔽的是模型可见表层,人类转录中的历史仍在其上方;卡片只报告
10
+ * 模型从何处起不再看到那段历史。summary 来自检查点引用的 compaction/summary
11
+ * 事件;窗口裁剪把该事件留在窗外时,行不可展开而不是显示空内容。
12
+ */
13
+ import type { ChatNode } from '@deepseek-ai/dsh-client-ui-conversation/client';
14
+ import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
15
+ /** Keyed renderer props: 装配好的卡片节点 + 绑定 `om-compaction` 命名空间的 locale 座。 */
16
+ export interface OmCompactionCardProps {
17
+ readonly node: ChatNode<'om-compaction'>;
18
+ readonly t: TranslateNS<'om-compaction'>;
19
+ }
20
+ /** 折叠式压缩卡片(统计标题行 + 代码块样式 summary 展开,同「上下文注入」卡片)。 */
21
+ export declare const OmCompactionCard: import("react").MemoExoticComponent<({ node, t }: OmCompactionCardProps) => import("react").JSX.Element>;
22
+ //# sourceMappingURL=OmCompactionCard.d.ts.map
@@ -0,0 +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,iCAyD/F,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * 压缩卡片业务定义:认领插件自产的压缩生命周期事件与替换检查点,
3
+ * 聚合出可渲染的摘要卡片节点。
4
+ *
5
+ * 宿主 conversation 客户端仅识别 source.plugin === 'compact' 的压缩检查点
6
+ * (ui-conversation 的 compactionDefinition),插件自产的检查点标记为
7
+ * PLUGIN_LABEL('dsh-plugin-om'),由本定义认领。生命周期事件(compaction/start
8
+ * |summary|end)同时会被宿主的 compactionDefinition 匹配,但宿主没有检查点证据
9
+ * 时不产出节点(buildViewNode 返回 null),因此双方共存无视觉冲突。
10
+ */
11
+ import type { ConversationMatch, ConversationNodeDefinition } from '@deepseek-ai/dsh-client-runtime/client';
12
+ import type { SessionEvent } from '@deepseek-ai/dsh-session/types';
13
+ /** 压缩卡片渲染器分发键(合并进 ChatNodeDataMap)。 */
14
+ export declare const COMPACTION_CARD_KIND = "om-compaction";
15
+ declare module '@deepseek-ai/dsh-client-ui-conversation/client' {
16
+ interface ChatNodeDataMap {
17
+ /** dsh-plugin-om 压缩替换检查点渲染的摘要卡片数据。 */
18
+ 'om-compaction': OmCompactionChatData;
19
+ }
20
+ }
21
+ /** 压缩卡片载荷:摘要文本与遮蔽统计(seq/time 由节点本体提供,不重复存放)。 */
22
+ export interface OmCompactionChatData {
23
+ /** compaction/summary 的文本摘要;窗口裁剪把该事件留在窗外时为 null(卡片不可展开)。 */
24
+ readonly summary: string | null;
25
+ /** 已载入的 compaction/summary 事件 seq,窗外时为 null。 */
26
+ readonly summaryEventSeq: number | null;
27
+ /** 被遮蔽的表层节点数,summary 事件缺失或载荷非法时为 null。 */
28
+ readonly shadowedItemCount: number | null;
29
+ /** 遮蔽的 token 数,summary 事件缺失或载荷非法时为 null。 */
30
+ readonly shadowedTokenCount: number | null;
31
+ /** 压缩前的字符数(被压缩内容文本长度合计),载荷缺失或非法时为 null。 */
32
+ readonly shadowedCharCount: number | null;
33
+ /** 压缩后的字符数(摘要文本长度),summary 不可用或非法时为 null。 */
34
+ readonly summaryCharCount: number | null;
35
+ /** 压缩后的估算 token 数(4 字符 ≈ 1 token,与服务端 estimateTextTokens 同一启发式),summary 不可用或非法时为 null。 */
36
+ readonly summaryTokenCount: number | null;
37
+ }
38
+ /** 压缩生命周期关联状态:summary / checkpoint 事件证据。 */
39
+ interface OmCompactionState {
40
+ readonly summary?: ConversationMatch;
41
+ readonly checkpoint?: ConversationMatch;
42
+ }
43
+ /**
44
+ * 从压缩替换检查点(user/message + replace surface + source.plugin 为本插件)
45
+ * 读取关联 identity。宿主的 'compact' 检查点由宿主自己渲染,本插件不认领,
46
+ * 避免同一压缩出现两张卡片。
47
+ */
48
+ export declare function checkpointCompactionId(event: SessionEvent): string | undefined;
49
+ /**
50
+ * 插件压缩生命周期定义:compaction/start 开启上下文,summary / 替换检查点 /
51
+ * end 作为 update 折叠证据;仅在存在替换检查点时产出卡片节点。
52
+ */
53
+ export declare const omCompactionDefinition: ConversationNodeDefinition<OmCompactionState>;
54
+ export {};
55
+ //# sourceMappingURL=definition.d.ts.map
@@ -0,0 +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;CAC3C;AAED,4CAA4C;AAC5C,UAAU,iBAAiB;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;CACzC;AAgBD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAe9E;AAyED;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,0BAA0B,CAAC,iBAAiB,CA8BhF,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * dsh-plugin-om 浏览器客户端贡献:压缩卡片。
3
+ *
4
+ * 服务端压缩替换消息继续使用插件自身的检查点标记(source.plugin =
5
+ * 'dsh-plugin-om');宿主 conversation UI 只识别内置的 'compact' 标记,因此本
6
+ * bundle 自行注册一条 conversation 业务定义 + keyed 渲染器,认领插件的压缩
7
+ * 生命周期事件与替换检查点,在消息列表渲染「已压缩」卡片。
8
+ */
9
+ import type { Context } from '@deepseek-ai/cordis';
10
+ /** Required services: 聊天节点槽、会话事件注册表与 locale 服务。 */
11
+ export declare const inject: string[];
12
+ /**
13
+ * Client plugin body: 注册压缩卡片的业务定义与 keyed 渲染器。
14
+ * 注册挂在 effect 包装器上,插件卸载时随之移除。
15
+ * @param ctx - client root context.
16
+ */
17
+ export declare function apply(ctx: Context): void;
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAYnD,mDAAmD;AACnD,eAAO,MAAM,MAAM,UAA4C,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAexC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * `om-compaction` namespace dictionaries: 插件压缩卡片的界面文案。
3
+ *
4
+ * 与宿主 conversation 命名空间分离(独立 NS),插件卡片走自己的 keyed 渲染器,
5
+ * 文案键不与对话插件的键冲突。
6
+ */
7
+ /** Dictionary namespace owned by this plugin. */
8
+ export declare const NS = "om-compaction";
9
+ /** Simplified Chinese dictionary (the key-set source of truth). */
10
+ export declare const zh: {
11
+ readonly compaction: "上下文已压缩";
12
+ readonly 'compaction.completed': "已压缩 {items} 条历史记录(约 {tokens} tokens)";
13
+ readonly 'compaction.stats': "压缩前 {items} 条消息 · {beforeChars} 字符(约 {beforeTokens} tokens)→ 压缩后 {afterChars} 字符(约 {afterTokens} tokens)";
14
+ readonly 'compaction.expand': "点击查看压缩摘要";
15
+ readonly 'compaction.unavailable': "压缩摘要不可用";
16
+ };
17
+ /** English dictionary(键集与 zh 一致)。 */
18
+ export declare const en: Record<keyof typeof zh, string>;
19
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
20
+ interface LocaleNamespaceMap {
21
+ /** Compaction card copy owned by dsh-plugin-om. */
22
+ 'om-compaction': keyof typeof zh;
23
+ }
24
+ }
25
+ //# sourceMappingURL=locales.d.ts.map
@@ -0,0 +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;;;;;;CAOL,CAAC;AAEX,qCAAqC;AACrC,eAAO,MAAM,EAAE,EAAE,MAAM,CAAC,MAAM,OAAO,EAAE,EAAE,MAAM,CAO9C,CAAC;AAEF,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,mDAAmD;QACnD,eAAe,EAAE,MAAM,OAAO,EAAE,CAAC;KAClC;CACF"}
package/dist/client.js ADDED
@@ -0,0 +1,259 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "dsh-plugin-om",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
8
+ let react = require("react");
9
+ let react_jsx_runtime = require("react/jsx-runtime");
10
+ //#endregion
11
+ //#region src/client/definition.ts
12
+ /** 压缩卡片渲染器分发键(合并进 ChatNodeDataMap)。 */
13
+ const COMPACTION_CARD_KIND = "om-compaction";
14
+ /**
15
+ * replace-surface 判定:surfaceOp 为 { op: 'replace' } 对象(与宿主 runtime 的
16
+ * isReplacementSurfaceEvent 同义)。宿主该助手位于浏览器 bundle 内
17
+ * (window.__ModuleLoader__ 闭包),node 端测试无法求值,故本地实现同一形状检查。
18
+ */
19
+ function isReplacementSurface(event) {
20
+ const surfaceOp = event.surfaceOp;
21
+ return typeof surfaceOp === "object" && surfaceOp !== null && surfaceOp.op === "replace";
22
+ }
23
+ /**
24
+ * 从压缩替换检查点(user/message + replace surface + source.plugin 为本插件)
25
+ * 读取关联 identity。宿主的 'compact' 检查点由宿主自己渲染,本插件不认领,
26
+ * 避免同一压缩出现两张卡片。
27
+ */
28
+ function checkpointCompactionId(event) {
29
+ if (event.type !== "user/message" || !isReplacementSurface(event)) return void 0;
30
+ const source = event.data.source;
31
+ if (source === void 0 || source.kind !== "plugin" || source.plugin !== "dsh-plugin-om" || typeof source.compactionId !== "string") return;
32
+ return source.compactionId;
33
+ }
34
+ /** 从 compaction/summary 载荷提取摘要文本与遮蔽统计(载荷非法时各字段回落 null)。 */
35
+ function compactSummaryData(summaryMatch) {
36
+ let summary = null;
37
+ let shadowedItemCount = null;
38
+ let shadowedTokenCount = null;
39
+ let shadowedCharCount = null;
40
+ if (summaryMatch?.event.type === "compaction/summary") {
41
+ const data = summaryMatch.event.data;
42
+ if (Array.isArray(data.summary)) {
43
+ const text = data.summary.map((block) => block.type === "text" ? block.text : "").join("");
44
+ summary = text.trim() === "" ? null : text;
45
+ }
46
+ shadowedItemCount = Array.isArray(data.shadowedSeqs) && data.shadowedSeqs.every((seq) => Number.isSafeInteger(seq) && seq >= 0) ? data.shadowedSeqs.length : null;
47
+ shadowedTokenCount = Number.isSafeInteger(data.shadowedTokenCount) && data.shadowedTokenCount >= 0 ? data.shadowedTokenCount : null;
48
+ shadowedCharCount = data.shadowedCharCount !== void 0 && Number.isSafeInteger(data.shadowedCharCount) && data.shadowedCharCount >= 0 ? data.shadowedCharCount : null;
49
+ }
50
+ return {
51
+ summary,
52
+ summaryEventSeq: summaryMatch?.event.seq ?? null,
53
+ shadowedItemCount,
54
+ shadowedTokenCount,
55
+ shadowedCharCount,
56
+ summaryCharCount: summary === null ? null : summary.length,
57
+ summaryTokenCount: summary === null ? null : Math.ceil(summary.length / 4)
58
+ };
59
+ }
60
+ /** 窗口只载入检查点(生命周期事件在窗外)时的回落证据扫描。 */
61
+ function fallbackState(context) {
62
+ const summary = context.matches.find((match) => match.event.type === "compaction/summary");
63
+ const checkpoint = context.matches.find((match) => checkpointCompactionId(match.event) !== void 0);
64
+ return {
65
+ ...summary === void 0 ? {} : { summary },
66
+ ...checkpoint === void 0 ? {} : { checkpoint }
67
+ };
68
+ }
69
+ /** 构建最终 Chat 目标节点(与 ui-conversation 的 chatNode 助手同构)。 */
70
+ function chatNode(context, kind, anchorSeq, data) {
71
+ return {
72
+ key: context.key,
73
+ kind,
74
+ id: context.id,
75
+ target: "chat",
76
+ anchorSeq,
77
+ location: context.start?.location ?? context.matches[0]?.location ?? { kind: "unresolved" },
78
+ visibility: "visible",
79
+ data
80
+ };
81
+ }
82
+ /**
83
+ * 插件压缩生命周期定义:compaction/start 开启上下文,summary / 替换检查点 /
84
+ * end 作为 update 折叠证据;仅在存在替换检查点时产出卡片节点。
85
+ */
86
+ const omCompactionDefinition = {
87
+ kind: COMPACTION_CARD_KIND,
88
+ target: "chat",
89
+ match: (event) => {
90
+ const compactionId = checkpointCompactionId(event);
91
+ if (compactionId !== void 0) return {
92
+ id: compactionId,
93
+ role: "update"
94
+ };
95
+ if (event.type === "compaction/start" || event.type === "compaction/summary" || event.type === "compaction/end") {
96
+ const id = event.data.compactionId;
97
+ if (typeof id !== "string" || id === "") return null;
98
+ return {
99
+ id,
100
+ role: event.type === "compaction/start" ? "start" : "update"
101
+ };
102
+ }
103
+ return null;
104
+ },
105
+ start: () => ({}),
106
+ update: (context, match) => {
107
+ if (match.event.type === "compaction/summary") return {
108
+ ...context.state,
109
+ summary: match
110
+ };
111
+ if (checkpointCompactionId(match.event) !== void 0) return {
112
+ ...context.state,
113
+ checkpoint: match
114
+ };
115
+ return context.state;
116
+ },
117
+ buildViewNode: (context) => {
118
+ const state = context.state ?? fallbackState(context);
119
+ if (state.checkpoint === void 0) return null;
120
+ const data = compactSummaryData(state.summary);
121
+ return chatNode(context, COMPACTION_CARD_KIND, state.checkpoint.event.seq, data);
122
+ }
123
+ };
124
+ //#endregion
125
+ //#region src/client/locales.ts
126
+ /**
127
+ * `om-compaction` namespace dictionaries: 插件压缩卡片的界面文案。
128
+ *
129
+ * 与宿主 conversation 命名空间分离(独立 NS),插件卡片走自己的 keyed 渲染器,
130
+ * 文案键不与对话插件的键冲突。
131
+ */
132
+ /** Dictionary namespace owned by this plugin. */
133
+ const NS = "om-compaction";
134
+ /** Simplified Chinese dictionary (the key-set source of truth). */
135
+ const zh = {
136
+ compaction: "上下文已压缩",
137
+ "compaction.completed": "已压缩 {items} 条历史记录(约 {tokens} tokens)",
138
+ "compaction.stats": "压缩前 {items} 条消息 · {beforeChars} 字符(约 {beforeTokens} tokens)→ 压缩后 {afterChars} 字符(约 {afterTokens} tokens)",
139
+ "compaction.expand": "点击查看压缩摘要",
140
+ "compaction.unavailable": "压缩摘要不可用"
141
+ };
142
+ /** English dictionary(键集与 zh 一致)。 */
143
+ const en = {
144
+ compaction: "Context compacted",
145
+ "compaction.completed": "Compacted {items} messages (~{tokens} tokens)",
146
+ "compaction.stats": "{items} messages · {beforeChars} chars (~{beforeTokens} tokens) before → {afterChars} chars (~{afterTokens} tokens) after",
147
+ "compaction.expand": "Click to view summary",
148
+ "compaction.unavailable": "Summary unavailable"
149
+ };
150
+ //#endregion
151
+ //#region src/client/OmCompactionCard.tsx
152
+ /** 卡片样式类名(与宿主 ContextInjectionRow.module.css 同款规则,见下方注册)。 */
153
+ const css = {
154
+ root: "om-compaction-root",
155
+ chevron: "om-compaction-chevron",
156
+ sep: "om-compaction-sep",
157
+ summary: "om-compaction-summary",
158
+ body: "om-compaction-body"
159
+ };
160
+ /** 宿主 ContextInjectionRow.module.css 的规则(逐字一致,仅类名按插件前缀)。 */
161
+ const cardCss = `
162
+ .${css.root}{min-width:0}
163
+ .${css.root}[data-open]{padding-bottom:4px}
164
+ .${css.chevron}{color:var(--dsw-alias-label-secondary)}
165
+ .${css.sep}{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}
166
+ .${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}
167
+ .${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}
168
+ `;
169
+ /** 注册卡片样式(与宿主 client bundle 同机制;无 document 的环境如 node 测试直接跳过)。 */
170
+ if (typeof document !== "undefined" && document.querySelector("style[data-dsh-plugin-om-card]") === null) {
171
+ const tag = document.createElement("style");
172
+ tag.dataset.dshPluginOmCard = "true";
173
+ tag.textContent = cardCss;
174
+ document.head.appendChild(tag);
175
+ }
176
+ /** 折叠式压缩卡片(统计标题行 + 代码块样式 summary 展开,同「上下文注入」卡片)。 */
177
+ const OmCompactionCard = (0, react.memo)(function OmCompactionCard({ node, t }) {
178
+ const [expanded, setExpanded] = (0, react.useState)(false);
179
+ const { data } = node;
180
+ const expandable = data.summary !== null;
181
+ const open = expandable && expanded;
182
+ const stats = data.shadowedItemCount !== null && data.shadowedCharCount !== null && data.shadowedTokenCount !== null && data.summaryCharCount !== null && data.summaryTokenCount !== null ? t("compaction.stats", {
183
+ items: data.shadowedItemCount,
184
+ beforeChars: data.shadowedCharCount,
185
+ beforeTokens: data.shadowedTokenCount,
186
+ afterChars: data.summaryCharCount,
187
+ afterTokens: data.summaryTokenCount
188
+ }) : data.shadowedItemCount !== null && data.shadowedTokenCount !== null ? t("compaction.completed", {
189
+ items: data.shadowedItemCount,
190
+ tokens: data.shadowedTokenCount
191
+ }) : expandable ? t("compaction.expand") : t("compaction.unavailable");
192
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
193
+ style: styles.row,
194
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
195
+ className: css.root,
196
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutline16, { size: 14 }),
197
+ chevronClassName: css.chevron,
198
+ title: t("compaction"),
199
+ collapsedContent: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
200
+ className: css.sep,
201
+ "aria-hidden": true
202
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
203
+ className: css.summary,
204
+ "data-om-compaction-summary": true,
205
+ children: stats
206
+ })] }),
207
+ keepContentWhenOpen: true,
208
+ expandable,
209
+ expandOnRowClick: true,
210
+ open,
211
+ onToggle: () => {
212
+ setExpanded((value) => !value);
213
+ },
214
+ children: data.summary !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
215
+ className: css.body,
216
+ style: styles.body,
217
+ children: data.summary
218
+ })
219
+ })
220
+ });
221
+ });
222
+ const styles = {
223
+ row: { padding: "2px 12px" },
224
+ /** 摘要为 <history> 文本,保留换行(宿主 body 的白色空间由内容形态各自处理)。 */
225
+ body: { whiteSpace: "pre-wrap" }
226
+ };
227
+ //#endregion
228
+ //#region src/client/index.ts
229
+ /** Required services: 聊天节点槽、会话事件注册表与 locale 服务。 */
230
+ const inject = [
231
+ "slots",
232
+ "conversationEvents",
233
+ "locale"
234
+ ];
235
+ /**
236
+ * Client plugin body: 注册压缩卡片的业务定义与 keyed 渲染器。
237
+ * 注册挂在 effect 包装器上,插件卸载时随之移除。
238
+ * @param ctx - client root context.
239
+ */
240
+ function apply(ctx) {
241
+ ctx.effect(() => ctx.locale.register(NS, {
242
+ zh,
243
+ en
244
+ }), "dsh-plugin-om: compaction card dictionaries");
245
+ ctx.effect(() => ctx.conversationEvents.register(omCompactionDefinition), "dsh-plugin-om: compaction definition");
246
+ ctx.slots.inject("conversation.chat.node", () => ctx.slots.register({
247
+ name: "conversation.chat.node",
248
+ key: "om-compaction",
249
+ locale: NS
250
+ }, OmCompactionCard));
251
+ }
252
+ //#endregion
253
+ exports.apply = apply;
254
+ exports.inject = inject;
255
+ return module.exports;
256
+ }
257
+ });
258
+
259
+ //# sourceMappingURL=client.js.map
@@ -0,0 +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 +1 @@
1
- {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../src/compress.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EACV,KAAK,EAEL,OAAO,EACP,YAAY,EACZ,OAAO,EAIR,MAAM,YAAY,CAAC;AACpB,OAAO,EAAgB,KAAK,YAAY,EAAsB,MAAM,YAAY,CAAC;AAEjF,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvD;AAwCD,+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;AA4FD;;;;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,CA2Gf;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,CAkIf;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"}
1
+ {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../src/compress.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EACV,KAAK,EAGL,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;AAiGD;;;;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,CAiHf;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,CA2If;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"}
@@ -13,7 +13,7 @@ export declare const HISTORY_TIP = "\u5F53\u524D\u5757\u662F\u5386\u53F2\u6D88\u
13
13
  * 用户消息指 user_message 中 source.kind 为 user 的部分;其余部分(宿主注入的上下文等)
14
14
  * 为系统消息,同样是一条完整消息。
15
15
  */
16
- export declare const COMPLETE_MESSAGE_DEFINITION = "`\u7528\u6237\u6D88\u606F`\uFF08user_message \u4E2D kind \u4E3A user \u7684\u90E8\u5206\uFF09\uFF0C`\u7CFB\u7EDF\u6D88\u606F`\uFF08user_message \u4E2D\u5176\u4F59 kind \u7684\u90E8\u5206\uFF09\uFF0C`\u6A21\u578B\u8F93\u51FA\u6587\u672C`\u548C`\u5177\u6709result\u7684toolcall`\u88AB\u89C6\u4F5C`\u5B8C\u6574\u6D88\u606F`\u3002\u9996\u6761`\u5B8C\u6574\u6D88\u606F`\u7684index\u662F0\uFF0C\u540E\u7EED\u7684index\u9012\u589E\u3002";
16
+ export declare const COMPLETE_MESSAGE_DEFINITION = "`\u5B8C\u6574\u6D88\u606F`\u88AB\u5B9A\u4E49\u4E3A`\u7528\u6237\u6D88\u606F`\uFF0C`\u7CFB\u7EDF\u6D88\u606F`\uFF0C`\u6A21\u578B\u8F93\u51FA\u6587\u672C`\u548C`\u5177\u6709result\u7684toolcall`\u7684\u96C6\u5408\u3002\u9996\u6761`\u5B8C\u6574\u6D88\u606F`\u7684index\u662F0\uFF0C\u540E\u7EED\u7684index\u9012\u589E\u3002";
17
17
  /** 判定 user/message 的 source 是否为本插件自产(压缩日志机制消息;含兼容旧宿主 checkpoint 标记 'compact')。这类消息不占完整消息 index。 */
18
18
  export declare function isPluginOwnedSource(source: {
19
19
  kind?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,oDAAoD;AACpD,eAAO,MAAM,YAAY,kBAAkB,CAAC;AAE5C,sEAAsE;AACtE,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,kDAAkD;AAClD,eAAO,MAAM,WAAW,iHAAuB,CAAC;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,kbACuG,CAAC;AAEhJ,mGAAmG;AACnG,wBAAgB,mBAAmB,CACjC,MAAM,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GACrD,OAAO,CAGT;AAED,0GAA0G;AAC1G,eAAO,MAAM,yBAAyB,YAAY,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,oDAAoD;AACpD,eAAO,MAAM,YAAY,kBAAkB,CAAC;AAE5C,sEAAsE;AACtE,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,kDAAkD;AAClD,eAAO,MAAM,WAAW,iHAAuB,CAAC;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,oUACgD,CAAC;AAEzF,mGAAmG;AACnG,wBAAgB,mBAAmB,CACjC,MAAM,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GACrD,OAAO,CAGT;AAED,0GAA0G;AAC1G,eAAO,MAAM,yBAAyB,YAAY,CAAC"}
package/dist/index.mjs CHANGED
@@ -22,7 +22,7 @@ const HISTORY_TIP = "当前块是历史消息的压缩产物,不要复述";
22
22
  * 用户消息指 user_message 中 source.kind 为 user 的部分;其余部分(宿主注入的上下文等)
23
23
  * 为系统消息,同样是一条完整消息。
24
24
  */
25
- const COMPLETE_MESSAGE_DEFINITION = "`用户消息`(user_message 中 kind 为 user 的部分),`系统消息`(user_message 中其余 kind 的部分),`模型输出文本`和`具有result的toolcall`被视作`完整消息`。首条`完整消息`的index是0,后续的index递增。";
25
+ const COMPLETE_MESSAGE_DEFINITION = "`完整消息`被定义为`用户消息`,`系统消息`,`模型输出文本`和`具有result的toolcall`的集合。首条`完整消息`的index是0,后续的index递增。";
26
26
  /** 判定 user/message 的 source 是否为本插件自产(压缩日志机制消息;含兼容旧宿主 checkpoint 标记 'compact')。这类消息不占完整消息 index。 */
27
27
  function isPluginOwnedSource(source) {
28
28
  if (source?.kind !== "plugin") return false;
@@ -49,6 +49,15 @@ function blocksToText(blocks) {
49
49
  for (const block of blocks) if (isRecord(block) && block.type === "text" && typeof block.text === "string") out.push(block.text);
50
50
  return out.join("");
51
51
  }
52
+ /** 消息内容的字符数:递归计入 text 块与 tool-result 内嵌文本(与宿主 token 估算口径一致)。 */
53
+ function textCharCount(message) {
54
+ if (!message || !Array.isArray(message.content)) return 0;
55
+ /** 累计字符数。 */
56
+ let total = 0;
57
+ for (const block of message.content) if (block.type === "text") total += block.text.length;
58
+ else if (block.type === "tool-result") total += blocksToText(block.content).length;
59
+ return total;
60
+ }
52
61
  /** 面向 recall 的完整消息呈现:text 原样;tool-call 展开(参数=代码);tool-result 取文本。 */
53
62
  function renderMessageText(message) {
54
63
  if (!message || !Array.isArray(message.content)) return "";
@@ -7615,7 +7624,7 @@ function buildSummaryOptions(session, instruction, contextText, maxTokens, targe
7615
7624
  };
7616
7625
  }
7617
7626
  /** 产出日志后插入首个 <history> 后的格式说明(XML 注释,完整消息定义 + 条目标签语义)。 */
7618
- const HISTORY_FORMAT_NOTE = `<!-- 完整消息:${COMPLETE_MESSAGE_DEFINITION} <user_message index="N"> 与 <assistant index="N"> 表示单条完整消息,<assistant start="A" end="B"> 表示连续模块,start/end 是首尾完整消息的 index;<sys type="KIND" index="N"> 表示系统消息,块中为空 -->`;
7627
+ const HISTORY_FORMAT_NOTE = `<!-- 完整消息:${COMPLETE_MESSAGE_DEFINITION} <TAG index="N">表示单条完整消息,<TAG start="A" end="B"> 表示连续模块,start/end 是首尾完整消息的 index;<sys type="KIND" index="N"> 表示被压缩的系统消息,块中为空 -->`;
7619
7628
  /** 读取元素整数属性(非负整数;缺失 / 非数字返回 undefined)。 */
7620
7629
  function intAttr(el, name) {
7621
7630
  /** 属性原始值(缺失为 null)。 */
@@ -7914,6 +7923,18 @@ function historyTextOf(event) {
7914
7923
  if (!rest.startsWith(">") && !rest.startsWith(" tip=")) return void 0;
7915
7924
  return text;
7916
7925
  }
7926
+ /** 提取 <history> 块内文(去掉开/闭标签与首尾空白;非块文本原样返回)。 */
7927
+ function historyInnerText(text) {
7928
+ /** 闭标签。 */
7929
+ const closeTag = `</${HISTORY_TAG}>`;
7930
+ const close = text.lastIndexOf(closeTag);
7931
+ if (close === -1) return text;
7932
+ const open = text.indexOf(`<${HISTORY_TAG}`);
7933
+ if (open === -1) return text;
7934
+ const gt = text.indexOf(">", open);
7935
+ if (gt === -1 || gt >= close) return text;
7936
+ return text.slice(gt + 1, close).trim();
7937
+ }
7917
7938
  /**
7918
7939
  * 未压缩消息 token 估算:最后一个 <history> 块之后的表层节点合计
7919
7940
  * (其前含自身视为已压缩,不计入观察阈值衡量对象;无压缩日志时计全部)。
@@ -8045,7 +8066,8 @@ function appendCompactionStart(session, lifecycle) {
8045
8066
  * summary 为完整合并后的 <history> 内文;usage 由摘要调用提取(无则省略)。
8046
8067
  */
8047
8068
  function appendCompactionSummary(session, data) {
8048
- return session.append("compaction/summary", {
8069
+ /** summary 事件载荷(宿主类型 + 插件扩展 shadowedCharCount;宿主 append 不做 schema 剥离,扩展字段原样持久化)。 */
8070
+ const payload = {
8049
8071
  compactionId: data.lifecycle.compactionId,
8050
8072
  summary: [{
8051
8073
  type: "text",
@@ -8054,11 +8076,13 @@ function appendCompactionSummary(session, data) {
8054
8076
  shadowedRange: data.shadowedRange,
8055
8077
  shadowedSeqs: data.shadowedSeqs,
8056
8078
  shadowedTokenCount: data.shadowedTokenCount,
8079
+ shadowedCharCount: data.shadowedCharCount,
8057
8080
  provider: data.provider,
8058
8081
  model: data.model,
8059
8082
  maxTokens: data.maxTokens,
8060
8083
  ...data.usage === void 0 ? {} : { usage: data.usage }
8061
- }).seq;
8084
+ };
8085
+ return session.append("compaction/summary", payload).seq;
8062
8086
  }
8063
8087
  /** 追加 compaction/end(log-only,结束生命周期;error 记录失败原因)。 */
8064
8088
  function appendCompactionEnd(session, lifecycle, error) {
@@ -8111,6 +8135,8 @@ async function reflectPass(ctx, agent, config, window, target, signal) {
8111
8135
  const threshold = Math.floor(window * config.historyMergeRatio);
8112
8136
  /** 全部块 token 估算合计(摘要总长)。 */
8113
8137
  const tokens = blocks.reduce((total, block) => total + estimateTextTokens(block.text), 0);
8138
+ /** 被压缩块区段的字符数合计(压缩前内文长度;UI 标题统计用,与观察路径一致只计内容不计标签)。 */
8139
+ const shadowedCharCount = blocks.reduce((total, block) => total + historyInnerText(block.text).length, 0);
8114
8140
  if (tokens < threshold) {
8115
8141
  logger.step(`反思:摘要 ${tokens} tokens < 阈值 ${threshold},跳过`);
8116
8142
  return;
@@ -8164,6 +8190,7 @@ async function reflectPass(ctx, agent, config, window, target, signal) {
8164
8190
  },
8165
8191
  shadowedSeqs: blockSeqs,
8166
8192
  shadowedTokenCount: tokens,
8193
+ shadowedCharCount,
8167
8194
  provider: target.provider,
8168
8195
  model: target.model,
8169
8196
  maxTokens: config.compressMaxTokens,
@@ -8257,6 +8284,14 @@ async function observePass(ctx, agent, config, window, tailCount, target, signal
8257
8284
  const message = event ? session.deriveEventMessage(event) : null;
8258
8285
  return total + (message ? ctx.tokenMeter.estimateMessage(message) : 0);
8259
8286
  }, 0);
8287
+ /** 被替换消息的字符数合计(压缩前文本长度;UI 标题统计用,递归计入 tool-result 内嵌文本)。 */
8288
+ const shadowedCharCount = replaceSeqs.reduce((total, seq) => {
8289
+ /** 当前表层事件。 */
8290
+ const event = session.events[seq];
8291
+ /** 事件对应的消息(取文本块字符数)。 */
8292
+ const message = event ? session.deriveEventMessage(event) : null;
8293
+ return total + (message ? textCharCount(message) : 0);
8294
+ }, 0);
8260
8295
  /** 本次压缩生命周期(compactionId + 当前轮次;摘要成功后才写入日志)。 */
8261
8296
  const lifecycle = {
8262
8297
  compactionId: newCompactionId(),
@@ -8276,6 +8311,7 @@ async function observePass(ctx, agent, config, window, tailCount, target, signal
8276
8311
  },
8277
8312
  shadowedSeqs: replaceSeqs,
8278
8313
  shadowedTokenCount,
8314
+ shadowedCharCount,
8279
8315
  provider: target.provider,
8280
8316
  model: target.model,
8281
8317
  maxTokens: config.compressMaxTokens,
@@ -8686,20 +8722,20 @@ function parseRecallArgs(raw) {
8686
8722
  function buildRecallTool(getPruner) {
8687
8723
  return {
8688
8724
  name: "recall",
8689
- description: `根据完整消息序号(index),回看指定区间的过往消息。${COMPLETE_MESSAGE_DEFINITION} start 必须传入,是区间的基准;end 和 offset 二选一:end 指定另一个边界(含两端,与 start 的位置关系不影响结果),offset 指定区间包含的完整消息数量(正数向后、负数向前)。`,
8725
+ description: `${COMPLETE_MESSAGE_DEFINITION}此工具可以精确查询完整消息。用index指定一个区间,返回区间内所有完整消息的内容。`,
8690
8726
  parameters: {
8691
8727
  start: {
8692
8728
  type: "number",
8693
- description: "完整消息序号(index),区间的基准边界",
8729
+ description: "完整消息序号(index),作为基准边界,和end或offset配合,指定区间",
8694
8730
  required: true
8695
8731
  },
8696
8732
  end: {
8697
8733
  type: "number",
8698
- description: "与 offset 互斥,指定区间的另一个边界(含)。与 start 的位置关系不影响结果。"
8734
+ description: "与 offset 互斥,指定区间的另一个边界。"
8699
8735
  },
8700
8736
  offset: {
8701
8737
  type: "number",
8702
- description: "与 end 互斥,指定区间包含的完整消息数量。传入正数查看 start 之后的若干条,负数则是之前的。"
8738
+ description: "与 end 互斥。相对 start 的步数:正数向后、负数向前。"
8703
8739
  }
8704
8740
  },
8705
8741
  output: {
@@ -8867,7 +8903,7 @@ function matchExplanation(query, text, score) {
8867
8903
  return `相似度 ${score.toFixed(3)}${keywords}`;
8868
8904
  }
8869
8905
  /** 模型未就绪时返回给模型的文案(告知即可;下载完成后无需另行通知,直接再次调用)。 */
8870
- const SEMANTIC_MODEL_NOT_READY_MESSAGE = "语义检索暂不可用:本地嵌入模型尚未就绪(正在后台下载约 113MB;下载完成后无需提示,直接再次调用本工具即可。若下载失败,下次调用会自动重试)。可稍后重试,或先用 recall 工具按完整消息 index 精确检索。";
8906
+ const SEMANTIC_MODEL_NOT_READY_MESSAGE = "语义检索暂不可用,本地向量模型尚未就绪。";
8871
8907
  /** 构建 recall-semantic 工具定义(embedder/modelStatus 可注入,测试传替身;缺省用本地模型)。 */
8872
8908
  function buildSemanticRecallTool(options) {
8873
8909
  /** pruner 获取器(可选,裁剪超大工具结果)。 */
@@ -8876,7 +8912,7 @@ function buildSemanticRecallTool(options) {
8876
8912
  const embed = options?.embedder ?? ((texts) => getEmbedder().then((fn) => fn(texts)));
8877
8913
  return {
8878
8914
  name: "recall-semantic",
8879
- description: `按语义(自然语言含义)在会话全部完整消息中检索:${COMPLETE_MESSAGE_DEFINITION} 用一句话描述你要找的内容(可混用中英文与代码术语)。返回最匹配的若干条完整消息、index 与匹配说明;如需精确定位某个 index 周边的消息,请再用 recall 工具。`,
8915
+ description: `${COMPLETE_MESSAGE_DEFINITION}此工具可以按自然语言含义,检索最符合的完整消息。默认在全消息范围搜索,可以指定区间。`,
8880
8916
  parameters: {
8881
8917
  query: {
8882
8918
  type: "string",
@@ -8889,15 +8925,15 @@ function buildSemanticRecallTool(options) {
8889
8925
  },
8890
8926
  start: {
8891
8927
  type: "number",
8892
- description: "完整消息序号(index),可选。限定检索区间:以该条为基准边界(意义同 recall)。缺省检索全部消息。区间不合法(越界)时自动回退全量检索并在结果中说明。"
8928
+ description: "完整消息序号(index),可选。作为基准边界,和end或offset配合,指定搜索区间。"
8893
8929
  },
8894
8930
  end: {
8895
8931
  type: "number",
8896
- description: " offset 互斥,限定区间的另一个边界(含;意义同 recall)。"
8932
+ description: "必须和start配合使用,与 offset 互斥,指定搜索区间的另一个边界。"
8897
8933
  },
8898
8934
  offset: {
8899
8935
  type: "number",
8900
- description: " end 互斥。相对 start 的步数:正数向后、负数向前(意义同 recall)。"
8936
+ description: "必须和start配合使用,与 end 互斥。相对 start 的步数:正数向后、负数向前。"
8901
8937
  }
8902
8938
  },
8903
8939
  output: {
@@ -1 +1 @@
1
- {"version":3,"file":"recall.d.ts","sourceRoot":"","sources":["../src/recall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,YAAY,CAAC;AAGjE;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;iBAQzB,CAAC;AAEL,4CAA4C;AAC5C,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAYxD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,OAAO,GAAG,cAAc,CAqFzE"}
1
+ {"version":3,"file":"recall.d.ts","sourceRoot":"","sources":["../src/recall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,YAAY,CAAC;AAGjE;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;iBAQzB,CAAC;AAEL,4CAA4C;AAC5C,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAYxD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,OAAO,GAAG,cAAc,CAoFzE"}
@@ -46,7 +46,7 @@ export declare function tokenize(text: string): Set<string>;
46
46
  /** 命中消息的匹配说明行:相似度 + 与 query 共有的关键词(最多 8 个)。 */
47
47
  export declare function matchExplanation(query: string, text: string, score: number): string;
48
48
  /** 模型未就绪时返回给模型的文案(告知即可;下载完成后无需另行通知,直接再次调用)。 */
49
- export declare const SEMANTIC_MODEL_NOT_READY_MESSAGE = "\u8BED\u4E49\u68C0\u7D22\u6682\u4E0D\u53EF\u7528\uFF1A\u672C\u5730\u5D4C\u5165\u6A21\u578B\u5C1A\u672A\u5C31\u7EEA\uFF08\u6B63\u5728\u540E\u53F0\u4E0B\u8F7D\u7EA6 113MB\uFF1B\u4E0B\u8F7D\u5B8C\u6210\u540E\u65E0\u9700\u63D0\u793A\uFF0C\u76F4\u63A5\u518D\u6B21\u8C03\u7528\u672C\u5DE5\u5177\u5373\u53EF\u3002\u82E5\u4E0B\u8F7D\u5931\u8D25\uFF0C\u4E0B\u6B21\u8C03\u7528\u4F1A\u81EA\u52A8\u91CD\u8BD5\uFF09\u3002\u53EF\u7A0D\u540E\u91CD\u8BD5\uFF0C\u6216\u5148\u7528 recall \u5DE5\u5177\u6309\u5B8C\u6574\u6D88\u606F index \u7CBE\u786E\u68C0\u7D22\u3002";
49
+ export declare const SEMANTIC_MODEL_NOT_READY_MESSAGE = "\u8BED\u4E49\u68C0\u7D22\u6682\u4E0D\u53EF\u7528\uFF0C\u672C\u5730\u5411\u91CF\u6A21\u578B\u5C1A\u672A\u5C31\u7EEA\u3002";
50
50
  /** 构建 recall-semantic 工具定义(embedder/modelStatus 可注入,测试传替身;缺省用本地模型)。 */
51
51
  export declare function buildSemanticRecallTool(options?: {
52
52
  getPruner?: () => unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"semantic-recall.d.ts","sourceRoot":"","sources":["../src/semantic-recall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAoB,KAAK,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE/F,OAAO,KAAK,EAAmB,cAAc,EAAkB,MAAM,YAAY,CAAC;AAGlF,qEAAqE;AACrE,eAAO,MAAM,wBAAwB;;;;;;iBAUjC,CAAC;AAEL,6DAA6D;AAC7D,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,+CAA+C;AAC/C,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAWxE;AAED,6DAA6D;AAC7D,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAExE;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,IAAI,CAAC,kBAAkB,EAAE,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC,GACzD,WAAW,CA2Bb;AAED,uCAAuC;AACvC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAOlD;AAED,+CAA+C;AAC/C,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAcnF;AAED,+CAA+C;AAC/C,eAAO,MAAM,gCAAgC,0iBACoE,CAAC;AAElH,uEAAuE;AACvE,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE;IAChD,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACxD,GAAG,cAAc,CAsHjB"}
1
+ {"version":3,"file":"semantic-recall.d.ts","sourceRoot":"","sources":["../src/semantic-recall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAoB,KAAK,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE/F,OAAO,KAAK,EAAmB,cAAc,EAAkB,MAAM,YAAY,CAAC;AAGlF,qEAAqE;AACrE,eAAO,MAAM,wBAAwB;;;;;;iBAUjC,CAAC;AAEL,6DAA6D;AAC7D,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,+CAA+C;AAC/C,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAWxE;AAED,6DAA6D;AAC7D,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAExE;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,IAAI,CAAC,kBAAkB,EAAE,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC,GACzD,WAAW,CA2Bb;AAED,uCAAuC;AACvC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAOlD;AAED,+CAA+C;AAC/C,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAcnF;AAED,+CAA+C;AAC/C,eAAO,MAAM,gCAAgC,6HAAyB,CAAC;AAEvE,uEAAuE;AACvE,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE;IAChD,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACxD,GAAG,cAAc,CAqHjB"}
@@ -39,7 +39,7 @@ export type SummarySubagentResult = {
39
39
  /** 日志最小有效长度:<history> 中间内容小于该长度视为不合法(C 段校验)。 */
40
40
  export declare const MIN_HISTORY_LENGTH = 10;
41
41
  /** 产出日志后插入首个 <history> 后的格式说明(XML 注释,完整消息定义 + 条目标签语义)。 */
42
- export declare const HISTORY_FORMAT_NOTE = "<!-- \u5B8C\u6574\u6D88\u606F\uFF1A`\u7528\u6237\u6D88\u606F`\uFF08user_message \u4E2D kind \u4E3A user \u7684\u90E8\u5206\uFF09\uFF0C`\u7CFB\u7EDF\u6D88\u606F`\uFF08user_message \u4E2D\u5176\u4F59 kind \u7684\u90E8\u5206\uFF09\uFF0C`\u6A21\u578B\u8F93\u51FA\u6587\u672C`\u548C`\u5177\u6709result\u7684toolcall`\u88AB\u89C6\u4F5C`\u5B8C\u6574\u6D88\u606F`\u3002\u9996\u6761`\u5B8C\u6574\u6D88\u606F`\u7684index\u662F0\uFF0C\u540E\u7EED\u7684index\u9012\u589E\u3002 <user_message index=\"N\"> \u4E0E <assistant index=\"N\"> \u8868\u793A\u5355\u6761\u5B8C\u6574\u6D88\u606F\uFF0C<assistant start=\"A\" end=\"B\"> \u8868\u793A\u8FDE\u7EED\u6A21\u5757\uFF0Cstart/end \u662F\u9996\u5C3E\u5B8C\u6574\u6D88\u606F\u7684 index\uFF1B<sys type=\"KIND\" index=\"N\"> \u8868\u793A\u7CFB\u7EDF\u6D88\u606F\uFF0C\u5757\u4E2D\u4E3A\u7A7A -->";
42
+ export declare const HISTORY_FORMAT_NOTE = "<!-- \u5B8C\u6574\u6D88\u606F\uFF1A`\u5B8C\u6574\u6D88\u606F`\u88AB\u5B9A\u4E49\u4E3A`\u7528\u6237\u6D88\u606F`\uFF0C`\u7CFB\u7EDF\u6D88\u606F`\uFF0C`\u6A21\u578B\u8F93\u51FA\u6587\u672C`\u548C`\u5177\u6709result\u7684toolcall`\u7684\u96C6\u5408\u3002\u9996\u6761`\u5B8C\u6574\u6D88\u606F`\u7684index\u662F0\uFF0C\u540E\u7EED\u7684index\u9012\u589E\u3002 <TAG index=\"N\">\u8868\u793A\u5355\u6761\u5B8C\u6574\u6D88\u606F\uFF0C<TAG start=\"A\" end=\"B\"> \u8868\u793A\u8FDE\u7EED\u6A21\u5757\uFF0Cstart/end \u662F\u9996\u5C3E\u5B8C\u6574\u6D88\u606F\u7684 index\uFF1B<sys type=\"KIND\" index=\"N\"> \u8868\u793A\u88AB\u538B\u7F29\u7684\u7CFB\u7EDF\u6D88\u606F\uFF0C\u5757\u4E2D\u4E3A\u7A7A -->";
43
43
  /** history 块内条目(单条 index 或模块 start/end)。 */
44
44
  export type HistoryEntryRange = {
45
45
  kind: 'user' | 'assistant' | 'sys';
@@ -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;CACpB,CAAC;AA8EF,gDAAgD;AAChD,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,0DAA0D;AAC1D,eAAO,MAAM,mBAAmB,8zBAAiN,CAAC;AAElP,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"}
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;CACpB,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
@@ -10,7 +10,7 @@ import type { Agent } from '@deepseek-ai/dsh-agent';
10
10
  import type { CompactionId } from '@deepseek-ai/dsh-compaction';
11
11
  import type { ToolResultPruner } from '@deepseek-ai/dsh-compaction-tool-result-pruner';
12
12
  import type { Message, TokenUsage, UserMessage } from '@deepseek-ai/dsh-llm';
13
- import type { Session, SessionEvent } from '@deepseek-ai/dsh-session';
13
+ import type { Session, SessionEvent, SessionEventMap } from '@deepseek-ai/dsh-session';
14
14
  import type { SubagentResult, SubagentRun, SubagentStartRequest } from '@deepseek-ai/dsh-subagent';
15
15
  import type { SystemPrompt } from '@deepseek-ai/dsh-system-prompt';
16
16
  import type { TokenMeter } from '@deepseek-ai/dsh-token-meter';
@@ -21,7 +21,7 @@ export type { PluginConfig } from './config.ts';
21
21
  * 官方包宿主类型再导出:插件 API 与工具签名统一从这里取型,
22
22
  * 避免各模块直接依赖不同版本的 dsh-* 包类型面。
23
23
  */
24
- export type { Agent, CompactionId, Context, EventOptions, Events, Message, Session, SessionEvent, SubagentResult, SubagentRun, SubagentStartRequest, SystemPrompt, TokenMeter, TokenUsage, ToolDefinition, ToolResultPruner, ToolRunContext, UserMessage, };
24
+ export type { Agent, CompactionId, Context, EventOptions, Events, Message, Session, SessionEvent, SessionEventMap, SubagentResult, SubagentRun, SubagentStartRequest, SystemPrompt, TokenMeter, TokenUsage, ToolDefinition, ToolResultPruner, ToolRunContext, UserMessage, };
25
25
  /**
26
26
  * 一条消息事件(user/assistant/tool-result),带稳定 message_id;
27
27
  * 消息级索引(indexMessages)的节点,按 message_id 定位消息序列下标。
@@ -64,4 +64,14 @@ export type CompleteMessage = {
64
64
  /** 工具调用 id(仅 toolcall 类;关联 tool/result 用)。 */
65
65
  callId?: string;
66
66
  };
67
+ /**
68
+ * 插件扩展的 compaction/summary 载荷:宿主类型 + shadowedCharCount(压缩前字符数)。
69
+ * 宿主 append 不做 schema 剥离,扩展字段原样持久化;旧会话载荷可能缺失该字段,
70
+ * 客户端读取时按可选处理。宿主类型是 union(rawOutput 分支),无法直接声明合并,
71
+ * 故用交叉类型 + 读取处收窄。
72
+ */
73
+ export type CompactionSummaryPayload = SessionEventMap['compaction/summary'] & {
74
+ /** 被压缩内容的字符数(压缩前文本长度合计;UI 标题统计用),旧载荷可能缺失。 */
75
+ shadowedCharCount?: number;
76
+ };
67
77
  //# sourceMappingURL=types.d.ts.map
@@ -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,MAAM,0BAA0B,CAAC;AACtE,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,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"}
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;CAC5B,CAAC"}
package/dist/utils.d.ts CHANGED
@@ -10,6 +10,8 @@ export declare function isRecord(value: unknown): value is Record<string, unknow
10
10
  export declare function uuid(): string;
11
11
  /** 提取 content 数组中的纯文本块(type === 'text' 的 block.text 拼接)。 */
12
12
  export declare function blocksToText(blocks: unknown): string;
13
+ /** 消息内容的字符数:递归计入 text 块与 tool-result 内嵌文本(与宿主 token 估算口径一致)。 */
14
+ export declare function textCharCount(message: Message | null | undefined): number;
13
15
  /** 面向 recall 的完整消息呈现:text 原样;tool-call 展开(参数=代码);tool-result 取文本。 */
14
16
  export declare function renderMessageText(message: Message | null | undefined): string;
15
17
  /** 安全 JSON 序列化:序列化失败时退回 String 呈现(避免渲染异常)。 */
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,oDAAoD;AACpD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,wDAAwD;AACxD,wBAAgB,IAAI,IAAI,MAAM,CAK7B;AAED,4DAA4D;AAC5D,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CASpD;AAED,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAe7E;AAED,8CAA8C;AAC9C,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAM/C;AAED,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAEvD;AAED,8CAA8C;AAC9C,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D,iDAAiD;AACjD,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,CASvE"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,oDAAoD;AACpD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,wDAAwD;AACxD,wBAAgB,IAAI,IAAI,MAAM,CAK7B;AAED,4DAA4D;AAC5D,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CASpD;AAED,gEAAgE;AAChE,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAYzE;AAED,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAe7E;AAED,8CAA8C;AAC9C,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAM/C;AAED,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAEvD;AAED,8CAA8C;AAC9C,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D,iDAAiD;AACjD,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,CASvE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-om",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "type": "module",
5
5
  "main": "./dist/index.mjs",
6
6
  "module": "./dist/index.mjs",
@@ -18,7 +18,12 @@
18
18
  ".": {
19
19
  "types": "./dist/index.d.ts",
20
20
  "import": "./dist/index.mjs"
21
- }
21
+ },
22
+ "./client": {
23
+ "types": "./dist/client/index.d.ts",
24
+ "default": "./dist/client.js"
25
+ },
26
+ "./package.json": "./package.json"
22
27
  },
23
28
  "files": [
24
29
  "dist",
@@ -30,6 +35,14 @@
30
35
  "dsh": {
31
36
  "bundle": {
32
37
  "patch": "./cordis.patch.yml"
38
+ },
39
+ "client": {
40
+ "inject": [
41
+ "@deepseek-ai/dsh-client-locale",
42
+ "@deepseek-ai/dsh-client-runtime",
43
+ "@deepseek-ai/dsh-client-ui-conversation"
44
+ ],
45
+ "platform": "web"
33
46
  }
34
47
  },
35
48
  "license": "MIT",
@@ -53,20 +66,29 @@
53
66
  "devDependencies": {
54
67
  "@biomejs/biome": "^2.5.8",
55
68
  "@deepseek-ai/cordis": "^4.0.1",
56
- "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
57
- "@deepseek-ai/dsh-code-runtime": "^0.1.0-rc.6",
58
- "@deepseek-ai/dsh-compaction": "^0.1.0-rc.6",
59
- "@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.0-rc.6",
60
- "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6",
61
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
62
- "@deepseek-ai/dsh-scope": "^0.1.0-rc.6",
63
- "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
64
- "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6",
65
- "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
66
- "@deepseek-ai/dsh-token-meter": "^0.1.0-rc.6",
67
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
68
- "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6",
69
+ "@deepseek-ai/dsh-agent": "^0.1.1-rc.1",
70
+ "@deepseek-ai/dsh-code-runtime": "^0.1.1-rc.1",
71
+ "@deepseek-ai/dsh-compaction": "^0.1.1-rc.1",
72
+ "@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.1-rc.1",
73
+ "@deepseek-ai/dsh-invariants": "^0.1.1-rc.1",
74
+ "@deepseek-ai/dsh-llm": "^0.1.1-rc.1",
75
+ "@deepseek-ai/dsh-scope": "^0.1.1-rc.1",
76
+ "@deepseek-ai/dsh-session": "^0.1.1-rc.1",
77
+ "@deepseek-ai/dsh-subagent": "^0.1.1-rc.1",
78
+ "@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.1",
79
+ "@deepseek-ai/dsh-token-meter": "^0.1.1-rc.1",
80
+ "@deepseek-ai/dsh-tools": "^0.1.1-rc.1",
81
+ "@deepseek-ai/dsh-client-locale": "^0.1.1-rc.1",
82
+ "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.1",
83
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.1-rc.1",
84
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.1",
85
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.1-rc.1",
86
+ "@deepseek-ai/dsh-user-approval": "^0.1.1-rc.1",
69
87
  "@types/node": "^22.20.0",
88
+ "@types/react": "~18.3.1",
89
+ "@types/react-dom": "~18.3.0",
90
+ "react": "^18.2.0",
91
+ "react-dom": "^18.2.0",
70
92
  "tsdown": "^0.22.14",
71
93
  "typescript": "^6.0.3",
72
94
  "vitest": "^4.1.10",