@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/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" | "informative" | "verbose" | "redundant";
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,15 +366,30 @@ type SmartAgentMemoryConfig = {
366
366
  readPolicy?: MemoryReadPolicy;
367
367
  };
368
368
  type SmartAgentToolResponseConfig = {
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
+ */
369
375
  maxToolResponseChars?: number;
376
+ /** Hard cap (approx. tokens) for the same eager truncation rule. */
370
377
  maxToolResponseTokens?: number;
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
+ */
371
383
  defaultPolicy?: ToolResponseRetentionPolicy;
372
- largeResponsePolicy?: ToolResponseRetentionPolicy;
384
+ /**
385
+ * Per-tool override of the summarizer retention policy. Wins over `defaultPolicy`.
386
+ * Critical tools cannot be reduced regardless of override.
387
+ */
373
388
  toolResponseRetentionByTool?: Record<string, ToolResponseRetentionPolicy>;
389
+ /** Tool names whose responses are never reduced by the summarizer or hard cap. */
374
390
  criticalTools?: string[];
375
391
  schemaValidation?: "strict" | "warn";
376
392
  retryOnSchemaError?: boolean;
377
- fallbackPolicy?: ToolResponseRetentionPolicy;
378
393
  };
379
394
  type SmartAgentCustomProfileConfig = {
380
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" | "informative" | "verbose" | "redundant";
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,15 +366,30 @@ type SmartAgentMemoryConfig = {
366
366
  readPolicy?: MemoryReadPolicy;
367
367
  };
368
368
  type SmartAgentToolResponseConfig = {
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
+ */
369
375
  maxToolResponseChars?: number;
376
+ /** Hard cap (approx. tokens) for the same eager truncation rule. */
370
377
  maxToolResponseTokens?: number;
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
+ */
371
383
  defaultPolicy?: ToolResponseRetentionPolicy;
372
- largeResponsePolicy?: ToolResponseRetentionPolicy;
384
+ /**
385
+ * Per-tool override of the summarizer retention policy. Wins over `defaultPolicy`.
386
+ * Critical tools cannot be reduced regardless of override.
387
+ */
373
388
  toolResponseRetentionByTool?: Record<string, ToolResponseRetentionPolicy>;
389
+ /** Tool names whose responses are never reduced by the summarizer or hard cap. */
374
390
  criticalTools?: string[];
375
391
  schemaValidation?: "strict" | "warn";
376
392
  retryOnSchemaError?: boolean;
377
- fallbackPolicy?: ToolResponseRetentionPolicy;
378
393
  };
379
394
  type SmartAgentCustomProfileConfig = {
380
395
  extends?: BuiltInRuntimeProfile;
package/dist/index.mjs CHANGED
@@ -2126,15 +2126,13 @@ var BASE_DEFAULTS = {
2126
2126
  requireJsonOutputContract: true
2127
2127
  },
2128
2128
  toolResponses: {
2129
- maxToolResponseChars: 3600,
2130
- maxToolResponseTokens: 1200,
2131
- defaultPolicy: "keep_structured",
2132
- largeResponsePolicy: "summarize_archive",
2129
+ maxToolResponseChars: 12e3,
2130
+ maxToolResponseTokens: 3e3,
2131
+ defaultPolicy: "summarize_archive",
2133
2132
  toolResponseRetentionByTool: {},
2134
2133
  criticalTools: [...DEFAULT_CRITICAL_TOOLS],
2135
2134
  schemaValidation: "strict",
2136
- retryOnSchemaError: true,
2137
- fallbackPolicy: "keep_structured"
2135
+ retryOnSchemaError: true
2138
2136
  }
2139
2137
  };
2140
2138
  function buildProfile(overrides) {
@@ -2173,7 +2171,7 @@ var DEFAULT_PROFILE_CONFIGS = {
2173
2171
  },
2174
2172
  memory: { readPolicy: "recent_only" },
2175
2173
  delegation: { mode: "off", maxDelegationDepth: 1, maxChildCalls: 2, maxParallelChild: 1, childContextPolicy: "minimal" },
2176
- toolResponses: { maxToolResponseChars: 2400, maxToolResponseTokens: 800 }
2174
+ toolResponses: { maxToolResponseChars: 8e3, maxToolResponseTokens: 2e3 }
2177
2175
  }),
