@wrongstack/core 0.109.1 → 0.141.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/dist/{agent-bridge-mOxbpFcg.d.ts → agent-bridge-r9y6gdn4.d.ts} +1 -1
- package/dist/{agent-subagent-runner-DukQLUcS.d.ts → agent-subagent-runner-1GeQE_L0.d.ts} +7 -8
- package/dist/{brain-Dfv4Y82E.d.ts → brain-Cp_3GIS2.d.ts} +14 -3
- package/dist/{compactor-DXLxLcmU.d.ts → compactor-BueGt7LG.d.ts} +9 -1
- package/dist/{config-BSU-6vah.d.ts → config-BaVThgnT.d.ts} +104 -3
- package/dist/{context-CNRYfhUv.d.ts → context-C7G_MtLV.d.ts} +38 -1
- package/dist/coordination/index.d.ts +12 -13
- package/dist/coordination/index.js +229 -17
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +26 -27
- package/dist/defaults/index.js +886 -721
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +15 -16
- package/dist/execution/index.js +535 -322
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +6 -7
- package/dist/{goal-preamble-CI8lxeY1.d.ts → goal-preamble-iuIUTQwk.d.ts} +48 -18
- package/dist/{index-BWRN6wOb.d.ts → index-BZdezm3g.d.ts} +9 -10
- package/dist/{index-DIKEcfgC.d.ts → index-CPweVoFM.d.ts} +7 -6
- package/dist/index.d.ts +51 -52
- package/dist/index.js +752 -545
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +6 -7
- package/dist/infrastructure/index.js +64 -19
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +10 -11
- package/dist/kernel/index.js.map +1 -1
- package/dist/llm-selector-CP72f1lC.d.ts +58 -0
- package/dist/{mcp-servers-CXCsANdY.d.ts → mcp-servers-Bl5LTvQg.d.ts} +3 -3
- package/dist/{mode-ARA3HrkY.d.ts → mode-CZlO9iU1.d.ts} +1 -1
- package/dist/models/index.d.ts +157 -53
- package/dist/models/index.js +475 -20
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-DU64QxQa.d.ts → models-registry-D90K9UnM.d.ts} +1 -1
- package/dist/{multi-agent-coordinator-51LvnXkD.d.ts → multi-agent-coordinator-QWEzJDlm.d.ts} +1 -1
- package/dist/{null-fleet-bus-D09hMzFQ.d.ts → null-fleet-bus-BUyfqh23.d.ts} +13 -10
- package/dist/observability/index.d.ts +2 -2
- package/dist/{parallel-eternal-engine-B2CbsKpc.d.ts → parallel-eternal-engine-Dj2SYzha.d.ts} +24 -11
- package/dist/{path-resolver-DDJiMAtX.d.ts → path-resolver-DRjQBkoO.d.ts} +3 -3
- package/dist/{permission-BDv7z0mk.d.ts → permission-B7nKnEvQ.d.ts} +1 -1
- package/dist/{permission-policy-dF74EpDp.d.ts → permission-policy-8-6zBmfA.d.ts} +2 -13
- package/dist/{pipeline-BqiA_UMr.d.ts → pipeline-BG7UgbDc.d.ts} +2 -2
- package/dist/{plan-templates-BdDxl9cI.d.ts → plan-templates-CkKNPU3I.d.ts} +6 -6
- package/dist/{provider-runner-BUunikwY.d.ts → provider-runner-BNpuIyOL.d.ts} +3 -3
- package/dist/{retry-policy-BcmuT_V0.d.ts → retry-policy-rutAfVeR.d.ts} +1 -1
- package/dist/sdd/index.d.ts +8 -9
- package/dist/sdd/index.js +208 -1
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-vault-DrOhc2i5.d.ts → secret-vault-BTcC_T5v.d.ts} +3 -2
- package/dist/security/index.d.ts +5 -7
- package/dist/security/index.js +4 -35
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-C7wcdqMA.d.ts → selector-4vDFZKt3.d.ts} +1 -1
- package/dist/{session-event-bridge-BpJ5trO9.d.ts → session-event-bridge-DWlvglC2.d.ts} +2 -2
- package/dist/{session-reader-DDz1Ek4V.d.ts → session-reader-BAtCxdaw.d.ts} +1 -1
- package/dist/storage/index.d.ts +14 -15
- package/dist/storage/index.js +140 -134
- package/dist/storage/index.js.map +1 -1
- package/dist/types/index.d.ts +19 -20
- package/dist/types/index.js +186 -102
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +38 -15
- package/dist/utils/index.js +62 -33
- package/dist/utils/index.js.map +1 -1
- package/dist/{wstack-paths-_lqjzErq.d.ts → wstack-paths-DD50Omgn.d.ts} +3 -0
- package/package.json +2 -2
- package/dist/models-registry-B6_KfS65.d.ts +0 -95
package/dist/execution/index.js
CHANGED
|
@@ -16,6 +16,17 @@ function expectDefined(value, label) {
|
|
|
16
16
|
|
|
17
17
|
// src/utils/token-estimate.ts
|
|
18
18
|
var RoughTokenEstimate = (text, charsPerToken = 3.5) => Math.max(1, Math.ceil(text.length / charsPerToken));
|
|
19
|
+
var CALIBRATION_GLOBAL_KEY = "__global__";
|
|
20
|
+
var _cals = /* @__PURE__ */ new Map();
|
|
21
|
+
function calState(key) {
|
|
22
|
+
let state = _cals.get(key);
|
|
23
|
+
if (!state) {
|
|
24
|
+
state = { ratio: 1, count: 0, prevEst: 0 };
|
|
25
|
+
_cals.set(key, state);
|
|
26
|
+
}
|
|
27
|
+
return state;
|
|
28
|
+
}
|
|
29
|
+
var MIN_SAMPLES_FOR_CALIBRATION = 3;
|
|
19
30
|
var ESTIMATE_CACHE = /* @__PURE__ */ new Map();
|
|
20
31
|
var ESTIMATE_CACHE_MAX_SIZE = 1e4;
|
|
21
32
|
function getCachedEstimate(key, compute) {
|
|
@@ -47,10 +58,25 @@ function estimateToolResultTokens(content) {
|
|
|
47
58
|
function estimateTextTokens(text) {
|
|
48
59
|
return RoughTokenEstimate(text);
|
|
49
60
|
}
|
|
61
|
+
function estimateMessageTokens(messages) {
|
|
62
|
+
let total = 0;
|
|
63
|
+
for (const m of messages) {
|
|
64
|
+
if (typeof m.content === "string") {
|
|
65
|
+
total += estimateTextTokens(m.content);
|
|
66
|
+
} else {
|
|
67
|
+
for (const b of m.content) {
|
|
68
|
+
if (b.type === "text") total += estimateTextTokens(b.text);
|
|
69
|
+
else if (b.type === "tool_use") total += estimateToolInputTokens(b.input);
|
|
70
|
+
else if (b.type === "tool_result") total += estimateToolResultTokens(b.content);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return total;
|
|
75
|
+
}
|
|
50
76
|
function estimateToolDefTokens(tool) {
|
|
51
77
|
return RoughTokenEstimate(tool.name) + RoughTokenEstimate(tool.description ?? "") + RoughTokenEstimate(JSON.stringify(tool.inputSchema));
|
|
52
78
|
}
|
|
53
|
-
function estimateRequestTokens(messages, systemPrompt, tools) {
|
|
79
|
+
function estimateRequestTokens(messages, systemPrompt, tools, calibrationKey = CALIBRATION_GLOBAL_KEY) {
|
|
54
80
|
let messagesTokens = 0;
|
|
55
81
|
if (typeof messages === "string") {
|
|
56
82
|
messagesTokens = RoughTokenEstimate(messages);
|
|
@@ -89,6 +115,7 @@ function estimateRequestTokens(messages, systemPrompt, tools) {
|
|
|
89
115
|
toolsTokens += estimateToolDefTokens(t);
|
|
90
116
|
}
|
|
91
117
|
const total = messagesTokens + systemTokens + toolsTokens;
|
|
118
|
+
calState(calibrationKey).prevEst = total;
|
|
92
119
|
return {
|
|
93
120
|
messages: messagesTokens,
|
|
94
121
|
systemPrompt: systemTokens,
|
|
@@ -96,8 +123,18 @@ function estimateRequestTokens(messages, systemPrompt, tools) {
|
|
|
96
123
|
total
|
|
97
124
|
};
|
|
98
125
|
}
|
|
99
|
-
function estimateRequestTokensCalibrated(messages, systemPrompt, tools) {
|
|
100
|
-
const result = estimateRequestTokens(messages, systemPrompt, tools);
|
|
126
|
+
function estimateRequestTokensCalibrated(messages, systemPrompt, tools, calibrationKey = CALIBRATION_GLOBAL_KEY) {
|
|
127
|
+
const result = estimateRequestTokens(messages, systemPrompt, tools, calibrationKey);
|
|
128
|
+
const cal = calState(calibrationKey);
|
|
129
|
+
if (cal.count >= MIN_SAMPLES_FOR_CALIBRATION) {
|
|
130
|
+
const safeRatio = Math.min(1.5, Math.max(0.5, cal.ratio));
|
|
131
|
+
return {
|
|
132
|
+
messages: Math.round(result.messages * safeRatio),
|
|
133
|
+
systemPrompt: Math.round(result.systemPrompt * safeRatio),
|
|
134
|
+
tools: Math.round(result.tools * safeRatio),
|
|
135
|
+
total: Math.round(result.total * safeRatio)
|
|
136
|
+
};
|
|
137
|
+
}
|
|
101
138
|
return result;
|
|
102
139
|
}
|
|
103
140
|
|
|
@@ -193,34 +230,149 @@ function isEmptyMessage(msg) {
|
|
|
193
230
|
return msg.content.length === 0;
|
|
194
231
|
}
|
|
195
232
|
|
|
233
|
+
// src/types/blocks.ts
|
|
234
|
+
function isTextBlock(b) {
|
|
235
|
+
return b.type === "text";
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/execution/compaction-core.ts
|
|
239
|
+
var estimateMessages = estimateMessageTokens;
|
|
240
|
+
function hasTextContent(m) {
|
|
241
|
+
if (typeof m.content === "string") return m.content.trim().length > 0;
|
|
242
|
+
return m.content.some((b) => b.type === "text" && b.text.trim().length > 0);
|
|
243
|
+
}
|
|
244
|
+
function findPreserveStart(messages, preserveK) {
|
|
245
|
+
let pairCount = 0;
|
|
246
|
+
let preserveStart = messages.length;
|
|
247
|
+
for (let i = messages.length - 1; i >= 0 && pairCount < preserveK; i--) {
|
|
248
|
+
const m = messages[i];
|
|
249
|
+
if (!m) continue;
|
|
250
|
+
if (m.role === "user" || m.role === "assistant") {
|
|
251
|
+
pairCount++;
|
|
252
|
+
preserveStart = i;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
for (let i = preserveStart; i < messages.length; i++) {
|
|
256
|
+
const m = messages[i];
|
|
257
|
+
if (!m || typeof m.content === "string" || !Array.isArray(m.content)) continue;
|
|
258
|
+
const hasToolUse2 = m.content.some((b) => b.type === "tool_use");
|
|
259
|
+
if (hasToolUse2 && i + 1 < messages.length) {
|
|
260
|
+
const next = messages[i + 1];
|
|
261
|
+
if (next && next.role === "user" && typeof next.content !== "string" && Array.isArray(next.content) && next.content.some((b) => b.type === "tool_result")) {
|
|
262
|
+
preserveStart = i + 1;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return preserveStart;
|
|
267
|
+
}
|
|
268
|
+
function eliseOldToolResults(messages, opts) {
|
|
269
|
+
const preserveStart = findPreserveStart(messages, opts.preserveK);
|
|
270
|
+
let saved = 0;
|
|
271
|
+
let changed = false;
|
|
272
|
+
const next = new Array(messages.length);
|
|
273
|
+
for (let i = 0; i < messages.length; i++) {
|
|
274
|
+
const msg = messages[i];
|
|
275
|
+
if (i >= preserveStart || !msg || !Array.isArray(msg.content)) {
|
|
276
|
+
next[i] = msg;
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
const original = msg.content;
|
|
280
|
+
const newContent = original.map((b) => {
|
|
281
|
+
if (b.type !== "tool_result") return b;
|
|
282
|
+
const tokens = estimateToolResultTokens(b.content);
|
|
283
|
+
if (tokens < opts.eliseThreshold) return b;
|
|
284
|
+
saved += tokens;
|
|
285
|
+
const elided = {
|
|
286
|
+
type: "tool_result",
|
|
287
|
+
tool_use_id: b.tool_use_id,
|
|
288
|
+
content: `[elided: ~${tokens} tokens]`,
|
|
289
|
+
is_error: b.is_error
|
|
290
|
+
};
|
|
291
|
+
return elided;
|
|
292
|
+
});
|
|
293
|
+
if (newContent.every((b, idx) => b === original[idx])) {
|
|
294
|
+
next[i] = msg;
|
|
295
|
+
} else {
|
|
296
|
+
next[i] = { ...msg, content: newContent };
|
|
297
|
+
changed = true;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return { messages: changed ? next : messages, saved, changed };
|
|
301
|
+
}
|
|
302
|
+
function buildLosslessDigest(messages) {
|
|
303
|
+
const lines = [];
|
|
304
|
+
for (const m of messages) {
|
|
305
|
+
let text;
|
|
306
|
+
let omitted = 0;
|
|
307
|
+
if (typeof m.content === "string") {
|
|
308
|
+
text = m.content;
|
|
309
|
+
} else {
|
|
310
|
+
const parts = [];
|
|
311
|
+
for (const b of m.content) {
|
|
312
|
+
if (isTextBlock(b)) parts.push(b.text);
|
|
313
|
+
else if (b.type === "tool_use" || b.type === "tool_result") omitted++;
|
|
314
|
+
}
|
|
315
|
+
text = parts.join(" ");
|
|
316
|
+
}
|
|
317
|
+
if (text.trim().length === 0 && omitted === 0) continue;
|
|
318
|
+
const marker = omitted > 0 ? ` [${omitted} tool call(s) omitted \u2014 see session log]` : "";
|
|
319
|
+
lines.push(`[${m.role}]: ${text}${marker}`);
|
|
320
|
+
}
|
|
321
|
+
return lines.join("\n");
|
|
322
|
+
}
|
|
323
|
+
function findSafeBoundary(messages, from, to) {
|
|
324
|
+
for (let i = to; i >= from; i--) {
|
|
325
|
+
const m = messages[i];
|
|
326
|
+
if (!m) continue;
|
|
327
|
+
if (m.role === "user" && hasTextContent(m)) {
|
|
328
|
+
return findExchangeStart(messages, i);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return -1;
|
|
332
|
+
}
|
|
333
|
+
function findExchangeStart(messages, userIndex) {
|
|
334
|
+
for (let i = userIndex - 1; i >= 0; i--) {
|
|
335
|
+
const m = messages[i];
|
|
336
|
+
if (!m) continue;
|
|
337
|
+
if (m.role === "assistant") {
|
|
338
|
+
const hasToolUse2 = Array.isArray(m.content) ? m.content.some((b) => b.type === "tool_use") : false;
|
|
339
|
+
if (!hasToolUse2) return i + 1;
|
|
340
|
+
} else if (m.role === "user") {
|
|
341
|
+
return i;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return 0;
|
|
345
|
+
}
|
|
346
|
+
|
|
196
347
|
// src/execution/compactor.ts
|
|
197
348
|
var HybridCompactor = class {
|
|
198
349
|
preserveK;
|
|
199
350
|
eliseThreshold;
|
|
200
|
-
estimator;
|
|
201
351
|
constructor(opts = {}) {
|
|
202
352
|
this.preserveK = opts.preserveK ?? 5;
|
|
203
353
|
this.eliseThreshold = opts.eliseThreshold ?? 2e3;
|
|
204
|
-
this.estimator = opts.estimator ?? estimateTextTokens;
|
|
205
354
|
}
|
|
206
355
|
async compact(ctx, opts = {}) {
|
|
207
|
-
const beforeTokens =
|
|
356
|
+
const beforeTokens = estimateMessages(ctx.messages);
|
|
208
357
|
const beforeFull = this.estimateFullRequest(ctx);
|
|
209
358
|
const reductions = [];
|
|
210
359
|
const policy = readContextWindowPolicy(ctx);
|
|
211
360
|
const preserveK = policy?.preserveK ?? this.preserveK;
|
|
212
361
|
const eliseThreshold = policy?.eliseThreshold ?? this.eliseThreshold;
|
|
213
|
-
const
|
|
214
|
-
if (
|
|
362
|
+
const elide = eliseOldToolResults(ctx.messages, { preserveK, eliseThreshold });
|
|
363
|
+
if (elide.changed) ctx.state.replaceMessages(elide.messages);
|
|
364
|
+
if (elide.saved > 0) reductions.push({ phase: "elision", saved: elide.saved });
|
|
365
|
+
let collapsedDigest;
|
|
215
366
|
if (opts.aggressive) {
|
|
216
|
-
const
|
|
217
|
-
if (
|
|
367
|
+
const phase2 = this.collapseAncientTurns(ctx, preserveK);
|
|
368
|
+
if (phase2.saved > 0) reductions.push({ phase: "summary", saved: phase2.saved });
|
|
369
|
+
collapsedDigest = phase2.digest;
|
|
218
370
|
}
|
|
219
371
|
const repaired = repairToolUseAdjacency(ctx.messages);
|
|
220
372
|
if (repaired.report.changed) {
|
|
221
373
|
ctx.state.replaceMessages(repaired.messages);
|
|
222
374
|
}
|
|
223
|
-
const afterTokens =
|
|
375
|
+
const afterTokens = estimateMessages(ctx.messages);
|
|
224
376
|
const afterFull = this.estimateFullRequest(ctx);
|
|
225
377
|
return {
|
|
226
378
|
before: beforeTokens,
|
|
@@ -228,6 +380,7 @@ var HybridCompactor = class {
|
|
|
228
380
|
fullRequestTokensBefore: beforeFull,
|
|
229
381
|
fullRequestTokensAfter: afterFull,
|
|
230
382
|
reductions,
|
|
383
|
+
collapsedDigest,
|
|
231
384
|
repaired: repaired.report.changed ? {
|
|
232
385
|
removedToolUses: repaired.report.removedToolUses,
|
|
233
386
|
removedToolResults: repaired.report.removedToolResults,
|
|
@@ -240,72 +393,23 @@ var HybridCompactor = class {
|
|
|
240
393
|
* This is the accurate figure for context-window pressure monitoring.
|
|
241
394
|
*/
|
|
242
395
|
estimateFullRequest(ctx) {
|
|
243
|
-
|
|
244
|
-
return breakdown.total;
|
|
245
|
-
}
|
|
246
|
-
eliseOldToolResults(ctx, preserveK = this.preserveK, eliseThreshold = this.eliseThreshold) {
|
|
247
|
-
const messages = ctx.messages;
|
|
248
|
-
let pairCount = 0;
|
|
249
|
-
let preserveStart = messages.length;
|
|
250
|
-
for (let i = messages.length - 1; i >= 0 && pairCount < preserveK; i--) {
|
|
251
|
-
const m = messages[i];
|
|
252
|
-
if (!m) continue;
|
|
253
|
-
if (m.role === "user" || m.role === "assistant") {
|
|
254
|
-
pairCount++;
|
|
255
|
-
preserveStart = i;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
for (let i = preserveStart; i < messages.length; i++) {
|
|
259
|
-
const m = messages[i];
|
|
260
|
-
if (!m || typeof m.content === "string" || !Array.isArray(m.content)) continue;
|
|
261
|
-
const hasToolUse2 = m.content.some((b) => b.type === "tool_use");
|
|
262
|
-
if (hasToolUse2 && i + 1 < messages.length) {
|
|
263
|
-
const next = messages[i + 1];
|
|
264
|
-
if (next && next.role === "user" && typeof next.content !== "string" && Array.isArray(next.content) && next.content.some((b) => b.type === "tool_result")) {
|
|
265
|
-
preserveStart = i + 1;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
let saved = 0;
|
|
270
|
-
let changed = false;
|
|
271
|
-
const nextMessages = new Array(messages.length);
|
|
272
|
-
for (let i = 0; i < messages.length; i++) {
|
|
273
|
-
const msg = messages[i];
|
|
274
|
-
if (i >= preserveStart) {
|
|
275
|
-
nextMessages[i] = msg;
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
if (!msg || !Array.isArray(msg.content)) {
|
|
279
|
-
nextMessages[i] = msg;
|
|
280
|
-
continue;
|
|
281
|
-
}
|
|
282
|
-
const newContent = msg.content.map((b) => {
|
|
283
|
-
if (b.type !== "tool_result") return b;
|
|
284
|
-
const tokens = estimateToolResultTokens(b.content);
|
|
285
|
-
if (tokens < eliseThreshold) return b;
|
|
286
|
-
saved += tokens;
|
|
287
|
-
const elided = {
|
|
288
|
-
type: "tool_result",
|
|
289
|
-
tool_use_id: b.tool_use_id,
|
|
290
|
-
content: `[elided: ~${tokens} tokens]`,
|
|
291
|
-
is_error: b.is_error
|
|
292
|
-
};
|
|
293
|
-
return elided;
|
|
294
|
-
});
|
|
295
|
-
if (newContent.length === msg.content.length && newContent.every((b, idx) => b === msg.content[idx])) {
|
|
296
|
-
nextMessages[i] = msg;
|
|
297
|
-
} else {
|
|
298
|
-
nextMessages[i] = { ...msg, content: newContent };
|
|
299
|
-
changed = true;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
if (changed) ctx.state.replaceMessages(nextMessages);
|
|
303
|
-
return saved;
|
|
396
|
+
return estimateRequestTokens(ctx.messages, ctx.systemPrompt, ctx.tools ?? []).total;
|
|
304
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* Lossless rule-based collapse of ancient turns into a single digest message.
|
|
400
|
+
*
|
|
401
|
+
* Preserves ALL textual content of the collapsed range — user instructions,
|
|
402
|
+
* assistant decisions/conclusions, and any prior digests (chained forward so
|
|
403
|
+
* the digest stays lossless across repeated compactions). Only `tool_use` /
|
|
404
|
+
* `tool_result` protocol blocks are dropped and replaced with a count marker;
|
|
405
|
+
* their full payload already lives in the session log. No sub-LLM call.
|
|
406
|
+
*
|
|
407
|
+
* Returns the token savings and the digest text (for audit logging).
|
|
408
|
+
*/
|
|
305
409
|
collapseAncientTurns(ctx, preserveK = this.preserveK) {
|
|
306
410
|
const messages = ctx.messages;
|
|
307
411
|
const cutTarget = Math.max(0, messages.length - preserveK * 2);
|
|
308
|
-
if (cutTarget <= 0) return 0;
|
|
412
|
+
if (cutTarget <= 0) return { saved: 0 };
|
|
309
413
|
let boundary = -1;
|
|
310
414
|
for (let i = cutTarget; i < messages.length; i++) {
|
|
311
415
|
const m = messages[i];
|
|
@@ -315,34 +419,20 @@ var HybridCompactor = class {
|
|
|
315
419
|
break;
|
|
316
420
|
}
|
|
317
421
|
}
|
|
318
|
-
if (boundary <= 0) return 0;
|
|
422
|
+
if (boundary <= 0) return { saved: 0 };
|
|
319
423
|
const removed = messages.slice(0, boundary);
|
|
320
|
-
const removedTokens =
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
{ role: "assistant", content: "Continuing from compacted context." }
|
|
327
|
-
];
|
|
424
|
+
const removedTokens = estimateMessages(removed);
|
|
425
|
+
const digest = buildLosslessDigest(removed) || `${removed.length} earlier turns (no textual content; tool I/O omitted \u2014 see session log)`;
|
|
426
|
+
const summaryMsg = {
|
|
427
|
+
role: "system",
|
|
428
|
+
content: `[prior_turns_digest: ${digest}]`
|
|
429
|
+
};
|
|
328
430
|
const tail = ctx.messages.slice(boundary);
|
|
329
|
-
ctx.state.replaceMessages([
|
|
330
|
-
return
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
for (const m of messages) {
|
|
335
|
-
if (typeof m.content === "string") {
|
|
336
|
-
total += this.estimator(m.content);
|
|
337
|
-
} else {
|
|
338
|
-
for (const b of m.content) {
|
|
339
|
-
if (b.type === "text") total += this.estimator(b.text);
|
|
340
|
-
else if (b.type === "tool_use") total += estimateToolInputTokens(b.input);
|
|
341
|
-
else if (b.type === "tool_result") total += estimateToolResultTokens(b.content);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
return total;
|
|
431
|
+
ctx.state.replaceMessages([summaryMsg, ...tail]);
|
|
432
|
+
return {
|
|
433
|
+
saved: Math.max(0, removedTokens - estimateMessages([summaryMsg])),
|
|
434
|
+
digest
|
|
435
|
+
};
|
|
346
436
|
}
|
|
347
437
|
};
|
|
348
438
|
function readContextWindowPolicy(ctx) {
|
|
@@ -354,15 +444,6 @@ function readContextWindowPolicy(ctx) {
|
|
|
354
444
|
}
|
|
355
445
|
return candidate;
|
|
356
446
|
}
|
|
357
|
-
function hasTextContent(m) {
|
|
358
|
-
if (typeof m.content === "string") return m.content.trim().length > 0;
|
|
359
|
-
return m.content.some((b) => b.type === "text" && b.text.trim().length > 0);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// src/types/blocks.ts
|
|
363
|
-
function isTextBlock(b) {
|
|
364
|
-
return b.type === "text";
|
|
365
|
-
}
|
|
366
447
|
|
|
367
448
|
// src/execution/intelligent-compactor.ts
|
|
368
449
|
var IntelligentCompactor = class {
|
|
@@ -387,23 +468,25 @@ var IntelligentCompactor = class {
|
|
|
387
468
|
this.summarizerModel = opts.summarizerModel;
|
|
388
469
|
}
|
|
389
470
|
async compact(ctx, opts = {}) {
|
|
390
|
-
const beforeTokens =
|
|
471
|
+
const beforeTokens = estimateMessages(ctx.messages);
|
|
391
472
|
const beforeFull = this.estimateFullRequest(ctx);
|
|
392
473
|
const reductions = [];
|
|
393
474
|
const load = beforeFull / this.maxContext;
|
|
394
475
|
const aggressive = load >= this.hardThreshold ? true : opts.aggressive ?? load >= this.softThreshold;
|
|
395
|
-
const saved1 = this.
|
|
476
|
+
const saved1 = this.elide(ctx);
|
|
396
477
|
if (saved1 > 0) reductions.push({ phase: "elision", saved: saved1 });
|
|
478
|
+
let collapsedDigest;
|
|
397
479
|
if (aggressive) {
|
|
398
|
-
const
|
|
399
|
-
if (
|
|
480
|
+
const phase2 = await this.summarizeAncientTurns(ctx);
|
|
481
|
+
if (phase2.saved > 0) reductions.push({ phase: "summary", saved: phase2.saved });
|
|
482
|
+
collapsedDigest = phase2.digest;
|
|
400
483
|
} else if (load >= this.warnThreshold) {
|
|
401
|
-
const saved2 = this.
|
|
484
|
+
const saved2 = this.elide(ctx);
|
|
402
485
|
if (saved2 > 0) reductions.push({ phase: "elision", saved: saved2 });
|
|
403
486
|
}
|
|
404
487
|
const repaired = repairToolUseAdjacency(ctx.messages);
|
|
405
488
|
if (repaired.report.changed) ctx.state.replaceMessages(repaired.messages);
|
|
406
|
-
const afterTokens =
|
|
489
|
+
const afterTokens = estimateMessages(ctx.messages);
|
|
407
490
|
const afterFull = this.estimateFullRequest(ctx);
|
|
408
491
|
return {
|
|
409
492
|
before: beforeTokens,
|
|
@@ -411,6 +494,7 @@ var IntelligentCompactor = class {
|
|
|
411
494
|
fullRequestTokensBefore: beforeFull,
|
|
412
495
|
fullRequestTokensAfter: afterFull,
|
|
413
496
|
reductions,
|
|
497
|
+
collapsedDigest,
|
|
414
498
|
repaired: repaired.report.changed ? {
|
|
415
499
|
removedToolUses: repaired.report.removedToolUses,
|
|
416
500
|
removedToolResults: repaired.report.removedToolResults,
|
|
@@ -423,75 +507,39 @@ var IntelligentCompactor = class {
|
|
|
423
507
|
* This is the accurate figure for context-window pressure monitoring.
|
|
424
508
|
*/
|
|
425
509
|
estimateFullRequest(ctx) {
|
|
426
|
-
|
|
427
|
-
|
|
510
|
+
return estimateRequestTokens(ctx.messages, ctx.systemPrompt, ctx.tools ?? []).total;
|
|
511
|
+
}
|
|
512
|
+
/** Run shared tool-result elision and commit through ConversationState. */
|
|
513
|
+
elide(ctx) {
|
|
514
|
+
const result = eliseOldToolResults(ctx.messages, {
|
|
515
|
+
preserveK: this.preserveK,
|
|
516
|
+
eliseThreshold: this.eliseThreshold
|
|
517
|
+
});
|
|
518
|
+
if (result.changed) ctx.state.replaceMessages(result.messages);
|
|
519
|
+
return result.saved;
|
|
428
520
|
}
|
|
429
521
|
async summarizeAncientTurns(ctx) {
|
|
430
522
|
const messages = ctx.messages;
|
|
431
523
|
const cutoff = Math.max(0, messages.length - this.preserveK * 2);
|
|
432
|
-
if (cutoff <= 2) return 0;
|
|
433
|
-
const boundary =
|
|
434
|
-
if (boundary <= 1) return 0;
|
|
524
|
+
if (cutoff <= 2) return { saved: 0 };
|
|
525
|
+
const boundary = findSafeBoundary(messages, 0, cutoff);
|
|
526
|
+
if (boundary <= 1) return { saved: 0 };
|
|
435
527
|
const toSummarize = messages.slice(0, boundary);
|
|
436
|
-
const removedTokens =
|
|
528
|
+
const removedTokens = estimateMessages(toSummarize);
|
|
437
529
|
let summaryText;
|
|
438
530
|
try {
|
|
439
531
|
summaryText = await this.callSummarizer(toSummarize, ctx);
|
|
440
532
|
} catch {
|
|
441
|
-
|
|
442
|
-
for (const m of toSummarize) {
|
|
443
|
-
if (m.role === "system") continue;
|
|
444
|
-
if (typeof m.content === "string") {
|
|
445
|
-
preservedMessages.push(m);
|
|
446
|
-
} else if (Array.isArray(m.content)) {
|
|
447
|
-
const textParts = m.content.filter(isTextBlock);
|
|
448
|
-
const toolParts = m.content.filter((b) => b.type === "tool_use" || b.type === "tool_result");
|
|
449
|
-
const next = {
|
|
450
|
-
role: m.role,
|
|
451
|
-
content: [
|
|
452
|
-
...textParts,
|
|
453
|
-
...toolParts.length > 0 ? [{ type: "text", text: `[${toolParts.length} tool call(s) omitted]` }] : []
|
|
454
|
-
]
|
|
455
|
-
};
|
|
456
|
-
preservedMessages.push(next);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
summaryText = preservedMessages.map((m) => `[${m.role}]: ${typeof m.content === "string" ? m.content : m.content.filter(isTextBlock).map((b) => b.text).join(" ")}`).join("\n");
|
|
460
|
-
if (!summaryText) summaryText = `${toSummarize.length} earlier turns (semantic content preserved)`;
|
|
533
|
+
summaryText = buildLosslessDigest(toSummarize) || `${toSummarize.length} earlier turns (semantic content preserved)`;
|
|
461
534
|
}
|
|
462
535
|
const summaryMsg = {
|
|
463
536
|
role: "system",
|
|
464
537
|
content: `[prior_turns_summary: ${summaryText}]`
|
|
465
538
|
};
|
|
466
|
-
const summaryTokens =
|
|
539
|
+
const summaryTokens = estimateMessages([summaryMsg]);
|
|
467
540
|
const tail = ctx.messages.slice(boundary);
|
|
468
541
|
ctx.state.replaceMessages([summaryMsg, ...tail]);
|
|
469
|
-
return Math.max(0, removedTokens - summaryTokens);
|
|
470
|
-
}
|
|
471
|
-
findSafeBoundary(messages, from, to) {
|
|
472
|
-
for (let i = to; i >= from; i--) {
|
|
473
|
-
const m = messages[i];
|
|
474
|
-
if (!m) continue;
|
|
475
|
-
if (m.role === "user" && this.hasTextContent(m)) {
|
|
476
|
-
return this.findExchangeStart(messages, i);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
return -1;
|
|
480
|
-
}
|
|
481
|
-
findExchangeStart(messages, userIndex) {
|
|
482
|
-
for (let i = userIndex - 1; i >= 0; i--) {
|
|
483
|
-
const m = messages[i];
|
|
484
|
-
if (!m) continue;
|
|
485
|
-
if (m.role === "assistant") {
|
|
486
|
-
const hasToolUse2 = Array.isArray(m.content) ? m.content.some((b) => b.type === "tool_use") : false;
|
|
487
|
-
if (!hasToolUse2) {
|
|
488
|
-
return i + 1;
|
|
489
|
-
}
|
|
490
|
-
} else if (m.role !== "user") ; else {
|
|
491
|
-
return i;
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
return 0;
|
|
542
|
+
return { saved: Math.max(0, removedTokens - summaryTokens), digest: summaryText };
|
|
495
543
|
}
|
|
496
544
|
async callSummarizer(messages, ctx) {
|
|
497
545
|
const prompt = [
|
|
@@ -526,86 +574,6 @@ var IntelligentCompactor = class {
|
|
|
526
574
|
}
|
|
527
575
|
return [{ type: "text", text: lines.join("\n") }];
|
|
528
576
|
}
|
|
529
|
-
lightweightCompact(ctx) {
|
|
530
|
-
return this.eliseOldToolResults(ctx);
|
|
531
|
-
}
|
|
532
|
-
eliseOldToolResults(ctx) {
|
|
533
|
-
const messages = ctx.messages;
|
|
534
|
-
let pairCount = 0;
|
|
535
|
-
let preserveStart = messages.length;
|
|
536
|
-
for (let i = messages.length - 1; i >= 0 && pairCount < this.preserveK; i--) {
|
|
537
|
-
const m = messages[i];
|
|
538
|
-
if (!m) continue;
|
|
539
|
-
if (m.role === "user" || m.role === "assistant") {
|
|
540
|
-
pairCount++;
|
|
541
|
-
preserveStart = i;
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
for (let i = preserveStart; i < messages.length; i++) {
|
|
545
|
-
const m = messages[i];
|
|
546
|
-
if (!m || typeof m.content === "string" || !Array.isArray(m.content)) continue;
|
|
547
|
-
const hasToolUse2 = m.content.some((b) => b.type === "tool_use");
|
|
548
|
-
if (hasToolUse2 && i + 1 < messages.length) {
|
|
549
|
-
const next = messages[i + 1];
|
|
550
|
-
if (next && next.role === "user" && typeof next.content !== "string" && Array.isArray(next.content) && next.content.some((b) => b.type === "tool_result")) {
|
|
551
|
-
preserveStart = i + 1;
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
let saved = 0;
|
|
556
|
-
let changed = false;
|
|
557
|
-
const nextMessages = new Array(messages.length);
|
|
558
|
-
for (let i = 0; i < messages.length; i++) {
|
|
559
|
-
const msg = messages[i];
|
|
560
|
-
if (i >= preserveStart) {
|
|
561
|
-
nextMessages[i] = msg;
|
|
562
|
-
continue;
|
|
563
|
-
}
|
|
564
|
-
if (!msg || !Array.isArray(msg.content)) {
|
|
565
|
-
nextMessages[i] = msg;
|
|
566
|
-
continue;
|
|
567
|
-
}
|
|
568
|
-
const newContent = msg.content.map((b) => {
|
|
569
|
-
if (b.type !== "tool_result") return b;
|
|
570
|
-
const tokens = estimateToolResultTokens(b.content);
|
|
571
|
-
if (tokens < this.eliseThreshold) return b;
|
|
572
|
-
saved += tokens;
|
|
573
|
-
return {
|
|
574
|
-
type: "tool_result",
|
|
575
|
-
tool_use_id: b.tool_use_id,
|
|
576
|
-
content: `[elided: ~${tokens} tokens]`,
|
|
577
|
-
is_error: b.is_error
|
|
578
|
-
};
|
|
579
|
-
});
|
|
580
|
-
if (newContent.length === msg.content.length && newContent.every((b, idx) => b === msg.content[idx])) {
|
|
581
|
-
nextMessages[i] = msg;
|
|
582
|
-
} else {
|
|
583
|
-
nextMessages[i] = { ...msg, content: newContent };
|
|
584
|
-
changed = true;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
if (changed) ctx.state.replaceMessages(nextMessages);
|
|
588
|
-
return saved;
|
|
589
|
-
}
|
|
590
|
-
hasTextContent(m) {
|
|
591
|
-
if (typeof m.content === "string") return m.content.trim().length > 0;
|
|
592
|
-
return m.content.some((b) => b.type === "text" && b.text.trim().length > 0);
|
|
593
|
-
}
|
|
594
|
-
estimateTokens(messages) {
|
|
595
|
-
let total = 0;
|
|
596
|
-
for (const m of messages) {
|
|
597
|
-
if (typeof m.content === "string") {
|
|
598
|
-
total += estimateTextTokens(m.content);
|
|
599
|
-
} else {
|
|
600
|
-
for (const b of m.content) {
|
|
601
|
-
if (b.type === "text") total += estimateTextTokens(b.text);
|
|
602
|
-
else if (b.type === "tool_use") total += estimateToolInputTokens(b.input);
|
|
603
|
-
else if (b.type === "tool_result") total += estimateToolResultTokens(b.content);
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
return total;
|
|
608
|
-
}
|
|
609
577
|
};
|
|
610
578
|
|
|
611
579
|
// src/models/llm-selector.ts
|
|
@@ -631,20 +599,6 @@ Rules:
|
|
|
631
599
|
- If unsure, keep rather than collapse (errors are more costly than waste)
|
|
632
600
|
|
|
633
601
|
Return ONLY the JSON object, no markdown, no explanation outside the JSON.`;
|
|
634
|
-
function estimateTokens(messages) {
|
|
635
|
-
let total = 0;
|
|
636
|
-
for (const m of messages) {
|
|
637
|
-
if (typeof m.content === "string") {
|
|
638
|
-
total += Math.ceil(m.content.length / 4);
|
|
639
|
-
} else if (Array.isArray(m.content)) {
|
|
640
|
-
for (const b of m.content) {
|
|
641
|
-
if (b.type === "text") total += Math.ceil(b.text.length / 4);
|
|
642
|
-
else total += Math.ceil(JSON.stringify(b).length / 4);
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
return total;
|
|
647
|
-
}
|
|
648
602
|
function formatMessages(messages, maxChars = 8e3) {
|
|
649
603
|
const lines = [];
|
|
650
604
|
let used = 0;
|
|
@@ -683,7 +637,7 @@ var LLMSelector = class {
|
|
|
683
637
|
async select(messages, maxToKeep) {
|
|
684
638
|
const effectiveBudget = Math.min(maxToKeep, this.maxContextTokens);
|
|
685
639
|
const historyText = formatMessages(messages);
|
|
686
|
-
const totalTokens =
|
|
640
|
+
const totalTokens = estimateMessageTokens(messages);
|
|
687
641
|
const systemText = `${this.systemPrompt}
|
|
688
642
|
|
|
689
643
|
Conversation (${messages.length} messages, ~${totalTokens} tokens, budget: ${effectiveBudget}):
|
|
@@ -715,10 +669,7 @@ IMPORTANT: Total conversation (${totalTokens} tokens) exceeds budget (${effectiv
|
|
|
715
669
|
let startIdx = 0;
|
|
716
670
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
717
671
|
const m = expectDefined(messages[i]);
|
|
718
|
-
const cost =
|
|
719
|
-
(acc, b) => acc + (b.type === "text" ? Math.ceil(b.text.length / 4) : Math.ceil(JSON.stringify(b).length / 4)),
|
|
720
|
-
0
|
|
721
|
-
);
|
|
672
|
+
const cost = estimateMessageTokens([m]);
|
|
722
673
|
if (tokenCount + cost <= budget) {
|
|
723
674
|
tokenCount += cost;
|
|
724
675
|
} else {
|
|
@@ -951,52 +902,12 @@ Summarize the following message range:`;
|
|
|
951
902
|
return Math.floor(this.maxContext * 0.75);
|
|
952
903
|
}
|
|
953
904
|
eliseOldToolResults(ctx) {
|
|
954
|
-
const
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
if (m.role === "user" || m.role === "assistant") {
|
|
961
|
-
pairCount++;
|
|
962
|
-
preserveStart = i;
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
let saved = 0;
|
|
966
|
-
let changed = false;
|
|
967
|
-
const nextMessages = new Array(messages.length);
|
|
968
|
-
for (let i = 0; i < messages.length; i++) {
|
|
969
|
-
const msg = messages[i];
|
|
970
|
-
if (i >= preserveStart) {
|
|
971
|
-
nextMessages[i] = msg;
|
|
972
|
-
continue;
|
|
973
|
-
}
|
|
974
|
-
if (!msg || !Array.isArray(msg.content)) {
|
|
975
|
-
nextMessages[i] = msg;
|
|
976
|
-
continue;
|
|
977
|
-
}
|
|
978
|
-
const newContent = msg.content.map((b) => {
|
|
979
|
-
if (b.type !== "tool_result") return b;
|
|
980
|
-
const text = typeof b.content === "string" ? b.content : JSON.stringify(b.content);
|
|
981
|
-
const tokens = this.roughTokenEstimate(text);
|
|
982
|
-
if (tokens < this.eliseThreshold) return b;
|
|
983
|
-
saved += tokens;
|
|
984
|
-
return {
|
|
985
|
-
type: "tool_result",
|
|
986
|
-
tool_use_id: b.tool_use_id,
|
|
987
|
-
content: `[elided: ~${tokens} tokens]`,
|
|
988
|
-
is_error: b.is_error
|
|
989
|
-
};
|
|
990
|
-
});
|
|
991
|
-
if (newContent.every((b, idx) => b === msg.content[idx])) {
|
|
992
|
-
nextMessages[i] = msg;
|
|
993
|
-
} else {
|
|
994
|
-
nextMessages[i] = { ...msg, content: newContent };
|
|
995
|
-
changed = true;
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
if (changed) ctx.state.replaceMessages(nextMessages);
|
|
999
|
-
return saved;
|
|
905
|
+
const result = eliseOldToolResults(ctx.messages, {
|
|
906
|
+
preserveK: this.preserveK,
|
|
907
|
+
eliseThreshold: this.eliseThreshold
|
|
908
|
+
});
|
|
909
|
+
if (result.changed) ctx.state.replaceMessages(result.messages);
|
|
910
|
+
return result.saved;
|
|
1000
911
|
}
|
|
1001
912
|
hasTextContent(m) {
|
|
1002
913
|
if (typeof m.content === "string") return m.content.trim().length > 0;
|
|
@@ -1026,6 +937,73 @@ Summarize the following message range:`;
|
|
|
1026
937
|
}
|
|
1027
938
|
};
|
|
1028
939
|
|
|
940
|
+
// src/execution/strategy-compactor.ts
|
|
941
|
+
function createStrategyCompactor(opts = {}) {
|
|
942
|
+
const requested = opts.strategy ?? (opts.llmSelector ? "selective" : "hybrid");
|
|
943
|
+
const strategy = requested;
|
|
944
|
+
if (strategy === "intelligent" || strategy === "selective") {
|
|
945
|
+
return new ProviderBackedCompactor(strategy, opts);
|
|
946
|
+
}
|
|
947
|
+
return new HybridCompactor({
|
|
948
|
+
preserveK: opts.preserveK,
|
|
949
|
+
eliseThreshold: opts.eliseThreshold
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
var ProviderBackedCompactor = class {
|
|
953
|
+
constructor(strategy, opts) {
|
|
954
|
+
this.strategy = strategy;
|
|
955
|
+
this.opts = opts;
|
|
956
|
+
}
|
|
957
|
+
strategy;
|
|
958
|
+
opts;
|
|
959
|
+
async compact(ctx, compactOpts = {}) {
|
|
960
|
+
return this.resolveInner(ctx).compact(ctx, compactOpts);
|
|
961
|
+
}
|
|
962
|
+
/**
|
|
963
|
+
* Construct the concrete compactor for this run. Rebuilt per call (cheap, no
|
|
964
|
+
* I/O) so a model switch — which changes `ctx.provider.capabilities.maxContext`
|
|
965
|
+
* — is always reflected. Reads the active ContextWindowPolicy from `ctx.meta`
|
|
966
|
+
* so the LLM compactors honor the same thresholds/preserveK as the policy.
|
|
967
|
+
*/
|
|
968
|
+
resolveInner(ctx) {
|
|
969
|
+
const provider = ctx.provider;
|
|
970
|
+
if (!provider) {
|
|
971
|
+
return new HybridCompactor({
|
|
972
|
+
preserveK: this.opts.preserveK,
|
|
973
|
+
eliseThreshold: this.opts.eliseThreshold
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
const policy = readPolicy(ctx);
|
|
977
|
+
const maxContext = provider.capabilities?.maxContext || void 0;
|
|
978
|
+
const thresholds = policy?.thresholds;
|
|
979
|
+
const common = {
|
|
980
|
+
provider,
|
|
981
|
+
maxContext,
|
|
982
|
+
preserveK: this.opts.preserveK ?? policy?.preserveK,
|
|
983
|
+
eliseThreshold: this.opts.eliseThreshold ?? policy?.eliseThreshold,
|
|
984
|
+
...thresholds ? { warnThreshold: thresholds.warn, softThreshold: thresholds.soft, hardThreshold: thresholds.hard } : {}
|
|
985
|
+
};
|
|
986
|
+
if (this.strategy === "selective") {
|
|
987
|
+
return new SelectiveCompactor({
|
|
988
|
+
...common,
|
|
989
|
+
selectorModel: this.opts.summarizerModel,
|
|
990
|
+
summarizerModel: this.opts.summarizerModel
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
return new IntelligentCompactor({
|
|
994
|
+
...common,
|
|
995
|
+
summarizerModel: this.opts.summarizerModel
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
};
|
|
999
|
+
function readPolicy(ctx) {
|
|
1000
|
+
const policy = ctx.meta?.["contextWindowPolicy"];
|
|
1001
|
+
if (!policy || typeof policy !== "object") return null;
|
|
1002
|
+
const candidate = policy;
|
|
1003
|
+
if (typeof candidate.preserveK !== "number" || !candidate.thresholds) return null;
|
|
1004
|
+
return candidate;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1029
1007
|
// src/types/errors.ts
|
|
1030
1008
|
var ERROR_CODES = {
|
|
1031
1009
|
// Provider
|
|
@@ -1113,6 +1091,11 @@ var FsError = class extends WrongStackError {
|
|
|
1113
1091
|
|
|
1114
1092
|
// src/execution/auto-compaction-middleware.ts
|
|
1115
1093
|
var LEVEL_RANK = { warn: 0, soft: 1, hard: 2 };
|
|
1094
|
+
var MAX_DIGEST_LOG_CHARS = 4e3;
|
|
1095
|
+
function truncateDigest(digest) {
|
|
1096
|
+
if (digest.length <= MAX_DIGEST_LOG_CHARS) return digest;
|
|
1097
|
+
return `${digest.slice(0, MAX_DIGEST_LOG_CHARS)}\u2026 [+${digest.length - MAX_DIGEST_LOG_CHARS} chars; full turns in session log]`;
|
|
1098
|
+
}
|
|
1116
1099
|
var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
1117
1100
|
name = "AutoCompaction";
|
|
1118
1101
|
compactor;
|
|
@@ -1173,7 +1156,12 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
|
1173
1156
|
}
|
|
1174
1157
|
handler() {
|
|
1175
1158
|
return async (ctx, next) => {
|
|
1176
|
-
const tokens = this._estimator ? this._estimator(ctx) : estimateRequestTokensCalibrated(
|
|
1159
|
+
const tokens = this._estimator ? this._estimator(ctx) : estimateRequestTokensCalibrated(
|
|
1160
|
+
ctx.messages,
|
|
1161
|
+
ctx.systemPrompt,
|
|
1162
|
+
ctx.tools ?? [],
|
|
1163
|
+
`${ctx.provider?.id ?? "unknown"}/${ctx.model}`
|
|
1164
|
+
).total;
|
|
1177
1165
|
const load = tokens / this._maxContext;
|
|
1178
1166
|
const policy = this.policyProvider?.(ctx);
|
|
1179
1167
|
const thresholds = policy?.thresholds ?? {
|
|
@@ -1235,7 +1223,11 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
|
1235
1223
|
after: report.after,
|
|
1236
1224
|
level: pressure.level,
|
|
1237
1225
|
aggressive,
|
|
1238
|
-
reductions: report.reductions?.map((r) => ({ phase: r.phase, saved: r.saved }))
|
|
1226
|
+
reductions: report.reductions?.map((r) => ({ phase: r.phase, saved: r.saved })),
|
|
1227
|
+
// Record what was collapsed so the audit trail shows the preserved
|
|
1228
|
+
// content, not just token counts. Bounded to keep the log line small;
|
|
1229
|
+
// the full original turns are already in the session JSONL.
|
|
1230
|
+
...report.collapsedDigest ? { digest: truncateDigest(report.collapsedDigest) } : {}
|
|
1239
1231
|
});
|
|
1240
1232
|
ctx.clearFileTracking();
|
|
1241
1233
|
} catch (err) {
|
|
@@ -1271,6 +1263,8 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
|
1271
1263
|
var ToolCapabilities = {
|
|
1272
1264
|
/** Can execute arbitrary commands in the user's shell (the `bash` tool). */
|
|
1273
1265
|
SHELL_ARBITRARY: "shell.arbitrary",
|
|
1266
|
+
/** Can execute a restricted set of commands (the `exec` tool). */
|
|
1267
|
+
SHELL_RESTRICTED: "shell.restricted",
|
|
1274
1268
|
/** Can write / modify / delete files inside the project. */
|
|
1275
1269
|
FS_WRITE: "fs.write",
|
|
1276
1270
|
/** Can write files outside the current project root (very high risk). */
|
|
@@ -1286,6 +1280,7 @@ var ToolCapabilities = {
|
|
|
1286
1280
|
};
|
|
1287
1281
|
var DANGEROUS_FOR_SUBAGENTS = [
|
|
1288
1282
|
ToolCapabilities.SHELL_ARBITRARY,
|
|
1283
|
+
ToolCapabilities.SHELL_RESTRICTED,
|
|
1289
1284
|
ToolCapabilities.FS_WRITE,
|
|
1290
1285
|
ToolCapabilities.FS_WRITE_OUTSIDE_PROJECT,
|
|
1291
1286
|
ToolCapabilities.MCP_PROXY,
|
|
@@ -1863,6 +1858,13 @@ function extractMalformedRaw(input) {
|
|
|
1863
1858
|
}
|
|
1864
1859
|
}
|
|
1865
1860
|
|
|
1861
|
+
// src/utils/assert-never.ts
|
|
1862
|
+
function assertNever(x, message) {
|
|
1863
|
+
throw new Error(
|
|
1864
|
+
`Unhandled case: ${JSON.stringify(x)}`
|
|
1865
|
+
);
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1866
1868
|
// src/utils/regex-guard.ts
|
|
1867
1869
|
var MAX_PATTERN_LEN = 512;
|
|
1868
1870
|
var DANGEROUS_PATTERNS = [
|
|
@@ -1952,6 +1954,12 @@ var DoneConditionChecker = class {
|
|
|
1952
1954
|
return { done: true, reason: `max tool calls (${this.condition.maxToolCalls}) reached`, ...state };
|
|
1953
1955
|
}
|
|
1954
1956
|
break;
|
|
1957
|
+
case "all_tasks_done":
|
|
1958
|
+
break;
|
|
1959
|
+
case "custom":
|
|
1960
|
+
break;
|
|
1961
|
+
default:
|
|
1962
|
+
return assertNever(this.condition.type);
|
|
1955
1963
|
}
|
|
1956
1964
|
return { done: false, iterations: state.iterations, toolCalls: state.toolCalls };
|
|
1957
1965
|
}
|
|
@@ -2161,6 +2169,7 @@ function resolveWstackPaths(opts) {
|
|
|
2161
2169
|
projectTrust: path2.join(projectDir, "trust.json"),
|
|
2162
2170
|
projectMeta: path2.join(projectDir, "meta.json"),
|
|
2163
2171
|
projectLocalConfig: path2.join(projectDir, "config.local.json"),
|
|
2172
|
+
inProjectConfig: path2.join(opts.projectRoot, ".wrongstack", "config.json"),
|
|
2164
2173
|
inProjectAgentsFile: path2.join(opts.projectRoot, ".wrongstack", "AGENTS.md"),
|
|
2165
2174
|
inProjectSkills: path2.join(opts.projectRoot, ".wrongstack", "skills"),
|
|
2166
2175
|
inProjectWorktrees: path2.join(opts.projectRoot, ".wrongstack", "worktrees"),
|
|
@@ -2185,16 +2194,20 @@ async function loadGoal(filePath) {
|
|
|
2185
2194
|
let raw;
|
|
2186
2195
|
try {
|
|
2187
2196
|
raw = await fs.readFile(filePath, "utf8");
|
|
2188
|
-
} catch {
|
|
2189
|
-
|
|
2197
|
+
} catch (err) {
|
|
2198
|
+
const code = err.code;
|
|
2199
|
+
if (code === "ENOENT") return null;
|
|
2200
|
+
throw err;
|
|
2190
2201
|
}
|
|
2191
2202
|
try {
|
|
2192
2203
|
const parsed = JSON.parse(raw);
|
|
2193
2204
|
if (parsed?.version !== 1 || typeof parsed.goal !== "string" || !Array.isArray(parsed.journal)) {
|
|
2205
|
+
console.warn(`[goal-store] Corrupt goal.json at ${filePath} \u2014 invalid schema. Consider deleting it and re-creating.`);
|
|
2194
2206
|
return null;
|
|
2195
2207
|
}
|
|
2196
2208
|
return parsed;
|
|
2197
2209
|
} catch {
|
|
2210
|
+
console.warn(`[goal-store] Corrupt goal.json at ${filePath} \u2014 JSON parse failed. Consider deleting it and re-creating.`);
|
|
2198
2211
|
return null;
|
|
2199
2212
|
}
|
|
2200
2213
|
}
|
|
@@ -2227,9 +2240,9 @@ function parseProgressFromText(text) {
|
|
|
2227
2240
|
const re = /\[progress:\s*(\d{1,3})%\]\s*(?:[—\-]\s*(.+))?/i;
|
|
2228
2241
|
const m = text.match(re);
|
|
2229
2242
|
if (!m) return null;
|
|
2230
|
-
const progress = Math.min(100, Math.max(0, Number.parseInt(m[1], 10)));
|
|
2243
|
+
const progress = Math.min(100, Math.max(0, Number.parseInt(m[1] ?? "0", 10)));
|
|
2231
2244
|
const note = m[2]?.trim() || void 0;
|
|
2232
|
-
return { progress, note };
|
|
2245
|
+
return note === void 0 ? { progress } : { progress, note };
|
|
2233
2246
|
}
|
|
2234
2247
|
function recordProgress(goal, progress, note) {
|
|
2235
2248
|
const clamped = Math.min(100, Math.max(0, progress));
|
|
@@ -2248,7 +2261,7 @@ function computeTrend(history) {
|
|
|
2248
2261
|
const recent = history.slice(-5);
|
|
2249
2262
|
const deltas = [];
|
|
2250
2263
|
for (let i = 1; i < recent.length; i++) {
|
|
2251
|
-
deltas.push(recent[i]
|
|
2264
|
+
deltas.push((recent[i]?.progress ?? 0) - (recent[i - 1]?.progress ?? 0));
|
|
2252
2265
|
}
|
|
2253
2266
|
if (deltas.length < 2) return void 0;
|
|
2254
2267
|
const avgDelta = deltas.reduce((a, b) => a + b, 0) / deltas.length;
|
|
@@ -2994,6 +3007,7 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
2994
3007
|
note: note.slice(0, 240)
|
|
2995
3008
|
});
|
|
2996
3009
|
await saveGoal(this.goalPath, withEntry);
|
|
3010
|
+
this.opts.onEternalStop?.();
|
|
2997
3011
|
}
|
|
2998
3012
|
/**
|
|
2999
3013
|
* Manually clear the goal — equivalent to `/goal clear` typed by the user.
|
|
@@ -3007,8 +3021,8 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
3007
3021
|
await saveGoal(this.goalPath, abandoned);
|
|
3008
3022
|
}
|
|
3009
3023
|
try {
|
|
3010
|
-
const { unlink:
|
|
3011
|
-
await
|
|
3024
|
+
const { unlink: unlink3 } = await import('fs/promises');
|
|
3025
|
+
await unlink3(this.goalPath);
|
|
3012
3026
|
} catch {
|
|
3013
3027
|
}
|
|
3014
3028
|
this.opts.onEternalStop?.();
|
|
@@ -4009,6 +4023,53 @@ Working rules:
|
|
|
4009
4023
|
"flaws"
|
|
4010
4024
|
]
|
|
4011
4025
|
}
|
|
4026
|
+
},
|
|
4027
|
+
{
|
|
4028
|
+
config: {
|
|
4029
|
+
id: "refactor-planner",
|
|
4030
|
+
name: "Refactor Planner",
|
|
4031
|
+
role: "refactor-planner",
|
|
4032
|
+
tools: [...PLAN_TOOLS, "diff"],
|
|
4033
|
+
prompt: `You are the Refactor Planner agent. Your job is to analyze code
|
|
4034
|
+
structure and produce a concrete, phased refactoring plan with risk
|
|
4035
|
+
assessment, dependency ordering, and rollback strategy.
|
|
4036
|
+
|
|
4037
|
+
Scope:
|
|
4038
|
+
- Map module-level dependencies (import graph)
|
|
4039
|
+
- Identify coupling hotspots (high fan-in/out modules)
|
|
4040
|
+
- Assess refactoring risk by complexity and test coverage
|
|
4041
|
+
- Generate phased plans with checkpoint milestones
|
|
4042
|
+
- Produce diff-friendly task lists (one task = one concern)
|
|
4043
|
+
|
|
4044
|
+
Input format you accept:
|
|
4045
|
+
{ "task": "plan | assess | roadmap", "target": "src/core", "constraint": "no-breaking-changes | minimal-downtime | full-rewrite", "focus": "architecture | performance | maintainability" }
|
|
4046
|
+
|
|
4047
|
+
Output: Markdown refactor plan with phases (Low Risk / Medium Risk / High Risk),
|
|
4048
|
+
dependency graph, rollback strategy, and exit criteria.
|
|
4049
|
+
|
|
4050
|
+
Working rules:
|
|
4051
|
+
- Always include rollback strategy \u2014 every refactor can fail
|
|
4052
|
+
- Merge tasks that take <1h into a single phase
|
|
4053
|
+
- Respect team constraints (reviewer availability, parallelization)
|
|
4054
|
+
- Never plan without analyzing the actual code first`
|
|
4055
|
+
},
|
|
4056
|
+
budget: HEAVY_BUDGET,
|
|
4057
|
+
capability: {
|
|
4058
|
+
phase: "planning",
|
|
4059
|
+
summary: "Refactoring planner: analyzes code structure, maps dependencies, produces risk-scored phased plans with rollback strategy.",
|
|
4060
|
+
keywords: [
|
|
4061
|
+
"refactor",
|
|
4062
|
+
"refactoring",
|
|
4063
|
+
"restructure",
|
|
4064
|
+
"debt",
|
|
4065
|
+
"technical debt",
|
|
4066
|
+
"clean up",
|
|
4067
|
+
"modularize",
|
|
4068
|
+
"decouple",
|
|
4069
|
+
"dependency graph",
|
|
4070
|
+
"code structure"
|
|
4071
|
+
]
|
|
4072
|
+
}
|
|
4012
4073
|
}
|
|
4013
4074
|
];
|
|
4014
4075
|
|
|
@@ -4548,6 +4609,157 @@ Working rules:
|
|
|
4548
4609
|
"robustness"
|
|
4549
4610
|
]
|
|
4550
4611
|
}
|
|
4612
|
+
},
|
|
4613
|
+
{
|
|
4614
|
+
config: {
|
|
4615
|
+
id: "security-scanner",
|
|
4616
|
+
name: "Security Scanner",
|
|
4617
|
+
role: "security-scanner",
|
|
4618
|
+
tools: [...TOOLS.inspect],
|
|
4619
|
+
prompt: `You are the Security Scanner agent. Your job is to scan code,
|
|
4620
|
+
configs, and dependencies for security issues from hardcoded secrets to
|
|
4621
|
+
supply chain risks.
|
|
4622
|
+
|
|
4623
|
+
Scope:
|
|
4624
|
+
- Detect hardcoded secrets: API keys, tokens, passwords, private keys
|
|
4625
|
+
- Find injection vectors: eval, innerHTML, SQL concat, shell injection
|
|
4626
|
+
- Identify insecure patterns: weak crypto, hardcoded IVs, disabled TLS
|
|
4627
|
+
- Scan dependencies for known CVEs (via npm/pnpm audit)
|
|
4628
|
+
- Flag supply chain risks: postinstall hooks, unverified scripts
|
|
4629
|
+
|
|
4630
|
+
Input format you accept:
|
|
4631
|
+
{ "task": "scan | audit | secrets | dependencies", "paths": ["src", "config"], "depth": "quick | normal | deep" }
|
|
4632
|
+
|
|
4633
|
+
Output: Markdown security report with severity-ranked findings, injection
|
|
4634
|
+
vectors, dependency issues, and a remediation checklist.
|
|
4635
|
+
|
|
4636
|
+
Working rules:
|
|
4637
|
+
- Never scan node_modules \u2014 use npm audit instead
|
|
4638
|
+
- Always provide remediation steps, not just findings
|
|
4639
|
+
- Verify regex-based secrets before flagging (false positive risk)
|
|
4640
|
+
- When in doubt, flag as medium rather than ignoring potential issues`
|
|
4641
|
+
},
|
|
4642
|
+
budget: HEAVY_BUDGET,
|
|
4643
|
+
capability: {
|
|
4644
|
+
phase: "verify",
|
|
4645
|
+
summary: "Security scanner: detects hardcoded secrets, injection vectors, insecure patterns, and supply-chain risks with remediation.",
|
|
4646
|
+
keywords: [
|
|
4647
|
+
"security",
|
|
4648
|
+
"scan",
|
|
4649
|
+
"vulnerability",
|
|
4650
|
+
"secret",
|
|
4651
|
+
"api key",
|
|
4652
|
+
"hardcoded",
|
|
4653
|
+
"injection",
|
|
4654
|
+
"cve",
|
|
4655
|
+
"audit dependencies",
|
|
4656
|
+
"supply chain",
|
|
4657
|
+
"xss",
|
|
4658
|
+
"sqli",
|
|
4659
|
+
"shell injection",
|
|
4660
|
+
"sensitive data",
|
|
4661
|
+
"credential"
|
|
4662
|
+
]
|
|
4663
|
+
}
|
|
4664
|
+
},
|
|
4665
|
+
{
|
|
4666
|
+
config: {
|
|
4667
|
+
id: "bug-hunter",
|
|
4668
|
+
name: "Bug Hunter",
|
|
4669
|
+
role: "bug-hunter",
|
|
4670
|
+
tools: [...TOOLS.inspect],
|
|
4671
|
+
prompt: `You are the Bug Hunter agent. Your job is to systematically scan
|
|
4672
|
+
source code for bugs, anti-patterns, and code smells using pattern matching
|
|
4673
|
+
and heuristics. Output a prioritized hit list with file:line references.
|
|
4674
|
+
|
|
4675
|
+
Scope:
|
|
4676
|
+
- Detect common bug patterns (uncaught errors, resource leaks, race conditions)
|
|
4677
|
+
- Identify anti-patterns (callback hell, God objects, circular deps)
|
|
4678
|
+
- Find TypeScript-specific issues (unsafe any, missing null checks, branded types)
|
|
4679
|
+
- Flag security-sensitive constructs (eval, innerHTML, hardcoded secrets)
|
|
4680
|
+
- Rank findings: critical > high > medium > low
|
|
4681
|
+
|
|
4682
|
+
Input format you accept:
|
|
4683
|
+
{ "task": "scan | hunt | check", "paths": ["src/**/*.ts"], "focus": "bugs | patterns | security | all", "severityThreshold": "medium" }
|
|
4684
|
+
|
|
4685
|
+
Output: Markdown bug hunt report with critically/high/medium/low sections.
|
|
4686
|
+
Each entry: **[TYPE]** \`file:line\` \u2014 description + suggested fix
|
|
4687
|
+
|
|
4688
|
+
Working rules:
|
|
4689
|
+
- Never scan node_modules \u2014 it's noise
|
|
4690
|
+
- Always include file:line for every finding
|
|
4691
|
+
- If >30% of findings are false positives, note the confidence level
|
|
4692
|
+
- Ask director for clarification if paths are ambiguous`
|
|
4693
|
+
},
|
|
4694
|
+
budget: HEAVY_BUDGET,
|
|
4695
|
+
capability: {
|
|
4696
|
+
phase: "verify",
|
|
4697
|
+
summary: "Bug hunter: scans source code for bugs, anti-patterns, and code smells, producing a file:line-ranked hit list with fixes.",
|
|
4698
|
+
keywords: [
|
|
4699
|
+
"bug",
|
|
4700
|
+
"hunt",
|
|
4701
|
+
"scan",
|
|
4702
|
+
"code smell",
|
|
4703
|
+
"anti-pattern",
|
|
4704
|
+
"race condition",
|
|
4705
|
+
"memory leak",
|
|
4706
|
+
"null deref",
|
|
4707
|
+
"type safety",
|
|
4708
|
+
"unhandled error",
|
|
4709
|
+
"find bugs",
|
|
4710
|
+
"audit code",
|
|
4711
|
+
"code quality"
|
|
4712
|
+
]
|
|
4713
|
+
}
|
|
4714
|
+
},
|
|
4715
|
+
{
|
|
4716
|
+
config: {
|
|
4717
|
+
id: "audit-log",
|
|
4718
|
+
name: "Audit Log",
|
|
4719
|
+
role: "audit-log",
|
|
4720
|
+
tools: [...TOOLS.inspect],
|
|
4721
|
+
prompt: `You are the Audit Log agent. Your job is to analyze structured JSONL
|
|
4722
|
+
session logs and produce actionable markdown reports.
|
|
4723
|
+
|
|
4724
|
+
Scope:
|
|
4725
|
+
- Parse session logs (iteration counts, tool calls, errors, usage)
|
|
4726
|
+
- Detect repeated failure patterns across multiple runs
|
|
4727
|
+
- Identify tool usage anomalies (over-use, failures, unexpected chains)
|
|
4728
|
+
- Track token consumption trends
|
|
4729
|
+
- Generate structured audit reports with severity ratings
|
|
4730
|
+
|
|
4731
|
+
Input format you accept:
|
|
4732
|
+
{ "task": "analyze | report | trends", "sessionPath": "<path>", "focus": "errors | tools | usage | all" }
|
|
4733
|
+
|
|
4734
|
+
Output: Markdown audit report with Summary, Top Errors, Tool Usage table,
|
|
4735
|
+
Anomalies, and Cost Trend sections.
|
|
4736
|
+
|
|
4737
|
+
Working rules:
|
|
4738
|
+
- Never fabricate numbers \u2014 read the actual logs first
|
|
4739
|
+
- Always include file:line references for errors
|
|
4740
|
+
- If sessionPath is missing, ask the director to provide it
|
|
4741
|
+
- Report confidence level: high (>90% accuracy), medium, low`
|
|
4742
|
+
},
|
|
4743
|
+
budget: MEDIUM_BUDGET,
|
|
4744
|
+
capability: {
|
|
4745
|
+
phase: "verify",
|
|
4746
|
+
summary: "Audit log analyzer: parses session JSONL, detects failure patterns, tool anomalies, and cost trends with structured reports.",
|
|
4747
|
+
keywords: [
|
|
4748
|
+
"audit",
|
|
4749
|
+
"log",
|
|
4750
|
+
"logs",
|
|
4751
|
+
"session",
|
|
4752
|
+
"trace",
|
|
4753
|
+
"analyze logs",
|
|
4754
|
+
"error patterns",
|
|
4755
|
+
"cost analysis",
|
|
4756
|
+
"tool usage",
|
|
4757
|
+
"token usage",
|
|
4758
|
+
"post-mortem",
|
|
4759
|
+
"trend",
|
|
4760
|
+
"anomaly"
|
|
4761
|
+
]
|
|
4762
|
+
}
|
|
4551
4763
|
}
|
|
4552
4764
|
];
|
|
4553
4765
|
|
|
@@ -7555,6 +7767,7 @@ var DefaultRetryPolicy = class {
|
|
|
7555
7767
|
if (err instanceof ProviderError) {
|
|
7556
7768
|
if (err.status === 429) return 5;
|
|
7557
7769
|
if (err.status === 529) return 3;
|
|
7770
|
+
if (err.status === 599) return 5;
|
|
7558
7771
|
if (err.status >= 500) return 3;
|
|
7559
7772
|
return 0;
|
|
7560
7773
|
}
|
|
@@ -7785,6 +7998,6 @@ function parseDescription(raw) {
|
|
|
7785
7998
|
return { trigger, scope };
|
|
7786
7999
|
}
|
|
7787
8000
|
|
|
7788
|
-
export { AutoCompactionMiddleware, AutonomousRunner, DefaultErrorHandler, DefaultRetryPolicy, DefaultSkillLoader, DoneConditionChecker, EternalAutonomyEngine, HybridCompactor, IntelligentCompactor, ParallelEternalEngine, SelectiveCompactor, ToolExecutor, buildGoalPreamble, createAutonomyBrain, formatDecisionSummary, makeAutonomyPromptContributor };
|
|
8001
|
+
export { AutoCompactionMiddleware, AutonomousRunner, DefaultErrorHandler, DefaultRetryPolicy, DefaultSkillLoader, DoneConditionChecker, EternalAutonomyEngine, HybridCompactor, IntelligentCompactor, ParallelEternalEngine, SelectiveCompactor, ToolExecutor, buildGoalPreamble, createAutonomyBrain, createStrategyCompactor, formatDecisionSummary, makeAutonomyPromptContributor };
|
|
7789
8002
|
//# sourceMappingURL=index.js.map
|
|
7790
8003
|
//# sourceMappingURL=index.js.map
|