nolo-cli 0.212.0-alpha.1 → 0.213.0
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-KE6MBNUJ.js → _executeModel-CUJLCFWR.js} +35 -35
- package/{addContentAction-N2YC5IL3.js → addContentAction-WERAONNY.js} +5 -5
- package/{addDialogAgentAction-3NKVQCEC.js → addDialogAgentAction-7VI7YRML.js} +4 -4
- package/{agentDeleteCommand-NWK7VU4N.js → agentDeleteCommand-XJORXPGU.js} +42 -42
- package/{agentEmailCommands-UZ4DHEX2.js → agentEmailCommands-XTYYFR6Z.js} +43 -43
- package/{agentListCommands-HE7L2A6L.js → agentListCommands-OBLRBLHS.js} +60 -51
- package/{agentMachineCommands-6TE4MBMP.js → agentMachineCommands-5FMT3OT5.js} +13 -12
- package/{agentRecordCommands-L3QQ7HZ4.js → agentRecordCommands-ZQ7SVYGG.js} +42 -42
- package/{agentRunCommand-2IFGQHCO.js → agentRunCommand-WS7IGO2W.js} +43 -43
- package/{agentRunControl-OI3LOENH.js → agentRunControl-TAMHJQSR.js} +3 -3
- package/{agentRuntimeLocal-HL526DNQ.js → agentRuntimeLocal-SOO2OPJG.js} +10 -10
- package/{agentSlice-TMYP2UEA.js → agentSlice-CHR6KOZN.js} +5 -5
- package/{appDeleteCommands-ZERW4AXY.js → appDeleteCommands-GUP6P5YE.js} +15 -14
- package/{appDeployCommands-DUWSMYHL.js → appDeployCommands-MH2FX4O5.js} +15 -14
- package/{appDeployStatusCommands-N2KIE4BF.js → appDeployStatusCommands-SUHN3HPJ.js} +15 -14
- package/{appGetCommands-YVR4NPVY.js → appGetCommands-YWDEX6Z4.js} +15 -14
- package/{appListCommands-JS6HOHZS.js → appListCommands-ZQVMLPAY.js} +15 -14
- package/{authCommand-FE2C3ZUM.js → authCommand-PWX2ZNUP.js} +2 -2
- package/{builtinSkillRegistry-3YOIGEF6.js → builtinSkillRegistry-2QETTQPM.js} +2 -2
- package/{chromeOpsCommands-HEN5AX2J.js → chromeOpsCommands-DIVM2K3T.js} +1 -1
- package/{chunk-YUXQAVRD.js → chunk-3UKL3HPD.js} +251 -14
- package/{chunk-PDGKOTO7.js → chunk-4T2WNOY7.js} +4 -4
- package/{chunk-NOMIGOST.js → chunk-5MQRBSMW.js} +35 -41
- package/{chunk-5RYBGBQH.js → chunk-6DWMYIUY.js} +3 -3
- package/{chunk-KSTEXKL6.js → chunk-75XIDFBW.js} +4 -3
- package/{chunk-CZM5YTZ7.js → chunk-7BT37FK3.js} +193 -305
- package/{chunk-GPO7FCEZ.js → chunk-7QTZCMKL.js} +159 -106
- package/{chunk-NJR3WKVP.js → chunk-7Y4YTDQF.js} +6 -6
- package/{chunk-CKAHAVMK.js → chunk-A7TFUNZO.js} +35 -25
- package/{chunk-PJNFNEJE.js → chunk-ALQ3657A.js} +28 -2
- package/{chunk-YJMRHHGY.js → chunk-BBJ22CLB.js} +5 -5
- package/{chunk-AVTVGMDY.js → chunk-COFEN36Z.js} +1 -1
- package/{chunk-DM6UMOEL.js → chunk-CRHOO2ZR.js} +1 -1
- package/{chunk-EYUBHHFB.js → chunk-EHGEOAHI.js} +2 -2
- package/{chunk-Y2WUYX4I.js → chunk-EHSZD5OI.js} +1 -1
- package/{chunk-QT6PKHYJ.js → chunk-FUGMREBO.js} +2 -2
- package/{chunk-BFM34N54.js → chunk-FW6YHHLI.js} +4 -4
- package/{chunk-3FOQHGHN.js → chunk-G2BQWAVT.js} +2 -2
- package/{chunk-VPAZOH2D.js → chunk-GPVRUGGY.js} +1 -1
- package/{chunk-JNKSDZFS.js → chunk-H4UOTUOX.js} +162 -48
- package/{chunk-UTV2AYEG.js → chunk-H5HF7TJA.js} +1 -1
- package/{chunk-IJXYFTV7.js → chunk-H7PPIYWP.js} +1 -1
- package/{chunk-NRFKLKRU.js → chunk-HSVBJRF4.js} +1 -1
- package/{chunk-GNDJKC4B.js → chunk-HUBHAQK2.js} +8 -8
- package/{chunk-LKDF3ATR.js → chunk-INUFILG6.js} +1 -1
- package/{chunk-OHNELDTO.js → chunk-IXNGOHV5.js} +2 -2
- package/{chunk-WXYLV624.js → chunk-J2NHJ7WX.js} +4 -4
- package/{chunk-YPD3VJZW.js → chunk-KFLT5KAD.js} +4 -4
- package/{chunk-OOF4UPC5.js → chunk-LLRPJECG.js} +4 -4
- package/{chunk-B7NJ3T4A.js → chunk-MDB67IWP.js} +4 -4
- package/{chunk-IF45XG7K.js → chunk-MOIJOHA5.js} +9 -4
- package/{chunk-IIQ6JGRI.js → chunk-NJLL224W.js} +1 -1
- package/{chunk-YOIW77S2.js → chunk-NOKUNJON.js} +2 -2
- package/{chunk-HIRC32DV.js → chunk-NSAPDIN2.js} +8 -4
- package/{chunk-JIT6FSXJ.js → chunk-O2TZF4AI.js} +1 -1
- package/{chunk-4KH4J3G5.js → chunk-OQPKUBPB.js} +1 -1
- package/{chunk-OXME3PEE.js → chunk-PCLE46CE.js} +1 -1
- package/{chunk-CJRONOYL.js → chunk-QG4AOSON.js} +8 -45
- package/{chunk-6OQUPIQF.js → chunk-QHPRUL4O.js} +3 -3
- package/{chunk-MMNYUVLW.js → chunk-R5O4QAWG.js} +1 -1
- package/{chunk-IAPCBNEE.js → chunk-RLBNLZVC.js} +1 -1
- package/{chunk-FHU44LN3.js → chunk-RSHTSUEG.js} +246 -77
- package/{chunk-25JZEIXN.js → chunk-RZOV7OMV.js} +11 -11
- package/{chunk-D2MDMY2M.js → chunk-SVYO6AO7.js} +7 -1
- package/{chunk-INSBKSBB.js → chunk-TAKB25RM.js} +1 -1
- package/{chunk-RU4SD66C.js → chunk-TX5EYMGT.js} +5 -5
- package/{chunk-D5RCRX4A.js → chunk-UYD5HQ6T.js} +746 -177
- package/{chunk-JTDORD5P.js → chunk-V5Y3R6BT.js} +110 -2
- package/{chunk-3RQVYR4B.js → chunk-VNYYOX3V.js} +59 -20
- package/{chunk-3AKFVZ2I.js → chunk-VO4WSAVP.js} +3 -3
- package/{chunk-6NSSLV67.js → chunk-WMTBPBMP.js} +6 -6
- package/{chunk-EZFQ6XRV.js → chunk-WRYQ35LQ.js} +4 -4
- package/{chunk-SOHTHFV2.js → chunk-WYDI6TGM.js} +14 -14
- package/{chunk-M6RL5JCD.js → chunk-X7SDOJUM.js} +3 -3
- package/{chunk-CQ46IRNN.js → chunk-XHQC4PXX.js} +48 -34
- package/{chunk-2WZXXAQD.js → chunk-YB3YZK56.js} +67 -1
- package/{chunk-22CIEBYO.js → chunk-YJAFKXMU.js} +11 -11
- package/{chunk-GSQNH63I.js → chunk-YTF4WH7J.js} +3 -19
- package/{chunk-5AQR3DGV.js → chunk-ZNWI6OVT.js} +2 -2
- package/{chunk-VZKUKCA6.js → chunk-ZXOUUDCG.js} +49 -40
- package/{commandRegistry-VVMTPFAX.js → commandRegistry-W63CYRZJ.js} +64 -64
- package/{contentThunks-N52O67MI.js → contentThunks-U7PL5MQD.js} +12 -12
- package/{cooldownCommands-YXLWOXWR.js → cooldownCommands-TIGUHXTD.js} +3 -3
- package/{createAgentAutomationAction-ZC57YRSV.js → createAgentAutomationAction-OLBQDD6R.js} +12 -12
- package/{createDialogAction-VQW5WDYX.js → createDialogAction-SVH6B3SB.js} +14 -14
- package/{createPageAction-M5VDA7SC.js → createPageAction-F4DIWZ2Z.js} +14 -14
- package/{dbSlice-HP7G4LX3.js → dbSlice-BVH2YZPQ.js} +4 -4
- package/{deleteFile-7VQGLK2V.js → deleteFile-5YOEKV4U.js} +2 -2
- package/{dialogCommands-JHMR2N2Y.js → dialogCommands-KHIEPY3M.js} +18 -18
- package/{dialogSlice-GRSVGDTF.js → dialogSlice-ZCTDV2PZ.js} +11 -11
- package/{docCreateCommands-F2K3UPSQ.js → docCreateCommands-DPMZI7G5.js} +14 -13
- package/{docDeleteCommands-XGXB5RFT.js → docDeleteCommands-IRQQLUBT.js} +16 -16
- package/{docReadCommands-7HWZZV6J.js → docReadCommands-LK37XH6L.js} +14 -13
- package/{docStore-KNZK6Y2G.js → docStore-V2KECILA.js} +5 -5
- package/{docUpdateCommands-OZZ7NQII.js → docUpdateCommands-O6T3HJHH.js} +14 -13
- package/{fetchMessages-M3QU7ZCQ.js → fetchMessages-NR4KNQLO.js} +2 -2
- package/{handleSendMessageAction-SHIH74GJ.js → handleSendMessageAction-2PE25WM3.js} +25 -25
- package/{hostCredentialCreate-X64WK4JD.js → hostCredentialCreate-S233UMAP.js} +42 -42
- package/index.js +7 -7
- package/{localDialogRead-XRLAH4CZ.js → localDialogRead-7NNDVVF7.js} +1 -1
- package/{localRuntimeAdapter-A7K3ABA6.js → localRuntimeAdapter-KY6WXNBR.js} +41 -41
- package/{machineCommands-DE3MR7CJ.js → machineCommands-Q6HA3IXF.js} +42 -42
- package/{machineWsRunDispatch-R26P5V36.js → machineWsRunDispatch-WWJQ6WR3.js} +42 -42
- package/{memberThunks-7WJAY5V6.js → memberThunks-7EDJADWU.js} +5 -5
- package/package.json +1 -1
- package/{projectArchive-GGL5HLMD.js → projectArchive-DRTDIMEV.js} +14 -14
- package/{read-4VZQODSN.js → read-4V2RMG7N.js} +2 -2
- package/{readDocTool-AVD32RUJ.js → readDocTool-BH6ATGQO.js} +1 -1
- package/{readlineWorkspace-XKYKNL2I.js → readlineWorkspace-2W4WRCOU.js} +322 -159
- package/{removeDialogAgentAction-FKL4BYMR.js → removeDialogAgentAction-LYAZGNKW.js} +5 -5
- package/{runAgentClientLoop-V7E2WBVM.js → runAgentClientLoop-J2VQBS2Z.js} +33 -33
- package/{secretCommands-4QS3HCA2.js → secretCommands-LXDWOLZ6.js} +1 -1
- package/{setDialogExtraReferencesAction-TLIOLWWI.js → setDialogExtraReferencesAction-OCRPGPYH.js} +5 -5
- package/{setPrimaryDialogAgentAction-2OLWRFYR.js → setPrimaryDialogAgentAction-HFJDQIBU.js} +5 -5
- package/{settingThunks-UGBPCNYF.js → settingThunks-RAMHMTGM.js} +7 -7
- package/{spaceCommands-4KSLKVNF.js → spaceCommands-KVJZVKVO.js} +14 -14
- package/{streamAgentChatTurn-7FR7X2NU.js → streamAgentChatTurn-GHBMJJ6S.js} +37 -37
- package/{switchDialogAgentAction-UZSAG2N5.js → switchDialogAgentAction-EBRMW3RA.js} +4 -4
- package/{tools-ZLKCC25W.js → tools-EWKCPKMS.js} +28 -28
- package/{tuiSummaryLlmCaller-WC54MVGP.js → tuiSummaryLlmCaller-ALQYUUWB.js} +41 -12
- package/{updateCommands-4744PL3P.js → updateCommands-ZQYU6SCI.js} +3 -3
- package/{updateDialogTitleAction-U53ZT7PJ.js → updateDialogTitleAction-5GGMBTDF.js} +12 -12
- package/{windowsSelfUpdate-XSQVF2GK.js → windowsSelfUpdate-257DV2T6.js} +2 -2
- package/{workloadLifecycle-4BEQHMSD.js → workloadLifecycle-4C42SVBD.js} +1 -0
|
@@ -40,71 +40,6 @@ function sha256Hex(text) {
|
|
|
40
40
|
return SHA256(text).toString();
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
// packages/ai/context/retention.ts
|
|
44
|
-
var SAFE_BUFFER_RATIO = 0.95;
|
|
45
|
-
var CACHE_FIRST_RETENTION_STRENGTH = 0.95;
|
|
46
|
-
var clamp = (v, min, max) => Math.min(max, Math.max(min, v));
|
|
47
|
-
var planContextUsage = (params) => {
|
|
48
|
-
const { contextWindow, summaryTokens, recentLoad } = params;
|
|
49
|
-
const safeWindowLimit = Math.floor(contextWindow * SAFE_BUFFER_RATIO);
|
|
50
|
-
const iq = CACHE_FIRST_RETENTION_STRENGTH;
|
|
51
|
-
const isLargeWindow = contextWindow >= 512e3;
|
|
52
|
-
const isSmallWindow = contextWindow <= 64e3;
|
|
53
|
-
let baseHistoryRatio;
|
|
54
|
-
if (isLargeWindow) {
|
|
55
|
-
baseHistoryRatio = 0.8 + 0.2 * iq;
|
|
56
|
-
} else if (isSmallWindow) {
|
|
57
|
-
baseHistoryRatio = 0.35 + 0.3 * iq;
|
|
58
|
-
} else {
|
|
59
|
-
baseHistoryRatio = 0.55 + 0.3 * iq;
|
|
60
|
-
}
|
|
61
|
-
let historyRatio = baseHistoryRatio;
|
|
62
|
-
switch (recentLoad) {
|
|
63
|
-
case "light": {
|
|
64
|
-
const maxRatio = isLargeWindow ? 1 : isSmallWindow ? 0.75 : 0.85;
|
|
65
|
-
historyRatio = clamp(historyRatio * 1.05, 0.3, maxRatio);
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
case "heavy": {
|
|
69
|
-
const maxRatio = isLargeWindow ? 0.98 : isSmallWindow ? 0.7 : 0.8;
|
|
70
|
-
const multiplier = isLargeWindow ? 0.98 : isSmallWindow ? 0.9 : 0.9;
|
|
71
|
-
historyRatio = clamp(historyRatio * multiplier, 0.3, maxRatio);
|
|
72
|
-
break;
|
|
73
|
-
}
|
|
74
|
-
case "medium":
|
|
75
|
-
default: {
|
|
76
|
-
const maxRatio = isLargeWindow ? 1 : isSmallWindow ? 0.75 : 0.85;
|
|
77
|
-
historyRatio = clamp(historyRatio, 0.3, maxRatio);
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
const historyBudget = Math.max(
|
|
82
|
-
0,
|
|
83
|
-
Math.floor(safeWindowLimit * historyRatio)
|
|
84
|
-
);
|
|
85
|
-
const minRawRatio = isSmallWindow ? 0.5 : isLargeWindow ? 0.2 : 0.3;
|
|
86
|
-
const rawMessageBudget = Math.max(
|
|
87
|
-
Math.floor(historyBudget * minRawRatio),
|
|
88
|
-
historyBudget - summaryTokens,
|
|
89
|
-
0
|
|
90
|
-
);
|
|
91
|
-
let minTailTokens;
|
|
92
|
-
if (recentLoad === "light") {
|
|
93
|
-
minTailTokens = Math.min(
|
|
94
|
-
Math.floor(safeWindowLimit * 0.3),
|
|
95
|
-
8e3
|
|
96
|
-
);
|
|
97
|
-
} else if (recentLoad === "heavy") {
|
|
98
|
-
minTailTokens = Math.max(
|
|
99
|
-
Math.floor(safeWindowLimit * 0.25),
|
|
100
|
-
16e3
|
|
101
|
-
);
|
|
102
|
-
} else {
|
|
103
|
-
minTailTokens = Math.floor(safeWindowLimit * 0.2);
|
|
104
|
-
}
|
|
105
|
-
return { historyBudget, rawMessageBudget, minTailTokens };
|
|
106
|
-
};
|
|
107
|
-
|
|
108
43
|
// packages/ai/context/toolOutputCap.ts
|
|
109
44
|
var TOOL_OUTPUT_CAP_WINDOW_RATIO = 0.12;
|
|
110
45
|
var TOOL_OUTPUT_CAP_MIN_TOKENS = 4e3;
|
|
@@ -114,8 +49,8 @@ var COMPRESSION_TRIGGER_RATIO_MIN = 0.5;
|
|
|
114
49
|
var ROUND_OVERHEAD_WINDOW_RATIO = 0.08;
|
|
115
50
|
var ROUND_OVERHEAD_MIN_TOKENS = 4e3;
|
|
116
51
|
var ROUND_OVERHEAD_MAX_TOKENS = 24e3;
|
|
117
|
-
var
|
|
118
|
-
var capToolOutputTokens = (contextWindow) =>
|
|
52
|
+
var clamp = (v, min, max) => Math.min(max, Math.max(min, v));
|
|
53
|
+
var capToolOutputTokens = (contextWindow) => clamp(
|
|
119
54
|
Math.floor(contextWindow * TOOL_OUTPUT_CAP_WINDOW_RATIO),
|
|
120
55
|
TOOL_OUTPUT_CAP_MIN_TOKENS,
|
|
121
56
|
TOOL_OUTPUT_CAP_MAX_TOKENS
|
|
@@ -124,12 +59,12 @@ var resolveCompressionTriggerRatio = (contextWindow) => {
|
|
|
124
59
|
if (typeof contextWindow !== "number" || !Number.isFinite(contextWindow) || contextWindow <= 0) {
|
|
125
60
|
return COMPRESSION_TRIGGER_RATIO_MAX;
|
|
126
61
|
}
|
|
127
|
-
const headroom = capToolOutputTokens(contextWindow) +
|
|
62
|
+
const headroom = capToolOutputTokens(contextWindow) + clamp(
|
|
128
63
|
Math.floor(contextWindow * ROUND_OVERHEAD_WINDOW_RATIO),
|
|
129
64
|
ROUND_OVERHEAD_MIN_TOKENS,
|
|
130
65
|
ROUND_OVERHEAD_MAX_TOKENS
|
|
131
66
|
);
|
|
132
|
-
return
|
|
67
|
+
return clamp(
|
|
133
68
|
1 - headroom / contextWindow,
|
|
134
69
|
COMPRESSION_TRIGGER_RATIO_MIN,
|
|
135
70
|
COMPRESSION_TRIGGER_RATIO_MAX
|
|
@@ -182,24 +117,6 @@ var getMessageTokenCount = (msg) => {
|
|
|
182
117
|
return tokens;
|
|
183
118
|
};
|
|
184
119
|
var hasOpenEndedToolCall = (msg) => !!msg && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0;
|
|
185
|
-
var classifyConversationLoad = (msgs) => {
|
|
186
|
-
const N = 20;
|
|
187
|
-
if (!Array.isArray(msgs) || msgs.length === 0) return "light";
|
|
188
|
-
const tail = msgs.slice(-N);
|
|
189
|
-
const tokenSamples = tail.map(getMessageTokenCount);
|
|
190
|
-
if (tokenSamples.length === 0) return "light";
|
|
191
|
-
const sum = tokenSamples.reduce((acc, v) => acc + v, 0);
|
|
192
|
-
const avg = sum / tokenSamples.length;
|
|
193
|
-
const sorted = [...tokenSamples].sort((a, b) => a - b);
|
|
194
|
-
const p95 = sorted[Math.floor((sorted.length - 1) * 0.95)];
|
|
195
|
-
if (p95 < 200 && avg < 120) {
|
|
196
|
-
return "light";
|
|
197
|
-
}
|
|
198
|
-
if (p95 > 2e3 || avg > 1200) {
|
|
199
|
-
return "heavy";
|
|
200
|
-
}
|
|
201
|
-
return "medium";
|
|
202
|
-
};
|
|
203
120
|
var normalizeContextUsageRatio = (value) => {
|
|
204
121
|
if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
|
|
205
122
|
const ratio = value > 1 ? value / 100 : value;
|
|
@@ -224,21 +141,18 @@ function findPendingMessages(allMsgs, summarizedBeforeId) {
|
|
|
224
141
|
}
|
|
225
142
|
function shouldTriggerCompaction(args) {
|
|
226
143
|
const {
|
|
227
|
-
pendingMsgCount,
|
|
228
144
|
totalUsed,
|
|
229
145
|
historyBudget,
|
|
230
146
|
triggerRatio,
|
|
231
147
|
force,
|
|
232
148
|
reason,
|
|
233
|
-
realContextUsagePercent
|
|
234
|
-
coldResume,
|
|
235
|
-
lastMsg
|
|
149
|
+
realContextUsagePercent
|
|
236
150
|
} = args;
|
|
237
151
|
const usageRatio = normalizeContextUsageRatio(realContextUsagePercent);
|
|
238
152
|
const triggeredByRealUsage = usageRatio !== void 0 && usageRatio >= triggerRatio;
|
|
239
153
|
const triggeredByEstimate = usageRatio === void 0 && totalUsed >= historyBudget;
|
|
240
|
-
const shouldRunActiveSummary = force && reason === "manual"
|
|
241
|
-
const triggeredByColdResume =
|
|
154
|
+
const shouldRunActiveSummary = force && reason === "manual";
|
|
155
|
+
const triggeredByColdResume = false;
|
|
242
156
|
return {
|
|
243
157
|
trigger: triggeredByRealUsage || triggeredByEstimate || shouldRunActiveSummary || triggeredByColdResume,
|
|
244
158
|
triggeredByRealUsage,
|
|
@@ -246,11 +160,7 @@ function shouldTriggerCompaction(args) {
|
|
|
246
160
|
triggeredByColdResume
|
|
247
161
|
};
|
|
248
162
|
}
|
|
249
|
-
function calculateCompressCount(pendingMsgs, rawMessageBudget
|
|
250
|
-
const { keepTailCount, totalUsed, historyBudget } = opts;
|
|
251
|
-
if (keepTailCount && totalUsed < historyBudget) {
|
|
252
|
-
return Math.max(0, pendingMsgs.length - ACTIVE_SUMMARY_TAIL_KEEP_COUNT);
|
|
253
|
-
}
|
|
163
|
+
function calculateCompressCount(pendingMsgs, rawMessageBudget) {
|
|
254
164
|
let tokensToKeep = 0;
|
|
255
165
|
let keepCount = 0;
|
|
256
166
|
for (let i = pendingMsgs.length - 1; i >= 0; i--) {
|
|
@@ -286,19 +196,20 @@ function resolveEffectiveCompactionBudgets(args) {
|
|
|
286
196
|
maxRetainedRatio
|
|
287
197
|
};
|
|
288
198
|
}
|
|
289
|
-
function guardToolChainBoundary(pendingMsgs, compressCount) {
|
|
290
|
-
let
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
} else {
|
|
298
|
-
count--;
|
|
299
|
-
break;
|
|
199
|
+
function guardToolChainBoundary(pendingMsgs, compressCount, preserveByProjection) {
|
|
200
|
+
let safeLimit = Math.max(0, pendingMsgs.length - 1);
|
|
201
|
+
if (!preserveByProjection) {
|
|
202
|
+
for (let i = pendingMsgs.length - 1; i >= 0; i--) {
|
|
203
|
+
if (pendingMsgs[i].role === "user") {
|
|
204
|
+
safeLimit = i;
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
300
207
|
}
|
|
301
208
|
}
|
|
209
|
+
let count = Math.min(compressCount, safeLimit);
|
|
210
|
+
while (count > 0 && (pendingMsgs[count]?.role === "tool" || hasOpenEndedToolCall(pendingMsgs[count - 1]))) {
|
|
211
|
+
count--;
|
|
212
|
+
}
|
|
302
213
|
return count;
|
|
303
214
|
}
|
|
304
215
|
function planCompression(input) {
|
|
@@ -310,7 +221,7 @@ function planCompression(input) {
|
|
|
310
221
|
force = false,
|
|
311
222
|
reason,
|
|
312
223
|
realContextUsagePercent,
|
|
313
|
-
|
|
224
|
+
preserveLatestUserByProjection = false
|
|
314
225
|
} = input;
|
|
315
226
|
const { pendingMsgs, startIndex } = findPendingMessages(allMsgs, summarizedBeforeId);
|
|
316
227
|
if (pendingMsgs.length === 0) {
|
|
@@ -329,30 +240,31 @@ function planCompression(input) {
|
|
|
329
240
|
}
|
|
330
241
|
const summaryTokens = estimateTokenCount(summary || "");
|
|
331
242
|
const pendingTokens = pendingMsgs.reduce((sum, msg) => sum + getMessageTokenCount(msg), 0);
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
243
|
+
let coveredUserTokens = 0;
|
|
244
|
+
if (preserveLatestUserByProjection && summary && startIndex > 0) {
|
|
245
|
+
for (let i = startIndex - 1; i >= 0; i--) {
|
|
246
|
+
if (allMsgs[i].role === "user") {
|
|
247
|
+
coveredUserTokens = getMessageTokenCount(allMsgs[i]);
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const totalUsed = summaryTokens + coveredUserTokens + pendingTokens;
|
|
340
253
|
const triggerRatio = resolveCompressionTriggerRatio(contextWindow);
|
|
254
|
+
const historyBudget = Math.floor(contextWindow * triggerRatio);
|
|
255
|
+
const rawMessageBudget = Math.max(0, historyBudget - summaryTokens);
|
|
341
256
|
const {
|
|
342
257
|
trigger,
|
|
343
258
|
triggeredByRealUsage,
|
|
344
259
|
shouldRunActiveSummary,
|
|
345
260
|
triggeredByColdResume
|
|
346
261
|
} = shouldTriggerCompaction({
|
|
347
|
-
pendingMsgCount: pendingMsgs.length,
|
|
348
262
|
totalUsed,
|
|
349
263
|
historyBudget,
|
|
350
264
|
triggerRatio,
|
|
351
265
|
force,
|
|
352
266
|
reason,
|
|
353
|
-
realContextUsagePercent
|
|
354
|
-
coldResume,
|
|
355
|
-
lastMsg: pendingMsgs[pendingMsgs.length - 1]
|
|
267
|
+
realContextUsagePercent
|
|
356
268
|
});
|
|
357
269
|
const diagnostics = {
|
|
358
270
|
pendingMsgCount: pendingMsgs.length,
|
|
@@ -371,44 +283,41 @@ function planCompression(input) {
|
|
|
371
283
|
emptyReason: "not-triggered"
|
|
372
284
|
});
|
|
373
285
|
}
|
|
374
|
-
const {
|
|
286
|
+
const { effectiveRawMessageBudget } = resolveEffectiveCompactionBudgets({
|
|
375
287
|
contextWindow,
|
|
376
288
|
triggerRatio,
|
|
377
289
|
historyBudget,
|
|
378
290
|
rawMessageBudget,
|
|
379
|
-
summaryTokens
|
|
291
|
+
summaryTokens: Math.max(summaryTokens, Math.min(1e3, Math.floor(contextWindow * 0.1)))
|
|
380
292
|
});
|
|
381
|
-
|
|
293
|
+
const minimumPrefixTokens = Math.min(1e3, Math.floor(contextWindow * 0.1));
|
|
294
|
+
const tailBudget = Math.min(effectiveRawMessageBudget, Math.max(0, pendingTokens - minimumPrefixTokens));
|
|
295
|
+
let compressCount = guardToolChainBoundary(
|
|
382
296
|
pendingMsgs,
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
keepTailCount: shouldRunActiveSummary || triggeredByRealUsage || triggeredByColdResume,
|
|
386
|
-
totalUsed,
|
|
387
|
-
historyBudget: effectiveHistoryBudget
|
|
388
|
-
}
|
|
297
|
+
calculateCompressCount(pendingMsgs, tailBudget),
|
|
298
|
+
preserveLatestUserByProjection
|
|
389
299
|
);
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
if (allowSmallPrefix && (compressCount < MIN_COMPRESS_COUNT || pendingMsgs.length < MIN_TRIGGER_PENDING_COUNT)) {
|
|
393
|
-
let safeLimit = pendingMsgs.length - 1;
|
|
300
|
+
if (preserveLatestUserByProjection) {
|
|
301
|
+
let latestUser = -1;
|
|
394
302
|
for (let i = pendingMsgs.length - 1; i >= 0; i--) {
|
|
395
303
|
if (pendingMsgs[i].role === "user") {
|
|
396
|
-
|
|
304
|
+
latestUser = i;
|
|
397
305
|
break;
|
|
398
306
|
}
|
|
399
307
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
compressCount
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
compressCount,
|
|
408
|
-
emptyReason: "no-safe-prefix"
|
|
409
|
-
});
|
|
308
|
+
const preservedTokens = latestUser >= 0 && latestUser < compressCount ? getMessageTokenCount(pendingMsgs[latestUser]) : latestUser < 0 ? coveredUserTokens : 0;
|
|
309
|
+
if (preservedTokens > 0) {
|
|
310
|
+
compressCount = guardToolChainBoundary(
|
|
311
|
+
pendingMsgs,
|
|
312
|
+
calculateCompressCount(pendingMsgs, Math.max(0, tailBudget - preservedTokens)),
|
|
313
|
+
true
|
|
314
|
+
);
|
|
410
315
|
}
|
|
411
316
|
}
|
|
317
|
+
if (compressCount === 0) {
|
|
318
|
+
return emptyPlan(startIndex, { ...diagnostics, compressCount, emptyReason: "no-safe-prefix" });
|
|
319
|
+
}
|
|
320
|
+
const allowSmallPrefix = reason !== "task_completed" && (shouldRunActiveSummary || triggeredByRealUsage || diagnostics.triggeredByEstimate);
|
|
412
321
|
const compressibleTokens = pendingMsgs.slice(0, compressCount).reduce((sum, msg) => sum + getMessageTokenCount(msg), 0);
|
|
413
322
|
if (compressCount < MIN_COMPRESS_COUNT && !(allowSmallPrefix && compressibleTokens >= 1e3)) {
|
|
414
323
|
return emptyPlan(startIndex, {
|
|
@@ -516,21 +425,139 @@ function extractFileOperationsFromCalls(calls, resolveCanonicalName) {
|
|
|
516
425
|
}
|
|
517
426
|
return result;
|
|
518
427
|
}
|
|
519
|
-
function
|
|
520
|
-
const
|
|
428
|
+
function makeBoundedExcerpt(content) {
|
|
429
|
+
const evidence = selectEvidenceLines(content.split("\n"));
|
|
430
|
+
return (maxChars) => {
|
|
431
|
+
if (content.length <= maxChars) return content;
|
|
432
|
+
const marker = `
|
|
433
|
+
[... ${content.length} chars projected ...]
|
|
434
|
+
`;
|
|
435
|
+
const available = maxChars - marker.length;
|
|
436
|
+
if (available < 3) return marker.trim();
|
|
437
|
+
const evidenceCap = Math.floor(available * 0.2);
|
|
438
|
+
const selected = [];
|
|
439
|
+
let evidenceLength = 0;
|
|
440
|
+
for (const line of evidence) {
|
|
441
|
+
const cost = line.length + 1;
|
|
442
|
+
if (evidenceLength + cost > evidenceCap) continue;
|
|
443
|
+
selected.push(line);
|
|
444
|
+
evidenceLength += cost;
|
|
445
|
+
}
|
|
446
|
+
const remainder = available - evidenceLength;
|
|
447
|
+
const headLength = Math.ceil(remainder / 2);
|
|
448
|
+
const tailLength = Math.floor(remainder / 2);
|
|
449
|
+
return content.slice(0, headLength) + marker + (selected.length ? selected.join("\n") + "\n" : "") + (tailLength ? content.slice(-tailLength) : "");
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
function buildBoundedCompactionRequest(args) {
|
|
453
|
+
const { msgsToCompress: msgs, previousSummary, contextWindow } = args;
|
|
454
|
+
if (!Number.isFinite(contextWindow) || contextWindow <= 0) return { status: "blocked", reason: "invalid-window" };
|
|
455
|
+
if (!msgs.length) return { status: "blocked", reason: "empty-input" };
|
|
456
|
+
const window = Math.floor(contextWindow);
|
|
457
|
+
const outputTokenBudget = Math.min(8192, Math.max(1, Math.floor(window / 4)));
|
|
458
|
+
const cap = Math.min(computeSummaryInputTokenCap(contextWindow), window - outputTokenBudget);
|
|
459
|
+
const systemTokens = estimateTokenCount(COMPACTION_SUMMARY_SYSTEM_PROMPT);
|
|
460
|
+
for (let i = 0; i < msgs.length; ) {
|
|
461
|
+
const msg = msgs[i];
|
|
462
|
+
if (msg.role === "tool") return { status: "blocked", reason: "no-safe-group" };
|
|
463
|
+
const calls = msg.role === "assistant" && Array.isArray(msg.tool_calls) ? msg.tool_calls : [];
|
|
464
|
+
if (!calls.length) {
|
|
465
|
+
i++;
|
|
466
|
+
continue;
|
|
467
|
+
}
|
|
468
|
+
const ids = calls.map((call) => call.id);
|
|
469
|
+
const hasIds = ids.every((id) => typeof id === "string" && id.length > 0);
|
|
470
|
+
if (!hasIds && ids.some((id) => id !== void 0) || hasIds && new Set(ids).size !== ids.length) {
|
|
471
|
+
return { status: "blocked", reason: "no-safe-group" };
|
|
472
|
+
}
|
|
473
|
+
const remaining2 = new Set(ids);
|
|
474
|
+
let count = 0;
|
|
475
|
+
i++;
|
|
476
|
+
while (i < msgs.length && msgs[i].role === "tool") {
|
|
477
|
+
const id = msgs[i].tool_call_id;
|
|
478
|
+
if (hasIds ? !id || !remaining2.delete(id) : id !== void 0) {
|
|
479
|
+
return { status: "blocked", reason: "no-safe-group" };
|
|
480
|
+
}
|
|
481
|
+
count++;
|
|
482
|
+
i++;
|
|
483
|
+
}
|
|
484
|
+
if (count !== calls.length || hasIds && remaining2.size) return { status: "blocked", reason: "no-safe-group" };
|
|
485
|
+
}
|
|
486
|
+
const canonicalize = args.canonicalizeToolName ?? ((name) => name);
|
|
487
|
+
const operations = /* @__PURE__ */ new Map();
|
|
521
488
|
for (const msg of msgs) {
|
|
522
489
|
if (!Array.isArray(msg.tool_calls)) continue;
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
490
|
+
for (const op of extractFileOperationsFromCalls(msg.tool_calls, canonicalize)) {
|
|
491
|
+
operations.set(JSON.stringify([op.type, op.path]), op);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
const labelsByOperation = { read: "\u8BFB\u53D6", write: "\u5199\u5165", edit: "\u7F16\u8F91" };
|
|
495
|
+
const fileOpsText = [...operations.values()].map((op) => `- ${labelsByOperation[op.type]}: ${op.path}`).join("\n") || "\u65E0";
|
|
496
|
+
const note = "\u4EE5\u4E0B\u662F\u6709\u635F\u6295\u5F71\uFF0C\u90E8\u5206\u6D88\u606F\u53EF\u80FD\u88AB\u622A\u53D6\uFF1B\u539F\u6587\u4ECD\u5B58\u5386\u53F2\u3002";
|
|
497
|
+
const omitted = "[... \u5185\u5BB9\u5DF2\u622A\u53D6 ...]";
|
|
498
|
+
const contents = msgs.map((msg) => serializeMessageContent(msg.content) || formatMessageContentFallback(msg));
|
|
499
|
+
const excerpts = contents.map((content, i) => msgs[i].role === "user" ? void 0 : makeBoundedExcerpt(content));
|
|
500
|
+
const raw = contents.map((content, i) => msgs[i].role === "tool" ? excerpts[i](TOOL_RESULT_TRUNCATE_CHARS) : content);
|
|
501
|
+
const labels = msgs.map((msg) => `${msg.role} [id=${JSON.stringify(msg.id)}]: `);
|
|
502
|
+
const projected = msgs.map((msg, i) => msg.role === "user" ? raw[i] : omitted);
|
|
503
|
+
const makePrompt = () => buildCompactionUserContent({
|
|
504
|
+
previousSummary,
|
|
505
|
+
fileOpsText,
|
|
506
|
+
messagesText: `${note}
|
|
507
|
+
${labels.map((label, i) => label + projected[i]).join("\n")}`
|
|
508
|
+
});
|
|
509
|
+
const base = makePrompt();
|
|
510
|
+
const baseTokens = systemTokens + estimateTokenCount(base);
|
|
511
|
+
if (baseTokens > cap) return { status: "blocked", reason: "no-budget" };
|
|
512
|
+
const remaining = cap - baseTokens;
|
|
513
|
+
const demands = raw.map((text, i) => msgs[i].role === "user" ? 0 : estimateTokenCount(text));
|
|
514
|
+
const weights = msgs.map((msg) => msg.role === "assistant" ? 2 : 1);
|
|
515
|
+
let low = 0;
|
|
516
|
+
let high = remaining + 1;
|
|
517
|
+
while (low + 1 < high) {
|
|
518
|
+
const mid = Math.floor((low + high) / 2);
|
|
519
|
+
const used = demands.reduce((sum, demand, i) => sum + Math.min(demand, mid * weights[i]), 0);
|
|
520
|
+
if (used <= remaining) low = mid;
|
|
521
|
+
else high = mid;
|
|
522
|
+
}
|
|
523
|
+
let extra = remaining - demands.reduce((sum, demand, i) => sum + Math.min(demand, low * weights[i]), 0);
|
|
524
|
+
for (let i = 0; i < msgs.length; i++) {
|
|
525
|
+
if (msgs[i].role === "user") continue;
|
|
526
|
+
let allowance = Math.min(demands[i], low * weights[i]);
|
|
527
|
+
const bonus = Math.min(extra, demands[i] - allowance);
|
|
528
|
+
allowance += bonus;
|
|
529
|
+
extra -= bonus;
|
|
530
|
+
if (demands[i] <= allowance) {
|
|
531
|
+
projected[i] = raw[i];
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
let lo = 0;
|
|
535
|
+
let hi = Math.min(contents[i].length, msgs[i].role === "tool" ? TOOL_RESULT_TRUNCATE_CHARS : contents[i].length);
|
|
536
|
+
let best = omitted;
|
|
537
|
+
while (lo <= hi) {
|
|
538
|
+
const mid = Math.floor((lo + hi) / 2);
|
|
539
|
+
const candidate = excerpts[i](mid);
|
|
540
|
+
if (estimateTokenCount(candidate) <= allowance) {
|
|
541
|
+
best = candidate;
|
|
542
|
+
lo = mid + 1;
|
|
543
|
+
} else {
|
|
544
|
+
hi = mid - 1;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
projected[i] = best;
|
|
526
548
|
}
|
|
527
|
-
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
549
|
+
const promptContent = makePrompt();
|
|
550
|
+
const inputTokens = systemTokens + estimateTokenCount(promptContent);
|
|
551
|
+
if (inputTokens > cap) return { status: "blocked", reason: "no-budget" };
|
|
552
|
+
return {
|
|
553
|
+
status: "ready",
|
|
554
|
+
promptContent,
|
|
555
|
+
coveredMessages: msgs.slice(),
|
|
556
|
+
summarizedBeforeId: msgs[msgs.length - 1].id,
|
|
557
|
+
inputTokens,
|
|
558
|
+
outputTokenBudget,
|
|
559
|
+
partial: false
|
|
532
560
|
};
|
|
533
|
-
return allOps.map((op) => `- ${typeLabelMap[op.type]}: ${op.path}`).join("\n");
|
|
534
561
|
}
|
|
535
562
|
var TOOL_RESULT_TRUNCATE_CHARS = 4e3;
|
|
536
563
|
var SUMMARY_INPUT_MAX_TOKENS = 3e4;
|
|
@@ -538,38 +565,6 @@ function computeSummaryInputTokenCap(contextWindow) {
|
|
|
538
565
|
const halfWindow = typeof contextWindow === "number" && Number.isFinite(contextWindow) && contextWindow > 0 ? Math.floor(contextWindow * 0.5) : SUMMARY_INPUT_MAX_TOKENS;
|
|
539
566
|
return Math.max(1, Math.min(SUMMARY_INPUT_MAX_TOKENS, halfWindow));
|
|
540
567
|
}
|
|
541
|
-
function capTextToTokenBudget(text, maxTokens) {
|
|
542
|
-
const marker = `
|
|
543
|
-
|
|
544
|
-
[... summary input capped to ${maxTokens} tokens ...]`;
|
|
545
|
-
const markerTokens = estimateTokenCount(marker);
|
|
546
|
-
const budget = Math.max(0, maxTokens - markerTokens);
|
|
547
|
-
if (estimateTokenCount(text) <= budget) return text;
|
|
548
|
-
let lo = 0;
|
|
549
|
-
let hi = text.length;
|
|
550
|
-
while (lo < hi) {
|
|
551
|
-
const mid = lo + hi + 1 >> 1;
|
|
552
|
-
if (estimateTokenCount(text.slice(0, mid)) <= budget) lo = mid;
|
|
553
|
-
else hi = mid - 1;
|
|
554
|
-
}
|
|
555
|
-
return `${text.slice(0, lo)}${marker}`;
|
|
556
|
-
}
|
|
557
|
-
function capSummaryInputToTokenBudget(items, maxTotalTokens) {
|
|
558
|
-
if (items.length === 0) return "";
|
|
559
|
-
const sepTokens = estimateTokenCount("\n");
|
|
560
|
-
const kept = [];
|
|
561
|
-
let used = 0;
|
|
562
|
-
for (let i = items.length - 1; i >= 0; i -= 1) {
|
|
563
|
-
const t = estimateTokenCount(items[i]);
|
|
564
|
-
const sep = kept.length > 0 ? sepTokens : 0;
|
|
565
|
-
if (kept.length > 0 && used + sep + t > maxTotalTokens) break;
|
|
566
|
-
used += sep + t;
|
|
567
|
-
kept.push(items[i]);
|
|
568
|
-
}
|
|
569
|
-
kept.reverse();
|
|
570
|
-
const result = kept.join("\n");
|
|
571
|
-
return estimateTokenCount(result) > maxTotalTokens ? capTextToTokenBudget(result, maxTotalTokens) : result;
|
|
572
|
-
}
|
|
573
568
|
var EVIDENCE_LINE_PATTERNS = [
|
|
574
569
|
// commit sha:必须带 git 语境(commit/sha/HEAD/merge/push 输出 a..b)且含字母+数字
|
|
575
570
|
/\b(?:commit|sha|HEAD|merge|revert|cherry-pick)\b[^\n]{0,24}\b(?=[0-9a-f]*[a-f])(?=[0-9a-f]*\d)[0-9a-f]{7,40}\b/i,
|
|
@@ -596,116 +591,6 @@ function isEvidenceLine(line) {
|
|
|
596
591
|
function selectEvidenceLines(lines) {
|
|
597
592
|
return lines.filter(isEvidenceLine);
|
|
598
593
|
}
|
|
599
|
-
var HEAD_SHARE = 0.4;
|
|
600
|
-
var TAIL_SHARE = 0.4;
|
|
601
|
-
function evidenceTruncateBudget(maxChars) {
|
|
602
|
-
const markerReserve = 96;
|
|
603
|
-
const usable = Math.max(0, maxChars - markerReserve);
|
|
604
|
-
const headCap = Math.floor(usable * HEAD_SHARE);
|
|
605
|
-
const tailCap = Math.floor(usable * TAIL_SHARE);
|
|
606
|
-
return {
|
|
607
|
-
markerReserve,
|
|
608
|
-
headCap,
|
|
609
|
-
tailCap,
|
|
610
|
-
evidenceCap: Math.max(0, usable - headCap - tailCap)
|
|
611
|
-
};
|
|
612
|
-
}
|
|
613
|
-
function takeHeadLines(lines, cap) {
|
|
614
|
-
let text = "";
|
|
615
|
-
let consumed = 0;
|
|
616
|
-
for (const line of lines) {
|
|
617
|
-
const candidate = consumed === 0 ? line : `${text}
|
|
618
|
-
${line}`;
|
|
619
|
-
if (candidate.length > cap) {
|
|
620
|
-
if (consumed === 0 && cap > 0) {
|
|
621
|
-
return { text: line.slice(0, cap), consumed: 1 };
|
|
622
|
-
}
|
|
623
|
-
break;
|
|
624
|
-
}
|
|
625
|
-
text = candidate;
|
|
626
|
-
consumed += 1;
|
|
627
|
-
}
|
|
628
|
-
return { text, consumed };
|
|
629
|
-
}
|
|
630
|
-
function takeTailLines(lines, cap) {
|
|
631
|
-
if (cap <= 0 || lines.length === 0) return { text: "", consumed: 0 };
|
|
632
|
-
let text = "";
|
|
633
|
-
let consumed = 0;
|
|
634
|
-
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
635
|
-
const candidate = consumed === 0 ? lines[i] : `${lines[i]}
|
|
636
|
-
${text}`;
|
|
637
|
-
if (candidate.length > cap) {
|
|
638
|
-
if (consumed === 0) return { text: lines[i].slice(-cap), consumed: 1 };
|
|
639
|
-
break;
|
|
640
|
-
}
|
|
641
|
-
text = candidate;
|
|
642
|
-
consumed += 1;
|
|
643
|
-
}
|
|
644
|
-
return { text, consumed };
|
|
645
|
-
}
|
|
646
|
-
function shrinkToFit(head, evidence, tail, makeMarker, maxChars) {
|
|
647
|
-
const joinBody = () => head.concat(evidence, tail).join("\n");
|
|
648
|
-
let marker = makeMarker(joinBody().length);
|
|
649
|
-
while (joinBody().length + marker.length > maxChars) {
|
|
650
|
-
if (evidence.length > 0) evidence.pop();
|
|
651
|
-
else if (tail.length > 0) tail.pop();
|
|
652
|
-
else if (head.length > 0) head.pop();
|
|
653
|
-
else break;
|
|
654
|
-
marker = makeMarker(joinBody().length);
|
|
655
|
-
}
|
|
656
|
-
const result = joinBody() + marker;
|
|
657
|
-
return result.length > maxChars ? result.slice(0, maxChars) : result;
|
|
658
|
-
}
|
|
659
|
-
function truncateContentForSummary(role, content, maxChars = TOOL_RESULT_TRUNCATE_CHARS) {
|
|
660
|
-
if (role !== "tool" || content.length <= maxChars) return content;
|
|
661
|
-
const lines = content.split("\n");
|
|
662
|
-
const budget = evidenceTruncateBudget(maxChars);
|
|
663
|
-
const head = takeHeadLines(lines, budget.headCap);
|
|
664
|
-
const tail = takeTailLines(
|
|
665
|
-
lines.slice(0, lines.length - head.consumed),
|
|
666
|
-
budget.tailCap
|
|
667
|
-
);
|
|
668
|
-
const middle = lines.slice(head.consumed, lines.length - tail.consumed);
|
|
669
|
-
const evidence = selectEvidenceLines(middle);
|
|
670
|
-
if (evidence.length === 0) {
|
|
671
|
-
return `${content.slice(0, maxChars)}
|
|
672
|
-
|
|
673
|
-
[... ${content.length - maxChars} chars truncated ...]`;
|
|
674
|
-
}
|
|
675
|
-
const headLines = head.text ? head.text.split("\n") : [];
|
|
676
|
-
const tailLines = tail.text ? tail.text.split("\n") : [];
|
|
677
|
-
const evidenceLines = [];
|
|
678
|
-
let evidenceUsed = 0;
|
|
679
|
-
for (const line of evidence) {
|
|
680
|
-
if (evidenceUsed + line.length > budget.evidenceCap) break;
|
|
681
|
-
evidenceLines.push(line);
|
|
682
|
-
evidenceUsed += line.length;
|
|
683
|
-
}
|
|
684
|
-
const marker = (bodyChars) => {
|
|
685
|
-
const note = evidenceLines.length > 0 ? `
|
|
686
|
-
[... \u5DF2\u4FDD\u7559 ${evidenceLines.length} \u6761\u8BC1\u636E\u884C ...]` : "";
|
|
687
|
-
return `
|
|
688
|
-
|
|
689
|
-
[... ${content.length - bodyChars} chars truncated ...]${note}`;
|
|
690
|
-
};
|
|
691
|
-
return shrinkToFit(headLines, evidenceLines, tailLines, marker, maxChars);
|
|
692
|
-
}
|
|
693
|
-
function formatMessagesForSummaryWithTruncation(msgs, maxToolResultChars = TOOL_RESULT_TRUNCATE_CHARS, maxTotalTokens) {
|
|
694
|
-
const items = msgs.map((msg) => {
|
|
695
|
-
const rawContent = serializeMessageContent(msg.content) || "";
|
|
696
|
-
const truncated = truncateContentForSummary(
|
|
697
|
-
msg.role,
|
|
698
|
-
rawContent,
|
|
699
|
-
maxToolResultChars
|
|
700
|
-
);
|
|
701
|
-
const text = truncated || formatMessageContentFallback(msg);
|
|
702
|
-
return `${msg.role}: ${text}`;
|
|
703
|
-
});
|
|
704
|
-
if (typeof maxTotalTokens === "number" && Number.isFinite(maxTotalTokens) && maxTotalTokens > 0) {
|
|
705
|
-
return capSummaryInputToTokenBudget(items, maxTotalTokens);
|
|
706
|
-
}
|
|
707
|
-
return items.join("\n");
|
|
708
|
-
}
|
|
709
594
|
function buildCompactionMetrics(args) {
|
|
710
595
|
const {
|
|
711
596
|
reason,
|
|
@@ -892,6 +777,11 @@ function fuzzyContextWindow(normalizedName) {
|
|
|
892
777
|
}
|
|
893
778
|
return void 0;
|
|
894
779
|
}
|
|
780
|
+
var findCodexOAuthPinnedContextWindow = (modelName, provider) => {
|
|
781
|
+
if (!modelName) return void 0;
|
|
782
|
+
if (isPlatformManagedProvider(provider, modelName)) return void 0;
|
|
783
|
+
return channelPinnedContextWindow(modelName.toLowerCase());
|
|
784
|
+
};
|
|
895
785
|
var findModelContextWindow = (modelName, provider) => {
|
|
896
786
|
if (!modelName) return void 0;
|
|
897
787
|
const onPlatformChannel = isPlatformManagedProvider(provider, modelName);
|
|
@@ -954,8 +844,8 @@ var getModelInfo = (modelName) => {
|
|
|
954
844
|
};
|
|
955
845
|
|
|
956
846
|
export {
|
|
957
|
-
planContextUsage,
|
|
958
847
|
DEFAULT_CONTEXT_WINDOW,
|
|
848
|
+
findCodexOAuthPinnedContextWindow,
|
|
959
849
|
findModelContextWindow,
|
|
960
850
|
getModelContextWindow,
|
|
961
851
|
getModelInfo,
|
|
@@ -963,14 +853,12 @@ export {
|
|
|
963
853
|
serializeMessageContent,
|
|
964
854
|
resolveCompressionTriggerRatio,
|
|
965
855
|
truncateToolOutputForContext,
|
|
856
|
+
getMessageTokenCount,
|
|
857
|
+
resolveEffectiveCompactionBudgets,
|
|
966
858
|
planCompression,
|
|
967
859
|
COMPACTION_SUMMARY_SCHEMA_VERSION,
|
|
968
860
|
COMPACTION_SUMMARY_SYSTEM_PROMPT,
|
|
969
|
-
|
|
970
|
-
formatFileOperationsFromMessages,
|
|
971
|
-
TOOL_RESULT_TRUNCATE_CHARS,
|
|
972
|
-
computeSummaryInputTokenCap,
|
|
973
|
-
formatMessagesForSummaryWithTruncation,
|
|
861
|
+
buildBoundedCompactionRequest,
|
|
974
862
|
buildCompactionMetricsFromPlan,
|
|
975
863
|
formatCompactionMetricsLog,
|
|
976
864
|
computeSummarySourceMetadata
|