@illuma-ai/agents 1.1.3 → 1.1.5
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/cjs/agents/AgentContext.cjs +6 -2
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/common/constants.cjs +10 -0
- package/dist/cjs/common/constants.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +86 -12
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/main.cjs +4 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/types/graph.cjs.map +1 -1
- package/dist/cjs/utils/fileManifest.cjs +49 -0
- package/dist/cjs/utils/fileManifest.cjs.map +1 -0
- package/dist/esm/agents/AgentContext.mjs +6 -2
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/common/constants.mjs +10 -1
- package/dist/esm/common/constants.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +87 -13
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/main.mjs +2 -1
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/types/graph.mjs.map +1 -1
- package/dist/esm/utils/fileManifest.mjs +46 -0
- package/dist/esm/utils/fileManifest.mjs.map +1 -0
- package/dist/types/agents/AgentContext.d.ts +4 -1
- package/dist/types/common/constants.d.ts +9 -0
- package/dist/types/types/graph.d.ts +35 -0
- package/dist/types/utils/fileManifest.d.ts +17 -0
- package/dist/types/utils/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/agents/AgentContext.ts +7 -0
- package/src/common/constants.ts +10 -0
- package/src/graphs/Graph.ts +92 -13
- package/src/graphs/gapFeatures.test.ts +246 -8
- package/src/types/graph.ts +36 -0
- package/src/utils/fileManifest.ts +49 -0
- package/src/utils/index.ts +1 -0
|
@@ -11,7 +11,7 @@ import { ensureThinkingBlockInMessages } from '../messages/format.mjs';
|
|
|
11
11
|
import { addCacheControl, addBedrockCacheControl } from '../messages/cache.mjs';
|
|
12
12
|
import { formatContentStrings } from '../messages/content.mjs';
|
|
13
13
|
import { GraphNodeKeys, Providers, ContentTypes, GraphEvents, MessageTypes, StepTypes, Constants } from '../common/enum.mjs';
|
|
14
|
-
import { TOOL_TURN_THINKING_BUDGET, PROACTIVE_SUMMARY_THRESHOLD, SUMMARIZATION_CONTEXT_THRESHOLD } from '../common/constants.mjs';
|
|
14
|
+
import { TOOL_TURN_THINKING_BUDGET, PROACTIVE_SUMMARY_THRESHOLD, SUMMARIZATION_CONTEXT_THRESHOLD, COMPACTION_RECENT_ROUNDS } from '../common/constants.mjs';
|
|
15
15
|
import { deduplicateSystemMessages } from '../messages/dedup.mjs';
|
|
16
16
|
import { resetIfNotEmpty, joinKeys } from '../utils/graph.mjs';
|
|
17
17
|
import { isOpenAILike, isGoogleLike } from '../utils/llm.mjs';
|
|
@@ -25,6 +25,7 @@ import 'zod-to-json-schema';
|
|
|
25
25
|
import { hasTaskTool, buildPostPruneNote, detectDocuments, shouldInjectMultiDocHint, buildMultiDocHintContent } from '../utils/contextPressure.mjs';
|
|
26
26
|
import { ToolDiscoveryCache } from '../utils/toolDiscoveryCache.mjs';
|
|
27
27
|
import { createPruneCalibration, applyCalibration, updatePruneCalibration } from '../utils/pruneCalibration.mjs';
|
|
28
|
+
import { buildFileManifestBlock } from '../utils/fileManifest.mjs';
|
|
28
29
|
import { getChatModelClass, manualToolStreamProviders } from '../llm/providers.mjs';
|
|
29
30
|
import { ToolNode, toolsCondition } from '../tools/ToolNode.mjs';
|
|
30
31
|
import { ChatOpenAI, AzureChatOpenAI } from '../llm/openai/index.mjs';
|
|
@@ -1179,17 +1180,52 @@ class StandardGraph extends Graph {
|
|
|
1179
1180
|
: 0;
|
|
1180
1181
|
// Budget for recent messages = total - system - summary - 3 (assistant priming)
|
|
1181
1182
|
const recentBudget = calibratedMax - systemTokens - summaryTokens - 3;
|
|
1182
|
-
// Step 3:
|
|
1183
|
+
// Step 3: Determine window of recent messages to include.
|
|
1184
|
+
//
|
|
1185
|
+
// Two modes:
|
|
1186
|
+
// A) No summary available → fill the budget (all messages that fit)
|
|
1187
|
+
// B) Summary available → keep last 2 conversation rounds (H+A pairs)
|
|
1188
|
+
// + any trailing tool messages. The summary covers everything else.
|
|
1189
|
+
// This avoids wasting tokens on raw messages the summary already covers.
|
|
1190
|
+
//
|
|
1191
|
+
// A "round" = one human message + one AI response (+ any tool messages between).
|
|
1183
1192
|
const contentStart = systemMsg != null ? 1 : 0;
|
|
1184
1193
|
let usedTokens = 0;
|
|
1185
1194
|
let windowStart = messages.length; // index where the recent window begins
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1195
|
+
let fileManifestTokens = 0; // populated in Step 4 if file manifest is injected
|
|
1196
|
+
if (summary == null || summary === '') {
|
|
1197
|
+
// Mode A: No summary — include as many recent messages as fit in budget
|
|
1198
|
+
for (let i = messages.length - 1; i >= contentStart; i--) {
|
|
1199
|
+
const msgTokens = agentContext.indexTokenCountMap[i] ?? 0;
|
|
1200
|
+
if (usedTokens + msgTokens > recentBudget) {
|
|
1201
|
+
break;
|
|
1202
|
+
}
|
|
1203
|
+
usedTokens += msgTokens;
|
|
1204
|
+
windowStart = i;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
else {
|
|
1208
|
+
// Mode B: Summary exists — keep last 2 rounds (4 core messages: H+A+H+A)
|
|
1209
|
+
// Walk backward counting human messages as round boundaries.
|
|
1210
|
+
const MAX_RECENT_ROUNDS = COMPACTION_RECENT_ROUNDS;
|
|
1211
|
+
let roundsSeen = 0;
|
|
1212
|
+
for (let i = messages.length - 1; i >= contentStart; i--) {
|
|
1213
|
+
const msgType = messages[i]?.getType();
|
|
1214
|
+
const msgTokens = agentContext.indexTokenCountMap[i] ?? 0;
|
|
1215
|
+
// Budget guard — even in round-limited mode, don't exceed budget
|
|
1216
|
+
if (usedTokens + msgTokens > recentBudget) {
|
|
1217
|
+
break;
|
|
1218
|
+
}
|
|
1219
|
+
usedTokens += msgTokens;
|
|
1220
|
+
windowStart = i;
|
|
1221
|
+
// Count a human message as a round boundary
|
|
1222
|
+
if (msgType === 'human') {
|
|
1223
|
+
roundsSeen++;
|
|
1224
|
+
if (roundsSeen >= MAX_RECENT_ROUNDS) {
|
|
1225
|
+
break;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1190
1228
|
}
|
|
1191
|
-
usedTokens += msgTokens;
|
|
1192
|
-
windowStart = i;
|
|
1193
1229
|
}
|
|
1194
1230
|
// Ensure we don't split tool-call / tool-result pairs.
|
|
1195
1231
|
// If windowStart lands on a ToolMessage, walk back to include its AI message.
|
|
@@ -1202,7 +1238,11 @@ class StandardGraph extends Graph {
|
|
|
1202
1238
|
const compactedMessages = messages.slice(contentStart, windowStart);
|
|
1203
1239
|
const hasSummary = summaryMsg != null;
|
|
1204
1240
|
// Step 4: Assemble the windowed view
|
|
1205
|
-
// [system] + [summary
|
|
1241
|
+
// [system] + [summary] + [file manifest] + [recent window]
|
|
1242
|
+
//
|
|
1243
|
+
// File manifest is injected ONLY when compaction is active (messages behind summary).
|
|
1244
|
+
// It provides the LLM with awareness of all conversation files so it can
|
|
1245
|
+
// retrieve content on demand via file_search or content_tool read.
|
|
1206
1246
|
const viewParts = [];
|
|
1207
1247
|
if (systemMsg != null) {
|
|
1208
1248
|
viewParts.push(systemMsg);
|
|
@@ -1210,12 +1250,46 @@ class StandardGraph extends Graph {
|
|
|
1210
1250
|
if (summaryMsg != null) {
|
|
1211
1251
|
viewParts.push(summaryMsg);
|
|
1212
1252
|
}
|
|
1253
|
+
// Inject file manifest when files exist and messages are being compacted
|
|
1254
|
+
const fileManifest = agentContext.fileManifest;
|
|
1255
|
+
if (fileManifest && fileManifest.length > 0 && compactedMessages.length > 0) {
|
|
1256
|
+
const manifestBlock = buildFileManifestBlock(fileManifest);
|
|
1257
|
+
if (manifestBlock) {
|
|
1258
|
+
const manifestMsg = new SystemMessage(manifestBlock);
|
|
1259
|
+
viewParts.push(manifestMsg);
|
|
1260
|
+
// Account for manifest tokens in the view token map
|
|
1261
|
+
const manifestTokens = tokenCounter != null ? tokenCounter(manifestMsg) : 0;
|
|
1262
|
+
// Will be inserted at the correct index when rebuilding viewTokenMap below
|
|
1263
|
+
fileManifestTokens = manifestTokens;
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1213
1266
|
viewParts.push(...recentMessages);
|
|
1214
1267
|
messagesToUse = viewParts;
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1268
|
+
// Rebuild indexTokenCountMap for the windowed view so downstream
|
|
1269
|
+
// analytics and summarization triggers see accurate token counts.
|
|
1270
|
+
const viewTokenMap = {};
|
|
1271
|
+
let viewIdx = 0;
|
|
1272
|
+
if (systemMsg != null) {
|
|
1273
|
+
viewTokenMap[viewIdx] = systemTokens;
|
|
1274
|
+
viewIdx++;
|
|
1275
|
+
}
|
|
1276
|
+
if (summaryMsg != null) {
|
|
1277
|
+
viewTokenMap[viewIdx] = summaryTokens;
|
|
1278
|
+
viewIdx++;
|
|
1279
|
+
}
|
|
1280
|
+
if (fileManifestTokens > 0) {
|
|
1281
|
+
viewTokenMap[viewIdx] = fileManifestTokens;
|
|
1282
|
+
viewIdx++;
|
|
1283
|
+
}
|
|
1284
|
+
for (let i = windowStart; i < messages.length; i++) {
|
|
1285
|
+
viewTokenMap[viewIdx] = agentContext.indexTokenCountMap[i];
|
|
1286
|
+
viewIdx++;
|
|
1287
|
+
}
|
|
1288
|
+
agentContext.indexTokenCountMap = viewTokenMap;
|
|
1289
|
+
console.debug(`[Graph:Compaction] ${messages.length}→${viewParts.length} msgs | ` +
|
|
1290
|
+
`compacted=${compactedMessages.length} window=${recentMessages.length} | ` +
|
|
1291
|
+
`summary=${summarySource} | budget=${usedTokens}/${recentBudget}` +
|
|
1292
|
+
(fileManifestTokens > 0 ? ` | manifest=${fileManifest?.length ?? 0} files (${fileManifestTokens}tok)` : ''));
|
|
1219
1293
|
// Step 5: Fire background summary update (non-blocking)
|
|
1220
1294
|
// Summarize messages outside the window so next iteration has a fresh summary.
|
|
1221
1295
|
// Only trigger if there are compacted messages worth summarizing.
|