@cognipeer/agent-sdk 0.5.3 → 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 +15 -1
- package/dist/index.cjs +92 -138
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.mjs +92 -138
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -136,7 +136,12 @@ const agent = createSmartAgent({
|
|
|
136
136
|
memory: { provider: "inMemory", scope: "session", writePolicy: "auto_important" },
|
|
137
137
|
summarization: { summaryTriggerTokens: 8000, summaryMode: "incremental" },
|
|
138
138
|
context: { policy: "hybrid", lastTurnsToKeep: 8 },
|
|
139
|
-
toolResponses: {
|
|
139
|
+
toolResponses: {
|
|
140
|
+
defaultPolicy: "summarize_archive",
|
|
141
|
+
toolResponseRetentionByTool: { read_skills: "keep_full" },
|
|
142
|
+
maxToolResponseChars: 4000,
|
|
143
|
+
maxToolResponseTokens: 1200,
|
|
144
|
+
},
|
|
140
145
|
limits: { maxToolCalls: 5, maxContextTokens: 12000 },
|
|
141
146
|
tracing: { enabled: true },
|
|
142
147
|
});
|
|
@@ -149,6 +154,14 @@ const result = await agent.invoke({
|
|
|
149
154
|
console.log(result.content);
|
|
150
155
|
```
|
|
151
156
|
|
|
157
|
+
Tool-response retention is lazy and summarizer-driven:
|
|
158
|
+
|
|
159
|
+
- Tool outputs are stored at full fidelity in `state.toolHistory` and are never reduced at tool-call time.
|
|
160
|
+
- When the summarizer runs (context limits reached), old tool messages are rewritten in place according to `defaultPolicy` (default: `summarize_archive`). The full payload is still recoverable via `get_tool_response` using the execution id embedded in the placeholder.
|
|
161
|
+
- `toolResponseRetentionByTool` lets you opt specific tools out of reduction (e.g. `read_skills: "keep_full"`).
|
|
162
|
+
- `criticalTools` are never reduced. The built-in list covers `response`, `manage_todo_list`, and `get_tool_response`.
|
|
163
|
+
- `maxToolResponseChars` / `maxToolResponseTokens` only drive an eager hard-cap truncation when a single tool output is big enough to blow up the very next model call. The truncated head always points at `get_tool_response` for recovery.
|
|
164
|
+
|
|
152
165
|
The smart wrapper now supports runtime presets (`fast`, `balanced`, `deep`, `research`), custom profiles layered on top of a base preset, structured summarization, hybrid context compaction, configurable tool-response retention, in-memory fact storage, delegation limits, and an eval harness via `runSmartAgentEvalHarness(...)`.
|
|
153
166
|
|
|
154
167
|
You can also define a custom profile by extending a built-in preset and overriding only the knobs you need:
|
|
@@ -201,6 +214,7 @@ console.log(res.content);
|
|
|
201
214
|
- **Native provider layer** – call OpenAI, Anthropic, Azure, Bedrock, Vertex, and any OpenAI-compatible API directly. No LangChain required. Unified `ChatCompletionRequest` / `ChatCompletionResponse` schema with per-provider wire format conversion.
|
|
202
215
|
- **Full token tracking** – every response surfaces `inputTokens`, `outputTokens`, `cachedInputTokens`, `cachedWriteTokens`, and `reasoningTokens` for all six providers.
|
|
203
216
|
- **Summarization pipeline** – automatic chunking keeps tool call history within `contextTokenLimit` / `summaryTokenLimit`, archiving originals so `get_tool_response` can fetch them later.
|
|
217
|
+
- **Retention controls** – tool outputs can be kept full, reduced to structured previews, archived, or dropped based on size tiers, critical-tool fallback, per-tool overrides, and recent-response pinning.
|
|
204
218
|
- **Planning discipline** – when planning is enabled the system prompt distinguishes full plan writes from incremental plan updates and emits `plan` events as todos change.
|
|
205
219
|
- **Structured output** – supply `outputSchema` and the framework adds a hidden `response` finalize tool; parsed JSON is returned as `result.output`.
|
|
206
220
|
- **Multi-agent orchestration** – reuse agents via `agent.asTool({ toolName })` or perform handoffs that swap runtimes mid-execution.
|
package/dist/index.cjs
CHANGED
|
@@ -2136,15 +2136,13 @@ var BASE_DEFAULTS = {
|
|
|
2136
2136
|
requireJsonOutputContract: true
|
|
2137
2137
|
},
|
|
2138
2138
|
toolResponses: {
|
|
2139
|
-
maxToolResponseChars:
|
|
2140
|
-
maxToolResponseTokens:
|
|
2141
|
-
defaultPolicy: "
|
|
2142
|
-
largeResponsePolicy: "summarize_archive",
|
|
2139
|
+
maxToolResponseChars: 12e3,
|
|
2140
|
+
maxToolResponseTokens: 3e3,
|
|
2141
|
+
defaultPolicy: "summarize_archive",
|
|
2143
2142
|
toolResponseRetentionByTool: {},
|
|
2144
2143
|
criticalTools: [...DEFAULT_CRITICAL_TOOLS],
|
|
2145
2144
|
schemaValidation: "strict",
|
|
2146
|
-
retryOnSchemaError: true
|
|
2147
|
-
fallbackPolicy: "keep_structured"
|
|
2145
|
+
retryOnSchemaError: true
|
|
2148
2146
|
}
|
|
2149
2147
|
};
|
|
2150
2148
|
function buildProfile(overrides) {
|
|
@@ -2183,7 +2181,7 @@ var DEFAULT_PROFILE_CONFIGS = {
|
|
|
2183
2181
|
},
|
|
2184
2182
|
memory: { readPolicy: "recent_only" },
|
|
2185
2183
|
delegation: { mode: "off", maxDelegationDepth: 1, maxChildCalls: 2, maxParallelChild: 1, childContextPolicy: "minimal" },
|
|
2186
|
-
toolResponses: { maxToolResponseChars:
|
|
2184
|
+
toolResponses: { maxToolResponseChars: 8e3, maxToolResponseTokens: 2e3 }
|
|
2187
2185
|
}),
|
|
2188
2186
|
balanced: buildProfile({}),
|
|
2189
2187
|
deep: buildProfile({
|
|
@@ -2200,7 +2198,7 @@ var DEFAULT_PROFILE_CONFIGS = {
|
|
|
2200
2198
|
},
|
|
2201
2199
|
memory: { scope: "workspace" },
|
|
2202
2200
|
delegation: { maxDelegationDepth: 3, maxChildCalls: 6 },
|
|
2203
|
-
toolResponses: { maxToolResponseChars:
|
|
2201
|
+
toolResponses: { maxToolResponseChars: 16e3, maxToolResponseTokens: 4e3 }
|
|
2204
2202
|
}),
|
|
2205
2203
|
research: buildProfile({
|
|
2206
2204
|
limits: { maxToolCalls: 20, maxParallelTools: 4, maxContextTokens: 56e3 },
|
|
@@ -2216,7 +2214,7 @@ var DEFAULT_PROFILE_CONFIGS = {
|
|
|
2216
2214
|
},
|
|
2217
2215
|
memory: { scope: "workspace" },
|
|
2218
2216
|
delegation: { mode: "automatic", maxDelegationDepth: 4, maxChildCalls: 8, maxParallelChild: 3, childContextPolicy: "full" },
|
|
2219
|
-
toolResponses: { maxToolResponseChars:
|
|
2217
|
+
toolResponses: { maxToolResponseChars: 24e3, maxToolResponseTokens: 6e3 }
|
|
2220
2218
|
})
|
|
2221
2219
|
};
|
|
2222
2220
|
function mergeLimits(base, override) {
|
|
@@ -2423,57 +2421,65 @@ function summarizeObject(value) {
|
|
|
2423
2421
|
return safeStringify(value);
|
|
2424
2422
|
}
|
|
2425
2423
|
function classifyToolResponse(toolName, output, config) {
|
|
2426
|
-
const serialized = safeStringify(output);
|
|
2427
|
-
const tokenCount = countApproxTokens(serialized);
|
|
2428
2424
|
const criticalTools = new Set(config.toolResponses.criticalTools);
|
|
2429
2425
|
if (criticalTools.has(toolName)) return "critical";
|
|
2426
|
+
const serialized = safeStringify(output);
|
|
2427
|
+
const tokenCount = countApproxTokens(serialized);
|
|
2430
2428
|
if (tokenCount >= config.toolResponses.maxToolResponseTokens || serialized.length >= config.toolResponses.maxToolResponseChars) {
|
|
2431
2429
|
return "verbose";
|
|
2432
2430
|
}
|
|
2433
|
-
if (serialized === "ok" || serialized === "true" || serialized === "null") {
|
|
2434
|
-
return "redundant";
|
|
2435
|
-
}
|
|
2436
2431
|
return "informative";
|
|
2437
2432
|
}
|
|
2438
|
-
function
|
|
2433
|
+
function applyToolResponseHardCap(toolName, output, executionId, config) {
|
|
2439
2434
|
const serialized = safeStringify(output);
|
|
2440
2435
|
const tokenCount = countApproxTokens(serialized);
|
|
2441
2436
|
const classification = classifyToolResponse(toolName, output, config);
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
if (classification === "critical") {
|
|
2445
|
-
retentionPolicy = byTool || config.toolResponses.fallbackPolicy;
|
|
2446
|
-
} else if (classification === "verbose") {
|
|
2447
|
-
retentionPolicy = byTool || config.toolResponses.largeResponsePolicy;
|
|
2448
|
-
} else if (classification === "redundant") {
|
|
2449
|
-
retentionPolicy = byTool || "drop";
|
|
2450
|
-
}
|
|
2451
|
-
const summary = summarizeObject(output);
|
|
2452
|
-
if (retentionPolicy === "keep_full") {
|
|
2453
|
-
return { classification, retentionPolicy, content: serialized, rawOutput: output, summary, tokenCount };
|
|
2454
|
-
}
|
|
2455
|
-
if (retentionPolicy === "keep_structured") {
|
|
2456
|
-
return { classification, retentionPolicy, content: summary, rawOutput: output, summary, tokenCount };
|
|
2457
|
-
}
|
|
2458
|
-
if (retentionPolicy === "summarize_archive") {
|
|
2459
|
-
return {
|
|
2460
|
-
classification,
|
|
2461
|
-
retentionPolicy,
|
|
2462
|
-
content: `ARCHIVED_TOOL_RESPONSE: ${summary}`,
|
|
2463
|
-
rawOutput: output,
|
|
2464
|
-
summary,
|
|
2465
|
-
tokenCount
|
|
2466
|
-
};
|
|
2437
|
+
if (classification !== "verbose") {
|
|
2438
|
+
return { classification, content: serialized, rawOutput: output, tokenCount, truncated: false };
|
|
2467
2439
|
}
|
|
2440
|
+
const cap = config.toolResponses.maxToolResponseChars;
|
|
2441
|
+
const head = serialized.slice(0, cap);
|
|
2442
|
+
const note = `
|
|
2443
|
+
... [TRUNCATED ${serialized.length - cap} chars by hard cap. Use get_tool_response with executionId="${executionId}" to fetch the full payload.]`;
|
|
2468
2444
|
return {
|
|
2469
2445
|
classification,
|
|
2470
|
-
|
|
2471
|
-
content: `DROPPED_TOOL_RESPONSE: ${summary}`,
|
|
2446
|
+
content: head + note,
|
|
2472
2447
|
rawOutput: output,
|
|
2473
|
-
|
|
2474
|
-
|
|
2448
|
+
tokenCount,
|
|
2449
|
+
truncated: true
|
|
2475
2450
|
};
|
|
2476
2451
|
}
|
|
2452
|
+
function resolveSummarizationRetention(toolName, config) {
|
|
2453
|
+
const criticalTools = new Set(config.toolResponses.criticalTools);
|
|
2454
|
+
if (criticalTools.has(toolName)) return "keep_full";
|
|
2455
|
+
const byTool = config.toolResponses.toolResponseRetentionByTool[toolName];
|
|
2456
|
+
return byTool || config.toolResponses.defaultPolicy;
|
|
2457
|
+
}
|
|
2458
|
+
function renderRetainedToolMessage(args) {
|
|
2459
|
+
const { policy, rawOutput, toolName, toolCallId, executionId, prebuiltSummary } = args;
|
|
2460
|
+
if (policy === "keep_full") {
|
|
2461
|
+
return typeof rawOutput === "string" ? rawOutput : safeStringify(rawOutput);
|
|
2462
|
+
}
|
|
2463
|
+
const summary = prebuiltSummary || summarizeObject(rawOutput);
|
|
2464
|
+
const refs = [
|
|
2465
|
+
`toolName=${toolName}`,
|
|
2466
|
+
toolCallId ? `toolCallId=${toolCallId}` : null,
|
|
2467
|
+
executionId ? `executionId=${executionId}` : null
|
|
2468
|
+
].filter(Boolean).join("; ");
|
|
2469
|
+
const refId = executionId || toolCallId || "";
|
|
2470
|
+
if (policy === "keep_structured") {
|
|
2471
|
+
return `STRUCTURED_TOOL_RESPONSE [${refs}]
|
|
2472
|
+
Preview: ${summary}
|
|
2473
|
+
Use get_tool_response with executionId "${refId}" to fetch the full payload when a specific field is needed.`;
|
|
2474
|
+
}
|
|
2475
|
+
if (policy === "summarize_archive") {
|
|
2476
|
+
return `ARCHIVED_TOOL_RESPONSE [${refs}]
|
|
2477
|
+
Summary: ${summary}
|
|
2478
|
+
Use get_tool_response with executionId "${refId}" to fetch the full payload.`;
|
|
2479
|
+
}
|
|
2480
|
+
return `DROPPED_TOOL_RESPONSE [${refs}]
|
|
2481
|
+
Use get_tool_response with executionId "${refId}" only if you must recover the original payload.`;
|
|
2482
|
+
}
|
|
2477
2483
|
function validateToolArgs(tool, args) {
|
|
2478
2484
|
const schema = tool.schema;
|
|
2479
2485
|
if (!schema || typeof schema.parse !== "function") {
|
|
@@ -2752,52 +2758,25 @@ function createToolsNode(initialTools, opts) {
|
|
|
2752
2758
|
state.ctx.__structuredOutputParsed = output.data;
|
|
2753
2759
|
state.ctx.__finalizedDueToStructuredOutput = true;
|
|
2754
2760
|
}
|
|
2755
|
-
const responsePolicy =
|
|
2761
|
+
const responsePolicy = applyToolResponseHardCap(toolName, output, executionId, resolved);
|
|
2756
2762
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2757
|
-
const storedOutput = responsePolicy.retentionPolicy === "keep_full" ? output : responsePolicy.summary;
|
|
2758
2763
|
toolHistory.push({
|
|
2759
2764
|
executionId,
|
|
2760
2765
|
toolName,
|
|
2761
2766
|
args,
|
|
2762
|
-
output
|
|
2767
|
+
output,
|
|
2763
2768
|
rawOutput: output,
|
|
2764
2769
|
timestamp,
|
|
2765
2770
|
tool_call_id: tc.id,
|
|
2766
|
-
summarized:
|
|
2771
|
+
summarized: false,
|
|
2767
2772
|
originalTokenCount: responsePolicy.tokenCount,
|
|
2768
2773
|
classification: responsePolicy.classification,
|
|
2769
|
-
retentionPolicy:
|
|
2770
|
-
summary:
|
|
2771
|
-
archiveId:
|
|
2774
|
+
retentionPolicy: "keep_full",
|
|
2775
|
+
summary: void 0,
|
|
2776
|
+
archiveId: void 0,
|
|
2772
2777
|
status: "success"
|
|
2773
2778
|
});
|
|
2774
|
-
|
|
2775
|
-
toolHistoryArchived.push({
|
|
2776
|
-
executionId,
|
|
2777
|
-
toolName,
|
|
2778
|
-
args,
|
|
2779
|
-
output,
|
|
2780
|
-
rawOutput: output,
|
|
2781
|
-
timestamp,
|
|
2782
|
-
tool_call_id: tc.id,
|
|
2783
|
-
summarized: true,
|
|
2784
|
-
originalTokenCount: responsePolicy.tokenCount,
|
|
2785
|
-
classification: responsePolicy.classification,
|
|
2786
|
-
retentionPolicy: responsePolicy.retentionPolicy,
|
|
2787
|
-
summary: responsePolicy.summary,
|
|
2788
|
-
archiveId: executionId,
|
|
2789
|
-
status: "success"
|
|
2790
|
-
});
|
|
2791
|
-
}
|
|
2792
|
-
let toolMessageContent = responsePolicy.content;
|
|
2793
|
-
if (responsePolicy.retentionPolicy === "summarize_archive") {
|
|
2794
|
-
toolMessageContent = `ARCHIVED_TOOL_RESPONSE [executionId=${executionId}]: ${responsePolicy.summary}
|
|
2795
|
-
Use get_tool_response with executionId "${executionId}" to retrieve the full output.`;
|
|
2796
|
-
} else if (responsePolicy.retentionPolicy === "drop") {
|
|
2797
|
-
toolMessageContent = `DROPPED_TOOL_RESPONSE [executionId=${executionId}]: ${responsePolicy.summary}
|
|
2798
|
-
Use get_tool_response with executionId "${executionId}" to retrieve the full output.`;
|
|
2799
|
-
}
|
|
2800
|
-
appended.push({ role: "tool", content: toolMessageContent, tool_call_id: tc.id || `${tc.name}_${appended.length}`, name: tc.name });
|
|
2779
|
+
appended.push({ role: "tool", content: responsePolicy.content, tool_call_id: tc.id || `${tc.name}_${appended.length}`, name: tc.name });
|
|
2801
2780
|
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: output, durationMs });
|
|
2802
2781
|
onProgress?.({ stage: "tools", message: `Tool ${tc.name} completed`, detail: { durationMs } });
|
|
2803
2782
|
if (needsApproval && approvalEntry) {
|
|
@@ -2841,8 +2820,9 @@ Use get_tool_response with executionId "${executionId}" to retrieve the full out
|
|
|
2841
2820
|
messageList,
|
|
2842
2821
|
debug: {
|
|
2843
2822
|
classification: responsePolicy.classification,
|
|
2844
|
-
retentionPolicy:
|
|
2845
|
-
originalTokenCount: responsePolicy.tokenCount
|
|
2823
|
+
retentionPolicy: "keep_full",
|
|
2824
|
+
originalTokenCount: responsePolicy.tokenCount,
|
|
2825
|
+
truncated: responsePolicy.truncated
|
|
2846
2826
|
}
|
|
2847
2827
|
});
|
|
2848
2828
|
toolCount += 1;
|
|
@@ -4203,24 +4183,8 @@ function extractCanonicalFacts(messages) {
|
|
|
4203
4183
|
}
|
|
4204
4184
|
return [...facts.values()];
|
|
4205
4185
|
}
|
|
4206
|
-
function flattenToolMessageContent(message) {
|
|
4207
|
-
if (typeof message.content === "string") {
|
|
4208
|
-
return message.content;
|
|
4209
|
-
}
|
|
4210
|
-
if (Array.isArray(message.content)) {
|
|
4211
|
-
return message.content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? String(part ?? "")).join(" ");
|
|
4212
|
-
}
|
|
4213
|
-
return "";
|
|
4214
|
-
}
|
|
4215
4186
|
function isSummarizedToolPlaceholder(content) {
|
|
4216
|
-
return typeof content === "string" && (content === "SUMMARIZED" || content.startsWith("SUMMARIZED_TOOL_RESPONSE"));
|
|
4217
|
-
}
|
|
4218
|
-
function summarizeToolMessagePreview(message) {
|
|
4219
|
-
const preview = flattenToolMessageContent(message).trim();
|
|
4220
|
-
if (!preview) {
|
|
4221
|
-
return "No summary available.";
|
|
4222
|
-
}
|
|
4223
|
-
return preview.length > 240 ? `${preview.slice(0, 240)}...` : preview;
|
|
4187
|
+
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"));
|
|
4224
4188
|
}
|
|
4225
4189
|
function findToolHistoryEntry(state, toolCallId, toolName) {
|
|
4226
4190
|
const entries = [
|
|
@@ -4246,29 +4210,6 @@ function findToolHistoryEntry(state, toolCallId, toolName) {
|
|
|
4246
4210
|
}
|
|
4247
4211
|
return void 0;
|
|
4248
4212
|
}
|
|
4249
|
-
function buildSummarizedToolMessage(message, state) {
|
|
4250
|
-
const toolName = message.name || "unknown_tool";
|
|
4251
|
-
const toolCallId = message.tool_call_id;
|
|
4252
|
-
const historyEntry = findToolHistoryEntry(state, toolCallId, toolName);
|
|
4253
|
-
const executionId = historyEntry?.executionId;
|
|
4254
|
-
const summary = historyEntry?.summary || summarizeToolMessagePreview(message);
|
|
4255
|
-
const references = [
|
|
4256
|
-
`toolName=${toolName}`,
|
|
4257
|
-
toolCallId ? `toolCallId=${toolCallId}` : null,
|
|
4258
|
-
executionId ? `executionId=${executionId}` : null
|
|
4259
|
-
].filter(Boolean).join("; ");
|
|
4260
|
-
let retrievalHint = "Use get_tool_response if exact details are still needed.";
|
|
4261
|
-
if (executionId && toolCallId) {
|
|
4262
|
-
retrievalHint = `Use get_tool_response with executionId "${executionId}" or tool call id "${toolCallId}" if exact details are still needed.`;
|
|
4263
|
-
} else if (executionId || toolCallId) {
|
|
4264
|
-
retrievalHint = `Use get_tool_response with executionId "${executionId || toolCallId}" if exact details are still needed.`;
|
|
4265
|
-
}
|
|
4266
|
-
return [
|
|
4267
|
-
`SUMMARIZED_TOOL_RESPONSE [${references}]`,
|
|
4268
|
-
`Summary: ${summary}`,
|
|
4269
|
-
retrievalHint
|
|
4270
|
-
].join("\n");
|
|
4271
|
-
}
|
|
4272
4213
|
function mergeStableFacts(summary, additionalFacts) {
|
|
4273
4214
|
if (additionalFacts.length === 0) return summary;
|
|
4274
4215
|
const merged = new Map(summary.stable_facts.map((fact) => [fact.key, fact]));
|
|
@@ -4326,18 +4267,13 @@ function createContextSummarizeNode(opts) {
|
|
|
4326
4267
|
const messages = state.messages || [];
|
|
4327
4268
|
const onEvent = state.ctx?.__onEvent;
|
|
4328
4269
|
const traceSession = state.ctx?.__traceSession;
|
|
4329
|
-
const toolResponsesConfigEarly = resolved.toolResponses;
|
|
4330
4270
|
const compressableMessages = messages.filter(
|
|
4331
4271
|
(m) => {
|
|
4332
4272
|
if (m.role !== "tool") return false;
|
|
4333
4273
|
if (isSummarizedToolPlaceholder(m.content)) return false;
|
|
4334
4274
|
if (isSyntheticSummaryMessage(m)) return false;
|
|
4335
|
-
const
|
|
4336
|
-
if (
|
|
4337
|
-
if (!histEntry?.retentionPolicy) {
|
|
4338
|
-
const byTool = toolResponsesConfigEarly.toolResponseRetentionByTool?.[m.name || ""];
|
|
4339
|
-
if ((byTool || toolResponsesConfigEarly.defaultPolicy) === "keep_full") return false;
|
|
4340
|
-
}
|
|
4275
|
+
const policy = resolveSummarizationRetention(m.name || "", resolved);
|
|
4276
|
+
if (policy === "keep_full") return false;
|
|
4341
4277
|
return true;
|
|
4342
4278
|
}
|
|
4343
4279
|
);
|
|
@@ -4517,7 +4453,8 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
4517
4453
|
break;
|
|
4518
4454
|
}
|
|
4519
4455
|
}
|
|
4520
|
-
const
|
|
4456
|
+
const archivedExecutions = [...state.toolHistoryArchived || []];
|
|
4457
|
+
const archivedIds = new Set(archivedExecutions.map((entry) => entry?.executionId).filter(Boolean));
|
|
4521
4458
|
const newMessages = messages.map((m) => {
|
|
4522
4459
|
if (m.role === "tool") {
|
|
4523
4460
|
if (isSyntheticSummaryMessage(m)) {
|
|
@@ -4530,23 +4467,38 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
4530
4467
|
if (isSummarizedToolPlaceholder(m.content)) return m;
|
|
4531
4468
|
if (toolCallId && protectedToolCallIds.has(toolCallId)) return m;
|
|
4532
4469
|
const toolName = m.name || "";
|
|
4470
|
+
const policy = resolveSummarizationRetention(toolName, resolved);
|
|
4471
|
+
if (policy === "keep_full") return m;
|
|
4533
4472
|
const historyEntry = findToolHistoryEntry(state, toolCallId, toolName);
|
|
4534
|
-
const
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4473
|
+
const rawOutput = historyEntry?.rawOutput ?? historyEntry?.output ?? m.content;
|
|
4474
|
+
const executionId = historyEntry?.executionId;
|
|
4475
|
+
const prebuiltSummary = historyEntry?.summary || summarizeObject(rawOutput);
|
|
4476
|
+
if ((policy === "summarize_archive" || policy === "drop") && historyEntry && executionId && !archivedIds.has(executionId)) {
|
|
4477
|
+
archivedExecutions.push({
|
|
4478
|
+
...historyEntry,
|
|
4479
|
+
summarized: true,
|
|
4480
|
+
retentionPolicy: policy,
|
|
4481
|
+
archiveId: executionId,
|
|
4482
|
+
summary: prebuiltSummary
|
|
4483
|
+
});
|
|
4484
|
+
archivedIds.add(executionId);
|
|
4540
4485
|
}
|
|
4541
4486
|
return {
|
|
4542
4487
|
...m,
|
|
4543
|
-
content:
|
|
4488
|
+
content: renderRetainedToolMessage({
|
|
4489
|
+
policy,
|
|
4490
|
+
rawOutput,
|
|
4491
|
+
toolName,
|
|
4492
|
+
toolCallId,
|
|
4493
|
+
executionId,
|
|
4494
|
+
prebuiltSummary
|
|
4495
|
+
})
|
|
4544
4496
|
};
|
|
4545
4497
|
}
|
|
4546
4498
|
return m;
|
|
4547
4499
|
}).filter((m) => m !== null);
|
|
4548
4500
|
const actuallyCompressed = newMessages.filter(
|
|
4549
|
-
(m) => m.role === "tool" &&
|
|
4501
|
+
(m) => m.role === "tool" && isSummarizedToolPlaceholder(m.content) && !messages.some((orig) => orig.tool_call_id === m.tool_call_id && isSummarizedToolPlaceholder(orig.content))
|
|
4550
4502
|
);
|
|
4551
4503
|
if (actuallyCompressed.length === 0) {
|
|
4552
4504
|
return {};
|
|
@@ -4625,7 +4577,8 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
4625
4577
|
return {
|
|
4626
4578
|
messages: finalMessages,
|
|
4627
4579
|
summaries,
|
|
4628
|
-
summaryRecords
|
|
4580
|
+
summaryRecords,
|
|
4581
|
+
toolHistoryArchived: archivedExecutions
|
|
4629
4582
|
};
|
|
4630
4583
|
};
|
|
4631
4584
|
}
|
|
@@ -4867,8 +4820,9 @@ function createContextTools(stateRef, opts) {
|
|
|
4867
4820
|
}
|
|
4868
4821
|
const getTool = createTool({
|
|
4869
4822
|
name: "get_tool_response",
|
|
4870
|
-
description: "RETRIEVE the full output of a tool execution whose response was archived, dropped, or later compacted in conversation history. When a tool response appears as 'ARCHIVED_TOOL_RESPONSE [executionId=xxx]', 'DROPPED_TOOL_RESPONSE [executionId=xxx]', or 'SUMMARIZED_TOOL_RESPONSE [...]', pass the referenced executionId to this tool to get the complete data. You can also pass the original tool_call_id from the tool call.",
|
|
4823
|
+
description: "RETRIEVE the full output of a tool execution whose response was archived, dropped, or later compacted in conversation history. Use this only when the preview or summary is missing a specific field, identifier, snippet, or exact payload you still need to finish the task. Do not call it reflexively for every archived response. When a tool response appears as 'ARCHIVED_TOOL_RESPONSE [executionId=xxx]', 'DROPPED_TOOL_RESPONSE [executionId=xxx]', or 'SUMMARIZED_TOOL_RESPONSE [...]', pass the referenced executionId to this tool to get the complete data. You can also pass the original tool_call_id from the tool call.",
|
|
4871
4824
|
schema: zod.z.object({ executionId: zod.z.string().describe("Tool execution id or original tool_call_id") }),
|
|
4825
|
+
maxExecutionsPerRun: 8,
|
|
4872
4826
|
func: async ({ executionId }) => {
|
|
4873
4827
|
const matchesExecution = (t) => t?.executionId === executionId || t?.tool_call_id === executionId;
|
|
4874
4828
|
let execution = stateRef.toolHistory?.find((t) => matchesExecution(t));
|