dsh-plugin-om 0.0.21 → 0.0.23
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 +70 -159
- package/dist/client/OmCompactionCard.d.ts +6 -11
- package/dist/client/OmCompactionCard.d.ts.map +1 -1
- package/dist/client/definition.d.ts +21 -20
- package/dist/client/definition.d.ts.map +1 -1
- package/dist/client/format.d.ts +2 -2
- package/dist/client/format.d.ts.map +1 -1
- package/dist/client/index.d.ts +5 -11
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/locales.d.ts +5 -4
- package/dist/client/locales.d.ts.map +1 -1
- package/dist/client.js +87 -28
- package/dist/client.js.map +1 -1
- package/dist/compress.d.ts +30 -48
- package/dist/compress.d.ts.map +1 -1
- package/dist/config.d.ts +13 -22
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +15 -10
- package/dist/constants.d.ts.map +1 -1
- package/dist/embedding.d.ts +19 -36
- package/dist/embedding.d.ts.map +1 -1
- package/dist/index.d.ts +1 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +584 -772
- package/dist/json-schema.d.ts +4 -7
- package/dist/json-schema.d.ts.map +1 -1
- package/dist/log-index.d.ts +19 -12
- package/dist/log-index.d.ts.map +1 -1
- package/dist/logger.d.ts +3 -3
- package/dist/logger.d.ts.map +1 -1
- package/dist/model-download.d.ts +7 -11
- package/dist/model-download.d.ts.map +1 -1
- package/dist/rate-limit.d.ts +9 -14
- package/dist/rate-limit.d.ts.map +1 -1
- package/dist/recall-output.d.ts +37 -0
- package/dist/recall-output.d.ts.map +1 -0
- package/dist/recall.d.ts +7 -17
- package/dist/recall.d.ts.map +1 -1
- package/dist/semantic-recall.d.ts +10 -19
- package/dist/semantic-recall.d.ts.map +1 -1
- package/dist/summarize.d.ts +56 -49
- package/dist/summarize.d.ts.map +1 -1
- package/dist/types.d.ts +22 -35
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +9 -8
- package/dist/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -13,17 +13,16 @@ window.__ModuleLoader__.load({
|
|
|
13
13
|
const COMPACTION_CARD_KIND = "om-compaction";
|
|
14
14
|
/**
|
|
15
15
|
* replace-surface 判定:surfaceOp 为 { op: 'replace' } 对象(与宿主 runtime 的
|
|
16
|
-
* isReplacementSurfaceEvent
|
|
17
|
-
*
|
|
16
|
+
* isReplacementSurfaceEvent 同义;宿主该助手位于浏览器 bundle,node 端测试无法求值,
|
|
17
|
+
* 故本地实现同一形状检查)。
|
|
18
18
|
*/
|
|
19
19
|
function isReplacementSurface(event) {
|
|
20
20
|
const surfaceOp = event.surfaceOp;
|
|
21
21
|
return typeof surfaceOp === "object" && surfaceOp !== null && surfaceOp.op === "replace";
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
|
-
* 从压缩替换检查点(user/message + replace surface + source.plugin
|
|
25
|
-
*
|
|
26
|
-
* 避免同一压缩出现两张卡片。
|
|
24
|
+
* 从压缩替换检查点(user/message + replace surface + source.plugin 为本插件)读取
|
|
25
|
+
* 关联 compactionId;其余事件返回 undefined。
|
|
27
26
|
*/
|
|
28
27
|
function checkpointCompactionId(event) {
|
|
29
28
|
if (event.type !== "user/message" || !isReplacementSurface(event)) return void 0;
|
|
@@ -52,6 +51,7 @@ window.__ModuleLoader__.load({
|
|
|
52
51
|
return {
|
|
53
52
|
running: false,
|
|
54
53
|
phase: null,
|
|
54
|
+
error: null,
|
|
55
55
|
summary,
|
|
56
56
|
summaryEventSeq: summaryMatch?.event.seq ?? null,
|
|
57
57
|
shadowedItemCount,
|
|
@@ -62,13 +62,38 @@ window.__ModuleLoader__.load({
|
|
|
62
62
|
retryCount
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
-
/**
|
|
66
|
-
function
|
|
67
|
-
/** start 事件载荷(phase 为插件扩展;非法值回退 null)。 */
|
|
65
|
+
/** 从 compaction/start 载荷读取压缩 pass(observe/reflect;缺失或非法时回落 null)。 */
|
|
66
|
+
function startPhase(start) {
|
|
68
67
|
const data = start?.event.data;
|
|
68
|
+
return data?.phase === "observe" || data?.phase === "reflect" ? data.phase : null;
|
|
69
|
+
}
|
|
70
|
+
/** 压缩进行中提示行的载荷(统计未就绪,全部为 null)。 */
|
|
71
|
+
function runningData(start) {
|
|
69
72
|
return {
|
|
70
73
|
running: true,
|
|
71
|
-
phase:
|
|
74
|
+
phase: startPhase(start),
|
|
75
|
+
error: null,
|
|
76
|
+
summary: null,
|
|
77
|
+
summaryEventSeq: null,
|
|
78
|
+
shadowedItemCount: null,
|
|
79
|
+
shadowedTokenCount: null,
|
|
80
|
+
shadowedCharCount: null,
|
|
81
|
+
summaryCharCount: null,
|
|
82
|
+
summaryTokenCount: null,
|
|
83
|
+
retryCount: null
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 压缩失败节点的载荷:end 已到且带非中止 error、无检查点时使用。
|
|
88
|
+
* error 取 compaction/end 载荷中的实际报错文案(非字符串或为空时回落 null);
|
|
89
|
+
* 摘要与统计字段全部为 null。
|
|
90
|
+
*/
|
|
91
|
+
function failureData(start, end) {
|
|
92
|
+
const data = end.event.data;
|
|
93
|
+
return {
|
|
94
|
+
running: false,
|
|
95
|
+
phase: startPhase(start),
|
|
96
|
+
error: typeof data?.error === "string" && data.error !== "" ? data.error : null,
|
|
72
97
|
summary: null,
|
|
73
98
|
summaryEventSeq: null,
|
|
74
99
|
shadowedItemCount: null,
|
|
@@ -104,8 +129,11 @@ window.__ModuleLoader__.load({
|
|
|
104
129
|
};
|
|
105
130
|
}
|
|
106
131
|
/**
|
|
107
|
-
* 插件压缩生命周期定义:compaction/start 开启上下文,summary / 替换检查点 /
|
|
108
|
-
*
|
|
132
|
+
* 插件压缩生命周期定义:compaction/start 开启上下文,summary / 替换检查点 / end
|
|
133
|
+
* 作为 update 折叠证据。有检查点时产出摘要卡片;end 已到且无检查点时,error 为
|
|
134
|
+
* 非中止报错则产出可见失败行,error 为中止标识或缺失则以 hidden 撤回进行中提示行
|
|
135
|
+
* (已物化节点以 hidden visibility 保留同一 key);仅 start 时渲染「正在压缩上下文…」
|
|
136
|
+
* 提示行。
|
|
109
137
|
*/
|
|
110
138
|
const omCompactionDefinition = {
|
|
111
139
|
kind: COMPACTION_CARD_KIND,
|
|
@@ -150,6 +178,8 @@ window.__ModuleLoader__.load({
|
|
|
150
178
|
}
|
|
151
179
|
if (state.end !== void 0) {
|
|
152
180
|
const anchorSeq = context.start?.event.seq ?? state.end.event.seq;
|
|
181
|
+
const endData = state.end.event.data;
|
|
182
|
+
if (typeof endData?.error === "string" && endData.error !== "" && !endData.error.startsWith("压缩已中止(signal aborted)")) return chatNode(context, COMPACTION_CARD_KIND, anchorSeq, failureData(context.start, state.end));
|
|
153
183
|
return chatNode(context, COMPACTION_CARD_KIND, anchorSeq, runningData(context.start), "hidden");
|
|
154
184
|
}
|
|
155
185
|
if (context.start !== void 0) return chatNode(context, COMPACTION_CARD_KIND, context.start.event.seq, runningData(context.start));
|
|
@@ -159,10 +189,8 @@ window.__ModuleLoader__.load({
|
|
|
159
189
|
//#endregion
|
|
160
190
|
//#region src/client/locales.ts
|
|
161
191
|
/**
|
|
162
|
-
* `om-compaction` namespace
|
|
163
|
-
*
|
|
164
|
-
* 与宿主 conversation 命名空间分离(独立 NS),插件卡片走自己的 keyed 渲染器,
|
|
165
|
-
* 文案键不与对话插件的键冲突。
|
|
192
|
+
* `om-compaction` namespace 字典:插件压缩卡片的界面文案(zh/en)。
|
|
193
|
+
* 导出 NS / zh / en;zh 为键集事实源,en 键集与 zh 一致。
|
|
166
194
|
*/
|
|
167
195
|
/** Dictionary namespace owned by this plugin. */
|
|
168
196
|
const NS = "om-compaction";
|
|
@@ -176,6 +204,9 @@ window.__ModuleLoader__.load({
|
|
|
176
204
|
"compaction.running": "正在压缩上下文…",
|
|
177
205
|
"compaction.running.observe": "正在压缩上下文(观察)…",
|
|
178
206
|
"compaction.running.reflect": "正在压缩上下文(反思)…",
|
|
207
|
+
"compaction.failed": "上下文压缩失败",
|
|
208
|
+
"compaction.failed.observe": "上下文压缩失败(观察)",
|
|
209
|
+
"compaction.failed.reflect": "上下文压缩失败(反思)",
|
|
179
210
|
"compaction.retries": "重试 {count} 次"
|
|
180
211
|
};
|
|
181
212
|
/** English dictionary(键集与 zh 一致)。 */
|
|
@@ -188,16 +219,18 @@ window.__ModuleLoader__.load({
|
|
|
188
219
|
"compaction.running": "Compressing context…",
|
|
189
220
|
"compaction.running.observe": "Compressing context (observation)…",
|
|
190
221
|
"compaction.running.reflect": "Compressing context (reflection)…",
|
|
222
|
+
"compaction.failed": "Context compaction failed",
|
|
223
|
+
"compaction.failed.observe": "Context compaction failed (observation)",
|
|
224
|
+
"compaction.failed.reflect": "Context compaction failed (reflection)",
|
|
191
225
|
"compaction.retries": "Retried {count} times"
|
|
192
226
|
};
|
|
193
227
|
//#endregion
|
|
194
228
|
//#region src/client/format.ts
|
|
195
229
|
/**
|
|
196
|
-
*
|
|
197
|
-
*
|
|
230
|
+
* 压缩卡片统计行的紧凑数字格式化。导出 formatCompactCount。
|
|
231
|
+
* <1k 原样;≥1k 用 k;≥1w(万)用 w;≥1M 用 M;保留 1 位小数并去掉末尾 .0。
|
|
198
232
|
*/
|
|
199
233
|
function formatCompactCount(value) {
|
|
200
|
-
/** 保留 1 位小数并去掉末尾 .0。 */
|
|
201
234
|
const trim = (n) => {
|
|
202
235
|
const text = String(Math.round(n * 10) / 10);
|
|
203
236
|
return text.endsWith(".0") ? text.slice(0, -2) : text;
|
|
@@ -226,19 +259,18 @@ window.__ModuleLoader__.load({
|
|
|
226
259
|
.${css.summary}{min-width:0;color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;flex:auto;font-size:14px;line-height:24px;overflow:hidden}
|
|
227
260
|
.${css.body}{box-sizing:border-box;background:var(--dsw-alias-markdown-code-block);width:calc(100% - 22px);max-height:141px;color:var(--dsw-alias-label-tertiary);font:400 11px/16px var(--ds-font-family-code);border:none;border-radius:8px;margin:4px 0 0 22px;padding:10px 16px 12px 12px;overflow:auto}
|
|
228
261
|
`;
|
|
229
|
-
/**
|
|
262
|
+
/** 注册卡片样式(无 document 的环境如 node 测试直接跳过)。 */
|
|
230
263
|
if (typeof document !== "undefined" && document.querySelector("style[data-dsh-plugin-om-card]") === null) {
|
|
231
264
|
const tag = document.createElement("style");
|
|
232
265
|
tag.dataset.dshPluginOmCard = "true";
|
|
233
266
|
tag.textContent = cardCss;
|
|
234
267
|
document.head.appendChild(tag);
|
|
235
268
|
}
|
|
236
|
-
/** 折叠式压缩卡片(统计标题行 + 代码块样式 summary
|
|
269
|
+
/** 折叠式压缩卡片(统计标题行 + 代码块样式 summary 展开)。 */
|
|
237
270
|
const OmCompactionCard = (0, react.memo)(function OmCompactionCard({ node, t }) {
|
|
238
271
|
const [expanded, setExpanded] = (0, react.useState)(false);
|
|
239
272
|
const { data } = node;
|
|
240
273
|
if (data.running) {
|
|
241
|
-
/** 提示行文案(按 phase 区分观察/反思;缺失回退通用文案)。 */
|
|
242
274
|
const runningLabel = data.phase === "observe" ? t("compaction.running.observe") : data.phase === "reflect" ? t("compaction.running.reflect") : t("compaction.running");
|
|
243
275
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
244
276
|
style: styles.row,
|
|
@@ -252,9 +284,40 @@ window.__ModuleLoader__.load({
|
|
|
252
284
|
})
|
|
253
285
|
});
|
|
254
286
|
}
|
|
287
|
+
if (data.error !== null) {
|
|
288
|
+
const failedLabel = data.phase === "observe" ? t("compaction.failed.observe") : data.phase === "reflect" ? t("compaction.failed.reflect") : t("compaction.failed");
|
|
289
|
+
const errorSummary = data.error.length > 80 ? `${data.error.slice(0, 80)}…` : data.error;
|
|
290
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
291
|
+
style: styles.row,
|
|
292
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
|
|
293
|
+
className: css.root,
|
|
294
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutline16, { size: 14 }),
|
|
295
|
+
chevronClassName: css.chevron,
|
|
296
|
+
title: failedLabel,
|
|
297
|
+
collapsedContent: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
298
|
+
className: css.sep,
|
|
299
|
+
"aria-hidden": true
|
|
300
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
301
|
+
className: css.summary,
|
|
302
|
+
children: errorSummary
|
|
303
|
+
})] }),
|
|
304
|
+
keepContentWhenOpen: true,
|
|
305
|
+
expandable: true,
|
|
306
|
+
expandOnRowClick: true,
|
|
307
|
+
open: expanded,
|
|
308
|
+
onToggle: () => {
|
|
309
|
+
setExpanded((value) => !value);
|
|
310
|
+
},
|
|
311
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
312
|
+
className: css.body,
|
|
313
|
+
style: styles.body,
|
|
314
|
+
children: data.error
|
|
315
|
+
})
|
|
316
|
+
})
|
|
317
|
+
});
|
|
318
|
+
}
|
|
255
319
|
const expandable = data.summary !== null;
|
|
256
320
|
const open = expandable && expanded;
|
|
257
|
-
/** 统计行文案(数字按 k/w/M 单位化;重试次数仅在有重试时追加;retryCount 缺失视为未重试)。 */
|
|
258
321
|
const stats = data.shadowedItemCount !== null && data.shadowedCharCount !== null && data.shadowedTokenCount !== null && data.summaryCharCount !== null && data.summaryTokenCount !== null ? t("compaction.stats", {
|
|
259
322
|
items: formatCompactCount(data.shadowedItemCount),
|
|
260
323
|
beforeChars: formatCompactCount(data.shadowedCharCount),
|
|
@@ -298,7 +361,7 @@ window.__ModuleLoader__.load({
|
|
|
298
361
|
});
|
|
299
362
|
const styles = {
|
|
300
363
|
row: {},
|
|
301
|
-
/**
|
|
364
|
+
/** 摘要与失败报错为多行文本,保留换行。 */
|
|
302
365
|
body: { whiteSpace: "pre-wrap" }
|
|
303
366
|
};
|
|
304
367
|
//#endregion
|
|
@@ -309,11 +372,7 @@ window.__ModuleLoader__.load({
|
|
|
309
372
|
"conversationEvents",
|
|
310
373
|
"locale"
|
|
311
374
|
];
|
|
312
|
-
/**
|
|
313
|
-
* Client plugin body: 注册压缩卡片的业务定义与 keyed 渲染器。
|
|
314
|
-
* 注册挂在 effect 包装器上,插件卸载时随之移除。
|
|
315
|
-
* @param ctx - client root context.
|
|
316
|
-
*/
|
|
375
|
+
/** Client plugin body: 注册压缩卡片的业务定义与 keyed 渲染器(随插件卸载移除)。 */
|
|
317
376
|
function apply(ctx) {
|
|
318
377
|
ctx.effect(() => ctx.locale.register(NS, {
|
|
319
378
|
zh,
|
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/format.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 即重试次数;缺失或非法时为 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 >= 0\n ? data.attemptCount\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} msgs · {beforeChars} chars ({beforeTokens} tokens) → {afterChars} chars ({afterTokens} tokens)',\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 * 压缩卡片统计行的紧凑数字格式:<1k 原样;≥1k 用 k;≥1w(万)用 w;≥1M 用 M。\n * 保留 1 位小数并去掉末尾的 .0(如 8642 → 8.6k、34567 → 3.5w、1234567 → 1.2M)。\n */\nexport function formatCompactCount(value: number): string {\n /** 保留 1 位小数并去掉末尾 .0。 */\n const trim = (n: number): string => {\n const text = String(Math.round(n * 10) / 10);\n return text.endsWith('.0') ? text.slice(0, -2) : text;\n };\n if (value >= 1_000_000) return `${trim(value / 1_000_000)}M`;\n if (value >= 10_000) return `${trim(value / 10_000)}w`;\n if (value >= 1_000) return `${trim(value / 1_000)}k`;\n return String(value);\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';\nimport { formatCompactCount } from './format.ts';\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={runningLabel}\n open={false}\n expandable={false}\n onToggle={() => {\n /* 进行中提示行不可展开 */\n }}\n />\n </div>\n );\n }\n const expandable = data.summary !== null;\n const open = expandable && expanded;\n /** 统计行文案(数字按 k/w/M 单位化;重试次数仅在有重试时追加;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: formatCompactCount(data.shadowedItemCount),\n beforeChars: formatCompactCount(data.shadowedCharCount),\n beforeTokens: formatCompactCount(data.shadowedTokenCount),\n afterChars: formatCompactCount(data.summaryCharCount),\n afterTokens: formatCompactCount(data.summaryTokenCount),\n })\n : data.shadowedItemCount !== null && data.shadowedTokenCount !== null\n ? t('compaction.completed', {\n items: formatCompactCount(data.shadowedItemCount),\n tokens: formatCompactCount(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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"}
|
|
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/format.ts","../src/client/OmCompactionCard.tsx","../src/client/index.ts"],"sourcesContent":["/**\n * 共享常量:插件级魔法字符串,集中定义避免散落各模块。\n * 导出 PLUGIN_LABEL / HISTORY_TAG / HISTORY_TIP / COMPLETE_MESSAGE_DEFINITION /\n * COMPACT_CHECKPOINT_PLUGIN / COMPACTION_ABORTED_ERROR / isPluginOwnedSource。\n */\n\n/** 插件标识:压缩消息 source.plugin 取值与日志前缀。 */\nexport const PLUGIN_LABEL = 'dsh-plugin-om';\n\n/** 压缩日志标签名:<history>...</history> 包裹观察/反思日志块。 */\nexport const HISTORY_TAG = 'history';\n\n/** 压缩日志块开标签的 tip 属性(对 AI 的提醒:本块是历史压缩产物,不要复述)。 */\nexport const HISTORY_TIP = '当前块是历史消息的压缩产物,不要复述';\n\n/**\n * 「完整消息」定义(提示词 / 工具描述 / 块顶注释共用)。\n * 完整消息是摘要日志与 recall 共用的定位单位;首条 index 为 0,按会话顺序递增、全局稳定。\n */\nexport const COMPLETE_MESSAGE_DEFINITION =\n '`完整消息`被定义为`用户消息`,`系统消息`,`模型输出文本`和`具有result的toolcall`的集合。首条`完整消息`的index是0,后续的index递增。';\n\n/** 旧日志压缩消息的宿主 checkpoint 标记 plugin 名(历史兼容识别用)。 */\nexport const COMPACT_CHECKPOINT_PLUGIN = 'compact';\n\n/**\n * 压缩因 signal 中止而放弃时 compaction/end 的 error 标识(服务端写入、客户端过滤):\n * 中止不是失败,客户端据此隐藏失败行(宿主不变量要求无 summary 的 end 必须带 error)。\n */\nexport const COMPACTION_ABORTED_ERROR = '压缩已中止(signal aborted)';\n\n/** 判定 user/message 的 source 是否为本插件自产(压缩日志消息;含旧宿主 checkpoint 标记兼容)。这类消息不占完整消息 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 * 压缩卡片业务定义:认领插件自产的压缩生命周期事件(compaction/start|summary|end)\n * 与替换检查点(source.plugin = 'dsh-plugin-om'),聚合出可渲染的摘要卡片节点。\n * 导出 COMPACTION_CARD_KIND / OmCompactionChatData / checkpointCompactionId /\n * omCompactionDefinition。宿主的 'compact' 检查点由宿主自己渲染,本定义不认领\n * (双方共存无视觉冲突:宿主无检查点证据时不产出节点)。\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 { COMPACTION_ABORTED_ERROR, 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/** 压缩卡片载荷:摘要文本与遮蔽统计。 */\nexport interface OmCompactionChatData {\n /** 压缩进行中(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),summary 不可用或非法时为 null。 */\n readonly summaryTokenCount: number | null;\n /** 摘要调用重试次数,载荷缺失或非法时为 null。 */\n readonly retryCount: number | null;\n /** 压缩失败的错误文案(来自 compaction/end 载荷 error);非失败节点为 null。 */\n readonly error: string | 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,node 端测试无法求值,\n * 故本地实现同一形状检查)。\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 * 关联 compactionId;其余事件返回 undefined。\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 >= 0\n ? data.attemptCount\n : null;\n }\n return {\n running: false,\n phase: null,\n error: 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/** 从 compaction/start 载荷读取压缩 pass(observe/reflect;缺失或非法时回落 null)。 */\nfunction startPhase(start: ConversationMatch | undefined): 'observe' | 'reflect' | null {\n const data = start?.event.data as { phase?: unknown } | undefined;\n return data?.phase === 'observe' || data?.phase === 'reflect' ? data.phase : null;\n}\n\n/** 压缩进行中提示行的载荷(统计未就绪,全部为 null)。 */\nfunction runningData(start: ConversationMatch | undefined): OmCompactionChatData {\n return {\n running: true,\n phase: startPhase(start),\n error: null,\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/**\n * 压缩失败节点的载荷:end 已到且带非中止 error、无检查点时使用。\n * error 取 compaction/end 载荷中的实际报错文案(非字符串或为空时回落 null);\n * 摘要与统计字段全部为 null。\n */\nfunction failureData(\n start: ConversationMatch | undefined,\n end: ConversationMatch,\n): OmCompactionChatData {\n const data = end.event.data as { error?: unknown } | undefined;\n return {\n running: false,\n phase: startPhase(start),\n error: typeof data?.error === 'string' && data.error !== '' ? data.error : null,\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 / 替换检查点 / end\n * 作为 update 折叠证据。有检查点时产出摘要卡片;end 已到且无检查点时,error 为\n * 非中止报错则产出可见失败行,error 为中止标识或缺失则以 hidden 撤回进行中提示行\n * (已物化节点以 hidden visibility 保留同一 key);仅 start 时渲染「正在压缩上下文…」\n * 提示行。\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 已到达但无检查点:error 为非中止的实际报错时渲染可见失败行;\n // 无 error 或 error 以 COMPACTION_ABORTED_ERROR 开头(用户中止)时,\n // 以 hidden visibility 撤回进行中提示行\n if (state.end !== undefined) {\n const anchorSeq = context.start?.event.seq ?? state.end.event.seq;\n const endData = state.end.event.data as { error?: unknown } | undefined;\n const isFailure =\n typeof endData?.error === 'string' &&\n endData.error !== '' &&\n !endData.error.startsWith(COMPACTION_ABORTED_ERROR);\n if (isFailure) {\n return chatNode(\n context,\n COMPACTION_CARD_KIND,\n anchorSeq,\n failureData(context.start, state.end),\n );\n }\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 字典:插件压缩卡片的界面文案(zh/en)。\n * 导出 NS / zh / en;zh 为键集事实源,en 键集与 zh 一致。\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.failed': '上下文压缩失败',\n 'compaction.failed.observe': '上下文压缩失败(观察)',\n 'compaction.failed.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} msgs · {beforeChars} chars ({beforeTokens} tokens) → {afterChars} chars ({afterTokens} tokens)',\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.failed': 'Context compaction failed',\n 'compaction.failed.observe': 'Context compaction failed (observation)',\n 'compaction.failed.reflect': 'Context compaction failed (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 * 压缩卡片统计行的紧凑数字格式化。导出 formatCompactCount。\n * <1k 原样;≥1k 用 k;≥1w(万)用 w;≥1M 用 M;保留 1 位小数并去掉末尾 .0。\n */\nexport function formatCompactCount(value: number): string {\n const trim = (n: number): string => {\n const text = String(Math.round(n * 10) / 10);\n return text.endsWith('.0') ? text.slice(0, -2) : text;\n };\n if (value >= 1_000_000) return `${trim(value / 1_000_000)}M`;\n if (value >= 10_000) return `${trim(value / 10_000)}w`;\n if (value >= 1_000) return `${trim(value / 1_000)}k`;\n return String(value);\n}\n","/**\n * 压缩卡片渲染器:与宿主「上下文注入」卡片同款的折叠行。\n * 复用平台原语 DisclosureRow;行内统计与展开体样式按宿主 ContextInjectionRow 的规则\n * 注入 <style>(宿主该卡片样式是编译期哈希的 CSS Module,插件 bundle 无法引用其类名)。\n * 卡片报告模型从何处起不再看到那段历史;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';\nimport { formatCompactCount } from './format.ts';\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/** 注册卡片样式(无 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 // 压缩进行中:不可展开的「正在压缩上下文…」提示行(按 phase 区分文案)\n if (data.running) {\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={runningLabel}\n open={false}\n expandable={false}\n onToggle={() => {\n /* 进行中提示行不可展开 */\n }}\n />\n </div>\n );\n }\n // 压缩失败:可展开的错误行(按 phase 区分文案),折叠行为错误摘要、展开体为完整报错\n if (data.error !== null) {\n const failedLabel =\n data.phase === 'observe'\n ? t('compaction.failed.observe')\n : data.phase === 'reflect'\n ? t('compaction.failed.reflect')\n : t('compaction.failed');\n const errorSummary = data.error.length > 80 ? `${data.error.slice(0, 80)}…` : data.error;\n return (\n <div style={styles.row}>\n <DisclosureRow\n className={css.root}\n icon={<IconBrowseOutline16 size={14} />}\n chevronClassName={css.chevron}\n title={failedLabel}\n collapsedContent={\n <>\n <span className={css.sep} aria-hidden />\n <span className={css.summary}>{errorSummary}</span>\n </>\n }\n keepContentWhenOpen\n expandable\n expandOnRowClick\n open={expanded}\n onToggle={() => {\n setExpanded((value) => !value);\n }}\n >\n <div className={css.body} style={styles.body}>\n {data.error}\n </div>\n </DisclosureRow>\n </div>\n );\n }\n const expandable = data.summary !== null;\n const open = expandable && expanded;\n // 统计行:优先完整压缩前后统计,载荷字段不全时逐级回落;重试次数仅在有重试时追加\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: formatCompactCount(data.shadowedItemCount),\n beforeChars: formatCompactCount(data.shadowedCharCount),\n beforeTokens: formatCompactCount(data.shadowedTokenCount),\n afterChars: formatCompactCount(data.summaryCharCount),\n afterTokens: formatCompactCount(data.summaryTokenCount),\n })\n : data.shadowedItemCount !== null && data.shadowedTokenCount !== null\n ? t('compaction.completed', {\n items: formatCompactCount(data.shadowedItemCount),\n tokens: formatCompactCount(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 /** 摘要与失败报错为多行文本,保留换行。 */\n body: { whiteSpace: 'pre-wrap' },\n};\n","/**\n * 浏览器客户端入口(exports[\"./client\"] → dist/client.js):注册压缩卡片的\n * locale 字典、conversation 业务定义与 keyed 渲染器。宿主 conversation UI 只识别\n * 内置 'compact' 检查点,插件自产的压缩检查点(source.plugin = 'dsh-plugin-om')\n * 由本 bundle 认领并在消息列表渲染「已压缩」卡片。\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 声明合并。\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/** Client plugin body: 注册压缩卡片的业务定义与 keyed 渲染器(随插件卸载移除)。 */\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
CHANGED
|
@@ -1,45 +1,24 @@
|
|
|
1
|
-
import type { Agent,
|
|
1
|
+
import type { Agent, Context, PluginConfig, Session } from './types.ts';
|
|
2
2
|
import { type RoutedTarget } from './utils.ts';
|
|
3
|
+
/** 压缩 pass 结果:failed=false 表示无需中断(成功、跳过或非摘要耗尽的局部失败);failed=true 携带最后一次尝试的实际报错与是否因 signal 中止。 */
|
|
4
|
+
export type CompressPassResult = {
|
|
5
|
+
failed: false;
|
|
6
|
+
} | {
|
|
7
|
+
failed: true;
|
|
8
|
+
error: string;
|
|
9
|
+
aborted: boolean;
|
|
10
|
+
};
|
|
3
11
|
/** 历史文本 token 估算:4 字符 ≈ 1 token(与宿主 dsh-token-meter 启发式一致)。 */
|
|
4
12
|
export declare function estimateTextTokens(text: string): number;
|
|
5
13
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* items 为空返回空数组。
|
|
9
|
-
*/
|
|
10
|
-
export declare function runWithConcurrency<T, R>(items: readonly T[], limit: number, task: (item: T, index: number) => Promise<R>): Promise<R[]>;
|
|
11
|
-
/**
|
|
12
|
-
* 按 token 边界把完整消息序列分块(观察并行压缩用):完整消息不跨块——
|
|
13
|
-
* 一条完整消息(含其 thinking/text/toolcall&result 全部 seqs)必然整体落在同一块,
|
|
14
|
-
* 单条超界的消息独立成块。空输入返回空数组。
|
|
15
|
-
*/
|
|
16
|
-
export declare function chunkCompleteMessages<M>(session: Session, cms: readonly CompleteMessage[], tokenBoundary: number, estimateMessage: (message: M) => number): CompleteMessage[][];
|
|
17
|
-
/**
|
|
18
|
-
* 合并分块摘要为单个 <history> 块:剥离各块的 <history> 开/闭标签(保留块内全部内容),
|
|
19
|
-
* 以统一的开标签(带 tip 属性)与闭标签包裹拼接。块内内容原样保留(含格式说明注释)。
|
|
20
|
-
*/
|
|
21
|
-
export declare function mergeChunkReports(parts: readonly string[]): string;
|
|
22
|
-
/** token 估算器的结构类型(仅需 estimateMessage;避免依赖完整 TokenMeter 接口)。 */
|
|
23
|
-
export type TokenEstimator = {
|
|
24
|
-
estimateMessage(message: unknown): number;
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* 未压缩消息 token 估算:最后一个 <history> 块之后的表层节点合计
|
|
28
|
-
* (其前含自身视为已压缩,不计入观察阈值衡量对象;无压缩日志时计全部)。
|
|
29
|
-
* 系统消息(user/message 中非 kind:user 的部分,如宿主注入的上下文)不计入阈值。
|
|
30
|
-
*/
|
|
31
|
-
export declare function measureUncompressedTokens(session: Session, meter: TokenEstimator): number;
|
|
32
|
-
/**
|
|
33
|
-
* 判定表层节点 seq 之后的切点是否 tool-call/result 配对平衡(与宿主
|
|
34
|
-
* dsh-compaction 的 toolPairingBalancedAfter 同语义):按表层顺序折叠未闭合的
|
|
35
|
-
* 工具调用数,处理到 seq 后计数为 0 即平衡。pre-step 时日志 call-result 完备,
|
|
36
|
-
* 该检查作为区间边界的安全网(防止把助手 tool-call 与其结果切到两侧)。
|
|
14
|
+
* 判定表层节点 seq 之后的切点是否 tool-call/result 配对平衡:按表层顺序折叠未闭合的
|
|
15
|
+
* 工具调用数,处理到 seq 后计数为 0 即平衡(防止把 tool-call 与其结果切到两侧)。
|
|
37
16
|
*/
|
|
38
17
|
export declare function isPairBalancedAfter(session: Session, seq: number): boolean;
|
|
39
18
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
19
|
+
* 观察压缩区间:压缩边界后的首个表层节点 → 表层长度-1-tailCount(尾部保留 tailCount
|
|
20
|
+
* 条不压缩);区间终点回退到 tool-call/result 配对平衡点(不切段)。无可行区间返回
|
|
21
|
+
* undefined。返回区间起止表层 seq 与被遮蔽 seq 列表。
|
|
43
22
|
*/
|
|
44
23
|
export declare function computeCompressRange(session: Session, tailCount: number): {
|
|
45
24
|
start: number;
|
|
@@ -48,9 +27,9 @@ export declare function computeCompressRange(session: Session, tailCount: number
|
|
|
48
27
|
} | undefined;
|
|
49
28
|
/**
|
|
50
29
|
* 压缩边界(historySection):扫描表层全部节点,收集所有合法 <history> 压缩日志块
|
|
51
|
-
* (内文 + seq,按表层顺序),并以最后一个块的 seq
|
|
52
|
-
*
|
|
53
|
-
*
|
|
30
|
+
* (内文 + seq,按表层顺序),并以最后一个块的 seq 作为压缩边界——边界之后的消息视为
|
|
31
|
+
* 未压缩,其前(含边界自身)视为已压缩。无压缩日志时 blocks 为空、boundarySeq 为
|
|
32
|
+
* undefined。
|
|
54
33
|
*/
|
|
55
34
|
export declare function historySection(session: Session): {
|
|
56
35
|
blocks: Array<{
|
|
@@ -60,19 +39,22 @@ export declare function historySection(session: Session): {
|
|
|
60
39
|
boundarySeq: number | undefined;
|
|
61
40
|
};
|
|
62
41
|
/**
|
|
63
|
-
* 反思:全部 <history> 块
|
|
64
|
-
*
|
|
65
|
-
*
|
|
42
|
+
* 反思:全部 <history> 块 token 合计 ≥ reflectThresholdTokens 时,摘要调用把整个块
|
|
43
|
+
* 区段合并替换为一条更紧凑的摘要。失败不产生部分替换;摘要尝试全部耗尽返回
|
|
44
|
+
* 失败结果(error = 最后一次尝试的实际报错/具体问题)。
|
|
66
45
|
*/
|
|
67
|
-
export declare function reflectPass(ctx: Context, agent: Agent, config: Readonly<PluginConfig>, target: RoutedTarget, signal?: AbortSignal): Promise<
|
|
46
|
+
export declare function reflectPass(ctx: Context, agent: Agent, config: Readonly<PluginConfig>, target: RoutedTarget, signal?: AbortSignal): Promise<CompressPassResult>;
|
|
68
47
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
48
|
+
* 观察:净压力 tokens(上下文压力 − 已压缩 <history> 块 token 合计 − 系统提示词
|
|
49
|
+
* token 估算 − 工具定义 token 估算)≥ observeThresholdTokens 时,摘要调用把未压缩
|
|
50
|
+
* 消息压缩为观察日志,追加到旧摘要并替换被压缩消息区间。失败不产生部分替换;
|
|
51
|
+
* 摘要尝试全部耗尽返回失败结果(error = 最后一次尝试的实际报错/具体问题)。
|
|
71
52
|
*/
|
|
72
|
-
export declare function observePass(ctx: Context, agent: Agent, config: Readonly<PluginConfig>, tailCount: number, target: RoutedTarget, signal?: AbortSignal): Promise<
|
|
53
|
+
export declare function observePass(ctx: Context, agent: Agent, config: Readonly<PluginConfig>, tailCount: number, target: RoutedTarget, signal?: AbortSignal): Promise<CompressPassResult>;
|
|
73
54
|
/**
|
|
74
|
-
* 压力检查 +
|
|
75
|
-
*
|
|
55
|
+
* 压力检查 + 两级压缩入口:先反思后观察,pre-step 阻塞串行执行;仅主会话生效。
|
|
56
|
+
* 反思摘要耗尽失败时直接返回失败结果(观察无需继续,本轮将被拒绝);观察失败同样
|
|
57
|
+
* 传播失败结果,由 pre-step 拒绝本 step 中断当前 turn。
|
|
76
58
|
*/
|
|
77
|
-
export declare function maybeCompress(ctx: Context, agent: Agent, config: Readonly<PluginConfig>, signal?: AbortSignal): Promise<
|
|
59
|
+
export declare function maybeCompress(ctx: Context, agent: Agent, config: Readonly<PluginConfig>, signal?: AbortSignal): Promise<CompressPassResult>;
|
|
78
60
|
//# sourceMappingURL=compress.d.ts.map
|
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":"AA6BA,OAAO,KAAK,EACV,KAAK,EAIL,OAAO,EACP,YAAY,EACZ,OAAO,EAIR,MAAM,YAAY,CAAC;AACpB,OAAO,EAAgB,KAAK,YAAY,EAAqC,MAAM,YAAY,CAAC;AAEhG,gGAAgG;AAChG,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,KAAK,CAAA;CAAE,GACjB;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtD,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvD;AA4CD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAY1E;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,CAqBpE;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,CAUA;AA0GD;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC9B,MAAM,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,kBAAkB,CAAC,CAiH7B;AAyCD;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC9B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,kBAAkB,CAAC,CAgJ7B;AAED;;;;GAIG;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,kBAAkB,CAAC,CAwB7B"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,39 +1,30 @@
|
|
|
1
1
|
/** 插件配置项(全部可选覆盖,未给出或留空的键用默认值)。 */
|
|
2
2
|
export type PluginConfig = {
|
|
3
|
-
/** 观察阈值(tokens
|
|
3
|
+
/** 观察阈值(tokens):净压力 ≥ 该值时触发观察压缩。 */
|
|
4
4
|
observeThresholdTokens: number;
|
|
5
|
-
/** 反思阈值(tokens):全部 <history> 块
|
|
5
|
+
/** 反思阈值(tokens):全部 <history> 块 token 合计 ≥ 该值时触发精简合并。 */
|
|
6
6
|
reflectThresholdTokens: number;
|
|
7
|
-
/**
|
|
8
|
-
compressMaxTokens: number;
|
|
9
|
-
/**
|
|
10
|
-
observeChunkTokens: number;
|
|
11
|
-
/** 观察分块单块摘要的生成上限(LLM maxTokens;每块独立调用)。 */
|
|
12
|
-
observeChunkMaxTokens: number;
|
|
13
|
-
/** 观察分块压缩的最大并行数:同时进行的单块摘要调用上限,其余块排队(默认 2)。 */
|
|
14
|
-
observeChunkParallelism: number;
|
|
15
|
-
/** 遇 429 限流后,下一次摘要请求发出前至少等待的毫秒数(全局限流冷却期,默认 60000)。 */
|
|
7
|
+
/** 单次摘要生成上限(LLM maxTokens);undefined 表示不设置,由模型适配器默认值决定。 */
|
|
8
|
+
compressMaxTokens: number | undefined;
|
|
9
|
+
/** 遇 429 限流后下一次摘要请求前的等待毫秒数(全局冷却期)。 */
|
|
16
10
|
rateLimitWaitMs: number;
|
|
17
|
-
/**
|
|
11
|
+
/** 尾部保留的不压缩消息条数。 */
|
|
18
12
|
tailMessageCount: number;
|
|
19
|
-
/**
|
|
13
|
+
/** 摘要失败后的最大重试次数(不含首次)。 */
|
|
20
14
|
compressRetryCount: number;
|
|
21
|
-
/**
|
|
15
|
+
/** 是否启用自动压缩(观察/反思)。 */
|
|
22
16
|
omEnabled: boolean;
|
|
23
|
-
/**
|
|
17
|
+
/** 步骤级日志开关(缺省按 NODE_ENV !== 'production' 判定)。 */
|
|
24
18
|
debug: boolean;
|
|
25
|
-
/** 是否注册 recall
|
|
19
|
+
/** 是否注册 recall 工具。 */
|
|
26
20
|
recallEnabled: boolean;
|
|
27
|
-
/** 是否注册 recall-semantic
|
|
21
|
+
/** 是否注册 recall-semantic 工具(false 时不触发模型下载)。 */
|
|
28
22
|
semanticRecallEnabled: boolean;
|
|
29
|
-
/**
|
|
23
|
+
/** 语义召回嵌入模型目录。 */
|
|
30
24
|
modelDir: string;
|
|
31
25
|
};
|
|
32
26
|
/** 默认配置(冻结对象,resolveConfig 合并的基底;debug 缺省值在解析时按 NODE_ENV 判定)。 */
|
|
33
27
|
export declare const DEFAULT_CONFIG: Readonly<PluginConfig>;
|
|
34
|
-
/**
|
|
35
|
-
* 解析合并配置:未知键忽略、不合法值回退默认值,返回冻结的完整配置。
|
|
36
|
-
* 允许所有配置留空——缺省 / null / 空串的键回退默认值,未给出的键亦取默认值。
|
|
37
|
-
*/
|
|
28
|
+
/** 解析合并配置:未知键忽略、不合法值回退默认值,返回冻结的完整配置。 */
|
|
38
29
|
export declare function resolveConfig(raw?: unknown): Readonly<PluginConfig>;
|
|
39
30
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAQA,kCAAkC;AAClC,MAAM,MAAM,YAAY,GAAG;IACzB,oCAAoC;IACpC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wDAAwD;IACxD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,2DAA2D;IAC3D,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,sCAAsC;IACtC,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,0BAA0B;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uBAAuB;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,iDAAiD;IACjD,KAAK,EAAE,OAAO,CAAC;IACf,sBAAsB;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,+CAA+C;IAC/C,qBAAqB,EAAE,OAAO,CAAC;IAC/B,kBAAkB;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,YAAY,CAYhD,CAAC;AAqCH,wCAAwC;AACxC,wBAAgB,aAAa,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,CAoBnE"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,24 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 共享常量:插件级魔法字符串,集中定义避免散落各模块。
|
|
3
|
+
* 导出 PLUGIN_LABEL / HISTORY_TAG / HISTORY_TIP / COMPLETE_MESSAGE_DEFINITION /
|
|
4
|
+
* COMPACT_CHECKPOINT_PLUGIN / COMPACTION_ABORTED_ERROR / isPluginOwnedSource。
|
|
3
5
|
*/
|
|
4
|
-
/** 插件标识:压缩消息 source.plugin
|
|
6
|
+
/** 插件标识:压缩消息 source.plugin 取值与日志前缀。 */
|
|
5
7
|
export declare const PLUGIN_LABEL = "dsh-plugin-om";
|
|
6
|
-
/** 压缩日志标签名:<history>...</history>
|
|
8
|
+
/** 压缩日志标签名:<history>...</history> 包裹观察/反思日志块。 */
|
|
7
9
|
export declare const HISTORY_TAG = "history";
|
|
8
|
-
/**
|
|
10
|
+
/** 压缩日志块开标签的 tip 属性(对 AI 的提醒:本块是历史压缩产物,不要复述)。 */
|
|
9
11
|
export declare const HISTORY_TIP = "\u5F53\u524D\u5757\u662F\u5386\u53F2\u6D88\u606F\u7684\u538B\u7F29\u4EA7\u7269\uFF0C\u4E0D\u8981\u590D\u8FF0";
|
|
10
12
|
/**
|
|
11
|
-
* 「完整消息」定义(提示词 /
|
|
13
|
+
* 「完整消息」定义(提示词 / 工具描述 / 块顶注释共用)。
|
|
12
14
|
* 完整消息是摘要日志与 recall 共用的定位单位;首条 index 为 0,按会话顺序递增、全局稳定。
|
|
13
|
-
* 用户消息指 user_message 中 source.kind 为 user 的部分;其余部分(宿主注入的上下文等)
|
|
14
|
-
* 为系统消息,同样是一条完整消息。
|
|
15
15
|
*/
|
|
16
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
|
+
/** 旧日志压缩消息的宿主 checkpoint 标记 plugin 名(历史兼容识别用)。 */
|
|
18
|
+
export declare const COMPACT_CHECKPOINT_PLUGIN = "compact";
|
|
19
|
+
/**
|
|
20
|
+
* 压缩因 signal 中止而放弃时 compaction/end 的 error 标识(服务端写入、客户端过滤):
|
|
21
|
+
* 中止不是失败,客户端据此隐藏失败行(宿主不变量要求无 summary 的 end 必须带 error)。
|
|
22
|
+
*/
|
|
23
|
+
export declare const COMPACTION_ABORTED_ERROR = "\u538B\u7F29\u5DF2\u4E2D\u6B62\uFF08signal aborted\uFF09";
|
|
24
|
+
/** 判定 user/message 的 source 是否为本插件自产(压缩日志消息;含旧宿主 checkpoint 标记兼容)。这类消息不占完整消息 index。 */
|
|
18
25
|
export declare function isPluginOwnedSource(source: {
|
|
19
26
|
kind?: string;
|
|
20
27
|
plugin?: string;
|
|
21
28
|
} | undefined): boolean;
|
|
22
|
-
/** 旧日志压缩消息的宿主 checkpoint 标记 plugin 名(dsh-compaction-basic 的 COMPACT_CHECKPOINT_MARKER.plugin;历史兼容识别用)。 */
|
|
23
|
-
export declare const COMPACT_CHECKPOINT_PLUGIN = "compact";
|
|
24
29
|
//# sourceMappingURL=constants.d.ts.map
|