nolo-cli 0.67.0 → 0.68.0-alpha.2
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/{_executeModel-C5K4UL5I.js → _executeModel-XCNYHC6S.js} +13 -13
- package/{agentDeleteCommand-7RESZDRC.js → agentDeleteCommand-Z3DTLQEG.js} +5 -5
- package/{agentEmailCommands-KES5FG2E.js → agentEmailCommands-DFK2MIXR.js} +14 -14
- package/{agentListCommands-VFBLREFU.js → agentListCommands-FSX7RY7U.js} +5 -5
- package/{agentMachineCommands-UJ77TKWZ.js → agentMachineCommands-FYPV45TJ.js} +6 -6
- package/{agentRecordCommands-MZBPYUGL.js → agentRecordCommands-SXOCVBX7.js} +14 -14
- package/{agentRunCommand-R3RWG53B.js → agentRunCommand-XISX4ICI.js} +14 -14
- package/{agentRuntimeLocal-BD7R3OJL.js → agentRuntimeLocal-2ENB2B2Z.js} +5 -5
- package/{agentSlice-UP66DIC2.js → agentSlice-QLZWET7H.js} +1 -1
- package/{appDeleteCommands-X3UF4ZHF.js → appDeleteCommands-XKAUWKUI.js} +5 -5
- package/{appDeployCommands-MFHLJIYZ.js → appDeployCommands-SNXZY5IX.js} +5 -5
- package/{appDeployStatusCommands-BGXSUHY6.js → appDeployStatusCommands-NXUJ6LXS.js} +5 -5
- package/{appGetCommands-KEA6FZTF.js → appGetCommands-DNRYKGOK.js} +5 -5
- package/{appListCommands-CZGMZW3L.js → appListCommands-URESGUKU.js} +5 -5
- package/{chatQueueReduxAdapter-VVXE2NXW.js → chatQueueReduxAdapter-FNXZNIAT.js} +4 -4
- package/{chunk-HQ3ZLBSI.js → chunk-2XENHR3P.js} +96 -0
- package/{chunk-TDTSQVDX.js → chunk-3E67YXGD.js} +85 -88
- package/{chunk-RCNQCXPM.js → chunk-5JTJG4OG.js} +115 -121
- package/{chunk-MN2XJEWL.js → chunk-7NG5APVZ.js} +16 -133
- package/{chunk-UZXOOSHF.js → chunk-AUA5DTWI.js} +15 -14
- package/{chunk-HPRMNGAM.js → chunk-IX6H4NKR.js} +1 -1
- package/{chunk-UBWLW3KY.js → chunk-IY2BLZKO.js} +3 -3
- package/{chunk-5DUAG5G7.js → chunk-K4326DRU.js} +202 -11729
- package/{chunk-AVJQ4TDL.js → chunk-K5YS7FAN.js} +1 -1
- package/{chunk-TTTW4DIT.js → chunk-LNOW66U4.js} +6 -6
- package/{chunk-NFTTUZ3L.js → chunk-LTLZPAO7.js} +1 -1
- package/{chunk-QPXRNDI3.js → chunk-MIN5X7GI.js} +2 -2
- package/{chunk-OHJWIXXW.js → chunk-RLZ6HZSX.js} +3 -3
- package/{chunk-BG7ZGBKH.js → chunk-SM4ED2LZ.js} +4 -4
- package/{chunk-FPT2E44F.js → chunk-VHADFQCI.js} +2 -2
- package/{chunk-UNAVSDC5.js → chunk-XHNOCBUU.js} +4 -2
- package/chunk-XNO3T6RB.js +18504 -0
- package/chunk-Z6S2JBE4.js +2471 -0
- package/{chunk-M3HN7RBV.js → chunk-ZCVO2HLZ.js} +1 -1
- package/{contentThunks-BHML6O7K.js → contentThunks-6K4RZXKH.js} +5 -5
- package/{createAgentAutomationAction-K5YJO4IA.js → createAgentAutomationAction-6XYIZ3GS.js} +5 -5
- package/{createDialogAction-SFMZLPS4.js → createDialogAction-TJWDXAKL.js} +6 -6
- package/{createPageAction-UD7BSFQS.js → createPageAction-EZ2LPB6K.js} +5 -5
- package/{dialogCommands-2ABSL4ND.js → dialogCommands-ULXMRIAM.js} +5 -5
- package/{dialogSlice-DEC5GV6X.js → dialogSlice-5DRM6AQQ.js} +4 -4
- package/{docCreateCommands-2QZCW4HZ.js → docCreateCommands-PPHO6KUM.js} +5 -5
- package/{docDeleteCommands-WKZKQAKM.js → docDeleteCommands-U2GVGQPR.js} +5 -5
- package/{docReadCommands-WMKJCR4Q.js → docReadCommands-CYY3DJXY.js} +5 -5
- package/{docStore-IBPCRTTX.js → docStore-OJXM46BB.js} +1 -1
- package/{docUpdateCommands-KPLM63NK.js → docUpdateCommands-B5UVFLJU.js} +5 -5
- package/{handleSendMessageAction-C7CZNGMB.js → handleSendMessageAction-EWY3J2AV.js} +4 -4
- package/index.js +41 -41
- package/{machineCommands-6BG3AHT5.js → machineCommands-B76BYAJF.js} +14 -14
- package/{machineWsRunDispatch-G2KJ6NQF.js → machineWsRunDispatch-LN6274EL.js} +14 -14
- package/package.json +1 -1
- package/{readlineWorkspace-5LZ3EDIQ.js → readlineWorkspace-UFHEJIDS.js} +77 -18
- package/{runAgentClientLoop-CICP3O2T.js → runAgentClientLoop-MAER6Y5K.js} +11 -11
- package/{spaceCommands-NQOIERT6.js → spaceCommands-2YT7C56D.js} +5 -5
- package/{streamAgentChatTurn-QUD4FY5I.js → streamAgentChatTurn-AKUDQL5W.js} +14 -14
- package/{tools-MAP6O2YZ.js → tools-NM36O7ZG.js} +8 -8
- package/{tuiSummaryLlmCaller-VL5RDGLT.js → tuiSummaryLlmCaller-ZGATEM35.js} +2 -2
- package/{updateDialogTitleAction-L6CCRVUK.js → updateDialogTitleAction-RHH353JB.js} +5 -5
- package/chunk-CLZYOOI3.js +0 -4463
- package/chunk-IF6UQNAK.js +0 -5062
|
@@ -1,12 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeTimingMs
|
|
3
|
+
} from "./chunk-3E67YXGD.js";
|
|
1
4
|
import {
|
|
2
5
|
MODEL_LOOKUP_MAP
|
|
3
6
|
} from "./chunk-TQC77XVE.js";
|
|
4
7
|
import {
|
|
5
8
|
ALL_MODELS
|
|
6
9
|
} from "./chunk-6IT5ECCC.js";
|
|
10
|
+
import {
|
|
11
|
+
asOptionalFiniteNumber
|
|
12
|
+
} from "./chunk-WWC7I6TA.js";
|
|
13
|
+
import {
|
|
14
|
+
asTrimmedNonEmptyStringArray
|
|
15
|
+
} from "./chunk-I42VC5KR.js";
|
|
7
16
|
import {
|
|
8
17
|
BUILTIN_NOLO_AGENT_KEY
|
|
9
18
|
} from "./chunk-4MKPBCTN.js";
|
|
19
|
+
import {
|
|
20
|
+
asOptionalTrimmedString
|
|
21
|
+
} from "./chunk-G3SUCT4W.js";
|
|
10
22
|
|
|
11
23
|
// packages/ai/llm/getModelContextWindow.ts
|
|
12
24
|
var DEFAULT_CONTEXT_WINDOW = 256e3;
|
|
@@ -181,6 +193,89 @@ var readCacheCreationInputTokens = (usage) => firstPositive(usage, [
|
|
|
181
193
|
topLevel("prompt_cache_miss_tokens")
|
|
182
194
|
]);
|
|
183
195
|
|
|
196
|
+
// packages/ai/token/normalizeUsage.ts
|
|
197
|
+
var normalizeStringArray = (value) => {
|
|
198
|
+
if (!Array.isArray(value)) return void 0;
|
|
199
|
+
const normalized = [...new Set(asTrimmedNonEmptyStringArray(value))];
|
|
200
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
201
|
+
};
|
|
202
|
+
var finiteTokenCount2 = (value) => {
|
|
203
|
+
const finite = asOptionalFiniteNumber(value);
|
|
204
|
+
if (finite === void 0) return void 0;
|
|
205
|
+
return Math.max(0, Math.floor(finite));
|
|
206
|
+
};
|
|
207
|
+
var readFiniteNumberField = (usage, field) => {
|
|
208
|
+
if (!usage || typeof usage !== "object") return void 0;
|
|
209
|
+
if (!(field in usage)) return void 0;
|
|
210
|
+
const candidate = usage[field];
|
|
211
|
+
return asOptionalFiniteNumber(candidate);
|
|
212
|
+
};
|
|
213
|
+
var readCostInUsdTicks = (usage) => readFiniteNumberField(usage, "cost_in_usd_ticks");
|
|
214
|
+
var normalizeUsage = (usage) => {
|
|
215
|
+
if (!usage || typeof usage !== "object") {
|
|
216
|
+
return {
|
|
217
|
+
input_tokens: 0,
|
|
218
|
+
output_tokens: 0,
|
|
219
|
+
total_tokens: 0,
|
|
220
|
+
cache_creation_input_tokens: 0,
|
|
221
|
+
cache_read_input_tokens: 0,
|
|
222
|
+
cost: 0
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
const inputTokens = "input_tokens" in usage ? usage.input_tokens ?? 0 : "prompt_tokens" in usage ? usage.prompt_tokens : 0;
|
|
226
|
+
const outputTokens = "output_tokens" in usage ? usage.output_tokens ?? 0 : "completion_tokens" in usage ? usage.completion_tokens : 0;
|
|
227
|
+
const cacheCreationInputTokens = readCacheCreationInputTokens(usage);
|
|
228
|
+
const cacheReadInputTokens = readCacheReadInputTokens(usage);
|
|
229
|
+
let cost = 0;
|
|
230
|
+
const providedCost = readFiniteNumberField(usage, "cost");
|
|
231
|
+
if (providedCost !== void 0) {
|
|
232
|
+
cost = providedCost;
|
|
233
|
+
}
|
|
234
|
+
const xaiTicks = readCostInUsdTicks(usage);
|
|
235
|
+
if (xaiTicks !== void 0 && providedCost === void 0) {
|
|
236
|
+
cost = xaiTicks / 1e10;
|
|
237
|
+
}
|
|
238
|
+
const billingProvider = asOptionalTrimmedString(usage.billing_provider);
|
|
239
|
+
const billingModel = asOptionalTrimmedString(usage.billing_model);
|
|
240
|
+
const billingServiceTier = asOptionalTrimmedString(usage.billing_service_tier);
|
|
241
|
+
const billingEstimated = "billing_estimated" in usage && usage.billing_estimated === true;
|
|
242
|
+
const serverBilled = "server_billed" in usage && usage.server_billed === true;
|
|
243
|
+
const providerCallId = asOptionalTrimmedString(usage.provider_call_id);
|
|
244
|
+
const imageGenerationCount = "image_generation_count" in usage ? asOptionalFiniteNumber(usage.image_generation_count) : void 0;
|
|
245
|
+
const providerResponseIds = normalizeStringArray(
|
|
246
|
+
usage.provider_response_ids
|
|
247
|
+
);
|
|
248
|
+
const providerRequestIds = normalizeStringArray(
|
|
249
|
+
usage.provider_request_ids
|
|
250
|
+
);
|
|
251
|
+
const firstOutputMs = normalizeTimingMs(
|
|
252
|
+
readFiniteNumberField(usage, "firstOutputMs") ?? readFiniteNumberField(usage, "firstTokenMs")
|
|
253
|
+
);
|
|
254
|
+
const callDurationMs = normalizeTimingMs(
|
|
255
|
+
readFiniteNumberField(usage, "callDurationMs") ?? readFiniteNumberField(usage, "durationMs")
|
|
256
|
+
);
|
|
257
|
+
return {
|
|
258
|
+
input_tokens: inputTokens,
|
|
259
|
+
output_tokens: outputTokens,
|
|
260
|
+
total_tokens: finiteTokenCount2(usage.total_tokens) ?? inputTokens + outputTokens,
|
|
261
|
+
cache_creation_input_tokens: cacheCreationInputTokens,
|
|
262
|
+
cache_read_input_tokens: cacheReadInputTokens,
|
|
263
|
+
cost,
|
|
264
|
+
...typeof imageGenerationCount === "number" ? { image_generation_count: imageGenerationCount } : {},
|
|
265
|
+
...providerResponseIds ? { provider_response_ids: providerResponseIds } : {},
|
|
266
|
+
...providerRequestIds ? { provider_request_ids: providerRequestIds } : {},
|
|
267
|
+
...billingProvider ? { billing_provider: billingProvider } : {},
|
|
268
|
+
...billingModel ? { billing_model: billingModel } : {},
|
|
269
|
+
...billingServiceTier ? { billing_service_tier: billingServiceTier } : {},
|
|
270
|
+
...billingEstimated ? { billing_estimated: true } : {},
|
|
271
|
+
...serverBilled ? { server_billed: true } : {},
|
|
272
|
+
...providerCallId ? { provider_call_id: providerCallId } : {},
|
|
273
|
+
...xaiTicks !== void 0 ? { cost_in_usd_ticks: xaiTicks } : {},
|
|
274
|
+
...firstOutputMs !== void 0 ? { firstOutputMs } : {},
|
|
275
|
+
...callDurationMs !== void 0 ? { callDurationMs } : {}
|
|
276
|
+
};
|
|
277
|
+
};
|
|
278
|
+
|
|
184
279
|
// packages/agent-runtime/emptyAssistantRepair.ts
|
|
185
280
|
var EMPTY_ASSISTANT_REPAIR_PROMPT = "\u8BF7\u7ED9\u51FA\u660E\u786E\u7684\u6587\u5B57\u56DE\u7B54\u6216\u6267\u884C\u4E0B\u4E00\u6B65\uFF1A\u5982\u679C\u4EFB\u52A1\u5DF2\u5B8C\u6210\uFF0C\u8BF7\u76F4\u63A5\u603B\u7ED3\u7ED3\u679C\uFF1B\u5982\u679C\u9700\u8981\u8C03\u7528\u5DE5\u5177\uFF0C\u53EA\u80FD\u8C03\u7528\u672C\u6B21\u8BF7\u6C42\u4E2D\u5DF2\u58F0\u660E\u7684\u5DE5\u5177\u2014\u2014\u4F60\u60F3\u7528\u7684\u5DE5\u5177\u4E0D\u5728\u58F0\u660E\u5217\u8868\u4E2D\u65F6\uFF0C\u4E0D\u8981\u5C1D\u8BD5\u8C03\u7528\u5B83\uFF0C\u76F4\u63A5\u7528\u6587\u5B57\u8BF4\u660E\u8BE5\u80FD\u529B\u5F53\u524D\u4E0D\u53EF\u7528\u3002\u8BF7\u5207\u52FF\u8FD4\u56DE\u7A7A\u5185\u5BB9\u3002";
|
|
186
281
|
var EMPTY_ASSISTANT_FALLBACK_MESSAGE = "\u6A21\u578B\u8FDE\u7EED\u8FD4\u56DE\u7A7A\u6D88\u606F\uFF0C\u5F53\u524D\u4EFB\u52A1\u672A\u5B8C\u6210\u3002\u8BF7\u91CD\u8BD5\u5F53\u524D\u6B65\u9AA4\uFF0C\u6216\u7ED9\u51FA\u66F4\u5177\u4F53\u7684\u4FEE\u6539\u8303\u56F4\u3002";
|
|
@@ -294,6 +389,7 @@ export {
|
|
|
294
389
|
DEFAULT_CONTEXT_WINDOW,
|
|
295
390
|
getModelContextWindow,
|
|
296
391
|
getModelInfo,
|
|
392
|
+
normalizeUsage,
|
|
297
393
|
EMPTY_ASSISTANT_REPAIR_PROMPT,
|
|
298
394
|
EMPTY_ASSISTANT_FALLBACK_MESSAGE,
|
|
299
395
|
LENGTH_TRUNCATED_FALLBACK_MESSAGE,
|
|
@@ -310,11 +310,64 @@ var planContextUsage = (params) => {
|
|
|
310
310
|
return { historyBudget, rawMessageBudget, minTailTokens };
|
|
311
311
|
};
|
|
312
312
|
|
|
313
|
+
// packages/ai/context/toolOutputCap.ts
|
|
314
|
+
var TOOL_OUTPUT_CAP_WINDOW_RATIO = 0.12;
|
|
315
|
+
var TOOL_OUTPUT_CAP_MIN_TOKENS = 4e3;
|
|
316
|
+
var TOOL_OUTPUT_CAP_MAX_TOKENS = 5e4;
|
|
317
|
+
var COMPRESSION_TRIGGER_RATIO_MAX = 0.78;
|
|
318
|
+
var COMPRESSION_TRIGGER_RATIO_MIN = 0.5;
|
|
319
|
+
var ROUND_OVERHEAD_WINDOW_RATIO = 0.08;
|
|
320
|
+
var ROUND_OVERHEAD_MIN_TOKENS = 4e3;
|
|
321
|
+
var ROUND_OVERHEAD_MAX_TOKENS = 24e3;
|
|
322
|
+
var clamp2 = (v, min, max) => Math.min(max, Math.max(min, v));
|
|
323
|
+
var capToolOutputTokens = (contextWindow) => clamp2(
|
|
324
|
+
Math.floor(contextWindow * TOOL_OUTPUT_CAP_WINDOW_RATIO),
|
|
325
|
+
TOOL_OUTPUT_CAP_MIN_TOKENS,
|
|
326
|
+
TOOL_OUTPUT_CAP_MAX_TOKENS
|
|
327
|
+
);
|
|
328
|
+
var resolveCompressionTriggerRatio = (contextWindow) => {
|
|
329
|
+
if (typeof contextWindow !== "number" || !Number.isFinite(contextWindow) || contextWindow <= 0) {
|
|
330
|
+
return COMPRESSION_TRIGGER_RATIO_MAX;
|
|
331
|
+
}
|
|
332
|
+
const headroom = capToolOutputTokens(contextWindow) + clamp2(
|
|
333
|
+
Math.floor(contextWindow * ROUND_OVERHEAD_WINDOW_RATIO),
|
|
334
|
+
ROUND_OVERHEAD_MIN_TOKENS,
|
|
335
|
+
ROUND_OVERHEAD_MAX_TOKENS
|
|
336
|
+
);
|
|
337
|
+
return clamp2(
|
|
338
|
+
1 - headroom / contextWindow,
|
|
339
|
+
COMPRESSION_TRIGGER_RATIO_MIN,
|
|
340
|
+
COMPRESSION_TRIGGER_RATIO_MAX
|
|
341
|
+
);
|
|
342
|
+
};
|
|
343
|
+
var truncateToolOutputForContext = (text, contextWindow) => {
|
|
344
|
+
if (!text) return text;
|
|
345
|
+
const capTokens = capToolOutputTokens(contextWindow);
|
|
346
|
+
if (estimateTokenCount(text) <= capTokens) return text;
|
|
347
|
+
const build = (keepChars) => {
|
|
348
|
+
const headChars = Math.floor(keepChars * 0.6);
|
|
349
|
+
const tailChars = keepChars - headChars;
|
|
350
|
+
const omittedTokens = estimateTokenCount(
|
|
351
|
+
text.slice(headChars, text.length - tailChars)
|
|
352
|
+
);
|
|
353
|
+
return text.slice(0, headChars) + `
|
|
354
|
+
...[tool output truncated: ~${omittedTokens} tokens omitted]...
|
|
355
|
+
` + text.slice(text.length - tailChars);
|
|
356
|
+
};
|
|
357
|
+
let lo = 0;
|
|
358
|
+
let hi = text.length;
|
|
359
|
+
while (lo < hi) {
|
|
360
|
+
const mid = Math.ceil((lo + hi) / 2);
|
|
361
|
+
if (estimateTokenCount(build(mid)) <= capTokens) lo = mid;
|
|
362
|
+
else hi = mid - 1;
|
|
363
|
+
}
|
|
364
|
+
return build(lo);
|
|
365
|
+
};
|
|
366
|
+
|
|
313
367
|
// packages/ai/context/planCompression.ts
|
|
314
368
|
var MIN_COMPRESS_COUNT = 5;
|
|
315
369
|
var ACTIVE_SUMMARY_TAIL_KEEP_COUNT = 2;
|
|
316
|
-
var
|
|
317
|
-
var TOOL_STUB_TEXT = "[tool output cleared to save context]";
|
|
370
|
+
var MIN_TRIGGER_PENDING_COUNT = MIN_COMPRESS_COUNT + ACTIVE_SUMMARY_TAIL_KEEP_COUNT;
|
|
318
371
|
var getMessageTokenCount = (msg) => {
|
|
319
372
|
const content = serializeMessageContent(msg.content) || "";
|
|
320
373
|
let tokens = estimateTokenCount(content);
|
|
@@ -333,13 +386,6 @@ var getMessageTokenCount = (msg) => {
|
|
|
333
386
|
return tokens;
|
|
334
387
|
};
|
|
335
388
|
var hasOpenEndedToolCall = (msg) => !!msg && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0;
|
|
336
|
-
var isActiveSummaryWorthDoing = (pendingTokens, contextWindow) => {
|
|
337
|
-
const minTokens = Math.min(
|
|
338
|
-
4e4,
|
|
339
|
-
Math.max(1e4, Math.floor(contextWindow * 0.05))
|
|
340
|
-
);
|
|
341
|
-
return pendingTokens >= minTokens;
|
|
342
|
-
};
|
|
343
389
|
var classifyConversationLoad = (msgs) => {
|
|
344
390
|
const N = 20;
|
|
345
391
|
if (!Array.isArray(msgs) || msgs.length === 0) return "light";
|
|
@@ -381,38 +427,27 @@ function findPendingMessages(allMsgs, summarizedBeforeId) {
|
|
|
381
427
|
}
|
|
382
428
|
function shouldTriggerCompaction(args) {
|
|
383
429
|
const {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
contextWindow,
|
|
430
|
+
pendingMsgCount,
|
|
431
|
+
totalUsed,
|
|
387
432
|
historyBudget,
|
|
433
|
+
triggerRatio,
|
|
388
434
|
force,
|
|
389
435
|
reason,
|
|
390
436
|
realContextUsagePercent,
|
|
391
|
-
|
|
437
|
+
coldResume,
|
|
392
438
|
lastMsg
|
|
393
439
|
} = args;
|
|
394
|
-
const totalUsed = summaryTokens + pendingTokens;
|
|
395
440
|
const usageRatio = normalizeContextUsageRatio(realContextUsagePercent);
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
407
|
-
if (typeof lastCompactedTokenCount === "number" && Number.isFinite(lastCompactedTokenCount) && lastCompactedTokenCount >= 0 && !force && !(usageRatio !== void 0 && usageRatio >= 0.78)) {
|
|
408
|
-
const minNewTokensToCompress = Math.min(4e4, Math.max(5e3, Math.floor(contextWindow * 0.03)));
|
|
409
|
-
if (totalUsed < lastCompactedTokenCount + minNewTokensToCompress) {
|
|
410
|
-
return { trigger: false, triggeredByRealUsage: false, shouldRunActiveSummary: false };
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
const shouldRunActiveSummary = force && reason === "manual" && !hasOpenEndedToolCall(lastMsg) && isActiveSummaryWorthDoing(pendingTokens, contextWindow);
|
|
414
|
-
const triggeredByRealUsage = usageRatio !== void 0 && shouldTriggerByUsage;
|
|
415
|
-
return { trigger: shouldTriggerByUsage || shouldRunActiveSummary, triggeredByRealUsage, shouldRunActiveSummary };
|
|
441
|
+
const triggeredByRealUsage = usageRatio !== void 0 && usageRatio >= triggerRatio;
|
|
442
|
+
const triggeredByEstimate = usageRatio === void 0 && totalUsed >= historyBudget;
|
|
443
|
+
const shouldRunActiveSummary = force && reason === "manual" && !hasOpenEndedToolCall(lastMsg) && pendingMsgCount >= MIN_TRIGGER_PENDING_COUNT;
|
|
444
|
+
const triggeredByColdResume = coldResume === true && pendingMsgCount >= MIN_TRIGGER_PENDING_COUNT;
|
|
445
|
+
return {
|
|
446
|
+
trigger: triggeredByRealUsage || triggeredByEstimate || shouldRunActiveSummary || triggeredByColdResume,
|
|
447
|
+
triggeredByRealUsage,
|
|
448
|
+
shouldRunActiveSummary,
|
|
449
|
+
triggeredByColdResume
|
|
450
|
+
};
|
|
416
451
|
}
|
|
417
452
|
function calculateCompressCount(pendingMsgs, rawMessageBudget, opts) {
|
|
418
453
|
const { keepTailCount, totalUsed, historyBudget } = opts;
|
|
@@ -429,45 +464,6 @@ function calculateCompressCount(pendingMsgs, rawMessageBudget, opts) {
|
|
|
429
464
|
}
|
|
430
465
|
return pendingMsgs.length - keepCount;
|
|
431
466
|
}
|
|
432
|
-
function tryComputeStubPlan(pendingMsgs, totalUsed, historyBudget, startIndex) {
|
|
433
|
-
const toolIndices = [];
|
|
434
|
-
for (let i = 0; i < pendingMsgs.length; i++) {
|
|
435
|
-
if (pendingMsgs[i].role === "tool") {
|
|
436
|
-
const content = serializeMessageContent(pendingMsgs[i].content) || "";
|
|
437
|
-
if (content !== TOOL_STUB_TEXT) toolIndices.push(i);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
if (toolIndices.length <= STUB_KEEP_COUNT) return null;
|
|
441
|
-
const firstStubbedIdx = toolIndices[toolIndices.length - STUB_KEEP_COUNT - 1];
|
|
442
|
-
const beforeMsg = pendingMsgs[firstStubbedIdx];
|
|
443
|
-
if (!beforeMsg) return null;
|
|
444
|
-
const stubOverhead = estimateTokenCount(TOOL_STUB_TEXT);
|
|
445
|
-
const stubbedMsgs = pendingMsgs.slice(0, firstStubbedIdx + 1).filter(
|
|
446
|
-
(m) => m.role === "tool"
|
|
447
|
-
);
|
|
448
|
-
const originalTokens = stubbedMsgs.reduce(
|
|
449
|
-
(s, m) => s + getMessageTokenCount(m),
|
|
450
|
-
0
|
|
451
|
-
);
|
|
452
|
-
const savedTokens = Math.max(0, originalTokens - stubOverhead * stubbedMsgs.length);
|
|
453
|
-
if (totalUsed - savedTokens > historyBudget) return null;
|
|
454
|
-
const keptMsgs = pendingMsgs.slice(firstStubbedIdx + 1);
|
|
455
|
-
return {
|
|
456
|
-
shouldCompress: true,
|
|
457
|
-
compressCount: stubbedMsgs.length,
|
|
458
|
-
msgsToCompress: stubbedMsgs,
|
|
459
|
-
msgsToKeep: keptMsgs,
|
|
460
|
-
newSummarizedBeforeId: void 0,
|
|
461
|
-
startIndex,
|
|
462
|
-
stub: {
|
|
463
|
-
// beforeId = 第一条被 stub 的 tool 结果的消息 id;投影端按
|
|
464
|
-
// 「abs index <= beforeId 的 index 的 tool 消息」判定是否 stub。
|
|
465
|
-
beforeId: beforeMsg.id,
|
|
466
|
-
stubbedCount: stubbedMsgs.length,
|
|
467
|
-
savedTokens
|
|
468
|
-
}
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
467
|
function guardToolChainBoundary(pendingMsgs, compressCount) {
|
|
472
468
|
let count = compressCount;
|
|
473
469
|
while (count > 0 && count < pendingMsgs.length && pendingMsgs[count].role === "tool") {
|
|
@@ -489,7 +485,8 @@ function planCompression(input) {
|
|
|
489
485
|
contextWindow,
|
|
490
486
|
force = false,
|
|
491
487
|
reason,
|
|
492
|
-
realContextUsagePercent
|
|
488
|
+
realContextUsagePercent,
|
|
489
|
+
coldResume
|
|
493
490
|
} = input;
|
|
494
491
|
const { pendingMsgs, startIndex } = findPendingMessages(allMsgs, summarizedBeforeId);
|
|
495
492
|
if (pendingMsgs.length === 0) return emptyPlan(startIndex);
|
|
@@ -503,27 +500,26 @@ function planCompression(input) {
|
|
|
503
500
|
summaryTokens: adjustedSummaryTokens,
|
|
504
501
|
recentLoad
|
|
505
502
|
});
|
|
506
|
-
const
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
503
|
+
const triggerRatio = resolveCompressionTriggerRatio(contextWindow);
|
|
504
|
+
const {
|
|
505
|
+
trigger,
|
|
506
|
+
triggeredByRealUsage,
|
|
507
|
+
shouldRunActiveSummary,
|
|
508
|
+
triggeredByColdResume
|
|
509
|
+
} = shouldTriggerCompaction({
|
|
510
|
+
pendingMsgCount: pendingMsgs.length,
|
|
511
|
+
totalUsed,
|
|
510
512
|
historyBudget,
|
|
513
|
+
triggerRatio,
|
|
511
514
|
force,
|
|
512
515
|
reason,
|
|
513
516
|
realContextUsagePercent,
|
|
514
|
-
|
|
517
|
+
coldResume,
|
|
515
518
|
lastMsg: pendingMsgs[pendingMsgs.length - 1]
|
|
516
519
|
});
|
|
517
520
|
if (!trigger) return emptyPlan(startIndex);
|
|
518
|
-
const stubPlan = tryComputeStubPlan(
|
|
519
|
-
pendingMsgs,
|
|
520
|
-
totalUsed,
|
|
521
|
-
historyBudget,
|
|
522
|
-
startIndex
|
|
523
|
-
);
|
|
524
|
-
if (stubPlan) return stubPlan;
|
|
525
521
|
let compressCount = calculateCompressCount(pendingMsgs, rawMessageBudget, {
|
|
526
|
-
keepTailCount: shouldRunActiveSummary || triggeredByRealUsage,
|
|
522
|
+
keepTailCount: shouldRunActiveSummary || triggeredByRealUsage || triggeredByColdResume,
|
|
527
523
|
totalUsed,
|
|
528
524
|
historyBudget
|
|
529
525
|
});
|
|
@@ -779,7 +775,8 @@ export {
|
|
|
779
775
|
buildDatabaseFileContentUrl,
|
|
780
776
|
serializeMessageContent,
|
|
781
777
|
normalizeAssistantContentBuffer,
|
|
782
|
-
|
|
778
|
+
resolveCompressionTriggerRatio,
|
|
779
|
+
truncateToolOutputForContext,
|
|
783
780
|
planCompression,
|
|
784
781
|
COMPACTION_SUMMARY_SCHEMA_VERSION,
|
|
785
782
|
COMPACTION_SUMMARY_SYSTEM_PROMPT,
|