2178
2176
  balanced: buildProfile({}),
2179
2177
  deep: buildProfile({
@@ -2190,7 +2188,7 @@ var DEFAULT_PROFILE_CONFIGS = {
2190
2188
  },
2191
2189
  memory: { scope: "workspace" },
2192
2190
  delegation: { maxDelegationDepth: 3, maxChildCalls: 6 },
2193
- toolResponses: { maxToolResponseChars: 5400, maxToolResponseTokens: 1800 }
2191
+ toolResponses: { maxToolResponseChars: 16e3, maxToolResponseTokens: 4e3 }
2194
2192
  }),
2195
2193
  research: buildProfile({
2196
2194
  limits: { maxToolCalls: 20, maxParallelTools: 4, maxContextTokens: 56e3 },
@@ -2206,7 +2204,7 @@ var DEFAULT_PROFILE_CONFIGS = {
2206
2204
  },
2207
2205
  memory: { scope: "workspace" },
2208
2206
  delegation: { mode: "automatic", maxDelegationDepth: 4, maxChildCalls: 8, maxParallelChild: 3, childContextPolicy: "full" },
2209
- toolResponses: { maxToolResponseChars: 7200, maxToolResponseTokens: 2200 }
2207
+ toolResponses: { maxToolResponseChars: 24e3, maxToolResponseTokens: 6e3 }
2210
2208
  })
2211
2209
  };
