@cognipeer/agent-sdk 0.6.6 → 0.7.1

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.mjs CHANGED
@@ -42,7 +42,7 @@ function getTokenCounter() {
42
42
  function countApproxTokens(text) {
43
43
  return activeTokenCounter(text || "");
44
44
  }
45
- function extractMessageText(m) {
45
+ function extractMessageText2(m) {
46
46
  if (!m) return "";
47
47
  const parts = [];
48
48
  parts.push(m.role || "");
@@ -92,7 +92,7 @@ function extractMessageText(m) {
92
92
  }
93
93
  function countMessagesTokens(messages) {
94
94
  if (!Array.isArray(messages) || messages.length === 0) return 0;
95
- const allText = messages.map(extractMessageText).join("\n");
95
+ const allText = messages.map(extractMessageText2).join("\n");
96
96
  return countApproxTokens(allText) + messages.length * 4;
97
97
  }
98
98
  var activeTokenCounter;
@@ -1262,6 +1262,7 @@ function eventToOtlpSpan(event) {
1262
1262
  stringAttr("cognipeer.actor.role", event.actor?.role),
1263
1263
  stringAttr("cognipeer.model", event.model),
1264
1264
  stringAttr("cognipeer.provider", event.provider),
1265
+ stringAttr("cognipeer.tool.details", event.toolDetails ? JSON.stringify(event.toolDetails) : void 0),
1265
1266
  intAttr("cognipeer.tokens.input", event.inputTokens),
1266
1267
  intAttr("cognipeer.tokens.output", event.outputTokens),
1267
1268
  intAttr("cognipeer.tokens.total", event.totalTokens),
@@ -1733,6 +1734,7 @@ function recordTraceEvent(session, event) {
1733
1734
  responseBytes,
1734
1735
  model: resolvedModel,
1735
1736
  provider: resolvedProvider,
1737
+ toolDetails: session.resolvedConfig.logData ? sanitizeTracePayload(event.toolDetails) : void 0,
1736
1738
  toolExecutionId: event.toolExecutionId,
1737
1739
  retryOf: event.retryOf,
1738
1740
  error: event.error ?? (status === "error" ? { message: "Unknown error" } : void 0) ?? void 0,
@@ -2183,16 +2185,99 @@ function createAgentCoreNode(opts) {
2183
2185
  };
2184
2186
  }
2185
2187
 
2188
+ // src/utils/content.ts
2189
+ function contentToString(content) {
2190
+ try {
2191
+ if (content == null) return "";
2192
+ if (typeof content === "string") return content;
2193
+ if (Array.isArray(content)) {
2194
+ return content.map((p) => {
2195
+ if (!p || typeof p !== "object") return String(p);
2196
+ if (p.type === "text") return String(p.text ?? "");
2197
+ if (p.type === "image_url") {
2198
+ const img = p.image_url;
2199
+ const url = typeof img === "string" ? img : img?.url;
2200
+ const detail = typeof img === "string" ? void 0 : img?.detail;
2201
+ return `[image:${url || "unknown"}${detail ? ` detail=${detail}` : ""}]`;
2202
+ }
2203
+ return JSON.stringify(p);
2204
+ }).join("\n");
2205
+ }
2206
+ return JSON.stringify(content);
2207
+ } catch {
2208
+ return String(content);
2209
+ }
2210
+ }
2211
+ function mergeContentsToString(contents) {
2212
+ return contents.map((c) => contentToString(c)).join("\n");
2213
+ }
2214
+ function safeStringify(value, pretty = false) {
2215
+ if (value == null) return "";
2216
+ if (typeof value === "string") return value;
2217
+ try {
2218
+ return JSON.stringify(value, null, pretty ? 2 : void 0) ?? String(value);
2219
+ } catch {
2220
+ return String(value);
2221
+ }
2222
+ }
2223
+ function extractMessageText(message) {
2224
+ if (!message) return "";
2225
+ const content = message.content;
2226
+ if (typeof content === "string") return content;
2227
+ if (Array.isArray(content)) {
2228
+ return content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? "").join("");
2229
+ }
2230
+ return "";
2231
+ }
2232
+
2233
+ // src/utils/traceSections.ts
2234
+ function truncate(text, max = 500) {
2235
+ if (!text) return "";
2236
+ return text.length > max ? `${text.slice(0, max)}\u2026` : text;
2237
+ }
2238
+ function summarizeToolOutput(output) {
2239
+ if (output == null) return "";
2240
+ if (typeof output === "string") return truncate(output.trim());
2241
+ if (Array.isArray(output)) {
2242
+ const preview = output.slice(0, 3).map((item, index) => `${index + 1}. ${truncate(safeStringify(item))}`).join("\n");
2243
+ const suffix = output.length > 3 ? `
2244
+ \u2026 (+${output.length - 3} more)` : "";
2245
+ return `${preview}${suffix}`.trim();
2246
+ }
2247
+ if (typeof output === "object") {
2248
+ if (Array.isArray(output.items)) {
2249
+ return summarizeToolOutput(output.items);
2250
+ }
2251
+ return truncate(safeStringify(output));
2252
+ }
2253
+ return truncate(String(output));
2254
+ }
2255
+ function extractToolItems(output) {
2256
+ const source = Array.isArray(output) ? output : Array.isArray(output?.items) ? output.items : void 0;
2257
+ if (!Array.isArray(source) || source.length === 0) return void 0;
2258
+ return source.slice(0, 5).map((item) => {
2259
+ if (item && typeof item === "object") {
2260
+ const snippetSource = item.content ?? item.snippet ?? item.description ?? item.text ?? item.summary ?? item;
2261
+ return {
2262
+ title: typeof item.title === "string" ? item.title : void 0,
2263
+ url: typeof item.url === "string" ? item.url : void 0,
2264
+ snippet: truncate(safeStringify(snippetSource))
2265
+ };
2266
+ }
2267
+ return { snippet: truncate(safeStringify(item)) };
2268
+ });
2269
+ }
2270
+
2186
2271
  // src/smart/runtimeConfig.ts
2187
2272
  var DEFAULT_CRITICAL_TOOLS = ["response", "manage_todo_list", "get_tool_response"];
2188
2273
  var BASE_DEFAULTS = {
2189
- limits: { maxToolCalls: 8, maxParallelTools: 2, maxContextTokens: 24e3, maxTotalOutputTokens: 0, maxCostUsd: 0, maxWallClockMs: 0 },
2274
+ limits: { maxToolCalls: 20, maxParallelTools: 5, maxContextTokens: 96e3, maxTotalOutputTokens: 0, maxCostUsd: 0, maxWallClockMs: 0 },
2190
2275
  summarization: {
2191
2276
  enable: true,
2192
- maxTokens: 24e3,
2193
- summaryTriggerTokens: 17e3,
2194
- summaryPromptMaxTokens: 7e3,
2195
- summaryCompressionRatioTarget: 0.35,
2277
+ maxTokens: 96e3,
2278
+ summaryTriggerTokens: 72e3,
2279
+ summaryPromptMaxTokens: 12e3,
2280
+ summaryCompressionRatioTarget: 0.45,
2196
2281
  summaryMode: "incremental",
2197
2282
  promptTemplate: "",
2198
2283
  toolFreeCall: true,
@@ -2200,13 +2285,13 @@ var BASE_DEFAULTS = {
2200
2285
  },
2201
2286
  context: {
2202
2287
  policy: "hybrid",
2203
- lastTurnsToKeep: 8,
2288
+ lastTurnsToKeep: 16,
2204
2289
  toolResponsePolicy: "summarize_archive",
2205
2290
  budget: {
2206
- systemReserveTokens: 1200,
2207
- goalsReserveTokens: 1200,
2208
- recentTurnsReserveTokens: 5200,
2209
- toolResponseReserveTokens: 2800
2291
+ systemReserveTokens: 2e3,
2292
+ goalsReserveTokens: 2e3,
2293
+ recentTurnsReserveTokens: 18e3,
2294
+ toolResponseReserveTokens: 9e3
2210
2295
  }
2211
2296
  },
2212
2297
  planning: {
@@ -2223,14 +2308,14 @@ var BASE_DEFAULTS = {
2223
2308
  delegation: {
2224
2309
  mode: "role_based",
2225
2310
  maxDelegationDepth: 2,
2226
- maxChildCalls: 4,
2227
- maxParallelChild: 2,
2311
+ maxChildCalls: 6,
2312
+ maxParallelChild: 3,
2228
2313
  childContextPolicy: "scoped",
2229
2314
  requireJsonOutputContract: true
2230
2315
  },
2231
2316
  toolResponses: {
2232
- maxToolResponseChars: 12e3,
2233
- maxToolResponseTokens: 3e3,
2317
+ maxToolResponseChars: 32e3,
2318
+ maxToolResponseTokens: 8e3,
2234
2319
  defaultPolicy: "summarize_archive",
2235
2320
  toolResponseRetentionByTool: {},
2236
2321
  criticalTools: [...DEFAULT_CRITICAL_TOOLS],
@@ -2259,54 +2344,54 @@ function buildProfile(overrides) {
2259
2344
  }
2260
2345
  var DEFAULT_PROFILE_CONFIGS = {
2261
2346
  fast: buildProfile({
2262
- limits: { maxToolCalls: 4, maxParallelTools: 1, maxContextTokens: 12e3 },
2347
+ limits: { maxToolCalls: 8, maxParallelTools: 3, maxContextTokens: 32e3 },
2263
2348
  summarization: {
2264
- maxTokens: 12e3,
2265
- summaryTriggerTokens: 9e3,
2266
- summaryPromptMaxTokens: 5e3,
2267
- summaryCompressionRatioTarget: 0.4
2349
+ maxTokens: 32e3,
2350
+ summaryTriggerTokens: 24e3,
2351
+ summaryPromptMaxTokens: 6e3,
2352
+ summaryCompressionRatioTarget: 0.5
2268
2353
  },
2269
2354
  context: {
2270
- lastTurnsToKeep: 6,
2355
+ lastTurnsToKeep: 8,
2271
2356
  toolResponsePolicy: "keep_structured",
2272
- budget: { systemReserveTokens: 1e3, goalsReserveTokens: 900, recentTurnsReserveTokens: 3200, toolResponseReserveTokens: 1800 }
2357
+ budget: { systemReserveTokens: 1500, goalsReserveTokens: 1200, recentTurnsReserveTokens: 6e3, toolResponseReserveTokens: 3500 }
2273
2358
  },
2274
2359
  memory: { readPolicy: "recent_only" },
2275
2360
  delegation: { mode: "off", maxDelegationDepth: 1, maxChildCalls: 2, maxParallelChild: 1, childContextPolicy: "minimal" },
2276
- toolResponses: { maxToolResponseChars: 8e3, maxToolResponseTokens: 2e3 }
2361
+ toolResponses: { maxToolResponseChars: 16e3, maxToolResponseTokens: 4e3 }
2277
2362
  }),
2278
2363
  balanced: buildProfile({}),
2279
2364
  deep: buildProfile({
2280
- limits: { maxToolCalls: 14, maxParallelTools: 3, maxContextTokens: 42e3 },
2365
+ limits: { maxToolCalls: 40, maxParallelTools: 8, maxContextTokens: 2e5 },
2281
2366
  summarization: {
2282
- maxTokens: 42e3,
2283
- summaryTriggerTokens: 3e4,
2284
- summaryPromptMaxTokens: 9e3,
2285
- summaryCompressionRatioTarget: 0.3
2367
+ maxTokens: 2e5,
2368
+ summaryTriggerTokens: 15e4,
2369
+ summaryPromptMaxTokens: 16e3,
2370
+ summaryCompressionRatioTarget: 0.4
2286
2371
  },
2287
2372
  context: {
2288
- lastTurnsToKeep: 12,
2289
- budget: { systemReserveTokens: 1400, goalsReserveTokens: 1600, recentTurnsReserveTokens: 7e3, toolResponseReserveTokens: 3600 }
2373
+ lastTurnsToKeep: 30,
2374
+ budget: { systemReserveTokens: 2500, goalsReserveTokens: 2500, recentTurnsReserveTokens: 36e3, toolResponseReserveTokens: 18e3 }
2290
2375
  },
2291
2376
  memory: { scope: "workspace" },
2292
- delegation: { maxDelegationDepth: 3, maxChildCalls: 6 },
2293
- toolResponses: { maxToolResponseChars: 16e3, maxToolResponseTokens: 4e3 }
2377
+ delegation: { maxDelegationDepth: 3, maxChildCalls: 10, maxParallelChild: 4 },
2378
+ toolResponses: { maxToolResponseChars: 64e3, maxToolResponseTokens: 16e3 }
2294
2379
  }),
2295
2380
  research: buildProfile({
2296
- limits: { maxToolCalls: 20, maxParallelTools: 4, maxContextTokens: 56e3 },
2381
+ limits: { maxToolCalls: 80, maxParallelTools: 10, maxContextTokens: 4e5 },
2297
2382
  summarization: {
2298
- maxTokens: 56e3,
2299
- summaryTriggerTokens: 42e3,
2300
- summaryPromptMaxTokens: 1e4,
2301
- summaryCompressionRatioTarget: 0.28
2383
+ maxTokens: 4e5,
2384
+ summaryTriggerTokens: 3e5,
2385
+ summaryPromptMaxTokens: 24e3,
2386
+ summaryCompressionRatioTarget: 0.35
2302
2387
  },
2303
2388
  context: {
2304
- lastTurnsToKeep: 20,
2305
- budget: { systemReserveTokens: 1600, goalsReserveTokens: 1800, recentTurnsReserveTokens: 9e3, toolResponseReserveTokens: 4800 }
2389
+ lastTurnsToKeep: 60,
2390
+ budget: { systemReserveTokens: 3e3, goalsReserveTokens: 3e3, recentTurnsReserveTokens: 72e3, toolResponseReserveTokens: 32e3 }
2306
2391
  },
2307
2392
  memory: { scope: "workspace" },
2308
- delegation: { mode: "automatic", maxDelegationDepth: 4, maxChildCalls: 8, maxParallelChild: 3, childContextPolicy: "full" },
2309
- toolResponses: { maxToolResponseChars: 24e3, maxToolResponseTokens: 6e3 }
2393
+ delegation: { mode: "automatic", maxDelegationDepth: 4, maxChildCalls: 16, maxParallelChild: 6, childContextPolicy: "full" },
2394
+ toolResponses: { maxToolResponseChars: 96e3, maxToolResponseTokens: 24e3 }
2310
2395
  })
2311
2396
  };
2312
2397
  function mergeLimits(base, override) {
@@ -2396,53 +2481,6 @@ function getResolvedSmartConfig(opts, runtime) {
2396
2481
 
2397
2482
  // src/smart/toolResponses.ts
2398
2483
  init_utilTokens();
2399
-
2400
- // src/utils/content.ts
2401
- function contentToString(content) {
2402
- try {
2403
- if (content == null) return "";
2404
- if (typeof content === "string") return content;
2405
- if (Array.isArray(content)) {
2406
- return content.map((p) => {
2407
- if (!p || typeof p !== "object") return String(p);
2408
- if (p.type === "text") return String(p.text ?? "");
2409
- if (p.type === "image_url") {
2410
- const img = p.image_url;
2411
- const url = typeof img === "string" ? img : img?.url;
2412
- const detail = typeof img === "string" ? void 0 : img?.detail;
2413
- return `[image:${url || "unknown"}${detail ? ` detail=${detail}` : ""}]`;
2414
- }
2415
- return JSON.stringify(p);
2416
- }).join("\n");
2417
- }
2418
- return JSON.stringify(content);
2419
- } catch {
2420
- return String(content);
2421
- }
2422
- }
2423
- function mergeContentsToString(contents) {
2424
- return contents.map((c) => contentToString(c)).join("\n");
2425
- }
2426
- function safeStringify(value, pretty = false) {
2427
- if (value == null) return "";
2428
- if (typeof value === "string") return value;
2429
- try {
2430
- return JSON.stringify(value, null, pretty ? 2 : void 0) ?? String(value);
2431
- } catch {
2432
- return String(value);
2433
- }
2434
- }
2435
- function extractMessageText2(message) {
2436
- if (!message) return "";
2437
- const content = message.content;
2438
- if (typeof content === "string") return content;
2439
- if (Array.isArray(content)) {
2440
- return content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? "").join("");
2441
- }
2442
- return "";
2443
- }
2444
-
2445
- // src/smart/toolResponses.ts
2446
2484
  function summarizeObject(value) {
2447
2485
  if (value == null) return "null";
2448
2486
  if (typeof value === "string") {
@@ -2557,6 +2595,97 @@ function normalizeToolCall(call) {
2557
2595
  args: call.args ?? call.arguments ?? call.input ?? call.function?.arguments ?? call.function_call?.arguments
2558
2596
  };
2559
2597
  }
2598
+ function normalizeToolSchema(tool, toolName) {
2599
+ const schema = tool.schema;
2600
+ if (!schema) return void 0;
2601
+ if (typeof schema === "object" && schema._def) {
2602
+ try {
2603
+ return sanitizeTracePayload(zodToJsonSchema(schema, { name: toolName }));
2604
+ } catch {
2605
+ }
2606
+ }
2607
+ if (schema && typeof schema === "object" && typeof schema.toJSON === "function") {
2608
+ try {
2609
+ return sanitizeTracePayload(schema.toJSON());
2610
+ } catch {
2611
+ }
2612
+ }
2613
+ return sanitizeTracePayload(schema);
2614
+ }
2615
+ function buildToolDetails(tool, toolName) {
2616
+ if (!tool) return void 0;
2617
+ const details = { name: toolName };
2618
+ if (typeof tool.description === "string" && tool.description.trim().length > 0) {
2619
+ details.description = tool.description;
2620
+ }
2621
+ const inputSchema = normalizeToolSchema(tool, toolName);
2622
+ if (inputSchema !== void 0) details.inputSchema = inputSchema;
2623
+ const needsApproval = typeof tool.needsApproval === "boolean" ? tool.needsApproval : void 0;
2624
+ if (needsApproval !== void 0 || tool.approvalPrompt !== void 0 || tool.approvalDefaults !== void 0) {
2625
+ details.approval = {
2626
+ required: needsApproval,
2627
+ prompt: typeof tool.approvalPrompt === "string" ? tool.approvalPrompt : void 0,
2628
+ defaults: tool.approvalDefaults !== void 0 ? sanitizeTracePayload(tool.approvalDefaults) : void 0
2629
+ };
2630
+ }
2631
+ const cache = tool.cache;
2632
+ if (cache !== void 0) {
2633
+ details.cache = {
2634
+ enabled: Boolean(cache),
2635
+ scope: cache && typeof cache === "object" && typeof cache.scope === "string" ? cache.scope : void 0,
2636
+ ttlMs: cache && typeof cache === "object" && typeof cache.ttlMs === "number" ? cache.ttlMs : void 0,
2637
+ hasKeyFn: Boolean(cache && typeof cache === "object" && typeof cache.keyFn === "function")
2638
+ };
2639
+ }
2640
+ const retry = tool.retry;
2641
+ if (retry && typeof retry === "object") {
2642
+ details.retry = {
2643
+ maxRetries: typeof retry.maxRetries === "number" ? retry.maxRetries : void 0,
2644
+ backoffMs: typeof retry.backoffMs === "number" ? retry.backoffMs : void 0,
2645
+ circuitBreakerThreshold: typeof retry.circuitBreakerThreshold === "number" ? retry.circuitBreakerThreshold : void 0,
2646
+ hasShouldRetry: typeof retry.shouldRetry === "function"
2647
+ };
2648
+ }
2649
+ if (tool.maxExecutionsPerRun !== void 0) {
2650
+ details.limits = { maxExecutionsPerRun: tool.maxExecutionsPerRun };
2651
+ }
2652
+ if (typeof tool.__source === "string") {
2653
+ details.source = tool.__source;
2654
+ }
2655
+ return details;
2656
+ }
2657
+ function buildToolTraceSections(params) {
2658
+ const sanitizedArgs = sanitizeTracePayload(params.args ?? {});
2659
+ const sanitizedOutput = sanitizeTracePayload(params.output);
2660
+ const summary = params.summary ?? summarizeToolOutput(sanitizedOutput);
2661
+ const items = extractToolItems(sanitizedOutput);
2662
+ return [
2663
+ {
2664
+ kind: "tool_call",
2665
+ label: `Tool Call: ${params.toolName}`,
2666
+ tool: params.toolName,
2667
+ arguments: sanitizedArgs,
2668
+ toolDetails: params.toolDetails
2669
+ },
2670
+ {
2671
+ kind: "tool_result",
2672
+ label: `Tool Result: ${params.toolName}`,
2673
+ tool: params.toolName,
2674
+ summary,
2675
+ items,
2676
+ output: sanitizedOutput,
2677
+ toolDetails: params.toolDetails,
2678
+ execution: {
2679
+ id: params.executionId,
2680
+ status: params.status,
2681
+ durationMs: params.durationMs,
2682
+ fromCache: params.fromCache
2683
+ },
2684
+ classification: params.classification,
2685
+ retentionPolicy: params.retentionPolicy
2686
+ }
2687
+ ];
2688
+ }
2560
2689
  function createToolsNode(initialTools, opts) {
2561
2690
  return async (state) => {
2562
2691
  const runtime = state.agent || {
@@ -2665,6 +2794,7 @@ function createToolsNode(initialTools, opts) {
2665
2794
  args = validatedArgs.value;
2666
2795
  }
2667
2796
  const toolName = tool.name || tc.name;
2797
+ const toolDetails = buildToolDetails(tool, toolName);
2668
2798
  const toolStateRef = tool._stateRef && typeof tool._stateRef === "object" ? tool._stateRef : null;
2669
2799
  if (toolStateRef) {
2670
2800
  toolStateRef.pendingApprovals = pendingApprovals;
@@ -2685,21 +2815,17 @@ function createToolsNode(initialTools, opts) {
2685
2815
  label: `Tool Skipped - ${toolName}`,
2686
2816
  actor: { scope: "tool", name: toolName, role: "tool" },
2687
2817
  status: "skipped",
2818
+ toolDetails,
2688
2819
  toolExecutionId: tc.id,
2689
- messageList: [
2690
- {
2691
- role: "assistant",
2692
- name: toolName,
2693
- content: limitMessage,
2694
- tool_calls: [
2695
- {
2696
- id: tc.id,
2697
- type: "function",
2698
- function: { name: toolName, arguments: sanitizeTracePayload(args) }
2699
- }
2700
- ]
2701
- }
2702
- ]
2820
+ sections: buildToolTraceSections({
2821
+ args,
2822
+ executionId: tc.id,
2823
+ output: limitMessage,
2824
+ status: "skipped",
2825
+ summary: limitMessage,
2826
+ toolDetails,
2827
+ toolName
2828
+ })
2703
2829
  });
2704
2830
  toolCount += 1;
2705
2831
  return { status: "error" };
@@ -2786,6 +2912,25 @@ function createToolsNode(initialTools, opts) {
2786
2912
  push({ role: "tool", content: breakerMsg, tool_call_id: toolCallId, name: tc.name });
2787
2913
  markToolFailure(breakerMsg, toolName, toolCallId);
2788
2914
  onEvent?.({ type: "tool_call", phase: "error", name: toolName, id: tc.id, args, error: { message: breakerMsg } });
2915
+ recordTraceEvent(traceSession, {
2916
+ type: "tool_call",
2917
+ label: `Tool Error - ${toolName}`,
2918
+ actor: { scope: "tool", name: toolName, role: "tool" },
2919
+ status: "error",
2920
+ requestBytes: inputBytes,
2921
+ toolDetails,
2922
+ toolExecutionId: toolCallId,
2923
+ error: { message: breakerMsg },
2924
+ sections: buildToolTraceSections({
2925
+ args,
2926
+ executionId: toolCallId,
2927
+ output: { message: breakerMsg },
2928
+ status: "error",
2929
+ summary: breakerMsg,
2930
+ toolDetails,
2931
+ toolName
2932
+ })
2933
+ });
2789
2934
  toolCount += 1;
2790
2935
  return { status: "error" };
2791
2936
  }
@@ -2810,6 +2955,38 @@ function createToolsNode(initialTools, opts) {
2810
2955
  });
2811
2956
  push({ role: "tool", content: responsePolicy2.content, tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
2812
2957
  onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: cachedHit, durationMs: 0 });
2958
+ const sanitizedCachedHit = sanitizeTracePayload(cachedHit);
2959
+ const outputBytes2 = traceSession?.resolvedConfig.logData ? estimatePayloadBytes(sanitizedCachedHit) : void 0;
2960
+ recordTraceEvent(traceSession, {
2961
+ type: "tool_call",
2962
+ label: `Tool Execution - ${toolName}`,
2963
+ actor: { scope: "tool", name: toolName, role: "tool" },
2964
+ durationMs: 0,
2965
+ requestBytes: inputBytes,
2966
+ responseBytes: outputBytes2,
2967
+ toolDetails,
2968
+ toolExecutionId: executionId2,
2969
+ sections: buildToolTraceSections({
2970
+ args,
2971
+ classification: responsePolicy2.classification,
2972
+ durationMs: 0,
2973
+ executionId: executionId2,
2974
+ fromCache: true,
2975
+ output: sanitizedCachedHit,
2976
+ retentionPolicy: "keep_full",
2977
+ status: "cached",
2978
+ summary: responsePolicy2.content,
2979
+ toolDetails,
2980
+ toolName
2981
+ }),
2982
+ debug: {
2983
+ classification: responsePolicy2.classification,
2984
+ retentionPolicy: "keep_full",
2985
+ originalTokenCount: responsePolicy2.tokenCount,
2986
+ truncated: responsePolicy2.truncated,
2987
+ fromCache: true
2988
+ }
2989
+ });
2813
2990
  toolCount += 1;
2814
2991
  return { status: "success" };
2815
2992
  }
@@ -2930,28 +3107,6 @@ function createToolsNode(initialTools, opts) {
2930
3107
  }
2931
3108
  const sanitizedOutput = sanitizeTracePayload(output);
2932
3109
  const outputBytes = traceSession?.resolvedConfig.logData ? estimatePayloadBytes(sanitizedOutput) : void 0;
2933
- const messageList = [
2934
- {
2935
- role: "assistant",
2936
- name: toolName,
2937
- content: "",
2938
- tool_calls: [
2939
- {
2940
- id: tc.id || executionId,
2941
- type: "function",
2942
- function: {
2943
- name: toolName,
2944
- arguments: sanitizedArgs
2945
- }
2946
- }
2947
- ]
2948
- },
2949
- {
2950
- role: "tool",
2951
- name: toolName,
2952
- content: responsePolicy.content
2953
- }
2954
- ];
2955
3110
  recordTraceEvent(traceSession, {
2956
3111
  type: "tool_call",
2957
3112
  label: `Tool Execution - ${toolName}`,
@@ -2959,8 +3114,20 @@ function createToolsNode(initialTools, opts) {
2959
3114
  durationMs,
2960
3115
  requestBytes: inputBytes,
2961
3116
  responseBytes: outputBytes,
3117
+ toolDetails,
2962
3118
  toolExecutionId: executionId,
2963
- messageList,
3119
+ sections: buildToolTraceSections({
3120
+ args: sanitizedArgs,
3121
+ classification: responsePolicy.classification,
3122
+ durationMs,
3123
+ executionId,
3124
+ output: sanitizedOutput,
3125
+ retentionPolicy: "keep_full",
3126
+ status: "success",
3127
+ summary: responsePolicy.content,
3128
+ toolDetails,
3129
+ toolName
3130
+ }),
2964
3131
  debug: {
2965
3132
  classification: responsePolicy.classification,
2966
3133
  retentionPolicy: "keep_full",
@@ -2979,6 +3146,7 @@ function createToolsNode(initialTools, opts) {
2979
3146
  markToolFailure(message, toolName, toolCallId);
2980
3147
  onEvent?.({ type: "tool_call", phase: "error", name: toolName, id: tc.id, args, error: { message } });
2981
3148
  onProgress?.({ stage: "tools", message: `Tool ${tc.name} failed`, detail: { error: message } });
3149
+ const errorOutput = { message, stack: error?.stack };
2982
3150
  recordTraceEvent(traceSession, {
2983
3151
  type: "tool_call",
2984
3152
  label: `Tool Error - ${toolName}`,
@@ -2986,27 +3154,20 @@ function createToolsNode(initialTools, opts) {
2986
3154
  status: "error",
2987
3155
  durationMs,
2988
3156
  requestBytes: inputBytes,
3157
+ responseBytes: traceSession?.resolvedConfig.logData ? estimatePayloadBytes(errorOutput) : void 0,
3158
+ toolDetails,
2989
3159
  toolExecutionId: executionId,
2990
3160
  error: { message, stack: error?.stack },
2991
- messageList: [
2992
- {
2993
- role: "assistant",
2994
- name: toolName,
2995
- content: "",
2996
- tool_calls: [
2997
- {
2998
- id: tc.id || executionId,
2999
- type: "function",
3000
- function: { name: toolName, arguments: sanitizedArgs }
3001
- }
3002
- ]
3003
- },
3004
- {
3005
- role: "tool",
3006
- name: toolName,
3007
- content: `Error executing tool: ${message}`
3008
- }
3009
- ]
3161
+ sections: buildToolTraceSections({
3162
+ args: sanitizedArgs,
3163
+ durationMs,
3164
+ executionId,
3165
+ output: errorOutput,
3166
+ status: "error",
3167
+ summary: `Error executing tool: ${message}`,
3168
+ toolDetails,
3169
+ toolName
3170
+ })
3010
3171
  });
3011
3172
  toolCount += 1;
3012
3173
  return { status: "error", approval: approvalEntry };
@@ -3083,29 +3244,26 @@ function createToolsNode(initialTools, opts) {
3083
3244
  }
3084
3245
  for (const tc of skipped) {
3085
3246
  onEvent?.({ type: "tool_call", phase: "skipped", name: tc.name, id: tc.id, args: tc.args });
3086
- const sanitizedArgs = sanitizeTracePayload(tc.args);
3247
+ const toolDetails = buildToolDetails(toolByName.get(tc.name), tc.name);
3248
+ const skipMessage = `Skipped tool due to tool-call limit: ${tc.name}`;
3087
3249
  recordTraceEvent(traceSession, {
3088
3250
  type: "tool_call",
3089
3251
  label: `Tool Skipped - ${tc.name}`,
3090
3252
  actor: { scope: "tool", name: tc.name, role: "tool" },
3091
3253
  status: "skipped",
3254
+ toolDetails,
3092
3255
  toolExecutionId: tc.id,
3093
- messageList: [
3094
- {
3095
- role: "assistant",
3096
- name: tc.name,
3097
- content: `Skipped tool due to tool-call limit: ${tc.name}`,
3098
- tool_calls: [
3099
- {
3100
- id: tc.id,
3101
- type: "function",
3102
- function: { name: tc.name, arguments: sanitizedArgs }
3103
- }
3104
- ]
3105
- }
3106
- ]
3256
+ sections: buildToolTraceSections({
3257
+ args: tc.args,
3258
+ executionId: tc.id,
3259
+ output: skipMessage,
3260
+ status: "skipped",
3261
+ summary: skipMessage,
3262
+ toolDetails,
3263
+ toolName: tc.name
3264
+ })
3107
3265
  });
3108
- appended.push({ role: "tool", content: `Skipped tool due to tool-call limit: ${tc.name}`, tool_call_id: tc.id || `${tc.name}_${appended.length}`, name: tc.name });
3266
+ appended.push({ role: "tool", content: skipMessage, tool_call_id: tc.id || `${tc.name}_${appended.length}`, name: tc.name });
3109
3267
  toolCount += 1;
3110
3268
  }
3111
3269
  if (!awaitingApproval && state.ctx?.__awaitingApproval) {
@@ -3177,15 +3335,40 @@ function countToolCallsInLastTurn(state) {
3177
3335
  function stripReflectionAskMessages(messages) {
3178
3336
  return messages.filter((m) => !(m?.role === "user" && m?.name === REFLECTION_ASK_NAME));
3179
3337
  }
3338
+ function lastTwoToolTurns(state) {
3339
+ const groups = [];
3340
+ let cur = [];
3341
+ let sawTool = false;
3342
+ for (let i = state.messages.length - 1; i >= 0; i--) {
3343
+ const m = state.messages[i];
3344
+ if (m?.role === "tool") {
3345
+ if (m.name) cur.push(m.name);
3346
+ sawTool = true;
3347
+ } else if (m?.role === "assistant") {
3348
+ if (sawTool) {
3349
+ groups.push(cur);
3350
+ cur = [];
3351
+ sawTool = false;
3352
+ if (groups.length >= 2) break;
3353
+ }
3354
+ }
3355
+ }
3356
+ if (sawTool && cur.length) groups.push(cur);
3357
+ return { current: groups[0] ?? [], previous: groups[1] ?? [] };
3358
+ }
3180
3359
  function shouldRunReflection(cadence, state, ranToolsThisTurn) {
3181
3360
  if (cadence === "off") return false;
3182
3361
  if (cadence === "every_turn") return true;
3183
3362
  if (cadence === "after_tool") return ranToolsThisTurn;
3363
+ if (cadence === "initial_then_after_tool") return ranToolsThisTurn;
3184
3364
  if (cadence === "on_branch") {
3185
- const reflections = state.reflections || [];
3186
- const lastReflectionTurn = reflections[reflections.length - 1]?.turn ?? -1;
3187
- const currentTurnId = state.toolCallCount ?? 0;
3188
- return currentTurnId - lastReflectionTurn >= 2;
3365
+ const { current, previous } = lastTwoToolTurns(state);
3366
+ if (previous.length === 0) return true;
3367
+ const a = new Set(current);
3368
+ const b = new Set(previous);
3369
+ for (const n of a) if (!b.has(n)) return true;
3370
+ for (const n of b) if (!a.has(n)) return true;
3371
+ return false;
3189
3372
  }
3190
3373
  return false;
3191
3374
  }
@@ -3202,7 +3385,10 @@ function createReflectionNode(opts, resolved) {
3202
3385
  const onEvent = state.ctx?.__onEvent;
3203
3386
  const traceSession = state.ctx?.__traceSession;
3204
3387
  const maxChars = resolved.maxChars;
3205
- const promptBody = (resolved.promptTemplate || DEFAULT_REFLECT_PROMPT).replace(/\$\{maxChars\}/g, String(maxChars));
3388
+ const turnNow = state.toolCallCount ?? 0;
3389
+ const hookCtx = { state, turn: turnNow, trigger, ranToolsThisTurn: true };
3390
+ const defaultPrompt = (resolved.promptTemplate || DEFAULT_REFLECT_PROMPT).replace(/\$\{maxChars\}/g, String(maxChars));
3391
+ const promptBody = resolved.buildPrompt ? String(resolved.buildPrompt({ ...hookCtx, defaultPrompt, maxChars }) ?? defaultPrompt) : defaultPrompt;
3206
3392
  const baseMessages = stripReflectionAskMessages([...state.messages]);
3207
3393
  const askMessage = {
3208
3394
  role: "user",
@@ -3236,6 +3422,8 @@ function createReflectionNode(opts, resolved) {
3236
3422
  const rawText = extractText(response);
3237
3423
  const text = trimToChars(String(rawText ?? "").trim(), maxChars);
3238
3424
  if (!text) return {};
3425
+ const prevText = (state.reflections?.[state.reflections.length - 1]?.text || "").trim();
3426
+ if (prevText && isNearDuplicate(prevText, text)) return {};
3239
3427
  const rawUsage = response?.usage_metadata || response?.response_metadata?.usage || response?.usage || response?.additional_kwargs?.usage;
3240
3428
  const usage = normalizeUsage(rawUsage);
3241
3429
  const { ids, names } = countToolCallsInLastTurn(state);
@@ -3284,6 +3472,12 @@ function createReflectionNode(opts, resolved) {
3284
3472
  } catch (e) {
3285
3473
  }
3286
3474
  }
3475
+ if (resolved.onReflection) {
3476
+ try {
3477
+ resolved.onReflection(record, hookCtx);
3478
+ } catch {
3479
+ }
3480
+ }
3287
3481
  const nextMessages = stripReflectionAskMessages([...state.messages]);
3288
3482
  const reflections = [...state.reflections || [], record];
3289
3483
  const kept = reflections.slice(-Math.max(1, resolved.keepLast));
@@ -3300,7 +3494,20 @@ ${r.text}
3300
3494
  metadata: { reflectionId: r.id, reflectionTurn: r.turn, reflectionTrigger: r.trigger }
3301
3495
  });
3302
3496
  }
3303
- return { messages: prunedMessages, reflections };
3497
+ const patch = { messages: prunedMessages, reflections };
3498
+ if (resolved.feedTo === "memory") {
3499
+ const fact = {
3500
+ key: `reflection_turn_${turn}`,
3501
+ value: text,
3502
+ sourceTurn: turn,
3503
+ confidence: 0.3,
3504
+ tags: ["reflection"]
3505
+ };
3506
+ patch.memoryFacts = [...state.memoryFacts || [], fact];
3507
+ } else if (resolved.feedTo === "plan" && state.plan) {
3508
+ patch.plan = { ...state.plan, lastReflection: text };
3509
+ }
3510
+ return patch;
3304
3511
  };
3305
3512
  }
3306
3513
  function extractText(chunk) {
@@ -3329,24 +3536,75 @@ function safeRandomId() {
3329
3536
  return `r_${Math.random().toString(36).slice(2, 10)}_${Date.now().toString(36)}`;
3330
3537
  }
3331
3538
  }
3539
+ function isNearDuplicate(a, b) {
3540
+ const norm = (s) => s.toLowerCase().replace(/\s+/g, " ").trim();
3541
+ const na = norm(a);
3542
+ const nb = norm(b);
3543
+ if (na === nb) return true;
3544
+ const tokensA = new Set(na.split(" ").filter(Boolean));
3545
+ const tokensB = new Set(nb.split(" ").filter(Boolean));
3546
+ if (tokensA.size === 0 || tokensB.size === 0) return false;
3547
+ let inter = 0;
3548
+ for (const t of tokensA) if (tokensB.has(t)) inter++;
3549
+ const union = tokensA.size + tokensB.size - inter;
3550
+ return union > 0 && inter / union >= 0.9;
3551
+ }
3332
3552
 
3333
3553
  // src/smart/reasoning.ts
3334
3554
  var LEVEL_DEFAULTS = {
3555
+ minimal: {
3556
+ native: { effort: "minimal" },
3557
+ reflection: { maxTokens: 150, maxChars: 400, cadence: "off" }
3558
+ },
3335
3559
  low: {
3336
3560
  native: { effort: "low" },
3337
3561
  reflection: { maxTokens: 200, maxChars: 600, cadence: "on_branch" }
3338
3562
  },
3339
3563
  medium: {
3340
3564
  native: { effort: "medium" },
3341
- reflection: { maxTokens: 350, maxChars: 1200, cadence: "after_tool" }
3565
+ reflection: { maxTokens: 350, maxChars: 1200, cadence: "initial_then_after_tool" }
3342
3566
  },
3343
3567
  high: {
3344
3568
  native: { effort: "high" },
3345
- reflection: { maxTokens: 600, maxChars: 2e3, cadence: "after_tool" }
3569
+ reflection: { maxTokens: 600, maxChars: 2e3, cadence: "initial_then_after_tool" }
3346
3570
  }
3347
3571
  };
3572
+ var VALID_LEVELS = ["minimal", "low", "medium", "high"];
3573
+ var VALID_CADENCES = ["off", "every_turn", "after_tool", "on_branch", "initial_then_after_tool"];
3574
+ var VALID_EFFORTS = ["minimal", "low", "medium", "high"];
3575
+ function validateReasoningConfig(input) {
3576
+ if (!input) return;
3577
+ if (input.level !== void 0 && !VALID_LEVELS.includes(input.level)) {
3578
+ throw new Error(`reasoning.level must be one of ${VALID_LEVELS.join(", ")} (got "${input.level}")`);
3579
+ }
3580
+ if (input.native) {
3581
+ const n = input.native;
3582
+ if (n.effort !== void 0 && !VALID_EFFORTS.includes(n.effort)) {
3583
+ throw new Error(`reasoning.native.effort must be one of ${VALID_EFFORTS.join(", ")} (got "${n.effort}")`);
3584
+ }
3585
+ if (n.budgetTokens !== void 0 && (!Number.isFinite(n.budgetTokens) || n.budgetTokens < 0)) {
3586
+ throw new Error(`reasoning.native.budgetTokens must be a non-negative number (got ${n.budgetTokens})`);
3587
+ }
3588
+ }
3589
+ if (input.reflection) {
3590
+ const r = input.reflection;
3591
+ if (r.cadence !== void 0 && !VALID_CADENCES.includes(r.cadence)) {
3592
+ throw new Error(`reasoning.reflection.cadence must be one of ${VALID_CADENCES.join(", ")} (got "${r.cadence}")`);
3593
+ }
3594
+ if (r.maxPerRun !== void 0 && (!Number.isFinite(r.maxPerRun) || r.maxPerRun < 0)) {
3595
+ throw new Error(`reasoning.reflection.maxPerRun must be a non-negative number (got ${r.maxPerRun})`);
3596
+ }
3597
+ if (r.everyNTurns !== void 0 && (!Number.isFinite(r.everyNTurns) || r.everyNTurns < 1)) {
3598
+ throw new Error(`reasoning.reflection.everyNTurns must be >= 1 (got ${r.everyNTurns})`);
3599
+ }
3600
+ if (r.feedTo !== void 0 && !["memory", "plan", "none"].includes(r.feedTo)) {
3601
+ throw new Error(`reasoning.reflection.feedTo must be "memory", "plan", or "none" (got "${r.feedTo}")`);
3602
+ }
3603
+ }
3604
+ }
3348
3605
  function resolveReasoning(input) {
3349
3606
  if (!input || input.enabled === false) return void 0;
3607
+ validateReasoningConfig(input);
3350
3608
  const enabled = input.enabled ?? (input.native !== void 0 || input.reflection !== void 0 || input.level !== void 0);
3351
3609
  if (!enabled) return void 0;
3352
3610
  const level = input.level ?? "medium";
@@ -3371,7 +3629,8 @@ function resolveReflection(input, preset) {
3371
3629
  keepLast: 3,
3372
3630
  summarize: false,
3373
3631
  emitEvents: true,
3374
- everyNTurns: 1
3632
+ everyNTurns: 1,
3633
+ feedTo: "none"
3375
3634
  };
3376
3635
  }
3377
3636
  const cfg = input ?? {};
@@ -3388,7 +3647,11 @@ function resolveReflection(input, preset) {
3388
3647
  promptTemplate: cfg.promptTemplate,
3389
3648
  emitEvents: cfg.emitEvents ?? true,
3390
3649
  maxPerRun: typeof cfg.maxPerRun === "number" && cfg.maxPerRun >= 0 ? cfg.maxPerRun : void 0,
3391
- everyNTurns: Math.max(1, Math.trunc(cfg.everyNTurns ?? 1))
3650
+ everyNTurns: Math.max(1, Math.trunc(cfg.everyNTurns ?? 1)),
3651
+ feedTo: cfg.feedTo ?? "none",
3652
+ shouldReflect: cfg.shouldReflect,
3653
+ buildPrompt: cfg.buildPrompt,
3654
+ onReflection: cfg.onReflection
3392
3655
  };
3393
3656
  }
3394
3657
  function ensureArray(value) {
@@ -4114,12 +4377,14 @@ function createAgent(opts) {
4114
4377
  if (summarizationThreshold === void 0) {
4115
4378
  state = clearNeedsSummarization(state);
4116
4379
  }
4117
- if (resolvedReasoning?.native) {
4380
+ if (resolvedReasoning) {
4118
4381
  const ctx = { ...state.ctx || {} };
4119
- if (!ctx.__reasoning) {
4382
+ if (resolvedReasoning.native) {
4120
4383
  ctx.__reasoning = resolvedReasoning.native;
4121
- state = { ...state, ctx };
4384
+ } else {
4385
+ delete ctx.__reasoning;
4122
4386
  }
4387
+ state = { ...state, ctx: Object.keys(ctx).length > 0 ? ctx : void 0 };
4123
4388
  }
4124
4389
  const mergedLimits = {
4125
4390
  ...opts.limits || {},
@@ -4167,6 +4432,7 @@ function createAgent(opts) {
4167
4432
  return { breached: false };
4168
4433
  };
4169
4434
  let iterations = 0;
4435
+ let reflectionsThisRun = 0;
4170
4436
  const onStateChange = config?.onStateChange;
4171
4437
  const checkpointReason = config?.checkpointReason;
4172
4438
  let pausedStage = null;
@@ -4212,6 +4478,16 @@ function createAgent(opts) {
4212
4478
  pausedStage = stage;
4213
4479
  return true;
4214
4480
  };
4481
+ if (reflectNode && resolvedReasoning?.reflection.enabled && resolvedReasoning.reflection.cadence === "initial_then_after_tool" && resumeStage === null && !state.ctx?.__awaitingApproval && !state.ctx?.__awaitingUserQuestion && !state.messages.some((m) => m?.role === "assistant")) {
4482
+ try {
4483
+ const patch = await reflectNode(state, "initial_then_after_tool");
4484
+ if (patch && Object.keys(patch).length > 0) {
4485
+ state = { ...state, ...patch };
4486
+ reflectionsThisRun++;
4487
+ }
4488
+ } catch {
4489
+ }
4490
+ }
4215
4491
  while (iterations < iterationLimit) {
4216
4492
  iterations++;
4217
4493
  const budget = checkBudgetBreached();
@@ -4356,7 +4632,7 @@ function createAgent(opts) {
4356
4632
  if (toolCalls.length === 0) {
4357
4633
  if (soManager && !state.ctx?.__finalizedDueToStructuredOutput && !state.ctx?.__structuredOutputForceFinalize) {
4358
4634
  if (soManager.strategy.kind === "native") {
4359
- const assistantText = extractMessageText2(lastMsg);
4635
+ const assistantText = extractMessageText(lastMsg);
4360
4636
  if (assistantText) {
4361
4637
  const parsed = soManager.parseFromContent(assistantText);
4362
4638
  if (parsed.success) {
@@ -4388,16 +4664,18 @@ function createAgent(opts) {
4388
4664
  if (reflectNode && resolvedReasoning?.reflection.enabled) {
4389
4665
  const cadence = resolvedReasoning.reflection.cadence;
4390
4666
  const refl = resolvedReasoning.reflection;
4391
- const reflectionsSoFar = state.reflections?.length ?? 0;
4392
4667
  const lastTurn = state.reflections?.at(-1)?.turn ?? -Infinity;
4393
4668
  const currentTurn = state.toolCallCount || 0;
4394
- const budgetExceeded = typeof refl.maxPerRun === "number" && reflectionsSoFar >= refl.maxPerRun;
4395
- const cadenceGap = currentTurn - (Number.isFinite(lastTurn) ? lastTurn : -refl.everyNTurns) < refl.everyNTurns;
4396
- if (!budgetExceeded && !cadenceGap && shouldRunReflection(cadence, state, true)) {
4669
+ const budgetExceeded = typeof refl.maxPerRun === "number" && reflectionsThisRun >= refl.maxPerRun;
4670
+ const sinceLast = currentTurn - (Number.isFinite(lastTurn) ? lastTurn : -refl.everyNTurns);
4671
+ const cadenceGap = sinceLast < refl.everyNTurns;
4672
+ const cadenceWantsIt = refl.shouldReflect ? !!refl.shouldReflect({ state, turn: currentTurn, trigger: cadence, ranToolsThisTurn: true }) : shouldRunReflection(cadence, state, true);
4673
+ if (!budgetExceeded && !cadenceGap && cadenceWantsIt) {
4397
4674
  try {
4398
4675
  const patch = await reflectNode(state, cadence);
4399
4676
  if (patch && Object.keys(patch).length > 0) {
4400
4677
  state = { ...state, ...patch };
4678
+ reflectionsThisRun++;
4401
4679
  }
4402
4680
  } catch {
4403
4681
  }
@@ -4407,7 +4685,7 @@ function createAgent(opts) {
4407
4685
  if (soManager && !state.ctx?.__finalizedDueToStructuredOutput) {
4408
4686
  const lastForParse = state.messages[state.messages.length - 1];
4409
4687
  if (lastForParse?.role === "assistant") {
4410
- const assistantText = extractMessageText2(lastForParse);
4688
+ const assistantText = extractMessageText(lastForParse);
4411
4689
  if (assistantText) {
4412
4690
  const parsed = soManager.parseFromContent(assistantText);
4413
4691
  if (parsed.success) {
@@ -4560,7 +4838,7 @@ function createAgent(opts) {
4560
4838
  const isTransientSummarizationExit = !!res.ctx?.__needsSummarization;
4561
4839
  const finalAssistantMsg = isTransientSummarizationExit ? void 0 : getLastAssistantMessage(res.messages);
4562
4840
  const finalIsSyntheticSummary = !isTransientSummarizationExit && finalAssistantMsg && isSyntheticSummaryMessage(finalAssistantMsg);
4563
- const content = isTransientSummarizationExit || finalIsSyntheticSummary ? "" : extractMessageText2(finalAssistantMsg);
4841
+ const content = isTransientSummarizationExit || finalIsSyntheticSummary ? "" : extractMessageText(finalAssistantMsg);
4564
4842
  let parsed = void 0;
4565
4843
  let outputError = void 0;
4566
4844
  if (soManager) {
@@ -4868,7 +5146,7 @@ function renderMemoryBlock(facts) {
4868
5146
  function clampToBudget(messages, maxContextTokens) {
4869
5147
  let working = [...messages];
4870
5148
  while (working.length > 2) {
4871
- const tokenCount = countApproxTokens(working.map(extractMessageText2).join("\n"));
5149
+ const tokenCount = countApproxTokens(working.map(extractMessageText).join("\n"));
4872
5150
  if (tokenCount <= maxContextTokens) return working;
4873
5151
  const firstNonSystem = working.findIndex((message, index) => !(index === 0 && message.role === "system"));
4874
5152
  if (firstNonSystem < 0) break;
@@ -5971,7 +6249,7 @@ function createSmartAgent(opts) {
5971
6249
  ].join("\n");
5972
6250
  function latestUserPrompt(messages) {
5973
6251
  const latest = [...messages].reverse().find((message) => message.role === "user");
5974
- return latest ? extractMessageText2(latest) : "";
6252
+ return latest ? extractMessageText(latest) : "";
5975
6253
  }
5976
6254
  async function syncMemory(state) {
5977
6255
  const query = latestUserPrompt(state.messages || []);
@@ -6660,6 +6938,20 @@ function parseSSEBlock(block) {
6660
6938
  }
6661
6939
 
6662
6940
  // src/providers/utils/reasoning.ts
6941
+ var ANTHROPIC_EFFORT_BUDGET = {
6942
+ minimal: 1024,
6943
+ low: 2048,
6944
+ medium: 8192,
6945
+ high: 16384
6946
+ };
6947
+ var GEMINI_EFFORT_BUDGET = {
6948
+ minimal: 512,
6949
+ low: 1024,
6950
+ medium: 4096,
6951
+ high: 12e3
6952
+ };
6953
+ var THINKING_OUTPUT_RESERVE = 1024;
6954
+ var THINKING_MIN_MAX_TOKENS = 4096;
6663
6955
  function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
6664
6956
  if (!reasoning) return;
6665
6957
  const effort = normalizeEffort(reasoning.effort);
@@ -6676,21 +6968,56 @@ function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
6676
6968
  }
6677
6969
  function applyAnthropicReasoning(body, reasoning) {
6678
6970
  if (!reasoning) return;
6679
- const budget = resolveBudget(reasoning, { low: 2048, medium: 8192, high: 16384, minimal: 1024 });
6971
+ let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
6680
6972
  if (!budget) return;
6973
+ const currentMax = typeof body.max_tokens === "number" ? body.max_tokens : 0;
6974
+ const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
6975
+ if (currentMax < requiredMax) {
6976
+ body.max_tokens = requiredMax;
6977
+ }
6978
+ budget = clampBudget(budget, body.max_tokens);
6681
6979
  const thinking = { type: "enabled", budget_tokens: budget };
6682
6980
  if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
6683
6981
  body.thinking = thinking;
6982
+ stripSamplingParams(body, ["temperature", "top_p", "top_k"]);
6983
+ }
6984
+ function applyBedrockReasoning(body, reasoning) {
6985
+ if (!reasoning) return;
6986
+ let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
6987
+ if (!budget) return;
6988
+ const inference = body.inferenceConfig ?? (body.inferenceConfig = {});
6989
+ const currentMax = typeof inference.maxTokens === "number" ? inference.maxTokens : 0;
6990
+ const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
6991
+ if (currentMax < requiredMax) {
6992
+ inference.maxTokens = requiredMax;
6993
+ }
6994
+ budget = clampBudget(budget, inference.maxTokens);
6995
+ const extra = body.additionalModelRequestFields ?? (body.additionalModelRequestFields = {});
6996
+ const thinking = { type: "enabled", budget_tokens: budget };
6997
+ if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
6998
+ extra.thinking = thinking;
6999
+ stripSamplingParams(inference, ["temperature", "topP"]);
6684
7000
  }
6685
7001
  function applyGeminiReasoning(generationConfig, reasoning) {
6686
7002
  if (!reasoning) return;
6687
- const budget = resolveBudget(reasoning, { low: 1024, medium: 4096, high: 12e3, minimal: 512 });
7003
+ const budget = resolveBudget(reasoning, GEMINI_EFFORT_BUDGET);
6688
7004
  if (budget == null) return;
6689
7005
  const thinkingConfig = { thinkingBudget: budget };
6690
7006
  if (reasoning.includeThoughts) thinkingConfig.includeThoughts = true;
6691
7007
  if (reasoning.providerExtras) Object.assign(thinkingConfig, reasoning.providerExtras);
6692
7008
  generationConfig.thinkingConfig = thinkingConfig;
6693
7009
  }
7010
+ function stripSamplingParams(target, keys) {
7011
+ for (const k of keys) {
7012
+ if (k in target) delete target[k];
7013
+ }
7014
+ }
7015
+ function clampBudget(budget, maxTokens) {
7016
+ if (typeof maxTokens !== "number" || maxTokens <= 0) return budget;
7017
+ const ceiling = maxTokens - THINKING_OUTPUT_RESERVE;
7018
+ if (ceiling < 1024) return Math.max(1024, Math.floor(maxTokens / 2));
7019
+ return Math.min(budget, ceiling);
7020
+ }
6694
7021
  function normalizeEffort(effort) {
6695
7022
  if (!effort) return void 0;
6696
7023
  const allowed = ["minimal", "low", "medium", "high"];
@@ -6719,13 +7046,38 @@ var OpenAIProvider = class extends BaseProvider {
6719
7046
  };
6720
7047
  if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
6721
7048
  }
7049
+ /** True when the request targets a reasoning model (o-series / gpt-5) so we
7050
+ * should route through the Responses API, which exposes `reasoning.effort`
7051
+ * and reasoning summaries. Chat Completions silently drops these. */
7052
+ useResponsesApi(request) {
7053
+ if (!request.reasoning) return false;
7054
+ return isReasoningModel(request.model || this.defaultModel);
7055
+ }
6722
7056
  async complete(request) {
7057
+ if (this.useResponsesApi(request)) {
7058
+ return this.completeResponses(request);
7059
+ }
6723
7060
  const body = this.buildRequestBody(request, false);
6724
7061
  const res = await this.doFetch(body);
6725
7062
  const json = await res.json();
6726
7063
  return this.parseResponse(json);
6727
7064
  }
6728
7065
  async *completeStream(request) {
7066
+ if (this.useResponsesApi(request)) {
7067
+ const response = await this.completeResponses(request);
7068
+ yield {
7069
+ id: response.id,
7070
+ model: response.model,
7071
+ delta: {
7072
+ content: response.content ?? void 0,
7073
+ toolCalls: response.toolCalls.length > 0 ? response.toolCalls : void 0,
7074
+ reasoning: response.reasoning
7075
+ },
7076
+ usage: response.usage,
7077
+ finishReason: response.finishReason
7078
+ };
7079
+ return;
7080
+ }
6729
7081
  const body = this.buildRequestBody(request, true);
6730
7082
  const res = await this.doFetch(body);
6731
7083
  if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
@@ -6824,6 +7176,156 @@ var OpenAIProvider = class extends BaseProvider {
6824
7176
  applyOpenAIReasoning(body, request.reasoning, "legacy_effort");
6825
7177
  return body;
6826
7178
  }
7179
+ // ─── Responses API (reasoning models) ──────────────────────────────────────
7180
+ async completeResponses(request) {
7181
+ const body = this.buildResponsesBody(request);
7182
+ const res = await this.responsesFetch(body);
7183
+ const json = await res.json();
7184
+ return this.parseResponsesResponse(json, request.model || this.defaultModel);
7185
+ }
7186
+ buildResponsesBody(request) {
7187
+ const body = {
7188
+ model: request.model || this.defaultModel,
7189
+ input: request.messages.map((m) => this.toResponsesInput(m))
7190
+ };
7191
+ if (request.maxTokens != null) body.max_output_tokens = request.maxTokens;
7192
+ if (request.topP != null) body.top_p = request.topP;
7193
+ if (request.tools?.length) {
7194
+ body.tools = request.tools.map((t) => ({
7195
+ type: "function",
7196
+ name: t.name,
7197
+ description: t.description,
7198
+ parameters: t.parameters,
7199
+ ...t.strict ? { strict: true } : {}
7200
+ }));
7201
+ }
7202
+ if (request.toolChoice != null && request.tools?.length) {
7203
+ if (typeof request.toolChoice === "string") {
7204
+ body.tool_choice = request.toolChoice;
7205
+ } else {
7206
+ body.tool_choice = { type: "function", name: request.toolChoice.name };
7207
+ }
7208
+ }
7209
+ if (request.responseFormat) {
7210
+ if (request.responseFormat.type === "json_schema") {
7211
+ body.text = {
7212
+ format: {
7213
+ type: "json_schema",
7214
+ name: request.responseFormat.name ?? "response",
7215
+ schema: request.responseFormat.schema,
7216
+ strict: true
7217
+ }
7218
+ };
7219
+ } else if (request.responseFormat.type === "json_object") {
7220
+ body.text = { format: { type: "json_object" } };
7221
+ }
7222
+ }
7223
+ if (request.extra) Object.assign(body, request.extra);
7224
+ applyOpenAIReasoning(body, request.reasoning, "responses");
7225
+ return body;
7226
+ }
7227
+ /** Maps a unified message to a Responses API `input` item. */
7228
+ toResponsesInput(m) {
7229
+ if (m.role === "tool" && m.toolCallId) {
7230
+ const output = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
7231
+ return { type: "function_call_output", call_id: m.toolCallId, output };
7232
+ }
7233
+ if (m.role === "assistant" && m.toolCalls?.length) {
7234
+ return {
7235
+ __assistantWithCalls: true,
7236
+ text: typeof m.content === "string" ? m.content : "",
7237
+ calls: m.toolCalls.map((tc) => ({
7238
+ type: "function_call",
7239
+ call_id: tc.id,
7240
+ name: tc.name,
7241
+ arguments: tc.arguments
7242
+ }))
7243
+ };
7244
+ }
7245
+ const role = m.role === "system" ? "system" : m.role === "assistant" ? "assistant" : "user";
7246
+ const textType = role === "assistant" ? "output_text" : "input_text";
7247
+ if (typeof m.content === "string") {
7248
+ return { role, content: [{ type: textType, text: m.content }] };
7249
+ }
7250
+ const content = m.content.map((part) => {
7251
+ if (part.type === "text") return { type: textType, text: part.text };
7252
+ if (part.type === "image") {
7253
+ const src = part.source;
7254
+ const url = src.type === "url" ? src.url : `data:${src.mediaType};base64,${src.data}`;
7255
+ return { type: "input_image", image_url: url };
7256
+ }
7257
+ return { type: textType, text: "" };
7258
+ });
7259
+ return { role, content };
7260
+ }
7261
+ async responsesFetch(body) {
7262
+ body.input = expandResponsesInput(body.input);
7263
+ const url = `${this.baseURL}/responses`;
7264
+ const headers = {
7265
+ "Content-Type": "application/json",
7266
+ Authorization: `Bearer ${this.apiKey}`,
7267
+ ...this.defaultHeaders
7268
+ };
7269
+ const payload = JSON.stringify(body);
7270
+ const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload }));
7271
+ if (!res.ok) {
7272
+ const text = await res.text().catch(() => "");
7273
+ throw new ProviderError(
7274
+ `OpenAI Responses API error ${res.status}: ${text}`,
7275
+ this.providerName,
7276
+ res.status,
7277
+ text
7278
+ );
7279
+ }
7280
+ return res;
7281
+ }
7282
+ parseResponsesResponse(json, modelId) {
7283
+ const textParts = [];
7284
+ const toolCalls = [];
7285
+ const summaryParts = [];
7286
+ for (const item of json.output ?? []) {
7287
+ if (item.type === "message") {
7288
+ for (const c of item.content ?? []) {
7289
+ if (c.type === "output_text" && typeof c.text === "string") textParts.push(c.text);
7290
+ }
7291
+ } else if (item.type === "function_call") {
7292
+ toolCalls.push({
7293
+ id: item.call_id ?? item.id ?? "",
7294
+ name: item.name ?? "",
7295
+ arguments: typeof item.arguments === "string" ? item.arguments : JSON.stringify(item.arguments ?? {})
7296
+ });
7297
+ } else if (item.type === "reasoning") {
7298
+ for (const s of item.summary ?? []) {
7299
+ if (typeof s.text === "string") summaryParts.push(s.text);
7300
+ }
7301
+ }
7302
+ }
7303
+ if (textParts.length === 0 && typeof json.output_text === "string") {
7304
+ textParts.push(json.output_text);
7305
+ }
7306
+ const usage = json.usage ?? {};
7307
+ const reasoningTokens = usage.output_tokens_details?.reasoning_tokens ?? 0;
7308
+ const tokenUsage = {
7309
+ inputTokens: usage.input_tokens ?? 0,
7310
+ outputTokens: usage.output_tokens ?? 0,
7311
+ totalTokens: usage.total_tokens ?? (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),
7312
+ cachedInputTokens: usage.input_tokens_details?.cached_tokens ?? 0,
7313
+ cachedWriteTokens: 0,
7314
+ cachedOutputTokens: 0,
7315
+ reasoningTokens
7316
+ };
7317
+ const finishReason = toolCalls.length > 0 ? "tool_calls" : json.status === "incomplete" ? "length" : "stop";
7318
+ return {
7319
+ id: json.id ?? "",
7320
+ model: json.model ?? modelId,
7321
+ content: textParts.join("") || null,
7322
+ toolCalls,
7323
+ usage: tokenUsage,
7324
+ finishReason,
7325
+ reasoning: summaryParts.length > 0 ? { summary: summaryParts.join("\n").trim() || void 0 } : void 0,
7326
+ raw: json
7327
+ };
7328
+ }
6827
7329
  toOpenAIMessage(m) {
6828
7330
  const msg = { role: m.role };
6829
7331
  if (typeof m.content === "string") {
@@ -6916,6 +7418,25 @@ var OpenAIProvider = class extends BaseProvider {
6916
7418
  };
6917
7419
  }
6918
7420
  };
7421
+ function isReasoningModel(model) {
7422
+ if (!model) return false;
7423
+ const m = model.toLowerCase();
7424
+ return /(^|[/_-])o[0-9]/.test(m) || m.startsWith("o1") || m.startsWith("o3") || m.startsWith("o4") || m.includes("gpt-5") || m.includes("gpt5");
7425
+ }
7426
+ function expandResponsesInput(input) {
7427
+ const out = [];
7428
+ for (const item of input) {
7429
+ if (item && item.__assistantWithCalls) {
7430
+ if (item.text) {
7431
+ out.push({ role: "assistant", content: [{ type: "output_text", text: item.text }] });
7432
+ }
7433
+ for (const call of item.calls) out.push(call);
7434
+ } else {
7435
+ out.push(item);
7436
+ }
7437
+ }
7438
+ return out;
7439
+ }
6919
7440
  function mapFinishReason(reason) {
6920
7441
  switch (reason) {
6921
7442
  case "stop":
@@ -6961,6 +7482,7 @@ var AnthropicProvider = class extends BaseProvider {
6961
7482
  let cacheReadInputTokens = 0;
6962
7483
  let cacheCreationInputTokens = 0;
6963
7484
  const currentToolCalls = /* @__PURE__ */ new Map();
7485
+ const reasoningBlocks = /* @__PURE__ */ new Map();
6964
7486
  for await (const event of parseSSEStream(res.body)) {
6965
7487
  let data;
6966
7488
  try {
@@ -6990,6 +7512,10 @@ var AnthropicProvider = class extends BaseProvider {
6990
7512
  name: block.name ?? "",
6991
7513
  arguments: ""
6992
7514
  });
7515
+ } else if (block?.type === "thinking") {
7516
+ reasoningBlocks.set(idx, { type: "thinking", text: block.thinking ?? "", signature: block.signature });
7517
+ } else if (block?.type === "redacted_thinking") {
7518
+ reasoningBlocks.set(idx, { type: "redacted_thinking", data: block.data });
6993
7519
  }
6994
7520
  break;
6995
7521
  }
@@ -7002,6 +7528,19 @@ var AnthropicProvider = class extends BaseProvider {
7002
7528
  model,
7003
7529
  delta: { content: delta.text }
7004
7530
  };
7531
+ } else if (delta?.type === "thinking_delta" && delta.thinking) {
7532
+ const blk = reasoningBlocks.get(idx) ?? { type: "thinking", text: "" };
7533
+ blk.text = (blk.text ?? "") + delta.thinking;
7534
+ reasoningBlocks.set(idx, blk);
7535
+ yield {
7536
+ id,
7537
+ model,
7538
+ delta: { reasoning: { summary: delta.thinking } }
7539
+ };
7540
+ } else if (delta?.type === "signature_delta" && delta.signature) {
7541
+ const blk = reasoningBlocks.get(idx) ?? { type: "thinking", text: "" };
7542
+ blk.signature = (blk.signature ?? "") + delta.signature;
7543
+ reasoningBlocks.set(idx, blk);
7005
7544
  } else if (delta?.type === "input_json_delta" && delta.partial_json) {
7006
7545
  const tc = currentToolCalls.get(idx);
7007
7546
  if (tc) {
@@ -7034,10 +7573,13 @@ var AnthropicProvider = class extends BaseProvider {
7034
7573
  cachedOutputTokens: 0,
7035
7574
  reasoningTokens: 0
7036
7575
  };
7576
+ const blocks = [...reasoningBlocks.values()].filter(
7577
+ (b) => b.type === "thinking" && b.signature || b.type === "redacted_thinking" && b.data
7578
+ );
7037
7579
  yield {
7038
7580
  id,
7039
7581
  model,
7040
- delta: {},
7582
+ delta: blocks.length > 0 ? { reasoning: { blocks } } : {},
7041
7583
  finishReason,
7042
7584
  usage
7043
7585
  };
@@ -7129,6 +7671,7 @@ var AnthropicProvider = class extends BaseProvider {
7129
7671
  }
7130
7672
  if (m.role === "assistant" && m.toolCalls?.length) {
7131
7673
  const content = [];
7674
+ appendReasoningBlocks(content, m.reasoning?.blocks);
7132
7675
  if (typeof m.content === "string" && m.content) {
7133
7676
  content.push({ type: "text", text: m.content });
7134
7677
  }
@@ -7142,6 +7685,13 @@ var AnthropicProvider = class extends BaseProvider {
7142
7685
  }
7143
7686
  return { role: "assistant", content };
7144
7687
  }
7688
+ if (m.role === "assistant" && m.reasoning?.blocks?.length) {
7689
+ const content = [];
7690
+ appendReasoningBlocks(content, m.reasoning.blocks);
7691
+ const text = typeof m.content === "string" ? m.content : "";
7692
+ if (text) content.push({ type: "text", text });
7693
+ return { role: "assistant", content };
7694
+ }
7145
7695
  const msg = { role: m.role };
7146
7696
  if (typeof m.content === "string") {
7147
7697
  msg.content = m.content;
@@ -7197,9 +7747,20 @@ var AnthropicProvider = class extends BaseProvider {
7197
7747
  parseResponse(json) {
7198
7748
  const textParts = [];
7199
7749
  const toolCalls = [];
7750
+ const reasoningBlocks = [];
7751
+ const summaryParts = [];
7200
7752
  for (const block of json.content ?? []) {
7201
7753
  if (block.type === "text") {
7202
7754
  textParts.push(block.text);
7755
+ } else if (block.type === "thinking") {
7756
+ reasoningBlocks.push({
7757
+ type: "thinking",
7758
+ text: block.thinking ?? "",
7759
+ signature: block.signature
7760
+ });
7761
+ if (block.thinking) summaryParts.push(block.thinking);
7762
+ } else if (block.type === "redacted_thinking") {
7763
+ reasoningBlocks.push({ type: "redacted_thinking", data: block.data });
7203
7764
  } else if (block.type === "tool_use") {
7204
7765
  toolCalls.push({
7205
7766
  id: block.id,
@@ -7216,6 +7777,9 @@ var AnthropicProvider = class extends BaseProvider {
7216
7777
  cachedInputTokens: usage.cache_read_input_tokens ?? 0,
7217
7778
  cachedWriteTokens: usage.cache_creation_input_tokens ?? 0,
7218
7779
  cachedOutputTokens: 0,
7780
+ // Anthropic bills thinking tokens inside `output_tokens` and does not
7781
+ // expose a separate count, so reasoningTokens stays 0 here (cost is still
7782
+ // captured via outputTokens). See docs for the limitation.
7219
7783
  reasoningTokens: 0
7220
7784
  };
7221
7785
  return {
@@ -7225,6 +7789,7 @@ var AnthropicProvider = class extends BaseProvider {
7225
7789
  toolCalls,
7226
7790
  usage: tokenUsage,
7227
7791
  finishReason: mapAnthropicStopReason(json.stop_reason),
7792
+ reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
7228
7793
  raw: json
7229
7794
  };
7230
7795
  }
@@ -7249,6 +7814,18 @@ function safeJsonParse(str) {
7249
7814
  return {};
7250
7815
  }
7251
7816
  }
7817
+ function appendReasoningBlocks(content, blocks) {
7818
+ if (!blocks?.length) return;
7819
+ for (const b of blocks) {
7820
+ if (b.type === "redacted_thinking") {
7821
+ if (b.data) content.push({ type: "redacted_thinking", data: b.data });
7822
+ } else if (b.type === "thinking") {
7823
+ if (b.signature) {
7824
+ content.push({ type: "thinking", thinking: b.text ?? "", signature: b.signature });
7825
+ }
7826
+ }
7827
+ }
7828
+ }
7252
7829
 
7253
7830
  // src/providers/azure.ts
7254
7831
  var AzureProvider = class extends OpenAIProvider {
@@ -7292,7 +7869,52 @@ var AzureProvider = class extends OpenAIProvider {
7292
7869
  }
7293
7870
  return res;
7294
7871
  }
7872
+ /** Azure exposes the Responses API at /openai/responses with api-key auth.
7873
+ * Reasoning summaries require a preview api-version; callers can override via
7874
+ * the `apiVersion` config. */
7875
+ async responsesFetch(body) {
7876
+ body.input = expandAzureResponsesInput(body.input);
7877
+ const deployment = this.deploymentName ?? body.model;
7878
+ if (!deployment) {
7879
+ throw new ProviderError("Azure requires a deploymentName or model", this.providerName);
7880
+ }
7881
+ const url = `${this.endpoint}/openai/responses?api-version=${this.apiVersion}`;
7882
+ const payload = JSON.stringify({ ...body, model: deployment });
7883
+ const res = await fetch(url, {
7884
+ method: "POST",
7885
+ headers: {
7886
+ "Content-Type": "application/json",
7887
+ "api-key": this.azureApiKey,
7888
+ ...this.defaultHeaders
7889
+ },
7890
+ body: payload
7891
+ });
7892
+ if (!res.ok) {
7893
+ const text = await res.text().catch(() => "");
7894
+ throw new ProviderError(
7895
+ `Azure OpenAI Responses API error ${res.status}: ${text}`,
7896
+ this.providerName,
7897
+ res.status,
7898
+ text
7899
+ );
7900
+ }
7901
+ return res;
7902
+ }
7295
7903
  };
7904
+ function expandAzureResponsesInput(input) {
7905
+ const out = [];
7906
+ for (const item of input) {
7907
+ if (item && item.__assistantWithCalls) {
7908
+ if (item.text) {
7909
+ out.push({ role: "assistant", content: [{ type: "output_text", text: item.text }] });
7910
+ }
7911
+ for (const call of item.calls) out.push(call);
7912
+ } else {
7913
+ out.push(item);
7914
+ }
7915
+ }
7916
+ return out;
7917
+ }
7296
7918
 
7297
7919
  // src/providers/openaiCompatible.ts
7298
7920
  var OpenAICompatibleProvider = class extends OpenAIProvider {
@@ -7465,6 +8087,7 @@ var BedrockProvider = class extends BaseProvider {
7465
8087
  if (request.extra) {
7466
8088
  Object.assign(body, request.extra);
7467
8089
  }
8090
+ applyBedrockReasoning(body, request.reasoning);
7468
8091
  return body;
7469
8092
  }
7470
8093
  splitSystemMessages(messages) {
@@ -7498,6 +8121,7 @@ var BedrockProvider = class extends BaseProvider {
7498
8121
  }
7499
8122
  if (m.role === "assistant" && m.toolCalls?.length) {
7500
8123
  const content2 = [];
8124
+ appendBedrockReasoning(content2, m.reasoning?.blocks);
7501
8125
  if (typeof m.content === "string" && m.content) {
7502
8126
  content2.push({ text: m.content });
7503
8127
  }
@@ -7578,9 +8202,23 @@ var BedrockProvider = class extends BaseProvider {
7578
8202
  const output = json.output?.message;
7579
8203
  const textParts = [];
7580
8204
  const toolCalls = [];
8205
+ const reasoningBlocks = [];
8206
+ const summaryParts = [];
7581
8207
  for (const block of output?.content ?? []) {
7582
8208
  if (block.text) {
7583
8209
  textParts.push(block.text);
8210
+ } else if (block.reasoningContent) {
8211
+ const rc = block.reasoningContent;
8212
+ if (rc.reasoningText) {
8213
+ reasoningBlocks.push({
8214
+ type: "thinking",
8215
+ text: rc.reasoningText.text ?? "",
8216
+ signature: rc.reasoningText.signature
8217
+ });
8218
+ if (rc.reasoningText.text) summaryParts.push(rc.reasoningText.text);
8219
+ } else if (rc.redactedContent) {
8220
+ reasoningBlocks.push({ type: "redacted_thinking", data: rc.redactedContent });
8221
+ }
7584
8222
  } else if (block.toolUse) {
7585
8223
  toolCalls.push({
7586
8224
  id: block.toolUse.toolUseId,
@@ -7597,6 +8235,7 @@ var BedrockProvider = class extends BaseProvider {
7597
8235
  cachedInputTokens: usage.cacheReadInputTokenCount ?? 0,
7598
8236
  cachedWriteTokens: usage.cacheWriteInputTokenCount ?? 0,
7599
8237
  cachedOutputTokens: 0,
8238
+ // Bedrock bills thinking tokens inside outputTokens; no separate count.
7600
8239
  reasoningTokens: 0
7601
8240
  };
7602
8241
  return {
@@ -7606,10 +8245,25 @@ var BedrockProvider = class extends BaseProvider {
7606
8245
  toolCalls,
7607
8246
  usage: tokenUsage,
7608
8247
  finishReason: mapBedrockStopReason(json.stopReason),
8248
+ reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
7609
8249
  raw: json
7610
8250
  };
7611
8251
  }
7612
8252
  };
8253
+ function appendBedrockReasoning(content, blocks) {
8254
+ if (!blocks?.length) return;
8255
+ for (const b of blocks) {
8256
+ if (b.type === "redacted_thinking") {
8257
+ if (b.data) content.push({ reasoningContent: { redactedContent: b.data } });
8258
+ } else if (b.type === "thinking") {
8259
+ if (b.signature) {
8260
+ content.push({
8261
+ reasoningContent: { reasoningText: { text: b.text ?? "", signature: b.signature } }
8262
+ });
8263
+ }
8264
+ }
8265
+ }
8266
+ }
7613
8267
  function mapBedrockStopReason(reason) {
7614
8268
  switch (reason) {
7615
8269
  case "end_turn":
@@ -7932,10 +8586,15 @@ var VertexProvider = class extends BaseProvider {
7932
8586
  const parts = candidate?.content?.parts ?? [];
7933
8587
  const textParts = [];
7934
8588
  const toolCalls = [];
8589
+ const thoughtParts = [];
7935
8590
  let toolCallIdx = 0;
7936
8591
  for (const part of parts) {
7937
8592
  if (part.text) {
7938
- textParts.push(part.text);
8593
+ if (part.thought === true) {
8594
+ thoughtParts.push(part.text);
8595
+ } else {
8596
+ textParts.push(part.text);
8597
+ }
7939
8598
  } else if (part.functionCall) {
7940
8599
  toolCalls.push({
7941
8600
  id: `call_${toolCallIdx++}`,
@@ -7961,6 +8620,7 @@ var VertexProvider = class extends BaseProvider {
7961
8620
  toolCalls,
7962
8621
  usage: tokenUsage,
7963
8622
  finishReason: mapGeminiFinishReason(candidate?.finishReason),
8623
+ reasoning: thoughtParts.length > 0 ? { summary: thoughtParts.join("\n").trim() || void 0 } : void 0,
7964
8624
  raw: json
7965
8625
  };
7966
8626
  }
@@ -7970,7 +8630,11 @@ var VertexProvider = class extends BaseProvider {
7970
8630
  const delta = {};
7971
8631
  for (const part of parts) {
7972
8632
  if (part.text) {
7973
- delta.content = (delta.content ?? "") + part.text;
8633
+ if (part.thought === true) {
8634
+ delta.reasoning = { summary: (delta.reasoning?.summary ?? "") + part.text };
8635
+ } else {
8636
+ delta.content = (delta.content ?? "") + part.text;
8637
+ }
7974
8638
  } else if (part.functionCall) {
7975
8639
  if (!delta.toolCalls) delta.toolCalls = [];
7976
8640
  delta.toolCalls.push({
@@ -8044,12 +8708,16 @@ function fromNativeProvider(provider, options) {
8044
8708
  let fullContent = "";
8045
8709
  let allToolCalls = [];
8046
8710
  let lastUsage;
8711
+ let reasoningBlocks;
8047
8712
  const toolCallBuffers = /* @__PURE__ */ new Map();
8048
8713
  for await (const chunk of provider.completeStream(request)) {
8049
8714
  if (chunk.delta.content) {
8050
8715
  fullContent += chunk.delta.content;
8051
8716
  yield chunk.delta.content;
8052
8717
  }
8718
+ if (chunk.delta.reasoning?.blocks?.length) {
8719
+ reasoningBlocks = chunk.delta.reasoning.blocks;
8720
+ }
8053
8721
  if (chunk.delta.toolCalls) {
8054
8722
  for (const tc of chunk.delta.toolCalls) {
8055
8723
  if (tc.id) {
@@ -8070,6 +8738,9 @@ function fromNativeProvider(provider, options) {
8070
8738
  }
8071
8739
  allToolCalls = [...toolCallBuffers.values()];
8072
8740
  const finalMessage = assembleMessage(fullContent, allToolCalls, lastUsage);
8741
+ if (reasoningBlocks?.length) {
8742
+ finalMessage.reasoning = { blocks: reasoningBlocks };
8743
+ }
8073
8744
  yield finalMessage;
8074
8745
  },
8075
8746
  bindTools: (tools, _bindOptions) => {
@@ -8132,6 +8803,10 @@ function toUnifiedMessage(msg) {
8132
8803
  arguments: tc.function?.arguments ?? tc.arguments ?? "{}"
8133
8804
  }));
8134
8805
  }
8806
+ const reasoning = msg.reasoning;
8807
+ if (reasoning && (reasoning.blocks?.length || reasoning.summary)) {
8808
+ unified.reasoning = reasoning;
8809
+ }
8135
8810
  return unified;
8136
8811
  }
8137
8812
  function convertContent(content) {
@@ -8340,6 +9015,9 @@ function toBaseChatMessage(response) {
8340
9015
  function: { name: tc.name, arguments: tc.arguments }
8341
9016
  }));
8342
9017
  }
9018
+ if (response.reasoning && (response.reasoning.blocks?.length || response.reasoning.summary)) {
9019
+ msg.reasoning = response.reasoning;
9020
+ }
8343
9021
  return msg;
8344
9022
  }
8345
9023
  function assembleMessage(content, toolCalls, usage) {
@@ -8436,6 +9114,6 @@ function createProvider(config) {
8436
9114
  }
8437
9115
  }
8438
9116
 
8439
- export { AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, DEFAULT_PROFILE_CONFIGS, GuardrailPhase, InMemoryMemoryStore, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, ProviderError, StructuredOutputManager, ToolBasedStrategy, VertexProvider, agentVerdictRule, buildSystemPrompt, captureSnapshot, codePresenceRule, cognipeerSink, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createCodeGuardrail, createContextSummarizeNode, createContextTools, createGetToolResponseTool, createGuardrail, createJsonGuardrail, createManageTodoTool, createProvider, createRegexGuardrail, createResolverNode, createSmartAgent, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customSink, defaultTokenCounter, emptyUsage, evaluateGuardrails, fileSink, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasToolResponseRecoveryReference, httpSink, isSmartModel, jsonSchemaRule, normalizeSmartAgentOptions, otlpSink, readMemoryFacts, regexRule, resolveMemoryStore, resolveStrategy, resolveToolApprovalState, resolveUserQuestionState, restoreSnapshot, runSmartAgentEvalHarness, setTokenCounter, startStreamingSession, traceSessionToOtlp, withTools, writeSummaryFactsToMemory };
9117
+ export { AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, DEFAULT_PROFILE_CONFIGS, GuardrailPhase, InMemoryMemoryStore, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, ProviderError, StructuredOutputManager, ToolBasedStrategy, VertexProvider, agentVerdictRule, buildSystemPrompt, captureSnapshot, codePresenceRule, cognipeerSink, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createCodeGuardrail, createContextSummarizeNode, createContextTools, createGetToolResponseTool, createGuardrail, createJsonGuardrail, createManageTodoTool, createProvider, createRegexGuardrail, createResolverNode, createSmartAgent, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customSink, defaultTokenCounter, emptyUsage, evaluateGuardrails, fileSink, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasToolResponseRecoveryReference, httpSink, isSmartModel, jsonSchemaRule, normalizeSmartAgentOptions, otlpSink, readMemoryFacts, regexRule, resolveMemoryStore, resolveReasoning, resolveStrategy, resolveToolApprovalState, resolveUserQuestionState, restoreSnapshot, runSmartAgentEvalHarness, setTokenCounter, startStreamingSession, traceSessionToOtlp, validateReasoningConfig, withTools, writeSummaryFactsToMemory };
8440
9118
  //# sourceMappingURL=index.mjs.map
8441
9119
  //# sourceMappingURL=index.mjs.map