@cognipeer/agent-sdk 0.8.6 → 0.8.8

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.cjs CHANGED
@@ -420,7 +420,8 @@ function createTool({
420
420
  approvalDefaults,
421
421
  maxExecutionsPerRun,
422
422
  cache,
423
- retry
423
+ retry,
424
+ retention
424
425
  }) {
425
426
  const execute = async (input) => func(input);
426
427
  const toolRecord = {
@@ -451,6 +452,9 @@ function createTool({
451
452
  if (retry !== void 0) {
452
453
  toolRecord.retry = retry;
453
454
  }
455
+ if (retention !== void 0) {
456
+ toolRecord.retention = retention;
457
+ }
454
458
  toolRecord.__source = toolRecord.__source || "smart";
455
459
  toolRecord.__impl = func;
456
460
  return toolRecord;
@@ -1972,6 +1976,270 @@ function estimatePayloadBytes(value) {
1972
1976
  }
1973
1977
  }
1974
1978
 
1979
+ // src/smart/toolResponses.ts
1980
+ init_utilTokens();
1981
+
1982
+ // src/utils/content.ts
1983
+ function contentToString(content) {
1984
+ try {
1985
+ if (content == null) return "";
1986
+ if (typeof content === "string") return content;
1987
+ if (Array.isArray(content)) {
1988
+ return content.map((p) => {
1989
+ if (!p || typeof p !== "object") return String(p);
1990
+ if (p.type === "text") return String(p.text ?? "");
1991
+ if (p.type === "image_url") {
1992
+ const img = p.image_url;
1993
+ const url = typeof img === "string" ? img : img?.url;
1994
+ const detail = typeof img === "string" ? void 0 : img?.detail;
1995
+ return `[image:${url || "unknown"}${detail ? ` detail=${detail}` : ""}]`;
1996
+ }
1997
+ return JSON.stringify(p);
1998
+ }).join("\n");
1999
+ }
2000
+ return JSON.stringify(content);
2001
+ } catch {
2002
+ return String(content);
2003
+ }
2004
+ }
2005
+ function mergeContentsToString(contents) {
2006
+ return contents.map((c) => contentToString(c)).join("\n");
2007
+ }
2008
+ function safeStringify(value, pretty = false) {
2009
+ if (value == null) return "";
2010
+ if (typeof value === "string") return value;
2011
+ try {
2012
+ return JSON.stringify(value, null, pretty ? 2 : void 0) ?? String(value);
2013
+ } catch {
2014
+ return String(value);
2015
+ }
2016
+ }
2017
+ function extractMessageText2(message) {
2018
+ if (!message) return "";
2019
+ const content = message.content;
2020
+ if (typeof content === "string") return content;
2021
+ if (Array.isArray(content)) {
2022
+ return content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? "").join("");
2023
+ }
2024
+ return "";
2025
+ }
2026
+
2027
+ // src/smart/toolResponses.ts
2028
+ var CONTROL_PLANE_TOOL_NAMES = [
2029
+ "response",
2030
+ "manage_todo_list",
2031
+ "get_tool_response",
2032
+ "ask_user_question",
2033
+ "open_skill",
2034
+ "bind_skill_tools",
2035
+ "search_skills"
2036
+ ];
2037
+ var DELEGATION_TOOL_NAMES = [
2038
+ "delegate_to",
2039
+ "spawn_subagent",
2040
+ "spawn_subagents_parallel"
2041
+ ];
2042
+ var INPUT_PROTECTED_TOOL_NAMES = /* @__PURE__ */ new Set([
2043
+ ...CONTROL_PLANE_TOOL_NAMES,
2044
+ ...DELEGATION_TOOL_NAMES
2045
+ ]);
2046
+ var CONTROL_PLANE_OUTPUT_DEFAULTS = new Set(CONTROL_PLANE_TOOL_NAMES);
2047
+ var DEFAULT_MAX_TOOL_INPUT_FIELD_CHARS = 2e3;
2048
+ var DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS = 200;
2049
+ var TOOL_INPUT_DIGEST_KEY = "__digest";
2050
+ function summarizeObject(value) {
2051
+ if (value == null) return "null";
2052
+ if (typeof value === "string") {
2053
+ return value.length > 240 ? `${value.slice(0, 240)}...` : value;
2054
+ }
2055
+ if (Array.isArray(value)) {
2056
+ const preview = value.slice(0, 3).map((entry) => safeStringify(entry).slice(0, 120)).join(" | ");
2057
+ return `array(length=${value.length}) ${preview}`.trim();
2058
+ }
2059
+ if (typeof value === "object") {
2060
+ const keys = Object.keys(value);
2061
+ const preview = keys.slice(0, 6).map((key) => `${key}=${safeStringify(value[key]).slice(0, 80)}`).join("; ");
2062
+ return `object(keys=${keys.length}) ${preview}`.trim();
2063
+ }
2064
+ return safeStringify(value);
2065
+ }
2066
+ function classifyToolResponse(toolName, output, config) {
2067
+ const criticalTools = new Set(config.toolResponses.criticalTools);
2068
+ if (criticalTools.has(toolName)) return "critical";
2069
+ const serialized = safeStringify(output);
2070
+ const tokenCount = countApproxTokens(serialized);
2071
+ if (tokenCount >= config.toolResponses.maxToolResponseTokens || serialized.length >= config.toolResponses.maxToolResponseChars) {
2072
+ return "verbose";
2073
+ }
2074
+ return "informative";
2075
+ }
2076
+ function applyToolResponseHardCap(toolName, output, executionId, config) {
2077
+ const serialized = safeStringify(output);
2078
+ const tokenCount = countApproxTokens(serialized);
2079
+ const classification = classifyToolResponse(toolName, output, config);
2080
+ if (classification !== "verbose") {
2081
+ return { classification, content: serialized, rawOutput: output, tokenCount, truncated: false };
2082
+ }
2083
+ const cap = config.toolResponses.maxToolResponseChars;
2084
+ const head = serialized.slice(0, cap);
2085
+ const note = `
2086
+ ... [TRUNCATED ${serialized.length - cap} chars by hard cap. Use get_tool_response with executionId="${executionId}" to fetch the full payload.]`;
2087
+ return {
2088
+ classification,
2089
+ content: head + note,
2090
+ rawOutput: output,
2091
+ tokenCount,
2092
+ truncated: true
2093
+ };
2094
+ }
2095
+ function collectToolRetentionDeclarations(tools) {
2096
+ const declarations = /* @__PURE__ */ new Map();
2097
+ if (!Array.isArray(tools)) return declarations;
2098
+ for (const tool of tools) {
2099
+ const spec = tool?.retention;
2100
+ const name = typeof tool?.name === "string" ? tool.name : "";
2101
+ if (!name || !spec || typeof spec !== "object") continue;
2102
+ declarations.set(name, spec);
2103
+ }
2104
+ return declarations;
2105
+ }
2106
+ function resolveSummarizationRetention(toolName, config, declarations) {
2107
+ const criticalTools = new Set(config.toolResponses.criticalTools);
2108
+ if (criticalTools.has(toolName)) return "keep_full";
2109
+ const twoAxis = config.toolResponses.retentionByTool?.[toolName]?.output;
2110
+ if (twoAxis) return twoAxis;
2111
+ const legacy = config.toolResponses.toolResponseRetentionByTool[toolName];
2112
+ if (legacy) return legacy;
2113
+ const declared = declarations?.get(toolName)?.output;
2114
+ if (declared) return declared;
2115
+ if (CONTROL_PLANE_OUTPUT_DEFAULTS.has(toolName)) return "keep_full";
2116
+ return config.toolResponses.defaultPolicy;
2117
+ }
2118
+ function resolveInputRetention(toolName, config, declarations) {
2119
+ if (INPUT_PROTECTED_TOOL_NAMES.has(toolName)) return "keep";
2120
+ const criticalTools = new Set(config.toolResponses.criticalTools);
2121
+ if (criticalTools.has(toolName)) return "keep";
2122
+ const twoAxis = config.toolResponses.retentionByTool?.[toolName]?.input;
2123
+ if (twoAxis) return twoAxis;
2124
+ const declared = declarations?.get(toolName)?.input;
2125
+ if (declared) return declared;
2126
+ return config.toolResponses.defaultInputPolicy;
2127
+ }
2128
+ function shortSha256(value) {
2129
+ return crypto.createHash("sha256").update(value, "utf8").digest("hex").slice(0, 16);
2130
+ }
2131
+ function isDigestMarker(value) {
2132
+ return Boolean(
2133
+ value && typeof value === "object" && !Array.isArray(value) && TOOL_INPUT_DIGEST_KEY in value
2134
+ );
2135
+ }
2136
+ function digestToolInputValue(value, options) {
2137
+ const maxFieldChars = options?.maxFieldChars ?? DEFAULT_MAX_TOOL_INPUT_FIELD_CHARS;
2138
+ const headChars = options?.headChars ?? DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS;
2139
+ const executionId = options?.executionId;
2140
+ const digestedPaths = [];
2141
+ let reclaimedChars = 0;
2142
+ const walk = (node, path2) => {
2143
+ if (typeof node === "string") {
2144
+ if (node.length <= maxFieldChars) return node;
2145
+ digestedPaths.push(path2 || "(root)");
2146
+ const marker = {
2147
+ chars: node.length,
2148
+ sha256: shortSha256(node),
2149
+ head: node.slice(0, headChars)
2150
+ };
2151
+ if (executionId) {
2152
+ marker.recover = `get_tool_response executionId="${executionId}" part="input"`;
2153
+ }
2154
+ const replacement = { [TOOL_INPUT_DIGEST_KEY]: marker };
2155
+ reclaimedChars += node.length - safeStringify(replacement).length;
2156
+ return replacement;
2157
+ }
2158
+ if (Array.isArray(node)) {
2159
+ let changed = false;
2160
+ const next = node.map((entry, index) => {
2161
+ const walked = walk(entry, path2 ? `${path2}[${index}]` : `[${index}]`);
2162
+ if (walked !== entry) changed = true;
2163
+ return walked;
2164
+ });
2165
+ return changed ? next : node;
2166
+ }
2167
+ if (node && typeof node === "object") {
2168
+ if (isDigestMarker(node)) return node;
2169
+ let changed = false;
2170
+ const next = {};
2171
+ for (const [key, entry] of Object.entries(node)) {
2172
+ const walked = walk(entry, path2 ? `${path2}.${key}` : key);
2173
+ if (walked !== entry) changed = true;
2174
+ next[key] = walked;
2175
+ }
2176
+ return changed ? next : node;
2177
+ }
2178
+ return node;
2179
+ };
2180
+ const nextValue = walk(value, "");
2181
+ return { value: nextValue, digestedPaths, reclaimedChars: Math.max(0, reclaimedChars) };
2182
+ }
2183
+ function digestToolInputArguments(argumentsJson, options) {
2184
+ const unchanged = { arguments: argumentsJson, digestedPaths: [], reclaimedChars: 0 };
2185
+ if (typeof argumentsJson !== "string" || argumentsJson.length === 0) return unchanged;
2186
+ let parsed;
2187
+ try {
2188
+ parsed = JSON.parse(argumentsJson);
2189
+ } catch {
2190
+ return unchanged;
2191
+ }
2192
+ const digested = digestToolInputValue(parsed, options);
2193
+ if (digested.digestedPaths.length === 0) return unchanged;
2194
+ const serialized = safeStringify(digested.value);
2195
+ if (serialized.length >= argumentsJson.length) return unchanged;
2196
+ return {
2197
+ arguments: serialized,
2198
+ digestedPaths: digested.digestedPaths,
2199
+ reclaimedChars: argumentsJson.length - serialized.length
2200
+ };
2201
+ }
2202
+ function renderRetainedToolMessage(args) {
2203
+ const { policy, rawOutput, toolName, toolCallId, executionId, prebuiltSummary } = args;
2204
+ if (policy === "keep_full") {
2205
+ return typeof rawOutput === "string" ? rawOutput : safeStringify(rawOutput);
2206
+ }
2207
+ const summary = prebuiltSummary || summarizeObject(rawOutput);
2208
+ const refs = [
2209
+ `toolName=${toolName}`,
2210
+ toolCallId ? `toolCallId=${toolCallId}` : null,
2211
+ executionId ? `executionId=${executionId}` : null
2212
+ ].filter(Boolean).join("; ");
2213
+ const refId = executionId || toolCallId || "";
2214
+ if (policy === "keep_structured") {
2215
+ return `STRUCTURED_TOOL_RESPONSE [${refs}]
2216
+ Preview: ${summary}
2217
+ Use get_tool_response with executionId "${refId}" to fetch the full payload when a specific field is needed.`;
2218
+ }
2219
+ if (policy === "summarize_archive") {
2220
+ return `ARCHIVED_TOOL_RESPONSE [${refs}]
2221
+ Summary: ${summary}
2222
+ Use get_tool_response with executionId "${refId}" to fetch the full payload.`;
2223
+ }
2224
+ return `DROPPED_TOOL_RESPONSE [${refs}]
2225
+ Use get_tool_response with executionId "${refId}" only if you must recover the original payload.`;
2226
+ }
2227
+ function validateToolArgs(tool, args) {
2228
+ const schema = tool.schema;
2229
+ if (!schema || typeof schema.parse !== "function") {
2230
+ return { ok: true, value: args };
2231
+ }
2232
+ try {
2233
+ return { ok: true, value: schema.parse(args) };
2234
+ } catch (error) {
2235
+ if (error instanceof zod.ZodError) {
2236
+ const message = error.issues.map((issue) => `${issue.path.join(".") || "root"}: ${issue.message}`).join("; ");
2237
+ return { ok: false, message };
2238
+ }
2239
+ return { ok: false, message: error instanceof Error ? error.message : String(error) };
2240
+ }
2241
+ }
2242
+
1975
2243
  // src/smart/runtimeConfig.ts
1976
2244
  var DEFAULT_CRITICAL_TOOLS = ["response", "manage_todo_list", "get_tool_response"];
1977
2245
  var BASE_DEFAULTS = {
@@ -2022,6 +2290,11 @@ var BASE_DEFAULTS = {
2022
2290
  maxToolResponseTokens: 8e3,
2023
2291
  defaultPolicy: "summarize_archive",
2024
2292
  toolResponseRetentionByTool: {},
2293
+ // Argument digesting is opt-in: the default never touches a tool's request.
2294
+ defaultInputPolicy: "keep",
2295
+ retentionByTool: {},
2296
+ maxToolInputFieldChars: DEFAULT_MAX_TOOL_INPUT_FIELD_CHARS,
2297
+ maxToolInputDigestHeadChars: DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS,
2025
2298
  criticalTools: [...DEFAULT_CRITICAL_TOOLS],
2026
2299
  schemaValidation: "strict"
2027
2300
  },
@@ -2076,7 +2349,8 @@ function buildProfile(overrides) {
2076
2349
  ...BASE_DEFAULTS.toolResponses,
2077
2350
  ...overrides.toolResponses,
2078
2351
  criticalTools: overrides.toolResponses?.criticalTools ?? [...DEFAULT_CRITICAL_TOOLS],
2079
- toolResponseRetentionByTool: overrides.toolResponses?.toolResponseRetentionByTool ?? {}
2352
+ toolResponseRetentionByTool: overrides.toolResponses?.toolResponseRetentionByTool ?? {},
2353
+ retentionByTool: overrides.toolResponses?.retentionByTool ?? {}
2080
2354
  },
2081
2355
  contextPilot: mergeContextPilot(BASE_DEFAULTS.contextPilot, overrides.contextPilot)
2082
2356
  };
@@ -2230,6 +2504,14 @@ function normalizeSmartAgentOptions(opts) {
2230
2504
  ...customProfile.toolResponses?.toolResponseRetentionByTool || {},
2231
2505
  ...opts.toolResponses?.toolResponseRetentionByTool || {}
2232
2506
  },
2507
+ // Two-axis map merges the same way, so a caller can layer a small override
2508
+ // on top of a profile's table instead of restating it.
2509
+ retentionByTool: {
2510
+ ...preset.toolResponses.retentionByTool,
2511
+ ...customProfile.toolResponses?.retentionByTool || {},
2512
+ ...opts.toolResponses?.retentionByTool || {}
2513
+ },
2514
+ defaultInputPolicy: opts.toolResponses?.defaultInputPolicy ?? customProfile.toolResponses?.defaultInputPolicy ?? preset.toolResponses.defaultInputPolicy,
2233
2515
  criticalTools: opts.toolResponses?.criticalTools ?? customProfile.toolResponses?.criticalTools ?? preset.toolResponses.criticalTools
2234
2516
  },
2235
2517
  contextPilot: mergeContextPilot(mergeContextPilot(preset.contextPilot, customProfile.contextPilot), opts.contextPilot)
@@ -2414,53 +2696,6 @@ function detectVolatileContent(text, limit = 20) {
2414
2696
 
2415
2697
  // src/smart/contextPilot/jsonCrusher.ts
2416
2698
  init_utilTokens();
2417
-
2418
- // src/utils/content.ts
2419
- function contentToString(content) {
2420
- try {
2421
- if (content == null) return "";
2422
- if (typeof content === "string") return content;
2423
- if (Array.isArray(content)) {
2424
- return content.map((p) => {
2425
- if (!p || typeof p !== "object") return String(p);
2426
- if (p.type === "text") return String(p.text ?? "");
2427
- if (p.type === "image_url") {
2428
- const img = p.image_url;
2429
- const url = typeof img === "string" ? img : img?.url;
2430
- const detail = typeof img === "string" ? void 0 : img?.detail;
2431
- return `[image:${url || "unknown"}${detail ? ` detail=${detail}` : ""}]`;
2432
- }
2433
- return JSON.stringify(p);
2434
- }).join("\n");
2435
- }
2436
- return JSON.stringify(content);
2437
- } catch {
2438
- return String(content);
2439
- }
2440
- }
2441
- function mergeContentsToString(contents) {
2442
- return contents.map((c) => contentToString(c)).join("\n");
2443
- }
2444
- function safeStringify(value, pretty = false) {
2445
- if (value == null) return "";
2446
- if (typeof value === "string") return value;
2447
- try {
2448
- return JSON.stringify(value, null, pretty ? 2 : void 0) ?? String(value);
2449
- } catch {
2450
- return String(value);
2451
- }
2452
- }
2453
- function extractMessageText2(message) {
2454
- if (!message) return "";
2455
- const content = message.content;
2456
- if (typeof content === "string") return content;
2457
- if (Array.isArray(content)) {
2458
- return content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? "").join("");
2459
- }
2460
- return "";
2461
- }
2462
-
2463
- // src/smart/contextPilot/jsonCrusher.ts
2464
2699
  var CONTEXT_PILOT_JSON_MARKER_KEY = "__contextPilotDropped";
2465
2700
  function findCompressibleArray(output, minItems) {
2466
2701
  if (Array.isArray(output)) {
@@ -3012,100 +3247,6 @@ function extractToolItems(output) {
3012
3247
  });
3013
3248
  }
3014
3249
 
3015
- // src/smart/toolResponses.ts
3016
- init_utilTokens();
3017
- function summarizeObject(value) {
3018
- if (value == null) return "null";
3019
- if (typeof value === "string") {
3020
- return value.length > 240 ? `${value.slice(0, 240)}...` : value;
3021
- }
3022
- if (Array.isArray(value)) {
3023
- const preview = value.slice(0, 3).map((entry) => safeStringify(entry).slice(0, 120)).join(" | ");
3024
- return `array(length=${value.length}) ${preview}`.trim();
3025
- }
3026
- if (typeof value === "object") {
3027
- const keys = Object.keys(value);
3028
- const preview = keys.slice(0, 6).map((key) => `${key}=${safeStringify(value[key]).slice(0, 80)}`).join("; ");
3029
- return `object(keys=${keys.length}) ${preview}`.trim();
3030
- }
3031
- return safeStringify(value);
3032
- }
3033
- function classifyToolResponse(toolName, output, config) {
3034
- const criticalTools = new Set(config.toolResponses.criticalTools);
3035
- if (criticalTools.has(toolName)) return "critical";
3036
- const serialized = safeStringify(output);
3037
- const tokenCount = countApproxTokens(serialized);
3038
- if (tokenCount >= config.toolResponses.maxToolResponseTokens || serialized.length >= config.toolResponses.maxToolResponseChars) {
3039
- return "verbose";
3040
- }
3041
- return "informative";
3042
- }
3043
- function applyToolResponseHardCap(toolName, output, executionId, config) {
3044
- const serialized = safeStringify(output);
3045
- const tokenCount = countApproxTokens(serialized);
3046
- const classification = classifyToolResponse(toolName, output, config);
3047
- if (classification !== "verbose") {
3048
- return { classification, content: serialized, rawOutput: output, tokenCount, truncated: false };
3049
- }
3050
- const cap = config.toolResponses.maxToolResponseChars;
3051
- const head = serialized.slice(0, cap);
3052
- const note = `
3053
- ... [TRUNCATED ${serialized.length - cap} chars by hard cap. Use get_tool_response with executionId="${executionId}" to fetch the full payload.]`;
3054
- return {
3055
- classification,
3056
- content: head + note,
3057
- rawOutput: output,
3058
- tokenCount,
3059
- truncated: true
3060
- };
3061
- }
3062
- function resolveSummarizationRetention(toolName, config) {
3063
- const criticalTools = new Set(config.toolResponses.criticalTools);
3064
- if (criticalTools.has(toolName)) return "keep_full";
3065
- const byTool = config.toolResponses.toolResponseRetentionByTool[toolName];
3066
- return byTool || config.toolResponses.defaultPolicy;
3067
- }
3068
- function renderRetainedToolMessage(args) {
3069
- const { policy, rawOutput, toolName, toolCallId, executionId, prebuiltSummary } = args;
3070
- if (policy === "keep_full") {
3071
- return typeof rawOutput === "string" ? rawOutput : safeStringify(rawOutput);
3072
- }
3073
- const summary = prebuiltSummary || summarizeObject(rawOutput);
3074
- const refs = [
3075
- `toolName=${toolName}`,
3076
- toolCallId ? `toolCallId=${toolCallId}` : null,
3077
- executionId ? `executionId=${executionId}` : null
3078
- ].filter(Boolean).join("; ");
3079
- const refId = executionId || toolCallId || "";
3080
- if (policy === "keep_structured") {
3081
- return `STRUCTURED_TOOL_RESPONSE [${refs}]
3082
- Preview: ${summary}
3083
- Use get_tool_response with executionId "${refId}" to fetch the full payload when a specific field is needed.`;
3084
- }
3085
- if (policy === "summarize_archive") {
3086
- return `ARCHIVED_TOOL_RESPONSE [${refs}]
3087
- Summary: ${summary}
3088
- Use get_tool_response with executionId "${refId}" to fetch the full payload.`;
3089
- }
3090
- return `DROPPED_TOOL_RESPONSE [${refs}]
3091
- Use get_tool_response with executionId "${refId}" only if you must recover the original payload.`;
3092
- }
3093
- function validateToolArgs(tool, args) {
3094
- const schema = tool.schema;
3095
- if (!schema || typeof schema.parse !== "function") {
3096
- return { ok: true, value: args };
3097
- }
3098
- try {
3099
- return { ok: true, value: schema.parse(args) };
3100
- } catch (error) {
3101
- if (error instanceof zod.ZodError) {
3102
- const message = error.issues.map((issue) => `${issue.path.join(".") || "root"}: ${issue.message}`).join("; ");
3103
- return { ok: false, message };
3104
- }
3105
- return { ok: false, message: error instanceof Error ? error.message : String(error) };
3106
- }
3107
- }
3108
-
3109
3250
  // src/utils/pendingToolCalls.ts
3110
3251
  function selectPendingToolCalls(messages) {
3111
3252
  if (!Array.isArray(messages) || messages.length === 0) return [];
@@ -5362,7 +5503,10 @@ function createAgent(opts) {
5362
5503
  }
5363
5504
  }
5364
5505
  }
