dsh-plugin-om 0.0.31 → 0.0.32
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 +6 -6
- package/dist/client/OmCompactionCard.d.ts.map +1 -1
- package/dist/client/definition.d.ts +0 -2
- package/dist/client/definition.d.ts.map +1 -1
- package/dist/client/locales.d.ts +0 -1
- package/dist/client/locales.d.ts.map +1 -1
- package/dist/client.js +5 -13
- package/dist/client.js.map +1 -1
- package/dist/compaction-log.d.ts +15 -8
- package/dist/compaction-log.d.ts.map +1 -1
- package/dist/compress-loop.d.ts +31 -4
- package/dist/compress-loop.d.ts.map +1 -1
- package/dist/compress-tools.d.ts +4 -4
- package/dist/compress-tools.d.ts.map +1 -1
- package/dist/compress-view.d.ts +15 -2
- package/dist/compress-view.d.ts.map +1 -1
- package/dist/compress.d.ts.map +1 -1
- package/dist/constants.d.ts +8 -3
- package/dist/constants.d.ts.map +1 -1
- package/dist/index.mjs +269 -53
- package/dist/log-index.d.ts +8 -2
- package/dist/log-index.d.ts.map +1 -1
- package/dist/types.d.ts +11 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -16,7 +16,8 @@ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).expor
|
|
|
16
16
|
/**
|
|
17
17
|
* 共享常量:插件级魔法字符串,集中定义避免散落各模块。
|
|
18
18
|
* 导出 PLUGIN_LABEL / HISTORY_TAG / HISTORY_TIP / COMPLETE_MESSAGE_DEFINITION /
|
|
19
|
-
*
|
|
19
|
+
* HISTORY_FORMAT_NOTE / SKILL_TOOL_NAME / COMPACT_CHECKPOINT_PLUGIN /
|
|
20
|
+
* COMPACTION_ABORTED_ERROR / isPluginOwnedSource。
|
|
20
21
|
*/
|
|
21
22
|
/** 插件标识:压缩消息 source.plugin 取值与日志前缀。 */
|
|
22
23
|
const PLUGIN_LABEL = "dsh-plugin-om";
|
|
@@ -29,8 +30,12 @@ const HISTORY_TIP = "当前块是历史消息的压缩产物,不要复述";
|
|
|
29
30
|
* 完整消息是摘要日志与 recall 共用的定位单位;首条 index 为 0,按会话顺序递增、全局稳定。
|
|
30
31
|
*/
|
|
31
32
|
const COMPLETE_MESSAGE_DEFINITION = "`完整消息`指一条`用户消息`、`系统消息`、`模型输出文本`或`具有result的toolcall`;首条 index 为 0,按会话顺序递增。";
|
|
32
|
-
/**
|
|
33
|
-
|
|
33
|
+
/**
|
|
34
|
+
* 最终 <history> 块内文块首的格式说明注释(XML 注释,完整消息定义 + 条目标签语义 + CDATA 约定)。
|
|
35
|
+
*/
|
|
36
|
+
const HISTORY_FORMAT_NOTE = `<!-- 完整消息:${COMPLETE_MESSAGE_DEFINITION} <TAG index="N">表示单条完整消息,<TAG start="A" end="B"> 表示连续模块,start/end 是首尾完整消息的 index;<sys type="KIND" index="N"> 表示被压缩的系统消息,块中为空;条目正文一律以 CDATA 包裹,CDATA 内为逐字原样内容;<skill_content name="S" index="N"> 表示未压缩的 skill 加载条目,内含 <skill_resources> 与 <skill_instructions> 两段,各自以 CDATA 包裹,内文为其工具返回内容 -->`;
|
|
37
|
+
/** skill 工具名:toolcall 条目的工具名为该值时视为 skill 加载,<history> 块中以 <skill_content> 元素呈现。 */
|
|
38
|
+
const SKILL_TOOL_NAME = "skill";
|
|
34
39
|
/**
|
|
35
40
|
* 压缩因 signal 中止而放弃时 compaction/end 的 error 标识(服务端写入、客户端过滤):
|
|
36
41
|
* 中止不是失败,客户端据此隐藏失败行(宿主不变量要求无 summary 的 end 必须带 error)。
|
|
@@ -134,13 +139,79 @@ function phaseLabel(phase) {
|
|
|
134
139
|
function compressionRecordLabel(phase, rounds, success) {
|
|
135
140
|
return `OM 压缩${success ? "会话记录" : "失败日志"}(${phaseLabel(phase)} · ${rounds} 轮)`;
|
|
136
141
|
}
|
|
142
|
+
/** usage 各桶文案(缺失桶显示 -)。 */
|
|
143
|
+
function usageLine(usage) {
|
|
144
|
+
const field = (value) => value === void 0 ? "-" : String(value);
|
|
145
|
+
return `input ${field(usage.inputTokens)} / output ${field(usage.outputTokens)} / cacheRead ${field(usage.cacheReadTokens)} / cacheWrite ${field(usage.cacheWriteTokens)} / reasoning ${field(usage.reasoningTokens)} tokens`;
|
|
146
|
+
}
|
|
147
|
+
/** 汇总逐轮 usage(各桶任一轮存在即求和保留;全部轮次无 usage 时返回 undefined)。 */
|
|
148
|
+
function sumRoundUsage(rounds) {
|
|
149
|
+
let total;
|
|
150
|
+
for (const round of rounds) {
|
|
151
|
+
if (round.usage === void 0) continue;
|
|
152
|
+
if (total === void 0) {
|
|
153
|
+
total = { ...round.usage };
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const sum = (a, b) => a === void 0 && b === void 0 ? void 0 : (a ?? 0) + (b ?? 0);
|
|
157
|
+
const merged = {
|
|
158
|
+
inputTokens: (total.inputTokens ?? 0) + (round.usage.inputTokens ?? 0),
|
|
159
|
+
outputTokens: (total.outputTokens ?? 0) + (round.usage.outputTokens ?? 0)
|
|
160
|
+
};
|
|
161
|
+
const cacheRead = sum(total.cacheReadTokens, round.usage.cacheReadTokens);
|
|
162
|
+
const cacheWrite = sum(total.cacheWriteTokens, round.usage.cacheWriteTokens);
|
|
163
|
+
const reasoning = sum(total.reasoningTokens, round.usage.reasoningTokens);
|
|
164
|
+
if (cacheRead !== void 0) merged.cacheReadTokens = cacheRead;
|
|
165
|
+
if (cacheWrite !== void 0) merged.cacheWriteTokens = cacheWrite;
|
|
166
|
+
if (reasoning !== void 0) merged.reasoningTokens = reasoning;
|
|
167
|
+
total = merged;
|
|
168
|
+
}
|
|
169
|
+
return total;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* 格式化压缩循环统计为统计消息文本:起止时间(ISO)、总耗时、逐轮请求耗时与
|
|
173
|
+
* usage、usage 合计。随会话记录在子会话末尾落盘。
|
|
174
|
+
*/
|
|
175
|
+
function formatCompressionStats(phase, success, stats) {
|
|
176
|
+
const lines = [
|
|
177
|
+
"【压缩统计】",
|
|
178
|
+
`阶段:${phaseLabel(phase)}|结果:${success ? "成功" : "失败"}`,
|
|
179
|
+
`开始:${new Date(stats.startedAt).toISOString()}`,
|
|
180
|
+
`结束:${new Date(stats.completedAt).toISOString()}`,
|
|
181
|
+
`总耗时:${stats.durationMs} ms`,
|
|
182
|
+
`请求轮数:${stats.rounds.length}`
|
|
183
|
+
];
|
|
184
|
+
if (stats.rounds.length > 0) {
|
|
185
|
+
lines.push("逐轮:");
|
|
186
|
+
for (const round of stats.rounds) lines.push(`- 第 ${round.round} 轮:耗时 ${round.durationMs} ms${round.usage === void 0 ? "" : `,${usageLine(round.usage)}`}`);
|
|
187
|
+
}
|
|
188
|
+
const usage = sumRoundUsage(stats.rounds);
|
|
189
|
+
if (usage !== void 0) lines.push(`usage 合计:${usageLine(usage)}`);
|
|
190
|
+
return lines.join("\n");
|
|
191
|
+
}
|
|
192
|
+
/** 构造插件自产 user 消息(子会话统计消息;id 为品牌类型 MessageId)。 */
|
|
193
|
+
function makeStatsMessage(text) {
|
|
194
|
+
return {
|
|
195
|
+
id: uuid(),
|
|
196
|
+
role: "user",
|
|
197
|
+
content: [{
|
|
198
|
+
type: "text",
|
|
199
|
+
text
|
|
200
|
+
}],
|
|
201
|
+
source: {
|
|
202
|
+
kind: "plugin",
|
|
203
|
+
plugin: PLUGIN_LABEL
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
}
|
|
137
207
|
/**
|
|
138
208
|
* 把一次压缩工具循环的完整会话消息组落盘为子会话:ctx.sessions.create 创建子会话
|
|
139
209
|
* (header origin 'subagent'、parentSession 指向主会话、delegationDepth = 父 + 1、
|
|
140
210
|
* cwd 继承主会话),追加 one-shot descriptor(provider om-compaction-log,label 含
|
|
141
211
|
* 压缩阶段与轮数),逐消息原样追加(user 指令/提醒与 tool-result 为 user/message,
|
|
142
|
-
* assistant 含 tool-call 块为 assistant/message
|
|
143
|
-
*
|
|
212
|
+
* assistant 含 tool-call 块为 assistant/message),末尾追加插件来源统计消息(起止
|
|
213
|
+
* 时间、总耗时、逐轮耗时与 usage),flush 持久化,返回子会话 id。成功与失败均调用;
|
|
214
|
+
* 落盘自身绝不抛错,任何失败仅 logger.warn 并返回 undefined。
|
|
144
215
|
*/
|
|
145
216
|
async function recordCompressionSession(ctx, parentSession, options) {
|
|
146
217
|
const logger = makeLogger(ctx, options.debug);
|
|
@@ -156,7 +227,7 @@ async function recordCompressionSession(ctx, parentSession, options) {
|
|
|
156
227
|
version: SUBAGENT_DESCRIPTOR_VERSION,
|
|
157
228
|
mode: "one-shot",
|
|
158
229
|
provider: COMPACTION_LOG_PROVIDER,
|
|
159
|
-
label: compressionRecordLabel(options.phase, options.rounds, options.success)
|
|
230
|
+
label: compressionRecordLabel(options.phase, options.stats.rounds.length, options.success)
|
|
160
231
|
});
|
|
161
232
|
let step = 0;
|
|
162
233
|
for (const message of options.messages) {
|
|
@@ -168,6 +239,7 @@ async function recordCompressionSession(ctx, parentSession, options) {
|
|
|
168
239
|
}, { surfaceOp: "append" });
|
|
169
240
|
else child.append("user/message", message, { surfaceOp: "append" });
|
|
170
241
|
}
|
|
242
|
+
child.append("user/message", makeStatsMessage(formatCompressionStats(options.phase, options.success, options.stats)), { surfaceOp: "append" });
|
|
171
243
|
try {
|
|
172
244
|
await ctx.sessions.flush(child);
|
|
173
245
|
} catch (error) {
|
|
@@ -7316,8 +7388,9 @@ var import_lib = (/* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
7316
7388
|
* 会话日志索引:完整消息索引与渲染。
|
|
7317
7389
|
* 导出 indexCompleteMessages(完整消息四类折叠索引,recall 与摘要共用同一套编号)、
|
|
7318
7390
|
* indexMessages / surfaceIndexOf / messageIdOfEvent(消息级定位辅助)、
|
|
7319
|
-
* collectImageRefs / renderCompleteMessageParts /
|
|
7320
|
-
*
|
|
7391
|
+
* collectImageRefs / toolResultMessageOf / renderToolResultText / renderCompleteMessageParts /
|
|
7392
|
+
* renderCompleteMessage(完整消息渲染与图片附件收集)。事件日志仅追加(被遮蔽的事件仍可读,
|
|
7393
|
+
* recall 依赖此性质)。
|
|
7321
7394
|
*
|
|
7322
7395
|
* 完整消息分四类:user(用户消息)、sys(系统消息,压缩日志中以 <sys> 空块表示)、
|
|
7323
7396
|
* assistant(模型输出文本)、toolcall(单个工具调用及其结果,result 按 callId 匹配并入)。
|
|
@@ -7418,7 +7491,28 @@ function collectImageRefs(content, out) {
|
|
|
7418
7491
|
}
|
|
7419
7492
|
}
|
|
7420
7493
|
/**
|
|
7421
|
-
*
|
|
7494
|
+
* 取 toolcall 完整消息的 tool/result 消息(超大结果经 pruner 裁剪):
|
|
7495
|
+
* 结果文本渲染与 <skill> 条目正文共用;非 toolcall 或无配对 result 时返回 undefined。
|
|
7496
|
+
*/
|
|
7497
|
+
function toolResultMessageOf(session, cm, pruner) {
|
|
7498
|
+
if (cm.type !== "toolcall") return void 0;
|
|
7499
|
+
const resultSeq = cm.seqs[1];
|
|
7500
|
+
const resultEvent = resultSeq === void 0 ? void 0 : session.events[resultSeq];
|
|
7501
|
+
if (resultEvent?.type !== "tool/result") return void 0;
|
|
7502
|
+
const message = session.deriveEventMessage(resultEvent);
|
|
7503
|
+
if (!message) return void 0;
|
|
7504
|
+
const pruned = pruner?.pruneContent?.(message.content);
|
|
7505
|
+
return pruned ? {
|
|
7506
|
+
...message,
|
|
7507
|
+
content: pruned
|
|
7508
|
+
} : message;
|
|
7509
|
+
}
|
|
7510
|
+
/** 渲染 toolcall 完整消息的工具返回文本(仅 result 内容;无配对 result 时为空串)。 */
|
|
7511
|
+
function renderToolResultText(session, cm, pruner) {
|
|
7512
|
+
const message = toolResultMessageOf(session, cm, pruner);
|
|
7513
|
+
return message ? renderMessageText(message) : "";
|
|
7514
|
+
}
|
|
7515
|
+
/** 渲染一条完整消息为「文本 + 图片」(recall / recall-semantic 输出用):
|
|
7422
7516
|
* user/sys 取消息原文,assistant 取文本块,toolcall 为调用块 + 结果文本
|
|
7423
7517
|
* (pruner 裁剪超大结果);同时收集该条完整消息携带的图片附件(含 tool-result 嵌套,
|
|
7424
7518
|
* pruner 裁剪掉的图片不收集)。
|
|
@@ -7465,19 +7559,10 @@ function renderCompleteMessageParts(session, cm, pruner) {
|
|
|
7465
7559
|
if (call) parts.push(`[tool-call ${String(call.name ?? "")} id=${String(call.id ?? "")}]\n${safeJson(call.arguments)}`);
|
|
7466
7560
|
}
|
|
7467
7561
|
}
|
|
7468
|
-
const
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
if (message && pruner?.pruneContent) {
|
|
7473
|
-
const pruned = pruner.pruneContent(message.content);
|
|
7474
|
-
if (pruned) message = {
|
|
7475
|
-
...message,
|
|
7476
|
-
content: pruned
|
|
7477
|
-
};
|
|
7478
|
-
}
|
|
7479
|
-
if (message && Array.isArray(message.content)) collectImageRefs(message.content, images);
|
|
7480
|
-
const text = message ? renderMessageText(message) : "";
|
|
7562
|
+
const resultMessage = toolResultMessageOf(session, cm, pruner);
|
|
7563
|
+
if (resultMessage && Array.isArray(resultMessage.content)) {
|
|
7564
|
+
collectImageRefs(resultMessage.content, images);
|
|
7565
|
+
const text = renderMessageText(resultMessage);
|
|
7481
7566
|
if (text.trim() !== "") parts.push(`[result]\n${text}`);
|
|
7482
7567
|
}
|
|
7483
7568
|
return {
|
|
@@ -7533,6 +7618,26 @@ function toolCallNameOf(session, cm) {
|
|
|
7533
7618
|
for (const block of message.content) if (block.type === "tool-call" && String(block.id ?? "") === (cm.callId ?? "")) return String(block.name ?? "");
|
|
7534
7619
|
}
|
|
7535
7620
|
/**
|
|
7621
|
+
* 提取 skill 条目的 skill 名(tool-call 参数 JSON 的 name 字段)。非 skill 工具的
|
|
7622
|
+
* toolcall 返回 undefined;toolName 为 skill 但参数缺失或非法时返回空串。
|
|
7623
|
+
*/
|
|
7624
|
+
function skillNameOf(session, cm) {
|
|
7625
|
+
if (toolCallNameOf(session, cm) !== "skill") return void 0;
|
|
7626
|
+
const seq = cm.seqs[0];
|
|
7627
|
+
const event = seq === void 0 ? void 0 : session.events[seq];
|
|
7628
|
+
if (event?.type !== "assistant/message") return "";
|
|
7629
|
+
const message = event.data.message;
|
|
7630
|
+
if (!message || !Array.isArray(message.content)) return "";
|
|
7631
|
+
for (const block of message.content) if (block.type === "tool-call" && String(block.id ?? "") === (cm.callId ?? "")) {
|
|
7632
|
+
try {
|
|
7633
|
+
const args = JSON.parse(String(block.arguments ?? ""));
|
|
7634
|
+
if (isRecord(args) && typeof args.name === "string") return args.name;
|
|
7635
|
+
} catch {}
|
|
7636
|
+
return "";
|
|
7637
|
+
}
|
|
7638
|
+
return "";
|
|
7639
|
+
}
|
|
7640
|
+
/**
|
|
7536
7641
|
* 观察视图:被压缩区间(表层 seq 集合)内的完整消息投影为条目——
|
|
7537
7642
|
* user → 原文(图片等非文本块为注释)、sys → 空条目、assistant/toolcall → 原文渲染,
|
|
7538
7643
|
* reasoning 作为参考条目置于其所属 assistant 条目之前(每条 assistant 消息输出一次;
|
|
@@ -7590,15 +7695,18 @@ function buildObserveView(session, seqs, options = {}) {
|
|
|
7590
7695
|
});
|
|
7591
7696
|
}
|
|
7592
7697
|
}
|
|
7593
|
-
const text = renderCompleteMessage(session, cm);
|
|
7594
|
-
if (text.trim() === "") continue;
|
|
7595
7698
|
const toolName = cm.type === "toolcall" ? toolCallNameOf(session, cm) : void 0;
|
|
7699
|
+
const isSkill = toolName === SKILL_TOOL_NAME;
|
|
7700
|
+
const text = isSkill ? renderToolResultText(session, cm) : renderCompleteMessage(session, cm);
|
|
7701
|
+
if (text.trim() === "") continue;
|
|
7702
|
+
const skillName = isSkill ? skillNameOf(session, cm) : void 0;
|
|
7596
7703
|
entries.push({
|
|
7597
7704
|
kind: "assistant",
|
|
7598
7705
|
lo: cm.index,
|
|
7599
7706
|
hi: cm.index,
|
|
7600
7707
|
text,
|
|
7601
|
-
...toolName === void 0 ? {} : { toolName }
|
|
7708
|
+
...toolName === void 0 ? {} : { toolName },
|
|
7709
|
+
...skillName === void 0 ? {} : { skillName }
|
|
7602
7710
|
});
|
|
7603
7711
|
}
|
|
7604
7712
|
return {
|
|
@@ -7638,10 +7746,50 @@ function intAttr(el, name) {
|
|
|
7638
7746
|
if (!/^\d+$/.test(raw)) return void 0;
|
|
7639
7747
|
return Number(raw);
|
|
7640
7748
|
}
|
|
7749
|
+
/** 读取元素第一个指定名子元素的正文(缺失返回 undefined)。 */
|
|
7750
|
+
function childText(el, tag) {
|
|
7751
|
+
const child = el.getElementsByTagName(tag)[0];
|
|
7752
|
+
return child === void 0 ? void 0 : child.textContent ?? "";
|
|
7753
|
+
}
|
|
7754
|
+
/**
|
|
7755
|
+
* 提取 skill 工具返回内容(原生 <skill_content> 包裹)中 <skill_resources> 与
|
|
7756
|
+
* <skill_instructions> 两段正文。非该包裹形态、两段缺失或两段之间存在其他内容时
|
|
7757
|
+
* 返回 undefined(调用方回退为整体 CDATA 原文)。
|
|
7758
|
+
*/
|
|
7759
|
+
function skillContentSections(text) {
|
|
7760
|
+
const wrapper = /^[\s]*<skill_content\b[^>]*>([\s\S]*)<\/skill_content>[\s]*$/.exec(text);
|
|
7761
|
+
if (!wrapper) return void 0;
|
|
7762
|
+
const body = wrapper[1] ?? "";
|
|
7763
|
+
const match = /^([\s\S]*?)<skill_resources>([\s\S]*?)<\/skill_resources>([\s\S]*?)<skill_instructions>([\s\S]*?)<\/skill_instructions>([\s\S]*)$/.exec(body);
|
|
7764
|
+
if (!match) return void 0;
|
|
7765
|
+
const before = match[1] ?? "";
|
|
7766
|
+
const resources = match[2] ?? "";
|
|
7767
|
+
const between = match[3] ?? "";
|
|
7768
|
+
const instructions = match[4] ?? "";
|
|
7769
|
+
const after = match[5] ?? "";
|
|
7770
|
+
if (before.trim() !== "" || between.trim() !== "" || after.trim() !== "") return void 0;
|
|
7771
|
+
return {
|
|
7772
|
+
resources,
|
|
7773
|
+
instructions
|
|
7774
|
+
};
|
|
7775
|
+
}
|
|
7776
|
+
/**
|
|
7777
|
+
* 向元素追加 CDATA 正文:正文统一以 CDATA 包裹(逐字原样,不做实体转义)。
|
|
7778
|
+
* 正文含 ]]> 时拆为相邻多个 CDATA 段,拼接后逐字还原原文,对读取方透明。
|
|
7779
|
+
*/
|
|
7780
|
+
function appendCdataText(doc, el, text) {
|
|
7781
|
+
const parts = text.split("]]>");
|
|
7782
|
+
for (let i = 0; i < parts.length; i += 1) if (i === 0) el.appendChild(doc.createCDATASection(parts[0] ?? ""));
|
|
7783
|
+
else {
|
|
7784
|
+
el.appendChild(doc.createCDATASection("]]"));
|
|
7785
|
+
el.appendChild(doc.createCDATASection(`>${parts[i] ?? ""}`));
|
|
7786
|
+
}
|
|
7787
|
+
}
|
|
7641
7788
|
/**
|
|
7642
7789
|
* 解析一个已有 <history> 块的内条目(反思视图):user_message / sys / assistant
|
|
7643
|
-
* (index 单条或 start/end 区间)/
|
|
7644
|
-
*
|
|
7790
|
+
* (index 单条或 start/end 区间)/ skill_content(name 属性 + index 定位)/ reasoning。
|
|
7791
|
+
* 整块无法解析或根非 <history> 时降级为单条不可定位的历史遗留条目(text 为块内文原文,
|
|
7792
|
+
* 构建最终块时原样保留)。
|
|
7645
7793
|
*/
|
|
7646
7794
|
function parseBlockEntries(blockText, blockSeq) {
|
|
7647
7795
|
const opaque = () => [{
|
|
@@ -7707,6 +7855,23 @@ function parseBlockEntries(blockText, blockSeq) {
|
|
|
7707
7855
|
text,
|
|
7708
7856
|
blockSeq
|
|
7709
7857
|
});
|
|
7858
|
+
} else if (el.nodeName === "skill_content") {
|
|
7859
|
+
const index = intAttr(el, "index");
|
|
7860
|
+
if (index !== void 0) {
|
|
7861
|
+
const name = el.getAttribute("name");
|
|
7862
|
+
const resources = childText(el, "skill_resources");
|
|
7863
|
+
const instructions = childText(el, "skill_instructions");
|
|
7864
|
+
const text = resources !== void 0 && instructions !== void 0 ? `<skill_content${name === null ? "" : ` name="${name}"`}><skill_resources>${resources}</skill_resources><skill_instructions>${instructions}</skill_instructions></skill_content>` : el.textContent ?? "";
|
|
7865
|
+
entries.push({
|
|
7866
|
+
kind: "assistant",
|
|
7867
|
+
lo: index,
|
|
7868
|
+
hi: index,
|
|
7869
|
+
text,
|
|
7870
|
+
toolName: SKILL_TOOL_NAME,
|
|
7871
|
+
...name === null ? {} : { skillName: name },
|
|
7872
|
+
blockSeq
|
|
7873
|
+
});
|
|
7874
|
+
}
|
|
7710
7875
|
} else if (el.nodeName === "reasoning") entries.push({
|
|
7711
7876
|
kind: "reasoning",
|
|
7712
7877
|
text,
|
|
@@ -7731,14 +7896,14 @@ function buildReflectView(blocks, options = {}) {
|
|
|
7731
7896
|
};
|
|
7732
7897
|
}
|
|
7733
7898
|
/**
|
|
7734
|
-
* 把一个视图条目构建为 XML
|
|
7899
|
+
* 把一个视图条目构建为 XML 元素(正文统一以 CDATA 包裹,逐字原样;user 条目的注释
|
|
7735
7900
|
* 输出为 XML 注释节点)。getHistory 输出与最终 <history> 块共用。
|
|
7736
7901
|
*/
|
|
7737
7902
|
function entryToElement(doc, entry) {
|
|
7738
7903
|
if (entry.kind === "user") {
|
|
7739
7904
|
const el = doc.createElement("user_message");
|
|
7740
7905
|
if (entry.lo !== void 0) el.setAttribute("index", String(entry.lo));
|
|
7741
|
-
|
|
7906
|
+
appendCdataText(doc, el, entry.text);
|
|
7742
7907
|
for (const note of entry.notes ?? []) el.appendChild(doc.createComment(note));
|
|
7743
7908
|
return el;
|
|
7744
7909
|
}
|
|
@@ -7746,12 +7911,27 @@ function entryToElement(doc, entry) {
|
|
|
7746
7911
|
const el = doc.createElement("sys");
|
|
7747
7912
|
el.setAttribute("type", entry.sysKind ?? "");
|
|
7748
7913
|
if (entry.lo !== void 0) el.setAttribute("index", String(entry.lo));
|
|
7749
|
-
|
|
7914
|
+
appendCdataText(doc, el, "");
|
|
7750
7915
|
return el;
|
|
7751
7916
|
}
|
|
7752
7917
|
if (entry.kind === "reasoning") {
|
|
7753
7918
|
const el = doc.createElement("reasoning");
|
|
7754
|
-
|
|
7919
|
+
appendCdataText(doc, el, entry.text);
|
|
7920
|
+
return el;
|
|
7921
|
+
}
|
|
7922
|
+
if (entry.kind === "assistant" && entry.toolName === "skill") {
|
|
7923
|
+
const el = doc.createElement("skill_content");
|
|
7924
|
+
el.setAttribute("name", entry.skillName ?? "");
|
|
7925
|
+
if (entry.lo !== void 0 && entry.lo === entry.hi) el.setAttribute("index", String(entry.lo));
|
|
7926
|
+
const sections = skillContentSections(entry.text);
|
|
7927
|
+
if (sections) {
|
|
7928
|
+
const resources = doc.createElement("skill_resources");
|
|
7929
|
+
appendCdataText(doc, resources, sections.resources);
|
|
7930
|
+
el.appendChild(resources);
|
|
7931
|
+
const instructions = doc.createElement("skill_instructions");
|
|
7932
|
+
appendCdataText(doc, instructions, sections.instructions);
|
|
7933
|
+
el.appendChild(instructions);
|
|
7934
|
+
} else appendCdataText(doc, el, entry.text);
|
|
7755
7935
|
return el;
|
|
7756
7936
|
}
|
|
7757
7937
|
const el = doc.createElement("assistant");
|
|
@@ -7760,7 +7940,7 @@ function entryToElement(doc, entry) {
|
|
|
7760
7940
|
el.setAttribute("start", String(entry.lo));
|
|
7761
7941
|
el.setAttribute("end", String(entry.hi));
|
|
7762
7942
|
}
|
|
7763
|
-
|
|
7943
|
+
appendCdataText(doc, el, entry.text);
|
|
7764
7944
|
return el;
|
|
7765
7945
|
}
|
|
7766
7946
|
/**
|
|
@@ -7772,6 +7952,8 @@ function renderEntriesXml(entries) {
|
|
|
7772
7952
|
const serializer = new import_lib.XMLSerializer();
|
|
7773
7953
|
return entries.map((entry) => serializer.serializeToString(entryToElement(doc, entry))).join("\n");
|
|
7774
7954
|
}
|
|
7955
|
+
//#endregion
|
|
7956
|
+
//#region src/compress-tools.ts
|
|
7775
7957
|
/** 压缩会话的工具状态:视图 + 替换记录 + skill 二次确认标记 + 完成标记。 */
|
|
7776
7958
|
var CompressionState = class CompressionState {
|
|
7777
7959
|
view;
|
|
@@ -7893,6 +8075,10 @@ var CompressionState = class CompressionState {
|
|
|
7893
8075
|
text: "content 必须是非空摘要文本",
|
|
7894
8076
|
isError: true
|
|
7895
8077
|
};
|
|
8078
|
+
if (content.includes("<![CDATA[")) return {
|
|
8079
|
+
text: "content 必须是纯文本摘要,不要包含 CDATA 包裹(<![CDATA[…]]>);CDATA 由插件在构建块时自动添加,请去除后重新提交",
|
|
8080
|
+
isError: true
|
|
8081
|
+
};
|
|
7896
8082
|
const hasIndex = args.index !== void 0 && args.index !== null;
|
|
7897
8083
|
const hasStart = args.start !== void 0 && args.start !== null;
|
|
7898
8084
|
const hasEnd = args.end !== void 0 && args.end !== null;
|
|
@@ -7999,7 +8185,7 @@ var CompressionState = class CompressionState {
|
|
|
7999
8185
|
}
|
|
8000
8186
|
/**
|
|
8001
8187
|
* 构建最终 <history> 块:按 index 顺序合并视图条目与替换记录——user / sys 条目
|
|
8002
|
-
* 原样、被替换区间生成 <assistant index|start end> 摘要条目(content
|
|
8188
|
+
* 原样、被替换区间生成 <assistant index|start end> 摘要条目(content 以 CDATA 包裹嵌入)、
|
|
8003
8189
|
* 未替换 assistant 条目原样保留、reasoning 不进产物;块首为格式说明注释,开标签
|
|
8004
8190
|
* 携带 tip 属性。产物为合法 XML,无需校验。
|
|
8005
8191
|
*/
|
|
@@ -8017,7 +8203,7 @@ var CompressionState = class CompressionState {
|
|
|
8017
8203
|
el.setAttribute("start", String(rep.lo));
|
|
8018
8204
|
el.setAttribute("end", String(rep.hi));
|
|
8019
8205
|
}
|
|
8020
|
-
|
|
8206
|
+
appendCdataText(doc, el, rep.content);
|
|
8021
8207
|
root.appendChild(el);
|
|
8022
8208
|
};
|
|
8023
8209
|
const flushReplacementsBefore = (lo) => {
|
|
@@ -8080,7 +8266,7 @@ const COMPRESSION_TOOL_SCHEMAS = [
|
|
|
8080
8266
|
},
|
|
8081
8267
|
content: {
|
|
8082
8268
|
type: "string",
|
|
8083
|
-
description: "
|
|
8269
|
+
description: "替换后的摘要文本(纯文本,不要包含 CDATA 包裹,插件自动包裹)"
|
|
8084
8270
|
}
|
|
8085
8271
|
},
|
|
8086
8272
|
required: ["content"]
|
|
@@ -8155,7 +8341,7 @@ async function gateRateLimit(waitMs, signal) {
|
|
|
8155
8341
|
* 工具驱动的压缩循环:以新会话方式直连 ctx.llm.stream(),模型通过 getHistory /
|
|
8156
8342
|
* compressHistory / completeCompression 三个工具完成压缩,替代直出 <history> 块。
|
|
8157
8343
|
* 导出 runCompressionLoop / buildCompressionPrompt / buildCompressionTaskText /
|
|
8158
|
-
* CompressionLoopOptions / CompressionOutcome / COMPRESSION_NUDGE_TEXT。
|
|
8344
|
+
* CompressionLoopOptions / CompressionOutcome / CompressionStats / COMPRESSION_NUDGE_TEXT。
|
|
8159
8345
|
*
|
|
8160
8346
|
* - 首条 user 消息仅含压缩指令与 start/end 区间(buildCompressionTaskText),不含
|
|
8161
8347
|
* 历史消息内容;共享压缩提示词作为 system
|
|
@@ -8166,7 +8352,8 @@ async function gateRateLimit(waitMs, signal) {
|
|
|
8166
8352
|
* - 模型输出纯文本(无工具调用)时追加提醒消息继续,连续 2 轮仍无工具调用判失败
|
|
8167
8353
|
* - 429 限流走全局限流等待门(gateRateLimit / noteRateLimit);其余请求级错误依赖
|
|
8168
8354
|
* dsh 运行时重试,插件不做整体重试,错误直接判失败
|
|
8169
|
-
* - signal 中止标记 aborted;token usage
|
|
8355
|
+
* - signal 中止标记 aborted;token usage 汇总全部轮次;统计循环起止时间戳、总耗时
|
|
8356
|
+
* 与逐轮请求统计(CompressionStats),随结果返回并随会话记录落盘
|
|
8170
8357
|
* - 成功与失败均把循环消息组原样落盘为子会话(recordCompressionSession),成功记
|
|
8171
8358
|
* 录 sessionId 于日志,失败记录作为诊断子会话 id 向上传播
|
|
8172
8359
|
*/
|
|
@@ -8182,7 +8369,7 @@ function buildCompressionPrompt(skipReasoning) {
|
|
|
8182
8369
|
"",
|
|
8183
8370
|
"【工具】",
|
|
8184
8371
|
"- getHistory(option?: {start?, end?}):查看压缩区间内的历史条目。start/end 缺省为要求区间的第一个/最后一个完整消息 index,必须在要求区间内。返回压缩视图:已压缩内容以摘要条目呈现,区间切入已压缩块时返回整块,不带 <history> 包裹。",
|
|
8185
|
-
"- compressHistory(option?: {index?, start?, end?, content}):把 index 单条或 start..end 连续区间的 assistant 类条目替换为 content
|
|
8372
|
+
"- compressHistory(option?: {index?, start?, end?, content}):把 index 单条或 start..end 连续区间的 assistant 类条目替换为 content 摘要(纯文本,不要包含 CDATA 包裹,插件自动包裹)。index 与 start/end 二选一,start==end 等同 index。区间不得覆盖用户消息或系统消息;与已有替换区间部分重叠会被拒绝,完全包含则覆盖。",
|
|
8186
8373
|
"- completeCompression():全部压缩完成后调用,立即结束。",
|
|
8187
8374
|
"",
|
|
8188
8375
|
"【压缩要求】",
|
|
@@ -8192,7 +8379,8 @@ function buildCompressionPrompt(skipReasoning) {
|
|
|
8192
8379
|
"- 单条重要的完整消息以 index 单独压缩",
|
|
8193
8380
|
"- 压缩后的 assistant 消息内,应当描述**行为逻辑**,强调关键的**结论、产出和任务**;涉及到的具体文件保留完整路径",
|
|
8194
8381
|
"- 摘要粒度越往后越细:靠近末尾(最近)的消息保留更多细节,开头(较早)的消息简写。",
|
|
8195
|
-
"-
|
|
8382
|
+
"- <history> 条目正文一律以 CDATA 包裹,CDATA 内为逐字原样内容。",
|
|
8383
|
+
"- 加载的 skill 以 <skill_content name=\"…\" index=\"N\"> 条目呈现,内含 <skill_resources> 与 <skill_instructions> 两段,内文为其工具返回内容,属于关键信息。仅在你明确判断该 skill 与后续任务无关时,压缩它;如果该 skill 与后续任务相关,或者你无法判断,不要压缩,**保持原文**。",
|
|
8196
8384
|
"- 未压缩的条目将原样保留;宁可保留也不要强行压缩不确定的内容。",
|
|
8197
8385
|
"- 全部完成后调用 completeCompression 结束;不要输出与工具调用无关的文本。"
|
|
8198
8386
|
].join("\n");
|
|
@@ -8277,20 +8465,34 @@ async function runCompressionLoop(ctx, session, options) {
|
|
|
8277
8465
|
let rounds = 0;
|
|
8278
8466
|
let nudges = 0;
|
|
8279
8467
|
let usage;
|
|
8280
|
-
const
|
|
8468
|
+
const startedAt = Date.now();
|
|
8469
|
+
const roundStats = [];
|
|
8470
|
+
/** 汇总当前循环统计(completedAt 取调用时刻;rounds 数组为引用共享)。 */
|
|
8471
|
+
const buildStats = () => {
|
|
8472
|
+
const completedAt = Date.now();
|
|
8473
|
+
return {
|
|
8474
|
+
startedAt,
|
|
8475
|
+
completedAt,
|
|
8476
|
+
durationMs: completedAt - startedAt,
|
|
8477
|
+
rounds: roundStats
|
|
8478
|
+
};
|
|
8479
|
+
};
|
|
8480
|
+
const recordSessionId = async (success, stats) => recordCompressionSession(ctx, session, {
|
|
8281
8481
|
phase: options.phase,
|
|
8282
8482
|
target: options.target,
|
|
8283
8483
|
messages,
|
|
8284
|
-
|
|
8484
|
+
stats,
|
|
8285
8485
|
success,
|
|
8286
8486
|
debug: options.debug
|
|
8287
8487
|
});
|
|
8288
8488
|
const failWith = async (error, aborted) => {
|
|
8289
|
-
const
|
|
8489
|
+
const stats = buildStats();
|
|
8490
|
+
const id = await recordSessionId(false, stats);
|
|
8290
8491
|
return {
|
|
8291
8492
|
ok: false,
|
|
8292
8493
|
error,
|
|
8293
8494
|
aborted,
|
|
8495
|
+
stats,
|
|
8294
8496
|
...id === void 0 ? {} : { recordSessionId: id }
|
|
8295
8497
|
};
|
|
8296
8498
|
};
|
|
@@ -8304,6 +8506,7 @@ async function runCompressionLoop(ctx, session, options) {
|
|
|
8304
8506
|
logger.warn("压缩循环中止(限流等待被 signal 中止),放弃本次压缩");
|
|
8305
8507
|
return await failWith(COMPACTION_ABORTED_ERROR, true);
|
|
8306
8508
|
}
|
|
8509
|
+
const roundStartedAt = Date.now();
|
|
8307
8510
|
const requestOptions = {
|
|
8308
8511
|
provider: options.target.provider,
|
|
8309
8512
|
model: options.target.model,
|
|
@@ -8346,6 +8549,12 @@ async function runCompressionLoop(ctx, session, options) {
|
|
|
8346
8549
|
}
|
|
8347
8550
|
rounds += 1;
|
|
8348
8551
|
if (assembler.usage !== void 0) usage = addUsage(usage, assembler.usage);
|
|
8552
|
+
roundStats.push({
|
|
8553
|
+
round: rounds,
|
|
8554
|
+
startedAt: roundStartedAt,
|
|
8555
|
+
durationMs: Date.now() - roundStartedAt,
|
|
8556
|
+
...assembler.usage === void 0 ? {} : { usage: assembler.usage }
|
|
8557
|
+
});
|
|
8349
8558
|
const assistantMessage = assembler.message({
|
|
8350
8559
|
kind: "model",
|
|
8351
8560
|
provider: options.target.provider,
|
|
@@ -8378,11 +8587,13 @@ async function runCompressionLoop(ctx, session, options) {
|
|
|
8378
8587
|
const text = state.buildFinalBlock();
|
|
8379
8588
|
if (state.replacementCount === 0) logger.warn("压缩完成但未执行任何压缩替换(空提交)");
|
|
8380
8589
|
logger.info(`压缩循环完成(${rounds} 轮,${state.replacementCount} 次压缩替换,输出 ${text.length} 字符)`);
|
|
8381
|
-
const
|
|
8590
|
+
const stats = buildStats();
|
|
8591
|
+
const id = await recordSessionId(true, stats);
|
|
8382
8592
|
return {
|
|
8383
8593
|
ok: true,
|
|
8384
8594
|
text,
|
|
8385
8595
|
rounds,
|
|
8596
|
+
stats,
|
|
8386
8597
|
...usage === void 0 ? {} : { usage },
|
|
8387
8598
|
...id === void 0 ? {} : { recordSessionId: id }
|
|
8388
8599
|
};
|
|
@@ -8542,7 +8753,7 @@ async function runPassLoop(ctx, session, lifecycle, options, logger, phase) {
|
|
|
8542
8753
|
if (!outcome.ok) {
|
|
8543
8754
|
logger.warn(`${phase === "reflect" ? "反思" : "观察"}:压缩循环失败(${outcome.error}),诊断子会话 ${outcome.recordSessionId ?? "未落盘"},追加 compaction/end(error)`);
|
|
8544
8755
|
try {
|
|
8545
|
-
appendCompactionEnd(session, lifecycle, outcome.error, outcome.recordSessionId);
|
|
8756
|
+
appendCompactionEnd(session, lifecycle, outcome.error, outcome.recordSessionId, outcome.stats.durationMs);
|
|
8546
8757
|
} catch {}
|
|
8547
8758
|
return outcome;
|
|
8548
8759
|
}
|
|
@@ -8703,7 +8914,8 @@ function appendCompactionStart(session, lifecycle, phase) {
|
|
|
8703
8914
|
}
|
|
8704
8915
|
/**
|
|
8705
8916
|
* 追加 compaction/summary(log-only,承担影子价格认领:紧随其后的替换消息消费 claim)。
|
|
8706
|
-
* summary 为完整合并后的 <history> 内文;usage
|
|
8917
|
+
* summary 为完整合并后的 <history> 内文;usage 由摘要调用提取(无则省略);stats 提供
|
|
8918
|
+
* 压缩循环计时(startedAt/completedAt/durationMs)。
|
|
8707
8919
|
*/
|
|
8708
8920
|
function appendCompactionSummary(session, data) {
|
|
8709
8921
|
const payload = {
|
|
@@ -8719,21 +8931,25 @@ function appendCompactionSummary(session, data) {
|
|
|
8719
8931
|
provider: data.provider,
|
|
8720
8932
|
model: data.model,
|
|
8721
8933
|
...data.maxTokens === void 0 ? {} : { maxTokens: data.maxTokens },
|
|
8722
|
-
|
|
8934
|
+
startedAt: data.stats.startedAt,
|
|
8935
|
+
completedAt: data.stats.completedAt,
|
|
8936
|
+
durationMs: data.stats.durationMs,
|
|
8723
8937
|
...data.usage === void 0 ? {} : { usage: data.usage }
|
|
8724
8938
|
};
|
|
8725
8939
|
return session.append("compaction/summary", payload).seq;
|
|
8726
8940
|
}
|
|
8727
8941
|
/**
|
|
8728
8942
|
* 追加 compaction/end(log-only,结束生命周期;error 记录失败原因,
|
|
8729
|
-
* diagnosticSessionId 记录最后一次摘要尝试(无论成功或失败)的诊断子会话 id
|
|
8943
|
+
* diagnosticSessionId 记录最后一次摘要尝试(无论成功或失败)的诊断子会话 id,
|
|
8944
|
+
* durationMs 记录失败路径的压缩循环耗时)。
|
|
8730
8945
|
*/
|
|
8731
|
-
function appendCompactionEnd(session, lifecycle, error, diagnosticSessionId) {
|
|
8946
|
+
function appendCompactionEnd(session, lifecycle, error, diagnosticSessionId, durationMs) {
|
|
8732
8947
|
const payload = {
|
|
8733
8948
|
compactionId: lifecycle.compactionId,
|
|
8734
8949
|
turn: lifecycle.turn,
|
|
8735
8950
|
...error === void 0 ? {} : { error },
|
|
8736
|
-
...diagnosticSessionId === void 0 ? {} : { diagnosticSessionId }
|
|
8951
|
+
...diagnosticSessionId === void 0 ? {} : { diagnosticSessionId },
|
|
8952
|
+
...durationMs === void 0 ? {} : { durationMs }
|
|
8737
8953
|
};
|
|
8738
8954
|
return session.append("compaction/end", payload).seq;
|
|
8739
8955
|
}
|
|
@@ -8837,7 +9053,7 @@ async function reflectPass(ctx, agent, config, target, signal) {
|
|
|
8837
9053
|
provider: target.provider,
|
|
8838
9054
|
model: target.model,
|
|
8839
9055
|
maxTokens: config.compressMaxTokens,
|
|
8840
|
-
|
|
9056
|
+
stats: summaryResult.stats,
|
|
8841
9057
|
...summaryResult.usage === void 0 ? {} : { usage: summaryResult.usage }
|
|
8842
9058
|
});
|
|
8843
9059
|
logger.step("反思提交:替换整个 <history> 块区段为合并摘要");
|
|
@@ -8854,7 +9070,7 @@ async function reflectPass(ctx, agent, config, target, signal) {
|
|
|
8854
9070
|
const message = error instanceof Error ? error.message : String(error);
|
|
8855
9071
|
logger.warn(`反思提交失败: ${message}`);
|
|
8856
9072
|
try {
|
|
8857
|
-
appendCompactionEnd(session, lifecycle, message);
|
|
9073
|
+
appendCompactionEnd(session, lifecycle, message, void 0, summaryResult.stats.durationMs);
|
|
8858
9074
|
} catch {}
|
|
8859
9075
|
return { failed: false };
|
|
8860
9076
|
}
|
|
@@ -9075,7 +9291,7 @@ async function observePass(ctx, agent, config, waitCount, target, signal) {
|
|
|
9075
9291
|
provider: target.provider,
|
|
9076
9292
|
model: target.model,
|
|
9077
9293
|
maxTokens: config.compressMaxTokens,
|
|
9078
|
-
|
|
9294
|
+
stats: summaryResult.stats,
|
|
9079
9295
|
...usage === void 0 ? {} : { usage }
|
|
9080
9296
|
});
|
|
9081
9297
|
logger.step("观察提交:替换被压缩新消息区间为 <history>(旧块保留)");
|
|
@@ -9093,7 +9309,7 @@ async function observePass(ctx, agent, config, waitCount, target, signal) {
|
|
|
9093
9309
|
const message = error instanceof Error ? error.message : String(error);
|
|
9094
9310
|
logger.warn(`观察压缩提交失败: ${message}`);
|
|
9095
9311
|
try {
|
|
9096
|
-
appendCompactionEnd(session, lifecycle, message);
|
|
9312
|
+
appendCompactionEnd(session, lifecycle, message, void 0, summaryResult.stats.durationMs);
|
|
9097
9313
|
} catch {}
|
|
9098
9314
|
return { failed: false };
|
|
9099
9315
|
}
|
package/dist/log-index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ImageRefValue } from './recall-output.ts';
|
|
2
|
-
import type { CompleteMessage, MessageIndex, Session, SessionEvent } from './types.ts';
|
|
2
|
+
import type { CompleteMessage, Message, MessageIndex, Session, SessionEvent } from './types.ts';
|
|
3
3
|
/** 工具结果裁剪器结构(tool-result-pruner;超大结果渲染前裁剪)。 */
|
|
4
4
|
export type PrunerLike = {
|
|
5
5
|
pruneContent?: (blocks: readonly unknown[]) => unknown[] | null;
|
|
@@ -22,7 +22,13 @@ export declare function indexCompleteMessages(session: Session): CompleteMessage
|
|
|
22
22
|
*/
|
|
23
23
|
export declare function collectImageRefs(content: unknown, out: ImageRefValue[]): void;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* 取 toolcall 完整消息的 tool/result 消息(超大结果经 pruner 裁剪):
|
|
26
|
+
* 结果文本渲染与 <skill> 条目正文共用;非 toolcall 或无配对 result 时返回 undefined。
|
|
27
|
+
*/
|
|
28
|
+
export declare function toolResultMessageOf(session: Session, cm: CompleteMessage, pruner?: PrunerLike): Message | undefined;
|
|
29
|
+
/** 渲染 toolcall 完整消息的工具返回文本(仅 result 内容;无配对 result 时为空串)。 */
|
|
30
|
+
export declare function renderToolResultText(session: Session, cm: CompleteMessage, pruner?: PrunerLike): string;
|
|
31
|
+
/** 渲染一条完整消息为「文本 + 图片」(recall / recall-semantic 输出用):
|
|
26
32
|
* user/sys 取消息原文,assistant 取文本块,toolcall 为调用块 + 结果文本
|
|
27
33
|
* (pruner 裁剪超大结果);同时收集该条完整消息携带的图片附件(含 tool-result 嵌套,
|
|
28
34
|
* pruner 裁剪掉的图片不收集)。
|
package/dist/log-index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-index.d.ts","sourceRoot":"","sources":["../src/log-index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"log-index.d.ts","sourceRoot":"","sources":["../src/log-index.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EACV,eAAe,EACf,OAAO,EACP,YAAY,EAEZ,OAAO,EACP,YAAY,EACb,MAAM,YAAY,CAAC;AAGpB,+CAA+C;AAC/C,MAAM,MAAM,UAAU,GAAG;IAAE,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,KAAK,OAAO,EAAE,GAAG,IAAI,CAAA;CAAE,CAAC;AAE7F,oCAAoC;AACpC,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAG5E;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAMpF;AAED,6CAA6C;AAC7C,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAoB5D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,EAAE,CA+DzE;AACD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,IAAI,CA+B7E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,eAAe,EACnB,MAAM,CAAC,EAAE,UAAU,GAClB,OAAO,GAAG,SAAS,CASrB;AAED,4DAA4D;AAC5D,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,eAAe,EACnB,MAAM,CAAC,EAAE,UAAU,GAClB,MAAM,CAGR;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,eAAe,EACnB,MAAM,CAAC,EAAE,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,aAAa,EAAE,CAAA;CAAE,CAiD3C;AAED,kEAAkE;AAClE,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,eAAe,EACnB,MAAM,CAAC,EAAE,UAAU,GAClB,MAAM,CAER"}
|