llmist 1.2.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -75
- package/dist/{chunk-KORMY3CD.js → chunk-RZTAKIDE.js} +605 -4
- package/dist/chunk-RZTAKIDE.js.map +1 -0
- package/dist/{chunk-LELPPETT.js → chunk-TFIKR2RK.js} +459 -3
- package/dist/chunk-TFIKR2RK.js.map +1 -0
- package/dist/cli.cjs +628 -23
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +49 -22
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +769 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +354 -32
- package/dist/index.d.ts +354 -32
- package/dist/index.js +177 -2
- package/dist/index.js.map +1 -1
- package/dist/{mock-stream-DKF5yatf.d.cts → mock-stream-DNt-HBTn.d.cts} +525 -79
- package/dist/{mock-stream-DKF5yatf.d.ts → mock-stream-DNt-HBTn.d.ts} +525 -79
- package/dist/testing/index.cjs +1063 -4
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +437 -3
- package/dist/testing/index.d.ts +437 -3
- package/dist/testing/index.js +54 -4
- package/package.json +1 -1
- package/dist/chunk-KORMY3CD.js.map +0 -1
- package/dist/chunk-LELPPETT.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -375,10 +375,21 @@ function resolveRulesTemplate(rules, context) {
|
|
|
375
375
|
}
|
|
376
376
|
return [resolved];
|
|
377
377
|
}
|
|
378
|
-
|
|
378
|
+
function resolveHintTemplate(template, defaultValue, context) {
|
|
379
|
+
const resolved = template ?? defaultValue;
|
|
380
|
+
if (typeof resolved === "function") {
|
|
381
|
+
return resolved(context);
|
|
382
|
+
}
|
|
383
|
+
return resolved.replace(/\{iteration\}/g, String(context.iteration)).replace(/\{maxIterations\}/g, String(context.maxIterations)).replace(/\{remaining\}/g, String(context.remaining));
|
|
384
|
+
}
|
|
385
|
+
var DEFAULT_HINTS, DEFAULT_PROMPTS;
|
|
379
386
|
var init_prompt_config = __esm({
|
|
380
387
|
"src/core/prompt-config.ts"() {
|
|
381
388
|
"use strict";
|
|
389
|
+
DEFAULT_HINTS = {
|
|
390
|
+
parallelGadgetsHint: "Tip: You can call multiple gadgets in a single response for efficiency.",
|
|
391
|
+
iterationProgressHint: "[Iteration {iteration}/{maxIterations}] Plan your actions accordingly."
|
|
392
|
+
};
|
|
382
393
|
DEFAULT_PROMPTS = {
|
|
383
394
|
mainInstruction: [
|
|
384
395
|
"\u26A0\uFE0F CRITICAL: RESPOND ONLY WITH GADGET INVOCATIONS",
|
|
@@ -1129,6 +1140,417 @@ var init_output_viewer = __esm({
|
|
|
1129
1140
|
}
|
|
1130
1141
|
});
|
|
1131
1142
|
|
|
1143
|
+
// src/agent/compaction/config.ts
|
|
1144
|
+
function resolveCompactionConfig(config = {}) {
|
|
1145
|
+
const trigger = config.triggerThresholdPercent ?? DEFAULT_COMPACTION_CONFIG.triggerThresholdPercent;
|
|
1146
|
+
const target = config.targetPercent ?? DEFAULT_COMPACTION_CONFIG.targetPercent;
|
|
1147
|
+
if (target >= trigger) {
|
|
1148
|
+
console.warn(
|
|
1149
|
+
`[llmist/compaction] targetPercent (${target}) should be less than triggerThresholdPercent (${trigger}) to be effective.`
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
1152
|
+
const strategy = config.strategy ?? DEFAULT_COMPACTION_CONFIG.strategy;
|
|
1153
|
+
const strategyName = typeof strategy === "object" && "name" in strategy ? strategy.name : strategy;
|
|
1154
|
+
return {
|
|
1155
|
+
enabled: config.enabled ?? DEFAULT_COMPACTION_CONFIG.enabled,
|
|
1156
|
+
strategy: strategyName,
|
|
1157
|
+
triggerThresholdPercent: trigger,
|
|
1158
|
+
targetPercent: target,
|
|
1159
|
+
preserveRecentTurns: config.preserveRecentTurns ?? DEFAULT_COMPACTION_CONFIG.preserveRecentTurns,
|
|
1160
|
+
summarizationModel: config.summarizationModel,
|
|
1161
|
+
summarizationPrompt: config.summarizationPrompt ?? DEFAULT_SUMMARIZATION_PROMPT,
|
|
1162
|
+
onCompaction: config.onCompaction
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
var DEFAULT_COMPACTION_CONFIG, DEFAULT_SUMMARIZATION_PROMPT;
|
|
1166
|
+
var init_config = __esm({
|
|
1167
|
+
"src/agent/compaction/config.ts"() {
|
|
1168
|
+
"use strict";
|
|
1169
|
+
DEFAULT_COMPACTION_CONFIG = {
|
|
1170
|
+
enabled: true,
|
|
1171
|
+
strategy: "hybrid",
|
|
1172
|
+
triggerThresholdPercent: 80,
|
|
1173
|
+
targetPercent: 50,
|
|
1174
|
+
preserveRecentTurns: 5
|
|
1175
|
+
};
|
|
1176
|
+
DEFAULT_SUMMARIZATION_PROMPT = `Summarize this conversation history concisely, preserving:
|
|
1177
|
+
1. Key decisions made and their rationale
|
|
1178
|
+
2. Important facts and data discovered
|
|
1179
|
+
3. Errors encountered and how they were resolved
|
|
1180
|
+
4. Current task context and goals
|
|
1181
|
+
|
|
1182
|
+
Format as a brief narrative paragraph, not bullet points.
|
|
1183
|
+
Previous conversation:`;
|
|
1184
|
+
}
|
|
1185
|
+
});
|
|
1186
|
+
|
|
1187
|
+
// src/agent/compaction/strategy.ts
|
|
1188
|
+
function groupIntoTurns(messages) {
|
|
1189
|
+
const turns = [];
|
|
1190
|
+
let currentTurn = [];
|
|
1191
|
+
for (const msg of messages) {
|
|
1192
|
+
if (msg.role === "user" && currentTurn.length > 0) {
|
|
1193
|
+
turns.push({
|
|
1194
|
+
messages: currentTurn,
|
|
1195
|
+
tokenEstimate: estimateTurnTokens(currentTurn)
|
|
1196
|
+
});
|
|
1197
|
+
currentTurn = [msg];
|
|
1198
|
+
} else {
|
|
1199
|
+
currentTurn.push(msg);
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
if (currentTurn.length > 0) {
|
|
1203
|
+
turns.push({
|
|
1204
|
+
messages: currentTurn,
|
|
1205
|
+
tokenEstimate: estimateTurnTokens(currentTurn)
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1208
|
+
return turns;
|
|
1209
|
+
}
|
|
1210
|
+
function estimateTurnTokens(messages) {
|
|
1211
|
+
return Math.ceil(messages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4);
|
|
1212
|
+
}
|
|
1213
|
+
function flattenTurns(turns) {
|
|
1214
|
+
return turns.flatMap((turn) => turn.messages);
|
|
1215
|
+
}
|
|
1216
|
+
var init_strategy = __esm({
|
|
1217
|
+
"src/agent/compaction/strategy.ts"() {
|
|
1218
|
+
"use strict";
|
|
1219
|
+
}
|
|
1220
|
+
});
|
|
1221
|
+
|
|
1222
|
+
// src/agent/compaction/strategies/sliding-window.ts
|
|
1223
|
+
var TRUNCATION_MARKER_TEMPLATE, SlidingWindowStrategy;
|
|
1224
|
+
var init_sliding_window = __esm({
|
|
1225
|
+
"src/agent/compaction/strategies/sliding-window.ts"() {
|
|
1226
|
+
"use strict";
|
|
1227
|
+
init_strategy();
|
|
1228
|
+
TRUNCATION_MARKER_TEMPLATE = "[Previous conversation truncated. Removed {count} turn(s) to fit context window.]";
|
|
1229
|
+
SlidingWindowStrategy = class {
|
|
1230
|
+
name = "sliding-window";
|
|
1231
|
+
async compact(messages, config, context) {
|
|
1232
|
+
const turns = groupIntoTurns(messages);
|
|
1233
|
+
const preserveCount = Math.min(config.preserveRecentTurns, turns.length);
|
|
1234
|
+
if (turns.length <= preserveCount) {
|
|
1235
|
+
return {
|
|
1236
|
+
messages,
|
|
1237
|
+
strategyName: this.name,
|
|
1238
|
+
metadata: {
|
|
1239
|
+
originalCount: messages.length,
|
|
1240
|
+
compactedCount: messages.length,
|
|
1241
|
+
tokensBefore: context.currentTokens,
|
|
1242
|
+
tokensAfter: context.currentTokens
|
|
1243
|
+
}
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
const turnsToKeep = turns.slice(-preserveCount);
|
|
1247
|
+
const turnsRemoved = turns.length - preserveCount;
|
|
1248
|
+
const truncationMarker = {
|
|
1249
|
+
role: "user",
|
|
1250
|
+
content: TRUNCATION_MARKER_TEMPLATE.replace("{count}", turnsRemoved.toString())
|
|
1251
|
+
};
|
|
1252
|
+
const compactedMessages = [truncationMarker, ...flattenTurns(turnsToKeep)];
|
|
1253
|
+
const tokensAfter = Math.ceil(
|
|
1254
|
+
compactedMessages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4
|
|
1255
|
+
);
|
|
1256
|
+
return {
|
|
1257
|
+
messages: compactedMessages,
|
|
1258
|
+
strategyName: this.name,
|
|
1259
|
+
metadata: {
|
|
1260
|
+
originalCount: messages.length,
|
|
1261
|
+
compactedCount: compactedMessages.length,
|
|
1262
|
+
tokensBefore: context.currentTokens,
|
|
1263
|
+
tokensAfter
|
|
1264
|
+
}
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
};
|
|
1268
|
+
}
|
|
1269
|
+
});
|
|
1270
|
+
|
|
1271
|
+
// src/agent/compaction/strategies/summarization.ts
|
|
1272
|
+
var SummarizationStrategy;
|
|
1273
|
+
var init_summarization = __esm({
|
|
1274
|
+
"src/agent/compaction/strategies/summarization.ts"() {
|
|
1275
|
+
"use strict";
|
|
1276
|
+
init_strategy();
|
|
1277
|
+
SummarizationStrategy = class {
|
|
1278
|
+
name = "summarization";
|
|
1279
|
+
async compact(messages, config, context) {
|
|
1280
|
+
const turns = groupIntoTurns(messages);
|
|
1281
|
+
const preserveCount = Math.min(config.preserveRecentTurns, turns.length);
|
|
1282
|
+
if (turns.length <= preserveCount) {
|
|
1283
|
+
return {
|
|
1284
|
+
messages,
|
|
1285
|
+
strategyName: this.name,
|
|
1286
|
+
metadata: {
|
|
1287
|
+
originalCount: messages.length,
|
|
1288
|
+
compactedCount: messages.length,
|
|
1289
|
+
tokensBefore: context.currentTokens,
|
|
1290
|
+
tokensAfter: context.currentTokens
|
|
1291
|
+
}
|
|
1292
|
+
};
|
|
1293
|
+
}
|
|
1294
|
+
const turnsToSummarize = turns.slice(0, -preserveCount);
|
|
1295
|
+
const turnsToKeep = turns.slice(-preserveCount);
|
|
1296
|
+
const conversationToSummarize = this.formatTurnsForSummary(flattenTurns(turnsToSummarize));
|
|
1297
|
+
const summary = await this.generateSummary(conversationToSummarize, config, context);
|
|
1298
|
+
const summaryMessage = {
|
|
1299
|
+
role: "user",
|
|
1300
|
+
content: `[Previous conversation summary]
|
|
1301
|
+
${summary}
|
|
1302
|
+
[End of summary - conversation continues below]`
|
|
1303
|
+
};
|
|
1304
|
+
const compactedMessages = [summaryMessage, ...flattenTurns(turnsToKeep)];
|
|
1305
|
+
const tokensAfter = Math.ceil(
|
|
1306
|
+
compactedMessages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4
|
|
1307
|
+
);
|
|
1308
|
+
return {
|
|
1309
|
+
messages: compactedMessages,
|
|
1310
|
+
summary,
|
|
1311
|
+
strategyName: this.name,
|
|
1312
|
+
metadata: {
|
|
1313
|
+
originalCount: messages.length,
|
|
1314
|
+
compactedCount: compactedMessages.length,
|
|
1315
|
+
tokensBefore: context.currentTokens,
|
|
1316
|
+
tokensAfter
|
|
1317
|
+
}
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
/**
|
|
1321
|
+
* Formats messages into a readable conversation format for summarization.
|
|
1322
|
+
*/
|
|
1323
|
+
formatTurnsForSummary(messages) {
|
|
1324
|
+
return messages.map((msg) => {
|
|
1325
|
+
const role = msg.role.charAt(0).toUpperCase() + msg.role.slice(1);
|
|
1326
|
+
return `${role}: ${msg.content}`;
|
|
1327
|
+
}).join("\n\n");
|
|
1328
|
+
}
|
|
1329
|
+
/**
|
|
1330
|
+
* Generates a summary using the configured LLM.
|
|
1331
|
+
*/
|
|
1332
|
+
async generateSummary(conversation, config, context) {
|
|
1333
|
+
const model = config.summarizationModel ?? context.model;
|
|
1334
|
+
const prompt = `${config.summarizationPrompt}
|
|
1335
|
+
|
|
1336
|
+
${conversation}`;
|
|
1337
|
+
const response = await context.client.complete(prompt, {
|
|
1338
|
+
model,
|
|
1339
|
+
temperature: 0.3
|
|
1340
|
+
// Low temperature for factual summarization
|
|
1341
|
+
});
|
|
1342
|
+
return response.trim();
|
|
1343
|
+
}
|
|
1344
|
+
};
|
|
1345
|
+
}
|
|
1346
|
+
});
|
|
1347
|
+
|
|
1348
|
+
// src/agent/compaction/strategies/hybrid.ts
|
|
1349
|
+
var MIN_TURNS_FOR_SUMMARIZATION, HybridStrategy;
|
|
1350
|
+
var init_hybrid = __esm({
|
|
1351
|
+
"src/agent/compaction/strategies/hybrid.ts"() {
|
|
1352
|
+
"use strict";
|
|
1353
|
+
init_strategy();
|
|
1354
|
+
init_sliding_window();
|
|
1355
|
+
init_summarization();
|
|
1356
|
+
MIN_TURNS_FOR_SUMMARIZATION = 3;
|
|
1357
|
+
HybridStrategy = class {
|
|
1358
|
+
name = "hybrid";
|
|
1359
|
+
slidingWindow = new SlidingWindowStrategy();
|
|
1360
|
+
summarization = new SummarizationStrategy();
|
|
1361
|
+
async compact(messages, config, context) {
|
|
1362
|
+
const turns = groupIntoTurns(messages);
|
|
1363
|
+
const preserveCount = Math.min(config.preserveRecentTurns, turns.length);
|
|
1364
|
+
if (turns.length <= preserveCount) {
|
|
1365
|
+
return {
|
|
1366
|
+
messages,
|
|
1367
|
+
strategyName: this.name,
|
|
1368
|
+
metadata: {
|
|
1369
|
+
originalCount: messages.length,
|
|
1370
|
+
compactedCount: messages.length,
|
|
1371
|
+
tokensBefore: context.currentTokens,
|
|
1372
|
+
tokensAfter: context.currentTokens
|
|
1373
|
+
}
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
const turnsToSummarize = turns.length - preserveCount;
|
|
1377
|
+
if (turnsToSummarize < MIN_TURNS_FOR_SUMMARIZATION) {
|
|
1378
|
+
return this.slidingWindow.compact(messages, config, context);
|
|
1379
|
+
}
|
|
1380
|
+
return this.summarization.compact(messages, config, context);
|
|
1381
|
+
}
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
});
|
|
1385
|
+
|
|
1386
|
+
// src/agent/compaction/strategies/index.ts
|
|
1387
|
+
var init_strategies = __esm({
|
|
1388
|
+
"src/agent/compaction/strategies/index.ts"() {
|
|
1389
|
+
"use strict";
|
|
1390
|
+
init_sliding_window();
|
|
1391
|
+
init_summarization();
|
|
1392
|
+
init_hybrid();
|
|
1393
|
+
}
|
|
1394
|
+
});
|
|
1395
|
+
|
|
1396
|
+
// src/agent/compaction/manager.ts
|
|
1397
|
+
function createStrategy(name) {
|
|
1398
|
+
switch (name) {
|
|
1399
|
+
case "sliding-window":
|
|
1400
|
+
return new SlidingWindowStrategy();
|
|
1401
|
+
case "summarization":
|
|
1402
|
+
return new SummarizationStrategy();
|
|
1403
|
+
case "hybrid":
|
|
1404
|
+
return new HybridStrategy();
|
|
1405
|
+
default:
|
|
1406
|
+
throw new Error(`Unknown compaction strategy: ${name}`);
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
var CompactionManager;
|
|
1410
|
+
var init_manager = __esm({
|
|
1411
|
+
"src/agent/compaction/manager.ts"() {
|
|
1412
|
+
"use strict";
|
|
1413
|
+
init_config();
|
|
1414
|
+
init_strategies();
|
|
1415
|
+
CompactionManager = class {
|
|
1416
|
+
client;
|
|
1417
|
+
model;
|
|
1418
|
+
config;
|
|
1419
|
+
strategy;
|
|
1420
|
+
modelLimits;
|
|
1421
|
+
// Statistics
|
|
1422
|
+
totalCompactions = 0;
|
|
1423
|
+
totalTokensSaved = 0;
|
|
1424
|
+
lastTokenCount = 0;
|
|
1425
|
+
constructor(client, model, config = {}) {
|
|
1426
|
+
this.client = client;
|
|
1427
|
+
this.model = model;
|
|
1428
|
+
this.config = resolveCompactionConfig(config);
|
|
1429
|
+
if (typeof config.strategy === "object" && "compact" in config.strategy) {
|
|
1430
|
+
this.strategy = config.strategy;
|
|
1431
|
+
} else {
|
|
1432
|
+
this.strategy = createStrategy(this.config.strategy);
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
/**
|
|
1436
|
+
* Check if compaction is needed and perform it if so.
|
|
1437
|
+
*
|
|
1438
|
+
* @param conversation - The conversation manager to compact
|
|
1439
|
+
* @param iteration - Current agent iteration (for event metadata)
|
|
1440
|
+
* @returns CompactionEvent if compaction was performed, null otherwise
|
|
1441
|
+
*/
|
|
1442
|
+
async checkAndCompact(conversation, iteration) {
|
|
1443
|
+
if (!this.config.enabled) {
|
|
1444
|
+
return null;
|
|
1445
|
+
}
|
|
1446
|
+
if (!this.modelLimits) {
|
|
1447
|
+
this.modelLimits = this.client.modelRegistry.getModelLimits(this.model);
|
|
1448
|
+
if (!this.modelLimits) {
|
|
1449
|
+
return null;
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
if (!this.client.countTokens) {
|
|
1453
|
+
return null;
|
|
1454
|
+
}
|
|
1455
|
+
const messages = conversation.getMessages();
|
|
1456
|
+
const currentTokens = await this.client.countTokens(this.model, messages);
|
|
1457
|
+
this.lastTokenCount = currentTokens;
|
|
1458
|
+
const usagePercent = currentTokens / this.modelLimits.contextWindow * 100;
|
|
1459
|
+
if (usagePercent < this.config.triggerThresholdPercent) {
|
|
1460
|
+
return null;
|
|
1461
|
+
}
|
|
1462
|
+
const historyMessages = conversation.getHistoryMessages();
|
|
1463
|
+
const baseMessages = conversation.getBaseMessages();
|
|
1464
|
+
const historyTokens = await this.client.countTokens(this.model, historyMessages);
|
|
1465
|
+
const baseTokens = await this.client.countTokens(this.model, baseMessages);
|
|
1466
|
+
return this.compact(conversation, iteration, {
|
|
1467
|
+
historyMessages,
|
|
1468
|
+
baseMessages,
|
|
1469
|
+
historyTokens,
|
|
1470
|
+
baseTokens,
|
|
1471
|
+
currentTokens: historyTokens + baseTokens
|
|
1472
|
+
});
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* Force compaction regardless of threshold.
|
|
1476
|
+
*
|
|
1477
|
+
* @param conversation - The conversation manager to compact
|
|
1478
|
+
* @param iteration - Current agent iteration (for event metadata). Use -1 for manual compaction.
|
|
1479
|
+
* @param precomputed - Optional pre-computed token counts (passed from checkAndCompact for efficiency)
|
|
1480
|
+
* @returns CompactionEvent with compaction details
|
|
1481
|
+
*/
|
|
1482
|
+
async compact(conversation, iteration, precomputed) {
|
|
1483
|
+
if (!this.modelLimits) {
|
|
1484
|
+
this.modelLimits = this.client.modelRegistry.getModelLimits(this.model);
|
|
1485
|
+
if (!this.modelLimits) {
|
|
1486
|
+
return null;
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
const historyMessages = precomputed?.historyMessages ?? conversation.getHistoryMessages();
|
|
1490
|
+
const baseMessages = precomputed?.baseMessages ?? conversation.getBaseMessages();
|
|
1491
|
+
const historyTokens = precomputed?.historyTokens ?? await this.client.countTokens(this.model, historyMessages);
|
|
1492
|
+
const baseTokens = precomputed?.baseTokens ?? await this.client.countTokens(this.model, baseMessages);
|
|
1493
|
+
const currentTokens = precomputed?.currentTokens ?? historyTokens + baseTokens;
|
|
1494
|
+
const targetTotalTokens = Math.floor(
|
|
1495
|
+
this.modelLimits.contextWindow * this.config.targetPercent / 100
|
|
1496
|
+
);
|
|
1497
|
+
const targetHistoryTokens = Math.max(0, targetTotalTokens - baseTokens);
|
|
1498
|
+
const result = await this.strategy.compact(historyMessages, this.config, {
|
|
1499
|
+
currentTokens: historyTokens,
|
|
1500
|
+
targetTokens: targetHistoryTokens,
|
|
1501
|
+
modelLimits: this.modelLimits,
|
|
1502
|
+
client: this.client,
|
|
1503
|
+
model: this.config.summarizationModel ?? this.model
|
|
1504
|
+
});
|
|
1505
|
+
conversation.replaceHistory(result.messages);
|
|
1506
|
+
const afterTokens = await this.client.countTokens(this.model, conversation.getMessages());
|
|
1507
|
+
const tokensSaved = currentTokens - afterTokens;
|
|
1508
|
+
this.totalCompactions++;
|
|
1509
|
+
this.totalTokensSaved += tokensSaved;
|
|
1510
|
+
this.lastTokenCount = afterTokens;
|
|
1511
|
+
const event = {
|
|
1512
|
+
strategy: result.strategyName,
|
|
1513
|
+
tokensBefore: currentTokens,
|
|
1514
|
+
tokensAfter: afterTokens,
|
|
1515
|
+
messagesBefore: historyMessages.length + baseMessages.length,
|
|
1516
|
+
messagesAfter: result.messages.length + baseMessages.length,
|
|
1517
|
+
summary: result.summary,
|
|
1518
|
+
iteration
|
|
1519
|
+
};
|
|
1520
|
+
if (this.config.onCompaction) {
|
|
1521
|
+
try {
|
|
1522
|
+
this.config.onCompaction(event);
|
|
1523
|
+
} catch (err) {
|
|
1524
|
+
console.warn("[llmist/compaction] onCompaction callback error:", err);
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
return event;
|
|
1528
|
+
}
|
|
1529
|
+
/**
|
|
1530
|
+
* Get compaction statistics.
|
|
1531
|
+
*/
|
|
1532
|
+
getStats() {
|
|
1533
|
+
const contextWindow = this.modelLimits?.contextWindow ?? 0;
|
|
1534
|
+
return {
|
|
1535
|
+
totalCompactions: this.totalCompactions,
|
|
1536
|
+
totalTokensSaved: this.totalTokensSaved,
|
|
1537
|
+
currentUsage: {
|
|
1538
|
+
tokens: this.lastTokenCount,
|
|
1539
|
+
percent: contextWindow > 0 ? this.lastTokenCount / contextWindow * 100 : 0
|
|
1540
|
+
},
|
|
1541
|
+
contextWindow
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
/**
|
|
1545
|
+
* Check if compaction is enabled.
|
|
1546
|
+
*/
|
|
1547
|
+
isEnabled() {
|
|
1548
|
+
return this.config.enabled;
|
|
1549
|
+
}
|
|
1550
|
+
};
|
|
1551
|
+
}
|
|
1552
|
+
});
|
|
1553
|
+
|
|
1132
1554
|
// src/agent/gadget-output-store.ts
|
|
1133
1555
|
var import_node_crypto, GadgetOutputStore;
|
|
1134
1556
|
var init_gadget_output_store = __esm({
|
|
@@ -1231,10 +1653,16 @@ var init_conversation_manager = __esm({
|
|
|
1231
1653
|
baseMessages;
|
|
1232
1654
|
initialMessages;
|
|
1233
1655
|
historyBuilder;
|
|
1656
|
+
startPrefix;
|
|
1657
|
+
endPrefix;
|
|
1658
|
+
argPrefix;
|
|
1234
1659
|
constructor(baseMessages, initialMessages, options = {}) {
|
|
1235
1660
|
this.baseMessages = baseMessages;
|
|
1236
1661
|
this.initialMessages = initialMessages;
|
|
1237
1662
|
this.historyBuilder = new LLMMessageBuilder();
|
|
1663
|
+
this.startPrefix = options.startPrefix;
|
|
1664
|
+
this.endPrefix = options.endPrefix;
|
|
1665
|
+
this.argPrefix = options.argPrefix;
|
|
1238
1666
|
if (options.startPrefix && options.endPrefix) {
|
|
1239
1667
|
this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix, options.argPrefix);
|
|
1240
1668
|
}
|
|
@@ -1251,6 +1679,25 @@ var init_conversation_manager = __esm({
|
|
|
1251
1679
|
getMessages() {
|
|
1252
1680
|
return [...this.baseMessages, ...this.initialMessages, ...this.historyBuilder.build()];
|
|
1253
1681
|
}
|
|
1682
|
+
getHistoryMessages() {
|
|
1683
|
+
return this.historyBuilder.build();
|
|
1684
|
+
}
|
|
1685
|
+
getBaseMessages() {
|
|
1686
|
+
return [...this.baseMessages, ...this.initialMessages];
|
|
1687
|
+
}
|
|
1688
|
+
replaceHistory(newHistory) {
|
|
1689
|
+
this.historyBuilder = new LLMMessageBuilder();
|
|
1690
|
+
if (this.startPrefix && this.endPrefix) {
|
|
1691
|
+
this.historyBuilder.withPrefixes(this.startPrefix, this.endPrefix, this.argPrefix);
|
|
1692
|
+
}
|
|
1693
|
+
for (const msg of newHistory) {
|
|
1694
|
+
if (msg.role === "user") {
|
|
1695
|
+
this.historyBuilder.addUser(msg.content);
|
|
1696
|
+
} else if (msg.role === "assistant") {
|
|
1697
|
+
this.historyBuilder.addAssistant(msg.content);
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1254
1701
|
};
|
|
1255
1702
|
}
|
|
1256
1703
|
});
|
|
@@ -2827,6 +3274,7 @@ var init_agent = __esm({
|
|
|
2827
3274
|
init_model_shortcuts();
|
|
2828
3275
|
init_output_viewer();
|
|
2829
3276
|
init_logger();
|
|
3277
|
+
init_manager();
|
|
2830
3278
|
init_gadget_output_store();
|
|
2831
3279
|
init_agent_internal_key();
|
|
2832
3280
|
init_conversation_manager();
|
|
@@ -2857,6 +3305,8 @@ var init_agent = __esm({
|
|
|
2857
3305
|
outputStore;
|
|
2858
3306
|
outputLimitEnabled;
|
|
2859
3307
|
outputLimitCharLimit;
|
|
3308
|
+
// Context compaction
|
|
3309
|
+
compactionManager;
|
|
2860
3310
|
/**
|
|
2861
3311
|
* Creates a new Agent instance.
|
|
2862
3312
|
* @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.
|
|
@@ -2916,6 +3366,14 @@ var init_agent = __esm({
|
|
|
2916
3366
|
if (options.userPrompt) {
|
|
2917
3367
|
this.conversation.addUserMessage(options.userPrompt);
|
|
2918
3368
|
}
|
|
3369
|
+
const compactionEnabled = options.compactionConfig?.enabled ?? true;
|
|
3370
|
+
if (compactionEnabled) {
|
|
3371
|
+
this.compactionManager = new CompactionManager(
|
|
3372
|
+
this.client,
|
|
3373
|
+
this.model,
|
|
3374
|
+
options.compactionConfig
|
|
3375
|
+
);
|
|
3376
|
+
}
|
|
2919
3377
|
}
|
|
2920
3378
|
/**
|
|
2921
3379
|
* Get the gadget registry for this agent.
|
|
@@ -2938,6 +3396,53 @@ var init_agent = __esm({
|
|
|
2938
3396
|
getRegistry() {
|
|
2939
3397
|
return this.registry;
|
|
2940
3398
|
}
|
|
3399
|
+
/**
|
|
3400
|
+
* Manually trigger context compaction.
|
|
3401
|
+
*
|
|
3402
|
+
* Forces compaction regardless of threshold. Useful for:
|
|
3403
|
+
* - Pre-emptive context management before expected long operations
|
|
3404
|
+
* - Testing compaction behavior
|
|
3405
|
+
*
|
|
3406
|
+
* @returns CompactionEvent if compaction was performed, null if not configured or no history
|
|
3407
|
+
*
|
|
3408
|
+
* @example
|
|
3409
|
+
* ```typescript
|
|
3410
|
+
* const agent = await LLMist.createAgent()
|
|
3411
|
+
* .withModel('sonnet')
|
|
3412
|
+
* .withCompaction()
|
|
3413
|
+
* .ask('...');
|
|
3414
|
+
*
|
|
3415
|
+
* // Manually compact before a long operation
|
|
3416
|
+
* const event = await agent.compact();
|
|
3417
|
+
* if (event) {
|
|
3418
|
+
* console.log(`Saved ${event.tokensBefore - event.tokensAfter} tokens`);
|
|
3419
|
+
* }
|
|
3420
|
+
* ```
|
|
3421
|
+
*/
|
|
3422
|
+
async compact() {
|
|
3423
|
+
if (!this.compactionManager) {
|
|
3424
|
+
return null;
|
|
3425
|
+
}
|
|
3426
|
+
return this.compactionManager.compact(this.conversation, -1);
|
|
3427
|
+
}
|
|
3428
|
+
/**
|
|
3429
|
+
* Get compaction statistics.
|
|
3430
|
+
*
|
|
3431
|
+
* @returns CompactionStats if compaction is enabled, null otherwise
|
|
3432
|
+
*
|
|
3433
|
+
* @example
|
|
3434
|
+
* ```typescript
|
|
3435
|
+
* const stats = agent.getCompactionStats();
|
|
3436
|
+
* if (stats) {
|
|
3437
|
+
* console.log(`Total compactions: ${stats.totalCompactions}`);
|
|
3438
|
+
* console.log(`Tokens saved: ${stats.totalTokensSaved}`);
|
|
3439
|
+
* console.log(`Current usage: ${stats.currentUsage.percent.toFixed(1)}%`);
|
|
3440
|
+
* }
|
|
3441
|
+
* ```
|
|
3442
|
+
*/
|
|
3443
|
+
getCompactionStats() {
|
|
3444
|
+
return this.compactionManager?.getStats() ?? null;
|
|
3445
|
+
}
|
|
2941
3446
|
/**
|
|
2942
3447
|
* Run the agent loop.
|
|
2943
3448
|
* Clean, simple orchestration - all complexity is in StreamProcessor.
|
|
@@ -2958,6 +3463,30 @@ var init_agent = __esm({
|
|
|
2958
3463
|
while (currentIteration < this.maxIterations) {
|
|
2959
3464
|
this.logger.debug("Starting iteration", { iteration: currentIteration });
|
|
2960
3465
|
try {
|
|
3466
|
+
if (this.compactionManager) {
|
|
3467
|
+
const compactionEvent = await this.compactionManager.checkAndCompact(
|
|
3468
|
+
this.conversation,
|
|
3469
|
+
currentIteration
|
|
3470
|
+
);
|
|
3471
|
+
if (compactionEvent) {
|
|
3472
|
+
this.logger.info("Context compacted", {
|
|
3473
|
+
strategy: compactionEvent.strategy,
|
|
3474
|
+
tokensBefore: compactionEvent.tokensBefore,
|
|
3475
|
+
tokensAfter: compactionEvent.tokensAfter
|
|
3476
|
+
});
|
|
3477
|
+
yield { type: "compaction", event: compactionEvent };
|
|
3478
|
+
await this.safeObserve(async () => {
|
|
3479
|
+
if (this.hooks.observers?.onCompaction) {
|
|
3480
|
+
await this.hooks.observers.onCompaction({
|
|
3481
|
+
iteration: currentIteration,
|
|
3482
|
+
event: compactionEvent,
|
|
3483
|
+
stats: this.compactionManager.getStats(),
|
|
3484
|
+
logger: this.logger
|
|
3485
|
+
});
|
|
3486
|
+
}
|
|
3487
|
+
});
|
|
3488
|
+
}
|
|
3489
|
+
}
|
|
2961
3490
|
let llmOptions = {
|
|
2962
3491
|
model: this.model,
|
|
2963
3492
|
messages: this.conversation.getMessages(),
|
|
@@ -2977,6 +3506,7 @@ var init_agent = __esm({
|
|
|
2977
3506
|
if (this.hooks.controllers?.beforeLLMCall) {
|
|
2978
3507
|
const context = {
|
|
2979
3508
|
iteration: currentIteration,
|
|
3509
|
+
maxIterations: this.maxIterations,
|
|
2980
3510
|
options: llmOptions,
|
|
2981
3511
|
logger: this.logger
|
|
2982
3512
|
};
|
|
@@ -3041,12 +3571,17 @@ var init_agent = __esm({
|
|
|
3041
3571
|
});
|
|
3042
3572
|
let finalMessage = result.finalMessage;
|
|
3043
3573
|
if (this.hooks.controllers?.afterLLMCall) {
|
|
3574
|
+
const gadgetCallCount = result.outputs.filter(
|
|
3575
|
+
(output) => output.type === "gadget_result"
|
|
3576
|
+
).length;
|
|
3044
3577
|
const context = {
|
|
3045
3578
|
iteration: currentIteration,
|
|
3579
|
+
maxIterations: this.maxIterations,
|
|
3046
3580
|
options: llmOptions,
|
|
3047
3581
|
finishReason: result.finishReason,
|
|
3048
3582
|
usage: result.usage,
|
|
3049
3583
|
finalMessage: result.finalMessage,
|
|
3584
|
+
gadgetCallCount,
|
|
3050
3585
|
logger: this.logger
|
|
3051
3586
|
};
|
|
3052
3587
|
const action = await this.hooks.controllers.afterLLMCall(context);
|
|
@@ -5281,6 +5816,7 @@ var init_builder = __esm({
|
|
|
5281
5816
|
defaultGadgetTimeoutMs;
|
|
5282
5817
|
gadgetOutputLimit;
|
|
5283
5818
|
gadgetOutputLimitPercent;
|
|
5819
|
+
compactionConfig;
|
|
5284
5820
|
constructor(client) {
|
|
5285
5821
|
this.client = client;
|
|
5286
5822
|
}
|
|
@@ -5676,6 +6212,57 @@ var init_builder = __esm({
|
|
|
5676
6212
|
this.gadgetOutputLimitPercent = percent;
|
|
5677
6213
|
return this;
|
|
5678
6214
|
}
|
|
6215
|
+
/**
|
|
6216
|
+
* Configure context compaction.
|
|
6217
|
+
*
|
|
6218
|
+
* Context compaction automatically manages conversation history to prevent
|
|
6219
|
+
* context window overflow in long-running agent conversations.
|
|
6220
|
+
*
|
|
6221
|
+
* @param config - Compaction configuration options
|
|
6222
|
+
* @returns This builder for chaining
|
|
6223
|
+
*
|
|
6224
|
+
* @example
|
|
6225
|
+
* ```typescript
|
|
6226
|
+
* // Custom thresholds
|
|
6227
|
+
* .withCompaction({
|
|
6228
|
+
* triggerThresholdPercent: 70,
|
|
6229
|
+
* targetPercent: 40,
|
|
6230
|
+
* preserveRecentTurns: 10,
|
|
6231
|
+
* })
|
|
6232
|
+
*
|
|
6233
|
+
* // Different strategy
|
|
6234
|
+
* .withCompaction({
|
|
6235
|
+
* strategy: 'sliding-window',
|
|
6236
|
+
* })
|
|
6237
|
+
*
|
|
6238
|
+
* // With callback
|
|
6239
|
+
* .withCompaction({
|
|
6240
|
+
* onCompaction: (event) => {
|
|
6241
|
+
* console.log(`Saved ${event.tokensBefore - event.tokensAfter} tokens`);
|
|
6242
|
+
* }
|
|
6243
|
+
* })
|
|
6244
|
+
* ```
|
|
6245
|
+
*/
|
|
6246
|
+
withCompaction(config) {
|
|
6247
|
+
this.compactionConfig = { ...config, enabled: config.enabled ?? true };
|
|
6248
|
+
return this;
|
|
6249
|
+
}
|
|
6250
|
+
/**
|
|
6251
|
+
* Disable context compaction.
|
|
6252
|
+
*
|
|
6253
|
+
* By default, compaction is enabled. Use this method to explicitly disable it.
|
|
6254
|
+
*
|
|
6255
|
+
* @returns This builder for chaining
|
|
6256
|
+
*
|
|
6257
|
+
* @example
|
|
6258
|
+
* ```typescript
|
|
6259
|
+
* .withoutCompaction() // Disable automatic compaction
|
|
6260
|
+
* ```
|
|
6261
|
+
*/
|
|
6262
|
+
withoutCompaction() {
|
|
6263
|
+
this.compactionConfig = { enabled: false };
|
|
6264
|
+
return this;
|
|
6265
|
+
}
|
|
5679
6266
|
/**
|
|
5680
6267
|
* Add a synthetic gadget call to the conversation history.
|
|
5681
6268
|
*
|
|
@@ -5791,7 +6378,8 @@ ${endPrefix}`
|
|
|
5791
6378
|
shouldContinueAfterError: this.shouldContinueAfterError,
|
|
5792
6379
|
defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
|
|
5793
6380
|
gadgetOutputLimit: this.gadgetOutputLimit,
|
|
5794
|
-
gadgetOutputLimitPercent: this.gadgetOutputLimitPercent
|
|
6381
|
+
gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,
|
|
6382
|
+
compactionConfig: this.compactionConfig
|
|
5795
6383
|
};
|
|
5796
6384
|
return new Agent(AGENT_INTERNAL_KEY, options);
|
|
5797
6385
|
}
|
|
@@ -5893,7 +6481,8 @@ ${endPrefix}`
|
|
|
5893
6481
|
shouldContinueAfterError: this.shouldContinueAfterError,
|
|
5894
6482
|
defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
|
|
5895
6483
|
gadgetOutputLimit: this.gadgetOutputLimit,
|
|
5896
|
-
gadgetOutputLimitPercent: this.gadgetOutputLimitPercent
|
|
6484
|
+
gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,
|
|
6485
|
+
compactionConfig: this.compactionConfig
|
|
5897
6486
|
};
|
|
5898
6487
|
return new Agent(AGENT_INTERNAL_KEY, options);
|
|
5899
6488
|
}
|
|
@@ -5908,8 +6497,12 @@ __export(index_exports, {
|
|
|
5908
6497
|
AnthropicMessagesProvider: () => AnthropicMessagesProvider,
|
|
5909
6498
|
BaseGadget: () => BaseGadget,
|
|
5910
6499
|
BreakLoopException: () => BreakLoopException,
|
|
6500
|
+
CompactionManager: () => CompactionManager,
|
|
5911
6501
|
ConversationManager: () => ConversationManager,
|
|
6502
|
+
DEFAULT_COMPACTION_CONFIG: () => DEFAULT_COMPACTION_CONFIG,
|
|
6503
|
+
DEFAULT_HINTS: () => DEFAULT_HINTS,
|
|
5912
6504
|
DEFAULT_PROMPTS: () => DEFAULT_PROMPTS,
|
|
6505
|
+
DEFAULT_SUMMARIZATION_PROMPT: () => DEFAULT_SUMMARIZATION_PROMPT,
|
|
5913
6506
|
Gadget: () => Gadget,
|
|
5914
6507
|
GadgetExecutor: () => GadgetExecutor,
|
|
5915
6508
|
GadgetOutputStore: () => GadgetOutputStore,
|
|
@@ -5917,6 +6510,7 @@ __export(index_exports, {
|
|
|
5917
6510
|
GeminiGenerativeProvider: () => GeminiGenerativeProvider,
|
|
5918
6511
|
HookPresets: () => HookPresets,
|
|
5919
6512
|
HumanInputException: () => HumanInputException,
|
|
6513
|
+
HybridStrategy: () => HybridStrategy,
|
|
5920
6514
|
LLMMessageBuilder: () => LLMMessageBuilder,
|
|
5921
6515
|
LLMist: () => LLMist,
|
|
5922
6516
|
MODEL_ALIASES: () => MODEL_ALIASES,
|
|
@@ -5926,8 +6520,10 @@ __export(index_exports, {
|
|
|
5926
6520
|
ModelIdentifierParser: () => ModelIdentifierParser,
|
|
5927
6521
|
ModelRegistry: () => ModelRegistry,
|
|
5928
6522
|
OpenAIChatProvider: () => OpenAIChatProvider,
|
|
6523
|
+
SlidingWindowStrategy: () => SlidingWindowStrategy,
|
|
5929
6524
|
StreamParser: () => StreamParser,
|
|
5930
6525
|
StreamProcessor: () => StreamProcessor,
|
|
6526
|
+
SummarizationStrategy: () => SummarizationStrategy,
|
|
5931
6527
|
collectEvents: () => collectEvents,
|
|
5932
6528
|
collectText: () => collectText,
|
|
5933
6529
|
complete: () => complete,
|
|
@@ -5935,6 +6531,7 @@ __export(index_exports, {
|
|
|
5935
6531
|
createGadget: () => createGadget,
|
|
5936
6532
|
createGadgetOutputViewer: () => createGadgetOutputViewer,
|
|
5937
6533
|
createGeminiProviderFromEnv: () => createGeminiProviderFromEnv,
|
|
6534
|
+
createHints: () => createHints,
|
|
5938
6535
|
createLogger: () => createLogger,
|
|
5939
6536
|
createMockAdapter: () => createMockAdapter,
|
|
5940
6537
|
createMockClient: () => createMockClient,
|
|
@@ -5947,7 +6544,10 @@ __export(index_exports, {
|
|
|
5947
6544
|
getModelId: () => getModelId,
|
|
5948
6545
|
getProvider: () => getProvider,
|
|
5949
6546
|
hasProviderPrefix: () => hasProviderPrefix,
|
|
6547
|
+
iterationProgressHint: () => iterationProgressHint,
|
|
5950
6548
|
mockLLM: () => mockLLM,
|
|
6549
|
+
parallelGadgetHint: () => parallelGadgetHint,
|
|
6550
|
+
resolveHintTemplate: () => resolveHintTemplate,
|
|
5951
6551
|
resolveModel: () => resolveModel,
|
|
5952
6552
|
resolvePromptTemplate: () => resolvePromptTemplate,
|
|
5953
6553
|
resolveRulesTemplate: () => resolveRulesTemplate,
|
|
@@ -6462,6 +7062,51 @@ var HookPresets = class _HookPresets {
|
|
|
6462
7062
|
}
|
|
6463
7063
|
};
|
|
6464
7064
|
}
|
|
7065
|
+
/**
|
|
7066
|
+
* Tracks context compaction events.
|
|
7067
|
+
*
|
|
7068
|
+
* **Output:**
|
|
7069
|
+
* - Compaction events with 🗜️ emoji
|
|
7070
|
+
* - Strategy name, tokens before/after, and savings
|
|
7071
|
+
* - Cumulative statistics
|
|
7072
|
+
*
|
|
7073
|
+
* **Use cases:**
|
|
7074
|
+
* - Monitoring long-running conversations
|
|
7075
|
+
* - Understanding when and how compaction occurs
|
|
7076
|
+
* - Debugging context management issues
|
|
7077
|
+
*
|
|
7078
|
+
* **Performance:** Minimal overhead. Simple console output.
|
|
7079
|
+
*
|
|
7080
|
+
* @returns Hook configuration that can be passed to .withHooks()
|
|
7081
|
+
*
|
|
7082
|
+
* @example
|
|
7083
|
+
* ```typescript
|
|
7084
|
+
* await LLMist.createAgent()
|
|
7085
|
+
* .withHooks(HookPresets.compactionTracking())
|
|
7086
|
+
* .ask("Your prompt");
|
|
7087
|
+
* ```
|
|
7088
|
+
*/
|
|
7089
|
+
static compactionTracking() {
|
|
7090
|
+
return {
|
|
7091
|
+
observers: {
|
|
7092
|
+
onCompaction: async (ctx) => {
|
|
7093
|
+
const saved = ctx.event.tokensBefore - ctx.event.tokensAfter;
|
|
7094
|
+
const percent = (saved / ctx.event.tokensBefore * 100).toFixed(1);
|
|
7095
|
+
console.log(
|
|
7096
|
+
`\u{1F5DC}\uFE0F Compaction (${ctx.event.strategy}): ${ctx.event.tokensBefore} \u2192 ${ctx.event.tokensAfter} tokens (saved ${saved}, ${percent}%)`
|
|
7097
|
+
);
|
|
7098
|
+
console.log(
|
|
7099
|
+
` Messages: ${ctx.event.messagesBefore} \u2192 ${ctx.event.messagesAfter}`
|
|
7100
|
+
);
|
|
7101
|
+
if (ctx.stats.totalCompactions > 1) {
|
|
7102
|
+
console.log(
|
|
7103
|
+
` Cumulative: ${ctx.stats.totalCompactions} compactions, ${ctx.stats.totalTokensSaved} tokens saved`
|
|
7104
|
+
);
|
|
7105
|
+
}
|
|
7106
|
+
}
|
|
7107
|
+
}
|
|
7108
|
+
};
|
|
7109
|
+
}
|
|
6465
7110
|
/**
|
|
6466
7111
|
* Returns empty hook configuration for clean output without any logging.
|
|
6467
7112
|
*
|
|
@@ -6692,6 +7337,113 @@ init_conversation_manager();
|
|
|
6692
7337
|
init_stream_processor();
|
|
6693
7338
|
init_gadget_output_store();
|
|
6694
7339
|
|
|
7340
|
+
// src/agent/compaction/index.ts
|
|
7341
|
+
init_config();
|
|
7342
|
+
init_strategy();
|
|
7343
|
+
init_strategies();
|
|
7344
|
+
init_manager();
|
|
7345
|
+
|
|
7346
|
+
// src/agent/hints.ts
|
|
7347
|
+
init_prompt_config();
|
|
7348
|
+
function iterationProgressHint(options) {
|
|
7349
|
+
const { timing = "always", showUrgency = true, template } = options ?? {};
|
|
7350
|
+
return {
|
|
7351
|
+
controllers: {
|
|
7352
|
+
beforeLLMCall: async (ctx) => {
|
|
7353
|
+
const iteration = ctx.iteration + 1;
|
|
7354
|
+
const maxIterations = ctx.maxIterations;
|
|
7355
|
+
const progress = iteration / maxIterations;
|
|
7356
|
+
if (timing === "late" && progress < 0.5) {
|
|
7357
|
+
return { action: "proceed" };
|
|
7358
|
+
}
|
|
7359
|
+
if (timing === "urgent" && progress < 0.8) {
|
|
7360
|
+
return { action: "proceed" };
|
|
7361
|
+
}
|
|
7362
|
+
const remaining = maxIterations - iteration;
|
|
7363
|
+
const hintContext = {
|
|
7364
|
+
iteration,
|
|
7365
|
+
maxIterations,
|
|
7366
|
+
remaining
|
|
7367
|
+
};
|
|
7368
|
+
let hint = resolveHintTemplate(
|
|
7369
|
+
template,
|
|
7370
|
+
DEFAULT_HINTS.iterationProgressHint,
|
|
7371
|
+
hintContext
|
|
7372
|
+
);
|
|
7373
|
+
if (showUrgency && progress >= 0.8) {
|
|
7374
|
+
hint += " \u26A0\uFE0F Running low on iterations - focus on completing the task.";
|
|
7375
|
+
}
|
|
7376
|
+
const messages = [...ctx.options.messages];
|
|
7377
|
+
let lastUserIndex = -1;
|
|
7378
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
7379
|
+
if (messages[i].role === "user") {
|
|
7380
|
+
lastUserIndex = i;
|
|
7381
|
+
break;
|
|
7382
|
+
}
|
|
7383
|
+
}
|
|
7384
|
+
if (lastUserIndex >= 0) {
|
|
7385
|
+
messages.splice(lastUserIndex + 1, 0, {
|
|
7386
|
+
role: "user",
|
|
7387
|
+
content: `[System Hint] ${hint}`
|
|
7388
|
+
});
|
|
7389
|
+
} else {
|
|
7390
|
+
messages.push({
|
|
7391
|
+
role: "user",
|
|
7392
|
+
content: `[System Hint] ${hint}`
|
|
7393
|
+
});
|
|
7394
|
+
}
|
|
7395
|
+
return {
|
|
7396
|
+
action: "proceed",
|
|
7397
|
+
modifiedOptions: { messages }
|
|
7398
|
+
};
|
|
7399
|
+
}
|
|
7400
|
+
}
|
|
7401
|
+
};
|
|
7402
|
+
}
|
|
7403
|
+
function parallelGadgetHint(options) {
|
|
7404
|
+
const {
|
|
7405
|
+
minGadgetsForEfficiency = 2,
|
|
7406
|
+
message = DEFAULT_HINTS.parallelGadgetsHint,
|
|
7407
|
+
enabled = true
|
|
7408
|
+
} = options ?? {};
|
|
7409
|
+
return {
|
|
7410
|
+
controllers: {
|
|
7411
|
+
afterLLMCall: async (ctx) => {
|
|
7412
|
+
if (!enabled) {
|
|
7413
|
+
return { action: "continue" };
|
|
7414
|
+
}
|
|
7415
|
+
if (ctx.gadgetCallCount > 0 && ctx.gadgetCallCount < minGadgetsForEfficiency) {
|
|
7416
|
+
return {
|
|
7417
|
+
action: "append_messages",
|
|
7418
|
+
messages: [
|
|
7419
|
+
{
|
|
7420
|
+
role: "user",
|
|
7421
|
+
content: `[System Hint] ${message}`
|
|
7422
|
+
}
|
|
7423
|
+
]
|
|
7424
|
+
};
|
|
7425
|
+
}
|
|
7426
|
+
return { action: "continue" };
|
|
7427
|
+
}
|
|
7428
|
+
}
|
|
7429
|
+
};
|
|
7430
|
+
}
|
|
7431
|
+
function createHints(config) {
|
|
7432
|
+
const hooksToMerge = [];
|
|
7433
|
+
if (config.iterationProgress) {
|
|
7434
|
+
const options = typeof config.iterationProgress === "boolean" ? {} : config.iterationProgress;
|
|
7435
|
+
hooksToMerge.push(iterationProgressHint(options));
|
|
7436
|
+
}
|
|
7437
|
+
if (config.parallelGadgets) {
|
|
7438
|
+
const options = typeof config.parallelGadgets === "boolean" ? {} : config.parallelGadgets;
|
|
7439
|
+
hooksToMerge.push(parallelGadgetHint(options));
|
|
7440
|
+
}
|
|
7441
|
+
if (config.custom) {
|
|
7442
|
+
hooksToMerge.push(...config.custom);
|
|
7443
|
+
}
|
|
7444
|
+
return HookPresets.merge(...hooksToMerge);
|
|
7445
|
+
}
|
|
7446
|
+
|
|
6695
7447
|
// src/index.ts
|
|
6696
7448
|
init_client();
|
|
6697
7449
|
init_messages();
|
|
@@ -7466,14 +8218,21 @@ function createMockClient(options) {
|
|
|
7466
8218
|
|
|
7467
8219
|
// src/testing/mock-gadget.ts
|
|
7468
8220
|
init_gadget();
|
|
8221
|
+
|
|
8222
|
+
// src/testing/cli-helpers.ts
|
|
8223
|
+
var import_node_stream = require("stream");
|
|
7469
8224
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7470
8225
|
0 && (module.exports = {
|
|
7471
8226
|
AgentBuilder,
|
|
7472
8227
|
AnthropicMessagesProvider,
|
|
7473
8228
|
BaseGadget,
|
|
7474
8229
|
BreakLoopException,
|
|
8230
|
+
CompactionManager,
|
|
7475
8231
|
ConversationManager,
|
|
8232
|
+
DEFAULT_COMPACTION_CONFIG,
|
|
8233
|
+
DEFAULT_HINTS,
|
|
7476
8234
|
DEFAULT_PROMPTS,
|
|
8235
|
+
DEFAULT_SUMMARIZATION_PROMPT,
|
|
7477
8236
|
Gadget,
|
|
7478
8237
|
GadgetExecutor,
|
|
7479
8238
|
GadgetOutputStore,
|
|
@@ -7481,6 +8240,7 @@ init_gadget();
|
|
|
7481
8240
|
GeminiGenerativeProvider,
|
|
7482
8241
|
HookPresets,
|
|
7483
8242
|
HumanInputException,
|
|
8243
|
+
HybridStrategy,
|
|
7484
8244
|
LLMMessageBuilder,
|
|
7485
8245
|
LLMist,
|
|
7486
8246
|
MODEL_ALIASES,
|
|
@@ -7490,8 +8250,10 @@ init_gadget();
|
|
|
7490
8250
|
ModelIdentifierParser,
|
|
7491
8251
|
ModelRegistry,
|
|
7492
8252
|
OpenAIChatProvider,
|
|
8253
|
+
SlidingWindowStrategy,
|
|
7493
8254
|
StreamParser,
|
|
7494
8255
|
StreamProcessor,
|
|
8256
|
+
SummarizationStrategy,
|
|
7495
8257
|
collectEvents,
|
|
7496
8258
|
collectText,
|
|
7497
8259
|
complete,
|
|
@@ -7499,6 +8261,7 @@ init_gadget();
|
|
|
7499
8261
|
createGadget,
|
|
7500
8262
|
createGadgetOutputViewer,
|
|
7501
8263
|
createGeminiProviderFromEnv,
|
|
8264
|
+
createHints,
|
|
7502
8265
|
createLogger,
|
|
7503
8266
|
createMockAdapter,
|
|
7504
8267
|
createMockClient,
|
|
@@ -7511,7 +8274,10 @@ init_gadget();
|
|
|
7511
8274
|
getModelId,
|
|
7512
8275
|
getProvider,
|
|
7513
8276
|
hasProviderPrefix,
|
|
8277
|
+
iterationProgressHint,
|
|
7514
8278
|
mockLLM,
|
|
8279
|
+
parallelGadgetHint,
|
|
8280
|
+
resolveHintTemplate,
|
|
7515
8281
|
resolveModel,
|
|
7516
8282
|
resolvePromptTemplate,
|
|
7517
8283
|
resolveRulesTemplate,
|