5365
- if (soManager && !state.ctx?.__finalizedDueToStructuredOutput) {
5506
+ const structuredFinalizeBlocked = Boolean(
5507
+ pausedStage || state.ctx?.__awaitingApproval || state.ctx?.__awaitingUserQuestion || state.ctx?.__cancelled || state.ctx?.__needsSummarization || state.ctx?.__limitBreached || state.ctx?.__guardrailBlocked
5508
+ );
5509
+ if (soManager && !state.ctx?.__finalizedDueToStructuredOutput && !structuredFinalizeBlocked) {
5366
5510
  const lastForParse = state.messages[state.messages.length - 1];
5367
5511
  if (lastForParse?.role === "assistant") {
5368
5512
  const assistantText = extractMessageText2(lastForParse);
@@ -5379,10 +5523,11 @@ function createAgent(opts) {
5379
5523
  }
5380
5524
  }
5381
5525
  }
5382
- if (soManager && soManager.strategy.kind === "tool_based" && !state.ctx?.__finalizedDueToStructuredOutput) {
5526
+ if (soManager && soManager.strategy.kind === "tool_based" && !state.ctx?.__finalizedDueToStructuredOutput && !structuredFinalizeBlocked) {
5383
5527
  const maxPostLoopRetries = soManager.maxRetries;
5384
5528
  for (let postRetry = 0; postRetry < maxPostLoopRetries; postRetry++) {
5385
5529
  if (state.ctx?.__finalizedDueToStructuredOutput) break;
5530
+ if (state.ctx?.__awaitingApproval || state.ctx?.__awaitingUserQuestion || state.ctx?.__cancelled || state.ctx?.__limitBreached) break;
5386
5531
  const last = state.messages[state.messages.length - 1];
5387
5532
  const lastHasToolCalls = Array.isArray(last?.tool_calls) && last.tool_calls.length > 0;
5388
5533
  if (!lastHasToolCalls) {
@@ -5779,7 +5924,7 @@ function collectRecentTurns(messages, lastTurnsToKeep) {
5779
5924
  if (turnCount >= lastTurnsToKeep) break;
5780
5925
  }
5781
5926
  }
5782
- if (countAssistantTurns && collected.length > 0 && collected[0].role !== "user") {
5927
+ if (collected.length > 0) {
5783
5928
  const firstUserMsg = body.find((m) => m.role === "user");
5784
5929
  if (firstUserMsg && !collected.includes(firstUserMsg)) {
5785
5930
  collected.unshift(firstUserMsg);
@@ -5811,12 +5956,18 @@ function renderMemoryBlock(facts) {
5811
5956
  ...facts.map((fact) => `- ${fact.key}: ${fact.value}`)
5812
5957
  ].join("\n");
5813
5958
  }
5959
+ function isClampProtected(message, index, firstUserIndex) {
5960
+ if (message.role === "system") return true;
5961
+ if (index === firstUserIndex) return true;
5962
+ return false;
5963
+ }
5814
5964
  function clampToBudget(messages, maxContextTokens) {
5815
5965
  let working = [...messages];
5816
5966
  while (working.length > 2) {
5817
5967
  const tokenCount = countApproxTokens(working.map(extractMessageText2).join("\n"));
5818
5968
  if (tokenCount <= maxContextTokens) return working;
5819
- const firstNonSystem = working.findIndex((message, index) => !(index === 0 && message.role === "system"));
5969
+ const firstUserIndex = working.findIndex((message) => message.role === "user");
5970
+ const firstNonSystem = working.findIndex((message, index) => !isClampProtected(message, index, firstUserIndex));
5820
5971
  if (firstNonSystem < 0) break;
5821
5972
  const target = working[firstNonSystem];
5822
5973
  if (target.role === "assistant" && Array.isArray(target.tool_calls) && target.tool_calls.length > 0) {
@@ -6255,9 +6406,42 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
6255
6406
  break;
6256
6407
  }
6257
6408
  }
6409
+ const retentionDeclarations = collectToolRetentionDeclarations(state.agent?.tools);
6410
+ const digestableToolCallIds = /* @__PURE__ */ new Set();
6411
+ for (const m of messages) {
6412
+ if (m.role !== "tool" || isSyntheticSummaryMessage(m)) continue;
6413
+ const toolCallId = m.tool_call_id;
6414
+ if (!toolCallId || !toolCallIdToAssistantIdx.has(toolCallId)) continue;
6415
+ if (protectedToolCallIds.has(toolCallId)) continue;
6416
+ const toolName = m.name || "";
6417
+ if (resolveInputRetention(toolName, resolved, retentionDeclarations) !== "digest") continue;
6418
+ digestableToolCallIds.add(toolCallId);
6419
+ }
6258
6420
  const archivedExecutions = [...state.toolHistoryArchived || []];
6259
6421
  const archivedIds = new Set(archivedExecutions.map((entry) => entry?.executionId).filter(Boolean));
6260
6422
  const newMessages = messages.map((m) => {
6423
+ if (m.role === "assistant" && Array.isArray(m.tool_calls) && m.tool_calls.length > 0) {
6424
+ if (m.reasoning?.blocks?.length) return m;
6425
+ let changed = false;
6426
+ const nextToolCalls = m.tool_calls.map((tc) => {
6427
+ const args = tc?.function?.arguments;
6428
+ if (!tc?.id || !digestableToolCallIds.has(tc.id)) return tc;
6429
+ if (typeof args !== "string") return tc;
6430
+ const historyEntry = findToolHistoryEntry(state, tc.id, tc.function?.name);
6431
+ const digested = digestToolInputArguments(args, {
6432
+ maxFieldChars: resolved.toolResponses.maxToolInputFieldChars,
6433
+ headChars: resolved.toolResponses.maxToolInputDigestHeadChars,
6434
+ executionId: historyEntry?.executionId ?? tc.id
6435
+ });
6436
+ if (digested.digestedPaths.length === 0) return tc;
6437
+ changed = true;
6438
+ return {
6439
+ ...tc,
6440
+ function: { ...tc.function, arguments: digested.arguments }
6441
+ };
6442
+ });
6443
+ return changed ? { ...m, tool_calls: nextToolCalls } : m;
6444
+ }
6261
6445
  if (m.role === "tool") {
6262
6446
  if (isSyntheticSummaryMessage(m)) {
6263
6447
  return m;
@@ -6393,7 +6577,9 @@ var TOOL_RESPONSE_RECOVERY_MARKERS = [
6393
6577
  /STRUCTURED_TOOL_RESPONSE\s*\[/,
6394
6578
  /SUMMARIZED_TOOL_RESPONSE\b/,
6395
6579
  /DROPPED_TOOL_RESPONSE\s*\[/,
6396
- /Use get_tool_response with executionId/i
6580
+ /Use get_tool_response with executionId/i,
6581
+ // Field-level ARGUMENT digest marker (see smart/toolResponses digestToolInputValue).
6582
+ /"__digest"\s*:/
6397
6583
  ];
6398
6584
  var todoStatusSchema = zod.z.enum(["not-started", "in-progress", "completed", "blocked"]);
6399
6585
  var todoWriteItemSchema = zod.z.object({
@@ -6485,6 +6671,24 @@ function flattenRecoveryContent(content) {
6485
6671
  }
6486
6672
  return "";
6487
6673
  }
6674
+ function flattenToolCallArguments(message) {
6675
+ const toolCalls = message?.tool_calls;
6676
+ if (!Array.isArray(toolCalls)) {
6677
+ return "";
6678
+ }
6679
+ return toolCalls.map((call) => {
6680
+ const args = call?.function?.arguments;
6681
+ if (typeof args === "string") return args;
6682
+ if (args && typeof args === "object") {
6683
+ try {
6684
+ return JSON.stringify(args);
6685
+ } catch {
6686
+ return "";
6687
+ }
6688
+ }
6689
+ return "";
6690
+ }).filter(Boolean).join("\n");
6691
+ }
6488
6692
  function hasToolResponseRecoveryReference(messages, executionId) {
6489
6693
  if (!Array.isArray(messages) || messages.length === 0) {
6490
6694
  return false;
@@ -6493,7 +6697,10 @@ function hasToolResponseRecoveryReference(messages, executionId) {
6493
6697
  if (message?.role === "system") {
6494
6698
  return false;
6495
6699
  }
6496
- const content = flattenRecoveryContent(message?.content);
6700
+ const content = [
6701
+ flattenRecoveryContent(message?.content),
6702
+ flattenToolCallArguments(message)
6703
+ ].filter(Boolean).join("\n");
6497
6704
  if (!content) {
6498
6705
  return false;
6499
6706
  }
@@ -6673,12 +6880,15 @@ function createManageTodoTool(stateRef) {
6673
6880
  function createGetToolResponseTool(stateRef) {
6674
6881
  const getTool = createTool({
6675
6882
  name: "get_tool_response",
6676
- description: "RETRIEVE the full output of a tool execution whose response was archived, dropped, truncated, or later compacted in conversation history. This tool is only useful when the visible transcript already shows a reduced tool-response marker for the referenced executionId or tool_call_id. Use it only when a marker such as 'ARCHIVED_TOOL_RESPONSE', 'STRUCTURED_TOOL_RESPONSE', 'SUMMARIZED_TOOL_RESPONSE', 'DROPPED_TOOL_RESPONSE', or an explicit truncation note points you to a missing field you still need. Do not call it to re-fetch a normal tool result that is already present in context.",
6677
- schema: zod.z.object({ executionId: zod.z.string().describe("Tool execution id or original tool_call_id") }),
6883
+ description: `RETRIEVE the full input or output of a tool execution that was reduced in conversation history. This tool is only useful when the visible transcript already shows a reduced marker for the referenced executionId or tool_call_id. Use it when a marker such as 'ARCHIVED_TOOL_RESPONSE', 'STRUCTURED_TOOL_RESPONSE', 'SUMMARIZED_TOOL_RESPONSE', 'DROPPED_TOOL_RESPONSE', an explicit truncation note, or a '__digest' descriptor inside a past tool call's arguments points you to something you still need. Pass part="input" to recover arguments that were digested (their small fields are still visible; only the large payload was replaced), or part="output" (the default) to recover an archived result. Do not call it to re-fetch a normal tool result that is already present in context.`,
6884
+ schema: zod.z.object({
6885
+ executionId: zod.z.string().describe("Tool execution id or original tool_call_id"),
6886
+ part: zod.z.enum(["input", "output"]).optional().describe('Which side of the exchange to recover. Defaults to "output".')
6887
+ }),
6678
6888
  maxExecutionsPerRun: 8,
6679
- func: async ({ executionId }) => {
6889
+ func: async ({ executionId, part }) => {
6680
6890
  if (!hasToolResponseRecoveryReference(stateRef.messages, executionId)) {
6681
- return "Execution not recoverable from the visible transcript. Use this only when the conversation already shows a reduced tool-response marker for that executionId.";
6891
+ return "Execution not recoverable from the visible transcript. Use this only when the conversation already shows a reduced tool-response or __digest marker for that executionId.";
6682
6892
  }
6683
6893
  const matchesExecution = (t) => t?.executionId === executionId || t?.tool_call_id === executionId;
6684
6894
  let execution = stateRef.toolHistory?.find((t) => matchesExecution(t));
@@ -6686,6 +6896,9 @@ function createGetToolResponseTool(stateRef) {
6686
6896
  execution = stateRef.toolHistoryArchived?.find((t) => matchesExecution(t));
6687
6897
  }
6688
6898
  if (execution) {
6899
+ if (part === "input") {
6900
+ return execution.args ?? "Arguments were not recorded for this execution.";
6901
+ }
6689
6902
  return execution.rawOutput || execution.output;
6690
6903
  }
6691
6904
  const ccrStore = stateRef.ctx?.__contextPilot?.ccrStore;
@@ -11025,10 +11238,14 @@ exports.BaseProvider = BaseProvider;
11025
11238
  exports.BedrockProvider = BedrockProvider;
11026
11239
  exports.CCRStore = CCRStore;
11027
11240
  exports.CONTEXT_PILOT_JSON_MARKER_KEY = CONTEXT_PILOT_JSON_MARKER_KEY;
11241
+ exports.CONTROL_PLANE_TOOL_NAMES = CONTROL_PLANE_TOOL_NAMES;
11242
+ exports.DEFAULT_MAX_TOOL_INPUT_FIELD_CHARS = DEFAULT_MAX_TOOL_INPUT_FIELD_CHARS;
11028
11243
  exports.DEFAULT_PROFILE_CONFIGS = DEFAULT_PROFILE_CONFIGS;
11029
11244
  exports.DEFAULT_SKILL_POLICY = DEFAULT_SKILL_POLICY;
11030
11245
  exports.DEFAULT_SUBAGENT_POLICY = DEFAULT_SUBAGENT_POLICY;
11031
11246
  exports.DEFAULT_SUBAGENT_TOOL_NAMES = DEFAULT_SUBAGENT_TOOL_NAMES;
11247
+ exports.DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS = DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS;
11248
+ exports.DELEGATION_TOOL_NAMES = DELEGATION_TOOL_NAMES;
11032
11249
  exports.DedupTracker = DedupTracker;
11033
11250
  exports.GuardrailPhase = GuardrailPhase;
11034
11251
  exports.InMemoryMemoryStore = InMemoryMemoryStore;
@@ -11038,6 +11255,7 @@ exports.OpenAIProvider = OpenAIProvider;
11038
11255
  exports.ProviderError = ProviderError;
11039
11256
  exports.SMALL_TIER_SKILL_POLICY = SMALL_TIER_SKILL_POLICY;
11040
11257
  exports.StructuredOutputManager = StructuredOutputManager;
11258
+ exports.TOOL_INPUT_DIGEST_KEY = TOOL_INPUT_DIGEST_KEY;
11041
11259
  exports.ToolBasedStrategy = ToolBasedStrategy;
11042
11260
  exports.VertexProvider = VertexProvider;
11043
11261
  exports.agentVerdictRule = agentVerdictRule;
@@ -11050,6 +11268,7 @@ exports.canSpawn = canSpawn;
11050
11268
  exports.captureSnapshot = captureSnapshot;
11051
11269
  exports.codePresenceRule = codePresenceRule;
11052
11270
  exports.cognipeerSink = cognipeerSink;
11271
+ exports.collectToolRetentionDeclarations = collectToolRetentionDeclarations;
11053
11272
  exports.composeToolSets = composeToolSets;
11054
11273
  exports.compressDiffOutput = compressDiffOutput;
11055
11274
  exports.compressJsonOutput = compressJsonOutput;
@@ -11093,6 +11312,8 @@ exports.dedupeToolsByName = dedupeToolsByName;
11093
11312
  exports.defaultTokenCounter = defaultTokenCounter;
11094
11313
  exports.detectTextFormat = detectTextFormat;
11095
11314
  exports.detectVolatileContent = detectVolatileContent;
11315
+ exports.digestToolInputArguments = digestToolInputArguments;
11316
+ exports.digestToolInputValue = digestToolInputValue;
11096
11317
  exports.emptyUsage = emptyUsage;
11097
11318
  exports.evaluateGuardrails = evaluateGuardrails;
11098
11319
  exports.extractLatestUserQuery = extractLatestUserQuery;
@@ -11120,10 +11341,12 @@ exports.readMemoryFacts = readMemoryFacts;
11120
11341
  exports.regexRule = regexRule;
11121
11342
  exports.resolveAvailableSkills = resolveAvailableSkills;
11122
11343
  exports.resolveAvailableSubagents = resolveAvailableSubagents;
11344
+ exports.resolveInputRetention = resolveInputRetention;
11123
11345
  exports.resolveMemoryStore = resolveMemoryStore;
11124
11346
  exports.resolveReasoning = resolveReasoning;
11125
11347
  exports.resolveStrategy = resolveStrategy;
11126
11348
  exports.resolveSubagentTools = resolveSubagentTools;
11349
+ exports.resolveSummarizationRetention = resolveSummarizationRetention;
11127
11350
  exports.resolveToolApprovalState = resolveToolApprovalState;
11128
11351
  exports.resolveUserQuestionState = resolveUserQuestionState;
11129
11352
  exports.restoreSnapshot = restoreSnapshot;
@@ -11134,6 +11357,7 @@ exports.seedChildMessages = seedChildMessages;
11134
11357
  exports.selectTopIndicesInOrder = selectTopIndicesInOrder;
11135
11358
  exports.setTokenCounter = setTokenCounter;
11136
11359
  exports.startStreamingSession = startStreamingSession;
11360
+ exports.summarizeObject = summarizeObject;
11137
11361
  exports.tokenize = tokenize;
11138
11362
  exports.traceSessionToOtlp = traceSessionToOtlp;
11139
11363
  exports.validateReasoningConfig = validateReasoningConfig;