@cognipeer/agent-sdk 0.5.4 → 0.6.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/README.md +8 -14
- package/dist/index.cjs +92 -186
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -20
- package/dist/index.d.ts +18 -20
- package/dist/index.mjs +92 -186
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -260,7 +260,7 @@ type RuntimeProfile = BuiltInRuntimeProfile | "custom";
|
|
|
260
260
|
type SummarizationMode = "incremental" | "full_rewrite";
|
|
261
261
|
type ContextPolicy = "raw" | "summary_only" | "hybrid";
|
|
262
262
|
type ToolResponseRetentionPolicy = "keep_full" | "keep_structured" | "summarize_archive" | "drop";
|
|
263
|
-
type ToolResponseClassification = "critical" | "
|
|
263
|
+
type ToolResponseClassification = "critical" | "informative" | "verbose";
|
|
264
264
|
type PlanningMode = "off" | "todo" | "planner_executor" | "reasoning_then_tools";
|
|
265
265
|
type ReplanPolicy = "never" | "on_failure" | "on_conflict" | "every_n_steps";
|
|
266
266
|
type DelegationMode = "off" | "role_based" | "automatic";
|
|
@@ -366,32 +366,30 @@ type SmartAgentMemoryConfig = {
|
|
|
366
366
|
readPolicy?: MemoryReadPolicy;
|
|
367
367
|
};
|
|
368
368
|
type SmartAgentToolResponseConfig = {
|
|
369
|
-
/**
|
|
369
|
+
/**
|
|
370
|
+
* Hard cap (in characters) applied at tool execution time to a single response.
|
|
371
|
+
* Anything larger is truncated immediately with a get_tool_response retrieval hint
|
|
372
|
+
* so a single oversized payload cannot blow up the next model call. Critical
|
|
373
|
+
* tools are exempt from this cap.
|
|
374
|
+
*/
|
|
370
375
|
maxToolResponseChars?: number;
|
|
371
|
-
/**
|
|
376
|
+
/** Hard cap (approx. tokens) for the same eager truncation rule. */
|
|
372
377
|
maxToolResponseTokens?: number;
|
|
373
|
-
/**
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
+
/**
|
|
379
|
+
* Retention policy applied to all non-critical tool responses by the summarizer
|
|
380
|
+
* when it fires (context limit reached). Has no effect at execution time.
|
|
381
|
+
* Defaults to "summarize_archive".
|
|
382
|
+
*/
|
|
378
383
|
defaultPolicy?: ToolResponseRetentionPolicy;
|
|
379
|
-
/**
|
|
380
|
-
|
|
381
|
-
|
|
384
|
+
/**
|
|
385
|
+
* Per-tool override of the summarizer retention policy. Wins over `defaultPolicy`.
|
|
386
|
+
* Critical tools cannot be reduced regardless of override.
|
|
387
|
+
*/
|
|
382
388
|
toolResponseRetentionByTool?: Record<string, ToolResponseRetentionPolicy>;
|
|
383
|
-
/** Tool names
|
|
389
|
+
/** Tool names whose responses are never reduced by the summarizer or hard cap. */
|
|
384
390
|
criticalTools?: string[];
|
|
385
391
|
schemaValidation?: "strict" | "warn";
|
|
386
392
|
retryOnSchemaError?: boolean;
|
|
387
|
-
/** Policy applied to critical tools. Should default to keep_full so critical payloads are never reduced. */
|
|
388
|
-
fallbackPolicy?: ToolResponseRetentionPolicy;
|
|
389
|
-
/**
|
|
390
|
-
* Number of most-recent successful tool responses to render at full content
|
|
391
|
-
* regardless of their classification. Older responses still follow their
|
|
392
|
-
* resolved policy. 0 disables the recency override. Defaults to 2.
|
|
393
|
-
*/
|
|
394
|
-
keepRecentFullCount?: number;
|
|
395
393
|
};
|
|
396
394
|
type SmartAgentCustomProfileConfig = {
|
|
397
395
|
extends?: BuiltInRuntimeProfile;
|
package/dist/index.d.ts
CHANGED
|
@@ -260,7 +260,7 @@ type RuntimeProfile = BuiltInRuntimeProfile | "custom";
|
|
|
260
260
|
type SummarizationMode = "incremental" | "full_rewrite";
|
|
261
261
|
type ContextPolicy = "raw" | "summary_only" | "hybrid";
|
|
262
262
|
type ToolResponseRetentionPolicy = "keep_full" | "keep_structured" | "summarize_archive" | "drop";
|
|
263
|
-
type ToolResponseClassification = "critical" | "
|
|
263
|
+
type ToolResponseClassification = "critical" | "informative" | "verbose";
|
|
264
264
|
type PlanningMode = "off" | "todo" | "planner_executor" | "reasoning_then_tools";
|
|
265
265
|
type ReplanPolicy = "never" | "on_failure" | "on_conflict" | "every_n_steps";
|
|
266
266
|
type DelegationMode = "off" | "role_based" | "automatic";
|
|
@@ -366,32 +366,30 @@ type SmartAgentMemoryConfig = {
|
|
|
366
366
|
readPolicy?: MemoryReadPolicy;
|
|
367
367
|
};
|
|
368
368
|
type SmartAgentToolResponseConfig = {
|
|
369
|
-
/**
|
|
369
|
+
/**
|
|
370
|
+
* Hard cap (in characters) applied at tool execution time to a single response.
|
|
371
|
+
* Anything larger is truncated immediately with a get_tool_response retrieval hint
|
|
372
|
+
* so a single oversized payload cannot blow up the next model call. Critical
|
|
373
|
+
* tools are exempt from this cap.
|
|
374
|
+
*/
|
|
370
375
|
maxToolResponseChars?: number;
|
|
371
|
-
/**
|
|
376
|
+
/** Hard cap (approx. tokens) for the same eager truncation rule. */
|
|
372
377
|
maxToolResponseTokens?: number;
|
|
373
|
-
/**
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
+
/**
|
|
379
|
+
* Retention policy applied to all non-critical tool responses by the summarizer
|
|
380
|
+
* when it fires (context limit reached). Has no effect at execution time.
|
|
381
|
+
* Defaults to "summarize_archive".
|
|
382
|
+
*/
|
|
378
383
|
defaultPolicy?: ToolResponseRetentionPolicy;
|
|
379
|
-
/**
|
|
380
|
-
|
|
381
|
-
|
|
384
|
+
/**
|
|
385
|
+
* Per-tool override of the summarizer retention policy. Wins over `defaultPolicy`.
|
|
386
|
+
* Critical tools cannot be reduced regardless of override.
|
|
387
|
+
*/
|
|
382
388
|
toolResponseRetentionByTool?: Record<string, ToolResponseRetentionPolicy>;
|
|
383
|
-
/** Tool names
|
|
389
|
+
/** Tool names whose responses are never reduced by the summarizer or hard cap. */
|
|
384
390
|
criticalTools?: string[];
|
|
385
391
|
schemaValidation?: "strict" | "warn";
|
|
386
392
|
retryOnSchemaError?: boolean;
|
|
387
|
-
/** Policy applied to critical tools. Should default to keep_full so critical payloads are never reduced. */
|
|
388
|
-
fallbackPolicy?: ToolResponseRetentionPolicy;
|
|
389
|
-
/**
|
|
390
|
-
* Number of most-recent successful tool responses to render at full content
|
|
391
|
-
* regardless of their classification. Older responses still follow their
|
|
392
|
-
* resolved policy. 0 disables the recency override. Defaults to 2.
|
|
393
|
-
*/
|
|
394
|
-
keepRecentFullCount?: number;
|
|
395
393
|
};
|
|
396
394
|
type SmartAgentCustomProfileConfig = {
|
|
397
395
|
extends?: BuiltInRuntimeProfile;
|
package/dist/index.mjs
CHANGED
|
@@ -2126,18 +2126,13 @@ var BASE_DEFAULTS = {
|
|
|
2126
2126
|
requireJsonOutputContract: true
|
|
2127
2127
|
},
|
|
2128
2128
|
toolResponses: {
|
|
2129
|
-
maxToolResponseChars:
|
|
2130
|
-
maxToolResponseTokens:
|
|
2131
|
-
|
|
2132
|
-
smallResponsePolicy: "keep_full",
|
|
2133
|
-
defaultPolicy: "keep_structured",
|
|
2134
|
-
largeResponsePolicy: "summarize_archive",
|
|
2129
|
+
maxToolResponseChars: 12e3,
|
|
2130
|
+
maxToolResponseTokens: 3e3,
|
|
2131
|
+
defaultPolicy: "summarize_archive",
|
|
2135
2132
|
toolResponseRetentionByTool: {},
|
|
2136
2133
|
criticalTools: [...DEFAULT_CRITICAL_TOOLS],
|
|
2137
2134
|
schemaValidation: "strict",
|
|
2138
|
-
retryOnSchemaError: true
|
|
2139
|
-
fallbackPolicy: "keep_full",
|
|
2140
|
-
keepRecentFullCount: 0
|
|
2135
|
+
retryOnSchemaError: true
|
|
2141
2136
|
}
|
|
2142
2137
|
};
|
|
2143
2138
|
function buildProfile(overrides) {
|
|
@@ -2176,7 +2171,7 @@ var DEFAULT_PROFILE_CONFIGS = {
|
|
|
2176
2171
|
},
|
|
2177
2172
|
memory: { readPolicy: "recent_only" },
|
|
2178
2173
|
delegation: { mode: "off", maxDelegationDepth: 1, maxChildCalls: 2, maxParallelChild: 1, childContextPolicy: "minimal" },
|
|
2179
|
-
toolResponses: { maxToolResponseChars:
|
|
2174
|
+
toolResponses: { maxToolResponseChars: 8e3, maxToolResponseTokens: 2e3 }
|
|
2180
2175
|
}),
|
|
2181
2176
|
balanced: buildProfile({}),
|
|
2182
2177
|
deep: buildProfile({
|
|
@@ -2193,7 +2188,7 @@ var DEFAULT_PROFILE_CONFIGS = {
|
|
|
2193
2188
|
},
|
|
2194
2189
|
memory: { scope: "workspace" },
|
|
2195
2190
|
delegation: { maxDelegationDepth: 3, maxChildCalls: 6 },
|
|
2196
|
-
toolResponses: { maxToolResponseChars:
|
|
2191
|
+
toolResponses: { maxToolResponseChars: 16e3, maxToolResponseTokens: 4e3 }
|
|
2197
2192
|
}),
|
|
2198
2193
|
research: buildProfile({
|
|
2199
2194
|
limits: { maxToolCalls: 20, maxParallelTools: 4, maxContextTokens: 56e3 },
|
|
@@ -2209,7 +2204,7 @@ var DEFAULT_PROFILE_CONFIGS = {
|
|
|
2209
2204
|
},
|
|
2210
2205
|
memory: { scope: "workspace" },
|
|
2211
2206
|
delegation: { mode: "automatic", maxDelegationDepth: 4, maxChildCalls: 8, maxParallelChild: 3, childContextPolicy: "full" },
|
|
2212
|
-
toolResponses: { maxToolResponseChars:
|
|
2207
|
+
toolResponses: { maxToolResponseChars: 24e3, maxToolResponseTokens: 6e3 }
|
|
2213
2208
|
})
|
|
2214
2209
|
};
|
|
2215
2210
|
function mergeLimits(base, override) {
|
|
@@ -2416,63 +2411,65 @@ function summarizeObject(value) {
|
|
|
2416
2411
|
return safeStringify(value);
|
|
2417
2412
|
}
|
|
2418
2413
|
function classifyToolResponse(toolName, output, config) {
|
|
2419
|
-
const serialized = safeStringify(output);
|
|
2420
|
-
const tokenCount = countApproxTokens(serialized);
|
|
2421
2414
|
const criticalTools = new Set(config.toolResponses.criticalTools);
|
|
2422
2415
|
if (criticalTools.has(toolName)) return "critical";
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
}
|
|
2416
|
+
const serialized = safeStringify(output);
|
|
2417
|
+
const tokenCount = countApproxTokens(serialized);
|
|
2426
2418
|
if (tokenCount >= config.toolResponses.maxToolResponseTokens || serialized.length >= config.toolResponses.maxToolResponseChars) {
|
|
2427
2419
|
return "verbose";
|
|
2428
2420
|
}
|
|
2429
|
-
const smallChars = config.toolResponses.smallResponseChars;
|
|
2430
|
-
if (smallChars > 0 && serialized.length <= smallChars) {
|
|
2431
|
-
return "small";
|
|
2432
|
-
}
|
|
2433
2421
|
return "informative";
|
|
2434
2422
|
}
|
|
2435
|
-
function
|
|
2423
|
+
function applyToolResponseHardCap(toolName, output, executionId, config) {
|
|
2436
2424
|
const serialized = safeStringify(output);
|
|
2437
2425
|
const tokenCount = countApproxTokens(serialized);
|
|
2438
2426
|
const classification = classifyToolResponse(toolName, output, config);
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
if (byTool) ; else if (classification === "critical") {
|
|
2442
|
-
retentionPolicy = config.toolResponses.fallbackPolicy;
|
|
2443
|
-
} else if (classification === "verbose") {
|
|
2444
|
-
retentionPolicy = config.toolResponses.largeResponsePolicy;
|
|
2445
|
-
} else if (classification === "small") {
|
|
2446
|
-
retentionPolicy = config.toolResponses.smallResponsePolicy;
|
|
2447
|
-
} else if (classification === "redundant") {
|
|
2448
|
-
retentionPolicy = "drop";
|
|
2449
|
-
}
|
|
2450
|
-
const summary = summarizeObject(output);
|
|
2451
|
-
if (retentionPolicy === "keep_full") {
|
|
2452
|
-
return { classification, retentionPolicy, content: serialized, rawOutput: output, summary, tokenCount };
|
|
2453
|
-
}
|
|
2454
|
-
if (retentionPolicy === "keep_structured") {
|
|
2455
|
-
return { classification, retentionPolicy, content: summary, rawOutput: output, summary, tokenCount };
|
|
2456
|
-
}
|
|
2457
|
-
if (retentionPolicy === "summarize_archive") {
|
|
2458
|
-
return {
|
|
2459
|
-
classification,
|
|
2460
|
-
retentionPolicy,
|
|
2461
|
-
content: `ARCHIVED_TOOL_RESPONSE: ${summary}`,
|
|
2462
|
-
rawOutput: output,
|
|
2463
|
-
summary,
|
|
2464
|
-
tokenCount
|
|
2465
|
-
};
|
|
2427
|
+
if (classification !== "verbose") {
|
|
2428
|
+
return { classification, content: serialized, rawOutput: output, tokenCount, truncated: false };
|
|
2466
2429
|
}
|
|
2430
|
+
const cap = config.toolResponses.maxToolResponseChars;
|
|
2431
|
+
const head = serialized.slice(0, cap);
|
|
2432
|
+
const note = `
|
|
2433
|
+
... [TRUNCATED ${serialized.length - cap} chars by hard cap. Use get_tool_response with executionId="${executionId}" to fetch the full payload.]`;
|
|
2467
2434
|
return {
|
|
2468
2435
|
classification,
|
|
2469
|
-
|
|
2470
|
-
content: `DROPPED_TOOL_RESPONSE: ${summary}`,
|
|
2436
|
+
content: head + note,
|
|
2471
2437
|
rawOutput: output,
|
|
2472
|
-
|
|
2473
|
-
|
|
2438
|
+
tokenCount,
|
|
2439
|
+
truncated: true
|
|
2474
2440
|
};
|
|
2475
2441
|
}
|
|
2442
|
+
function resolveSummarizationRetention(toolName, config) {
|
|
2443
|
+
const criticalTools = new Set(config.toolResponses.criticalTools);
|
|
2444
|
+
if (criticalTools.has(toolName)) return "keep_full";
|
|
2445
|
+
const byTool = config.toolResponses.toolResponseRetentionByTool[toolName];
|
|
2446
|
+
return byTool || config.toolResponses.defaultPolicy;
|
|
2447
|
+
}
|
|
2448
|
+
function renderRetainedToolMessage(args) {
|
|
2449
|
+
const { policy, rawOutput, toolName, toolCallId, executionId, prebuiltSummary } = args;
|
|
2450
|
+
if (policy === "keep_full") {
|
|
2451
|
+
return typeof rawOutput === "string" ? rawOutput : safeStringify(rawOutput);
|
|
2452
|
+
}
|
|
2453
|
+
const summary = prebuiltSummary || summarizeObject(rawOutput);
|
|
2454
|
+
const refs = [
|
|
2455
|
+
`toolName=${toolName}`,
|
|
2456
|
+
toolCallId ? `toolCallId=${toolCallId}` : null,
|
|
2457
|
+
executionId ? `executionId=${executionId}` : null
|
|
2458
|
+
].filter(Boolean).join("; ");
|
|
2459
|
+
const refId = executionId || toolCallId || "";
|
|
2460
|
+
if (policy === "keep_structured") {
|
|
2461
|
+
return `STRUCTURED_TOOL_RESPONSE [${refs}]
|
|
2462
|
+
Preview: ${summary}
|
|
2463
|
+
Use get_tool_response with executionId "${refId}" to fetch the full payload when a specific field is needed.`;
|
|
2464
|
+
}
|
|
2465
|
+
if (policy === "summarize_archive") {
|
|
2466
|
+
return `ARCHIVED_TOOL_RESPONSE [${refs}]
|
|
2467
|
+
Summary: ${summary}
|
|
2468
|
+
Use get_tool_response with executionId "${refId}" to fetch the full payload.`;
|
|
2469
|
+
}
|
|
2470
|
+
return `DROPPED_TOOL_RESPONSE [${refs}]
|
|
2471
|
+
Use get_tool_response with executionId "${refId}" only if you must recover the original payload.`;
|
|
2472
|
+
}
|
|
2476
2473
|
function validateToolArgs(tool, args) {
|
|
2477
2474
|
const schema = tool.schema;
|
|
2478
2475
|
if (!schema || typeof schema.parse !== "function") {
|
|
@@ -2751,52 +2748,25 @@ function createToolsNode(initialTools, opts) {
|
|
|
2751
2748
|
state.ctx.__structuredOutputParsed = output.data;
|
|
2752
2749
|
state.ctx.__finalizedDueToStructuredOutput = true;
|
|
2753
2750
|
}
|
|
2754
|
-
const responsePolicy =
|
|
2751
|
+
const responsePolicy = applyToolResponseHardCap(toolName, output, executionId, resolved);
|
|
2755
2752
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2756
|
-
const storedOutput = responsePolicy.retentionPolicy === "keep_full" ? output : responsePolicy.summary;
|
|
2757
2753
|
toolHistory.push({
|
|
2758
2754
|
executionId,
|
|
2759
2755
|
toolName,
|
|
2760
2756
|
args,
|
|
2761
|
-
output
|
|
2757
|
+
output,
|
|
2762
2758
|
rawOutput: output,
|
|
2763
2759
|
timestamp,
|
|
2764
2760
|
tool_call_id: tc.id,
|
|
2765
|
-
summarized:
|
|
2761
|
+
summarized: false,
|
|
2766
2762
|
originalTokenCount: responsePolicy.tokenCount,
|
|
2767
2763
|
classification: responsePolicy.classification,
|
|
2768
|
-
retentionPolicy:
|
|
2769
|
-
summary:
|
|
2770
|
-
archiveId:
|
|
2764
|
+
retentionPolicy: "keep_full",
|
|
2765
|
+
summary: void 0,
|
|
2766
|
+
archiveId: void 0,
|
|
2771
2767
|
status: "success"
|
|
2772
2768
|
});
|
|
2773
|
-
|
|
2774
|
-
toolHistoryArchived.push({
|
|
2775
|
-
executionId,
|
|
2776
|
-
toolName,
|
|
2777
|
-
args,
|
|
2778
|
-
output,
|
|
2779
|
-
rawOutput: output,
|
|
2780
|
-
timestamp,
|
|
2781
|
-
tool_call_id: tc.id,
|
|
2782
|
-
summarized: true,
|
|
2783
|
-
originalTokenCount: responsePolicy.tokenCount,
|
|
2784
|
-
classification: responsePolicy.classification,
|
|
2785
|
-
retentionPolicy: responsePolicy.retentionPolicy,
|
|
2786
|
-
summary: responsePolicy.summary,
|
|
2787
|
-
archiveId: executionId,
|
|
2788
|
-
status: "success"
|
|
2789
|
-
});
|
|
2790
|
-
}
|
|
2791
|
-
let toolMessageContent = responsePolicy.content;
|
|
2792
|
-
if (responsePolicy.retentionPolicy === "summarize_archive") {
|
|
2793
|
-
toolMessageContent = `ARCHIVED_TOOL_RESPONSE [executionId=${executionId}]: ${responsePolicy.summary}
|
|
2794
|
-
Only use get_tool_response with executionId "${executionId}" if this summary is missing a specific field, id, snippet, or exact payload you still need.`;
|
|
2795
|
-
} else if (responsePolicy.retentionPolicy === "drop") {
|
|
2796
|
-
toolMessageContent = `DROPPED_TOOL_RESPONSE [executionId=${executionId}]: ${responsePolicy.summary}
|
|
2797
|
-
Only use get_tool_response with executionId "${executionId}" if this summary is missing a specific field, id, snippet, or exact payload you still need.`;
|
|
2798
|
-
}
|
|
2799
|
-
appended.push({ role: "tool", content: toolMessageContent, tool_call_id: tc.id || `${tc.name}_${appended.length}`, name: tc.name });
|
|
2769
|
+
appended.push({ role: "tool", content: responsePolicy.content, tool_call_id: tc.id || `${tc.name}_${appended.length}`, name: tc.name });
|
|
2800
2770
|
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: output, durationMs });
|
|
2801
2771
|
onProgress?.({ stage: "tools", message: `Tool ${tc.name} completed`, detail: { durationMs } });
|
|
2802
2772
|
if (needsApproval && approvalEntry) {
|
|
@@ -2840,8 +2810,9 @@ Only use get_tool_response with executionId "${executionId}" if this summary is
|
|
|
2840
2810
|
messageList,
|
|
2841
2811
|
debug: {
|
|
2842
2812
|
classification: responsePolicy.classification,
|
|
2843
|
-
retentionPolicy:
|
|
2844
|
-
originalTokenCount: responsePolicy.tokenCount
|
|
2813
|
+
retentionPolicy: "keep_full",
|
|
2814
|
+
originalTokenCount: responsePolicy.tokenCount,
|
|
2815
|
+
truncated: responsePolicy.truncated
|
|
2845
2816
|
}
|
|
2846
2817
|
});
|
|
2847
2818
|
toolCount += 1;
|
|
@@ -3980,40 +3951,6 @@ function createAgentNode(opts) {
|
|
|
3980
3951
|
}
|
|
3981
3952
|
|
|
3982
3953
|
// src/smart/contextPolicy.ts
|
|
3983
|
-
function collectRecentFullToolCallIds(state, keepRecentFullCount) {
|
|
3984
|
-
if (!keepRecentFullCount || keepRecentFullCount <= 0) return /* @__PURE__ */ new Set();
|
|
3985
|
-
const history = state.toolHistory || [];
|
|
3986
|
-
const ids = [];
|
|
3987
|
-
for (let index = history.length - 1; index >= 0 && ids.length < keepRecentFullCount; index -= 1) {
|
|
3988
|
-
const entry = history[index];
|
|
3989
|
-
if (!entry || !entry.tool_call_id) continue;
|
|
3990
|
-
if (entry.status && entry.status !== "success") continue;
|
|
3991
|
-
ids.push(entry.tool_call_id);
|
|
3992
|
-
}
|
|
3993
|
-
return new Set(ids);
|
|
3994
|
-
}
|
|
3995
|
-
function applyRecentFullOverride(messages, state, config) {
|
|
3996
|
-
const keepN = config.toolResponses.keepRecentFullCount;
|
|
3997
|
-
if (!keepN || keepN <= 0) return messages;
|
|
3998
|
-
const recentIds = collectRecentFullToolCallIds(state, keepN);
|
|
3999
|
-
if (recentIds.size === 0) return messages;
|
|
4000
|
-
const history = state.toolHistory || [];
|
|
4001
|
-
const byCallId = /* @__PURE__ */ new Map();
|
|
4002
|
-
for (const entry of history) {
|
|
4003
|
-
if (entry?.tool_call_id) byCallId.set(entry.tool_call_id, entry);
|
|
4004
|
-
}
|
|
4005
|
-
return messages.map((message) => {
|
|
4006
|
-
if (message.role !== "tool" || !message.tool_call_id) return message;
|
|
4007
|
-
if (!recentIds.has(message.tool_call_id)) return message;
|
|
4008
|
-
const entry = byCallId.get(message.tool_call_id);
|
|
4009
|
-
if (!entry) return message;
|
|
4010
|
-
const raw = entry.rawOutput ?? entry.output;
|
|
4011
|
-
if (raw === void 0) return message;
|
|
4012
|
-
const fullContent = typeof raw === "string" ? raw : safeStringify(raw);
|
|
4013
|
-
if (!fullContent || fullContent === message.content) return message;
|
|
4014
|
-
return { ...message, content: fullContent };
|
|
4015
|
-
});
|
|
4016
|
-
}
|
|
4017
3954
|
function collectRecentTurns(messages, lastTurnsToKeep) {
|
|
4018
3955
|
if (lastTurnsToKeep <= 0) return [];
|
|
4019
3956
|
const systemPrefix = messages.filter((message, index) => index === 0 && message.role === "system");
|
|
@@ -4114,7 +4051,7 @@ function clampToBudget(messages, maxContextTokens) {
|
|
|
4114
4051
|
function buildModelMessages(state, config) {
|
|
4115
4052
|
const rawMessages = state.messages || [];
|
|
4116
4053
|
if (config.context.policy === "raw") {
|
|
4117
|
-
return clampToBudget(
|
|
4054
|
+
return clampToBudget(rawMessages, config.limits.maxContextTokens);
|
|
4118
4055
|
}
|
|
4119
4056
|
const recentMessages = collectRecentTurns(rawMessages, config.context.lastTurnsToKeep);
|
|
4120
4057
|
const latestSummary = state.summaryRecords?.[state.summaryRecords.length - 1];
|
|
@@ -4134,7 +4071,7 @@ function buildModelMessages(state, config) {
|
|
|
4134
4071
|
...syntheticContextMessages,
|
|
4135
4072
|
...config.context.policy === "summary_only" ? body.filter((message) => message.role === "user" || message.role === "assistant").slice(-2) : body
|
|
4136
4073
|
];
|
|
4137
|
-
return clampToBudget(
|
|
4074
|
+
return clampToBudget(assembled, config.limits.maxContextTokens);
|
|
4138
4075
|
}
|
|
4139
4076
|
|
|
4140
4077
|
// src/nodes/contextSummarize.ts
|
|
@@ -4236,24 +4173,8 @@ function extractCanonicalFacts(messages) {
|
|
|
4236
4173
|
}
|
|
4237
4174
|
return [...facts.values()];
|
|
4238
4175
|
}
|
|
4239
|
-
function flattenToolMessageContent(message) {
|
|
4240
|
-
if (typeof message.content === "string") {
|
|
4241
|
-
return message.content;
|
|
4242
|
-
}
|
|
4243
|
-
if (Array.isArray(message.content)) {
|
|
4244
|
-
return message.content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? String(part ?? "")).join(" ");
|
|
4245
|
-
}
|
|
4246
|
-
return "";
|
|
4247
|
-
}
|
|
4248
4176
|
function isSummarizedToolPlaceholder(content) {
|
|
4249
|
-
return typeof content === "string" && (content === "SUMMARIZED" || content.startsWith("SUMMARIZED_TOOL_RESPONSE"));
|
|
4250
|
-
}
|
|
4251
|
-
function summarizeToolMessagePreview(message) {
|
|
4252
|
-
const preview = flattenToolMessageContent(message).trim();
|
|
4253
|
-
if (!preview) {
|
|
4254
|
-
return "No summary available.";
|
|
4255
|
-
}
|
|
4256
|
-
return preview.length > 240 ? `${preview.slice(0, 240)}...` : preview;
|
|
4177
|
+
return typeof content === "string" && (content === "SUMMARIZED" || content.startsWith("SUMMARIZED_TOOL_RESPONSE") || content.startsWith("ARCHIVED_TOOL_RESPONSE") || content.startsWith("STRUCTURED_TOOL_RESPONSE") || content.startsWith("DROPPED_TOOL_RESPONSE"));
|
|
4257
4178
|
}
|
|
4258
4179
|
function findToolHistoryEntry(state, toolCallId, toolName) {
|
|
4259
4180
|
const entries = [
|
|
@@ -4279,29 +4200,6 @@ function findToolHistoryEntry(state, toolCallId, toolName) {
|
|
|
4279
4200
|
}
|
|
4280
4201
|
return void 0;
|
|
4281
4202
|
}
|
|
4282
|
-
function buildSummarizedToolMessage(message, state) {
|
|
4283
|
-
const toolName = message.name || "unknown_tool";
|
|
4284
|
-
const toolCallId = message.tool_call_id;
|
|
4285
|
-
const historyEntry = findToolHistoryEntry(state, toolCallId, toolName);
|
|
4286
|
-
const executionId = historyEntry?.executionId;
|
|
4287
|
-
const summary = historyEntry?.summary || summarizeToolMessagePreview(message);
|
|
4288
|
-
const references = [
|
|
4289
|
-
`toolName=${toolName}`,
|
|
4290
|
-
toolCallId ? `toolCallId=${toolCallId}` : null,
|
|
4291
|
-
executionId ? `executionId=${executionId}` : null
|
|
4292
|
-
].filter(Boolean).join("; ");
|
|
4293
|
-
let retrievalHint = "Only use get_tool_response if this summary is missing a specific field, id, snippet, or exact payload you still need.";
|
|
4294
|
-
if (executionId && toolCallId) {
|
|
4295
|
-
retrievalHint = `Only use get_tool_response with executionId "${executionId}" or tool call id "${toolCallId}" if this summary is missing a specific field, id, snippet, or exact payload you still need.`;
|
|
4296
|
-
} else if (executionId || toolCallId) {
|
|
4297
|
-
retrievalHint = `Only use get_tool_response with executionId "${executionId || toolCallId}" if this summary is missing a specific field, id, snippet, or exact payload you still need.`;
|
|
4298
|
-
}
|
|
4299
|
-
return [
|
|
4300
|
-
`SUMMARIZED_TOOL_RESPONSE [${references}]`,
|
|
4301
|
-
`Summary: ${summary}`,
|
|
4302
|
-
retrievalHint
|
|
4303
|
-
].join("\n");
|
|
4304
|
-
}
|
|
4305
4203
|
function mergeStableFacts(summary, additionalFacts) {
|
|
4306
4204
|
if (additionalFacts.length === 0) return summary;
|
|
4307
4205
|
const merged = new Map(summary.stable_facts.map((fact) => [fact.key, fact]));
|
|
@@ -4359,20 +4257,13 @@ function createContextSummarizeNode(opts) {
|
|
|
4359
4257
|
const messages = state.messages || [];
|
|
4360
4258
|
const onEvent = state.ctx?.__onEvent;
|
|
4361
4259
|
const traceSession = state.ctx?.__traceSession;
|
|
4362
|
-
const toolResponsesConfigEarly = resolved.toolResponses;
|
|
4363
|
-
const recentFullToolCallIdsEarly = collectRecentFullToolCallIds(state, toolResponsesConfigEarly.keepRecentFullCount);
|
|
4364
4260
|
const compressableMessages = messages.filter(
|
|
4365
4261
|
(m) => {
|
|
4366
4262
|
if (m.role !== "tool") return false;
|
|
4367
4263
|
if (isSummarizedToolPlaceholder(m.content)) return false;
|
|
4368
4264
|
if (isSyntheticSummaryMessage(m)) return false;
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
if (histEntry?.retentionPolicy === "keep_full") return false;
|
|
4372
|
-
if (!histEntry?.retentionPolicy) {
|
|
4373
|
-
const byTool = toolResponsesConfigEarly.toolResponseRetentionByTool?.[m.name || ""];
|
|
4374
|
-
if ((byTool || toolResponsesConfigEarly.defaultPolicy) === "keep_full") return false;
|
|
4375
|
-
}
|
|
4265
|
+
const policy = resolveSummarizationRetention(m.name || "", resolved);
|
|
4266
|
+
if (policy === "keep_full") return false;
|
|
4376
4267
|
return true;
|
|
4377
4268
|
}
|
|
4378
4269
|
);
|
|
@@ -4552,8 +4443,8 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
4552
4443
|
break;
|
|
4553
4444
|
}
|
|
4554
4445
|
}
|
|
4555
|
-
const
|
|
4556
|
-
const
|
|
4446
|
+
const archivedExecutions = [...state.toolHistoryArchived || []];
|
|
4447
|
+
const archivedIds = new Set(archivedExecutions.map((entry) => entry?.executionId).filter(Boolean));
|
|
4557
4448
|
const newMessages = messages.map((m) => {
|
|
4558
4449
|
if (m.role === "tool") {
|
|
4559
4450
|
if (isSyntheticSummaryMessage(m)) {
|
|
@@ -4565,25 +4456,39 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
4565
4456
|
}
|
|
4566
4457
|
if (isSummarizedToolPlaceholder(m.content)) return m;
|
|
4567
4458
|
if (toolCallId && protectedToolCallIds.has(toolCallId)) return m;
|
|
4568
|
-
if (toolCallId && recentFullToolCallIds.has(toolCallId)) return m;
|
|
4569
4459
|
const toolName = m.name || "";
|
|
4460
|
+
const policy = resolveSummarizationRetention(toolName, resolved);
|
|
4461
|
+
if (policy === "keep_full") return m;
|
|
4570
4462
|
const historyEntry = findToolHistoryEntry(state, toolCallId, toolName);
|
|
4571
|
-
const
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4463
|
+
const rawOutput = historyEntry?.rawOutput ?? historyEntry?.output ?? m.content;
|
|
4464
|
+
const executionId = historyEntry?.executionId;
|
|
4465
|
+
const prebuiltSummary = historyEntry?.summary || summarizeObject(rawOutput);
|
|
4466
|
+
if ((policy === "summarize_archive" || policy === "drop") && historyEntry && executionId && !archivedIds.has(executionId)) {
|
|
4467
|
+
archivedExecutions.push({
|
|
4468
|
+
...historyEntry,
|
|
4469
|
+
summarized: true,
|
|
4470
|
+
retentionPolicy: policy,
|
|
4471
|
+
archiveId: executionId,
|
|
4472
|
+
summary: prebuiltSummary
|
|
4473
|
+
});
|
|
4474
|
+
archivedIds.add(executionId);
|
|
4577
4475
|
}
|
|
4578
4476
|
return {
|
|
4579
4477
|
...m,
|
|
4580
|
-
content:
|
|
4478
|
+
content: renderRetainedToolMessage({
|
|
4479
|
+
policy,
|
|
4480
|
+
rawOutput,
|
|
4481
|
+
toolName,
|
|
4482
|
+
toolCallId,
|
|
4483
|
+
executionId,
|
|
4484
|
+
prebuiltSummary
|
|
4485
|
+
})
|
|
4581
4486
|
};
|
|
4582
4487
|
}
|
|
4583
4488
|
return m;
|
|
4584
4489
|
}).filter((m) => m !== null);
|
|
4585
4490
|
const actuallyCompressed = newMessages.filter(
|
|
4586
|
-
(m) => m.role === "tool" &&
|
|
4491
|
+
(m) => m.role === "tool" && isSummarizedToolPlaceholder(m.content) && !messages.some((orig) => orig.tool_call_id === m.tool_call_id && isSummarizedToolPlaceholder(orig.content))
|
|
4587
4492
|
);
|
|
4588
4493
|
if (actuallyCompressed.length === 0) {
|
|
4589
4494
|
return {};
|
|
@@ -4662,7 +4567,8 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
4662
4567
|
return {
|
|
4663
4568
|
messages: finalMessages,
|
|
4664
4569
|
summaries,
|
|
4665
|
-
summaryRecords
|
|
4570
|
+
summaryRecords,
|
|
4571
|
+
toolHistoryArchived: archivedExecutions
|
|
4666
4572
|
};
|
|
4667
4573
|
};
|
|
4668
4574
|
}
|