2212
2210
  function mergeLimits(base, override) {
@@ -2413,57 +2411,65 @@ function summarizeObject(value) {
2413
2411
  return safeStringify(value);
2414
2412
  }
2415
2413
  function classifyToolResponse(toolName, output, config) {
2416
- const serialized = safeStringify(output);
2417
- const tokenCount = countApproxTokens(serialized);
2418
2414
  const criticalTools = new Set(config.toolResponses.criticalTools);
2419
2415
  if (criticalTools.has(toolName)) return "critical";
2416
+ const serialized = safeStringify(output);
2417
+ const tokenCount = countApproxTokens(serialized);
2420
2418
  if (tokenCount >= config.toolResponses.maxToolResponseTokens || serialized.length >= config.toolResponses.maxToolResponseChars) {
2421
2419
  return "verbose";
2422
2420
  }
2423
- if (serialized === "ok" || serialized === "true" || serialized === "null") {
2424
- return "redundant";
2425
- }
2426
2421
  return "informative";
2427
2422
  }
2428
- function resolveToolResponsePolicy(toolName, output, config) {
2423
+ function applyToolResponseHardCap(toolName, output, executionId, config) {
2429
2424
  const serialized = safeStringify(output);
2430
2425
  const tokenCount = countApproxTokens(serialized);
2431
2426
  const classification = classifyToolResponse(toolName, output, config);
2432
- const byTool = config.toolResponses.toolResponseRetentionByTool[toolName];
2433
- let retentionPolicy = byTool || config.toolResponses.defaultPolicy;
2434
- if (classification === "critical") {
2435
- retentionPolicy = byTool || config.toolResponses.fallbackPolicy;
2436
- } else if (classification === "verbose") {
2437
- retentionPolicy = byTool || config.toolResponses.largeResponsePolicy;
2438
- } else if (classification === "redundant") {
2439
- retentionPolicy = byTool || "drop";
2440
- }
2441
- const summary = summarizeObject(output);
2442
- if (retentionPolicy === "keep_full") {
2443
- return { classification, retentionPolicy, content: serialized, rawOutput: output, summary, tokenCount };
2444
- }
2445
- if (retentionPolicy === "keep_structured") {
2446
- return { classification, retentionPolicy, content: summary, rawOutput: output, summary, tokenCount };
2447
- }
2448
- if (retentionPolicy === "summarize_archive") {
2449
- return {
2450
- classification,
2451
- retentionPolicy,
2452
- content: `ARCHIVED_TOOL_RESPONSE: ${summary}`,
2453
- rawOutput: output,
2454
- summary,
2455
- tokenCount
2456
- };
2427
+ if (classification !== "verbose") {
2428
+ return { classification, content: serialized, rawOutput: output, tokenCount, truncated: false };
2457
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.]`;
2458
2434
  return {
2459
2435
  classification,
2460
- retentionPolicy,
2461
- content: `DROPPED_TOOL_RESPONSE: ${summary}`,
2436
+ content: head + note,
2462
2437
  rawOutput: output,
2463
- summary,
2464
- tokenCount
2438
+ tokenCount,
2439
+ truncated: true
2465
2440
  };
2466
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
+ }
2467
2473
  function validateToolArgs(tool, args) {
2468
2474
  const schema = tool.schema;
2469
2475
  if (!schema || typeof schema.parse !== "function") {
@@ -2742,52 +2748,25 @@ function createToolsNode(initialTools, opts) {
2742
2748
  state.ctx.__structuredOutputParsed = output.data;
2743
2749
  state.ctx.__finalizedDueToStructuredOutput = true;
2744
2750
  }
2745
- const responsePolicy = resolveToolResponsePolicy(toolName, output, resolved);
2751
+ const responsePolicy = applyToolResponseHardCap(toolName, output, executionId, resolved);
2746
2752
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2747
- const storedOutput = responsePolicy.retentionPolicy === "keep_full" ? output : responsePolicy.summary;
2748
2753
  toolHistory.push({
2749
2754
  executionId,
2750
2755
  toolName,
2751
2756
  args,
2752
- output: storedOutput,
2757
+ output,
2753
2758
  rawOutput: output,
2754
2759
  timestamp,
2755
2760
  tool_call_id: tc.id,
2756
- summarized: responsePolicy.retentionPolicy !== "keep_full",
2761
+ summarized: false,
2757
2762
  originalTokenCount: responsePolicy.tokenCount,
2758
2763
  classification: responsePolicy.classification,
2759
- retentionPolicy: responsePolicy.retentionPolicy,
2760
- summary: responsePolicy.summary,
2761
- archiveId: responsePolicy.retentionPolicy === "summarize_archive" || responsePolicy.retentionPolicy === "drop" ? executionId : void 0,
2764
+ retentionPolicy: "keep_full",
2765
+ summary: void 0,
2766
+ archiveId: void 0,
2762
2767
  status: "success"
2763
2768
  });
2764
- if (resolved.context.archiveLargeToolResponses && (responsePolicy.retentionPolicy === "summarize_archive" || responsePolicy.retentionPolicy === "drop")) {
2765
- toolHistoryArchived.push({
2766
- executionId,
2767
- toolName,
2768
- args,
2769
- output,
2770
- rawOutput: output,
2771
- timestamp,
2772
- tool_call_id: tc.id,
2773
- summarized: true,
2774
- originalTokenCount: responsePolicy.tokenCount,
2775
- classification: responsePolicy.classification,
2776
- retentionPolicy: responsePolicy.retentionPolicy,
2777
- summary: responsePolicy.summary,
2778
- archiveId: executionId,
2779
- status: "success"
2780
- });
2781
- }
2782
- let toolMessageContent = responsePolicy.content;
2783
- if (responsePolicy.retentionPolicy === "summarize_archive") {
2784
- toolMessageContent = `ARCHIVED_TOOL_RESPONSE [executionId=${executionId}]: ${responsePolicy.summary}
2785
- Use get_tool_response with executionId "${executionId}" to retrieve the full output.`;
2786
- } else if (responsePolicy.retentionPolicy === "drop") {
2787
- toolMessageContent = `DROPPED_TOOL_RESPONSE [executionId=${executionId}]: ${responsePolicy.summary}
2788
- Use get_tool_response with executionId "${executionId}" to retrieve the full output.`;
2789
- }
2790
- 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 });
2791
2770
  onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: output, durationMs });
2792
2771
  onProgress?.({ stage: "tools", message: `Tool ${tc.name} completed`, detail: { durationMs } });
2793
2772
  if (needsApproval && approvalEntry) {
@@ -2831,8 +2810,9 @@ Use get_tool_response with executionId "${executionId}" to retrieve the full out
2831
2810
  messageList,
2832
2811
  debug: {
2833
2812
  classification: responsePolicy.classification,
2834
- retentionPolicy: responsePolicy.retentionPolicy,
2835
- originalTokenCount: responsePolicy.tokenCount
2813
+ retentionPolicy: "keep_full",
2814
+ originalTokenCount: responsePolicy.tokenCount,
2815
+ truncated: responsePolicy.truncated
2836
2816
  }
2837
2817
  });
2838
2818
  toolCount += 1;
@@ -4193,24 +4173,8 @@ function extractCanonicalFacts(messages) {
4193
4173
  }
4194
4174
  return [...facts.values()];
4195
4175
  }
4196
- function flattenToolMessageContent(message) {
4197
- if (typeof message.content === "string") {
4198
- return message.content;
4199
- }
4200
- if (Array.isArray(message.content)) {
4201
- return message.content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? String(part ?? "")).join(" ");
4202
- }
4203
- return "";
4204
- }
4205
4176
  function isSummarizedToolPlaceholder(content) {
4206
- return typeof content === "string" && (content === "SUMMARIZED" || content.startsWith("SUMMARIZED_TOOL_RESPONSE"));
4207
- }
4208
- function summarizeToolMessagePreview(message) {
4209
- const preview = flattenToolMessageContent(message).trim();
4210
- if (!preview) {
4211
- return "No summary available.";
4212
- }
4213
- 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"));
4214
4178
  }
4215
4179
  function findToolHistoryEntry(state, toolCallId, toolName) {
4216
4180
  const entries = [
@@ -4236,29 +4200,6 @@ function findToolHistoryEntry(state, toolCallId, toolName) {
4236
4200
  }
4237
4201
  return void 0;
4238
4202
  }
4239
- function buildSummarizedToolMessage(message, state) {
4240
- const toolName = message.name || "unknown_tool";
4241
- const toolCallId = message.tool_call_id;
4242
- const historyEntry = findToolHistoryEntry(state, toolCallId, toolName);
4243
- const executionId = historyEntry?.executionId;
4244
- const summary = historyEntry?.summary || summarizeToolMessagePreview(message);
4245
- const references = [
4246
- `toolName=${toolName}`,
4247
- toolCallId ? `toolCallId=${toolCallId}` : null,
4248
- executionId ? `executionId=${executionId}` : null
4249
- ].filter(Boolean).join("; ");
4250
- let retrievalHint = "Use get_tool_response if exact details are still needed.";
4251
- if (executionId && toolCallId) {
4252
- retrievalHint = `Use get_tool_response with executionId "${executionId}" or tool call id "${toolCallId}" if exact details are still needed.`;
4253
- } else if (executionId || toolCallId) {
4254
- retrievalHint = `Use get_tool_response with executionId "${executionId || toolCallId}" if exact details are still needed.`;
4255
- }
4256
- return [
4257
- `SUMMARIZED_TOOL_RESPONSE [${references}]`,
4258
- `Summary: ${summary}`,
4259
- retrievalHint
4260
- ].join("\n");
4261
- }
4262
4203
  function mergeStableFacts(summary, additionalFacts) {
4263
4204
  if (additionalFacts.length === 0) return summary;
4264
4205
  const merged = new Map(summary.stable_facts.map((fact) => [fact.key, fact]));
@@ -4316,18 +4257,13 @@ function createContextSummarizeNode(opts) {
4316
4257
  const messages = state.messages || [];
4317
4258
  const onEvent = state.ctx?.__onEvent;
4318
4259
  const traceSession = state.ctx?.__traceSession;
4319
- const toolResponsesConfigEarly = resolved.toolResponses;
4320
4260
  const compressableMessages = messages.filter(
4321
4261
  (m) => {
4322
4262
  if (m.role !== "tool") return false;
4323
4263
  if (isSummarizedToolPlaceholder(m.content)) return false;
4324
4264
  if (isSyntheticSummaryMessage(m)) return false;
4325
- const histEntry = findToolHistoryEntry(state, m.tool_call_id, m.name);
4326
- if (histEntry?.retentionPolicy === "keep_full") return false;
4327
- if (!histEntry?.retentionPolicy) {
4328
- const byTool = toolResponsesConfigEarly.toolResponseRetentionByTool?.[m.name || ""];
4329
- if ((byTool || toolResponsesConfigEarly.defaultPolicy) === "keep_full") return false;
4330
- }
4265
+ const policy = resolveSummarizationRetention(m.name || "", resolved);
4266
+ if (policy === "keep_full") return false;
4331
4267
  return true;
4332
4268
  }
4333
4269
  );
@@ -4507,7 +4443,8 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4507
4443
  break;
4508
4444
  }
4509
4445
  }
4510
- const toolResponsesConfig = resolved.toolResponses;
4446
+ const archivedExecutions = [...state.toolHistoryArchived || []];
4447
+ const archivedIds = new Set(archivedExecutions.map((entry) => entry?.executionId).filter(Boolean));
4511
4448
  const newMessages = messages.map((m) => {
4512
4449
  if (m.role === "tool") {
4513
4450
  if (isSyntheticSummaryMessage(m)) {
@@ -4520,23 +4457,38 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4520
4457
  if (isSummarizedToolPlaceholder(m.content)) return m;
4521
4458
  if (toolCallId && protectedToolCallIds.has(toolCallId)) return m;
4522
4459
  const toolName = m.name || "";
4460
+ const policy = resolveSummarizationRetention(toolName, resolved);
4461
+ if (policy === "keep_full") return m;
4523
4462
  const historyEntry = findToolHistoryEntry(state, toolCallId, toolName);
4524
- const entryRetention = historyEntry?.retentionPolicy;
4525
- if (entryRetention === "keep_full") return m;
4526
- if (!entryRetention) {
4527
- const byTool = toolResponsesConfig.toolResponseRetentionByTool?.[toolName];
4528
- const configPolicy = byTool || toolResponsesConfig.defaultPolicy;
4529
- if (configPolicy === "keep_full") return m;
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);
4530
4475
  }
4531
4476
  return {
4532
4477
  ...m,
4533
- content: buildSummarizedToolMessage(m, state)
4478
+ content: renderRetainedToolMessage({
4479
+ policy,
4480
+ rawOutput,
4481
+ toolName,
4482
+ toolCallId,
4483
+ executionId,
4484
+ prebuiltSummary
4485
+ })
4534
4486
  };
4535
4487
  }
4536
4488
  return m;
4537
4489
  }).filter((m) => m !== null);
4538
4490
  const actuallyCompressed = newMessages.filter(
4539
- (m) => m.role === "tool" && typeof m.content === "string" && m.content.startsWith("SUMMARIZED_TOOL_RESPONSE") && !messages.some((orig) => orig.tool_call_id === m.tool_call_id && isSummarizedToolPlaceholder(orig.content))
4491
+ (m) => m.role === "tool" && isSummarizedToolPlaceholder(m.content) && !messages.some((orig) => orig.tool_call_id === m.tool_call_id && isSummarizedToolPlaceholder(orig.content))
4540
4492
  );
4541
4493
  if (actuallyCompressed.length === 0) {
4542
4494
  return {};
@@ -4615,7 +4567,8 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4615
4567
  return {
4616
4568
  messages: finalMessages,
4617
4569
  summaries,
4618
- summaryRecords
4570
+ summaryRecords,
4571
+ toolHistoryArchived: archivedExecutions
4619
4572
  };
4620
4573
  };
4621
4574
  }
@@ -4857,8 +4810,9 @@ function createContextTools(stateRef, opts) {
4857
4810
  }
4858
4811
  const getTool = createTool({
4859
4812
  name: "get_tool_response",
4860
- 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.",
4813
+ 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.",
4861
4814
  schema: z.object({ executionId: z.string().describe("Tool execution id or original tool_call_id") }),
4815
+ maxExecutionsPerRun: 8,
4862
4816
  func: async ({ executionId }) => {
4863
4817
  const matchesExecution = (t) => t?.executionId === executionId || t?.tool_call_id === executionId;
4864
4818
  let execution = stateRef.toolHistory?.find((t) => matchesExecution(t));