@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.cjs +868 -188
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +148 -3
- package/dist/index.d.ts +148 -3
- package/dist/index.mjs +867 -189
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -52,7 +52,7 @@ function getTokenCounter() {
|
|
|
52
52
|
function countApproxTokens(text) {
|
|
53
53
|
return activeTokenCounter(text || "");
|
|
54
54
|
}
|
|
55
|
-
function
|
|
55
|
+
function extractMessageText2(m) {
|
|
56
56
|
if (!m) return "";
|
|
57
57
|
const parts = [];
|
|
58
58
|
parts.push(m.role || "");
|
|
@@ -102,7 +102,7 @@ function extractMessageText(m) {
|
|
|
102
102
|
}
|
|
103
103
|
function countMessagesTokens(messages) {
|
|
104
104
|
if (!Array.isArray(messages) || messages.length === 0) return 0;
|
|
105
|
-
const allText = messages.map(
|
|
105
|
+
const allText = messages.map(extractMessageText2).join("\n");
|
|
106
106
|
return countApproxTokens(allText) + messages.length * 4;
|
|
107
107
|
}
|
|
108
108
|
var activeTokenCounter;
|
|
@@ -1272,6 +1272,7 @@ function eventToOtlpSpan(event) {
|
|
|
1272
1272
|
stringAttr("cognipeer.actor.role", event.actor?.role),
|
|
1273
1273
|
stringAttr("cognipeer.model", event.model),
|
|
1274
1274
|
stringAttr("cognipeer.provider", event.provider),
|
|
1275
|
+
stringAttr("cognipeer.tool.details", event.toolDetails ? JSON.stringify(event.toolDetails) : void 0),
|
|
1275
1276
|
intAttr("cognipeer.tokens.input", event.inputTokens),
|
|
1276
1277
|
intAttr("cognipeer.tokens.output", event.outputTokens),
|
|
1277
1278
|
intAttr("cognipeer.tokens.total", event.totalTokens),
|
|
@@ -1743,6 +1744,7 @@ function recordTraceEvent(session, event) {
|
|
|
1743
1744
|
responseBytes,
|
|
1744
1745
|
model: resolvedModel,
|
|
1745
1746
|
provider: resolvedProvider,
|
|
1747
|
+
toolDetails: session.resolvedConfig.logData ? sanitizeTracePayload(event.toolDetails) : void 0,
|
|
1746
1748
|
toolExecutionId: event.toolExecutionId,
|
|
1747
1749
|
retryOf: event.retryOf,
|
|
1748
1750
|
error: event.error ?? (status === "error" ? { message: "Unknown error" } : void 0) ?? void 0,
|
|
@@ -2193,16 +2195,99 @@ function createAgentCoreNode(opts) {
|
|
|
2193
2195
|
};
|
|
2194
2196
|
}
|
|
2195
2197
|
|
|
2198
|
+
// src/utils/content.ts
|
|
2199
|
+
function contentToString(content) {
|
|
2200
|
+
try {
|
|
2201
|
+
if (content == null) return "";
|
|
2202
|
+
if (typeof content === "string") return content;
|
|
2203
|
+
if (Array.isArray(content)) {
|
|
2204
|
+
return content.map((p) => {
|
|
2205
|
+
if (!p || typeof p !== "object") return String(p);
|
|
2206
|
+
if (p.type === "text") return String(p.text ?? "");
|
|
2207
|
+
if (p.type === "image_url") {
|
|
2208
|
+
const img = p.image_url;
|
|
2209
|
+
const url = typeof img === "string" ? img : img?.url;
|
|
2210
|
+
const detail = typeof img === "string" ? void 0 : img?.detail;
|
|
2211
|
+
return `[image:${url || "unknown"}${detail ? ` detail=${detail}` : ""}]`;
|
|
2212
|
+
}
|
|
2213
|
+
return JSON.stringify(p);
|
|
2214
|
+
}).join("\n");
|
|
2215
|
+
}
|
|
2216
|
+
return JSON.stringify(content);
|
|
2217
|
+
} catch {
|
|
2218
|
+
return String(content);
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
function mergeContentsToString(contents) {
|
|
2222
|
+
return contents.map((c) => contentToString(c)).join("\n");
|
|
2223
|
+
}
|
|
2224
|
+
function safeStringify(value, pretty = false) {
|
|
2225
|
+
if (value == null) return "";
|
|
2226
|
+
if (typeof value === "string") return value;
|
|
2227
|
+
try {
|
|
2228
|
+
return JSON.stringify(value, null, pretty ? 2 : void 0) ?? String(value);
|
|
2229
|
+
} catch {
|
|
2230
|
+
return String(value);
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
function extractMessageText(message) {
|
|
2234
|
+
if (!message) return "";
|
|
2235
|
+
const content = message.content;
|
|
2236
|
+
if (typeof content === "string") return content;
|
|
2237
|
+
if (Array.isArray(content)) {
|
|
2238
|
+
return content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? "").join("");
|
|
2239
|
+
}
|
|
2240
|
+
return "";
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
// src/utils/traceSections.ts
|
|
2244
|
+
function truncate(text, max = 500) {
|
|
2245
|
+
if (!text) return "";
|
|
2246
|
+
return text.length > max ? `${text.slice(0, max)}\u2026` : text;
|
|
2247
|
+
}
|
|
2248
|
+
function summarizeToolOutput(output) {
|
|
2249
|
+
if (output == null) return "";
|
|
2250
|
+
if (typeof output === "string") return truncate(output.trim());
|
|
2251
|
+
if (Array.isArray(output)) {
|
|
2252
|
+
const preview = output.slice(0, 3).map((item, index) => `${index + 1}. ${truncate(safeStringify(item))}`).join("\n");
|
|
2253
|
+
const suffix = output.length > 3 ? `
|
|
2254
|
+
\u2026 (+${output.length - 3} more)` : "";
|
|
2255
|
+
return `${preview}${suffix}`.trim();
|
|
2256
|
+
}
|
|
2257
|
+
if (typeof output === "object") {
|
|
2258
|
+
if (Array.isArray(output.items)) {
|
|
2259
|
+
return summarizeToolOutput(output.items);
|
|
2260
|
+
}
|
|
2261
|
+
return truncate(safeStringify(output));
|
|
2262
|
+
}
|
|
2263
|
+
return truncate(String(output));
|
|
2264
|
+
}
|
|
2265
|
+
function extractToolItems(output) {
|
|
2266
|
+
const source = Array.isArray(output) ? output : Array.isArray(output?.items) ? output.items : void 0;
|
|
2267
|
+
if (!Array.isArray(source) || source.length === 0) return void 0;
|
|
2268
|
+
return source.slice(0, 5).map((item) => {
|
|
2269
|
+
if (item && typeof item === "object") {
|
|
2270
|
+
const snippetSource = item.content ?? item.snippet ?? item.description ?? item.text ?? item.summary ?? item;
|
|
2271
|
+
return {
|
|
2272
|
+
title: typeof item.title === "string" ? item.title : void 0,
|
|
2273
|
+
url: typeof item.url === "string" ? item.url : void 0,
|
|
2274
|
+
snippet: truncate(safeStringify(snippetSource))
|
|
2275
|
+
};
|
|
2276
|
+
}
|
|
2277
|
+
return { snippet: truncate(safeStringify(item)) };
|
|
2278
|
+
});
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2196
2281
|
// src/smart/runtimeConfig.ts
|
|
2197
2282
|
var DEFAULT_CRITICAL_TOOLS = ["response", "manage_todo_list", "get_tool_response"];
|
|
2198
2283
|
var BASE_DEFAULTS = {
|
|
2199
|
-
limits: { maxToolCalls:
|
|
2284
|
+
limits: { maxToolCalls: 20, maxParallelTools: 5, maxContextTokens: 96e3, maxTotalOutputTokens: 0, maxCostUsd: 0, maxWallClockMs: 0 },
|
|
2200
2285
|
summarization: {
|
|
2201
2286
|
enable: true,
|
|
2202
|
-
maxTokens:
|
|
2203
|
-
summaryTriggerTokens:
|
|
2204
|
-
summaryPromptMaxTokens:
|
|
2205
|
-
summaryCompressionRatioTarget: 0.
|
|
2287
|
+
maxTokens: 96e3,
|
|
2288
|
+
summaryTriggerTokens: 72e3,
|
|
2289
|
+
summaryPromptMaxTokens: 12e3,
|
|
2290
|
+
summaryCompressionRatioTarget: 0.45,
|
|
2206
2291
|
summaryMode: "incremental",
|
|
2207
2292
|
promptTemplate: "",
|
|
2208
2293
|
toolFreeCall: true,
|
|
@@ -2210,13 +2295,13 @@ var BASE_DEFAULTS = {
|
|
|
2210
2295
|
},
|
|
2211
2296
|
context: {
|
|
2212
2297
|
policy: "hybrid",
|
|
2213
|
-
lastTurnsToKeep:
|
|
2298
|
+
lastTurnsToKeep: 16,
|
|
2214
2299
|
toolResponsePolicy: "summarize_archive",
|
|
2215
2300
|
budget: {
|
|
2216
|
-
systemReserveTokens:
|
|
2217
|
-
goalsReserveTokens:
|
|
2218
|
-
recentTurnsReserveTokens:
|
|
2219
|
-
toolResponseReserveTokens:
|
|
2301
|
+
systemReserveTokens: 2e3,
|
|
2302
|
+
goalsReserveTokens: 2e3,
|
|
2303
|
+
recentTurnsReserveTokens: 18e3,
|
|
2304
|
+
toolResponseReserveTokens: 9e3
|
|
2220
2305
|
}
|
|
2221
2306
|
},
|
|
2222
2307
|
planning: {
|
|
@@ -2233,14 +2318,14 @@ var BASE_DEFAULTS = {
|
|
|
2233
2318
|
delegation: {
|
|
2234
2319
|
mode: "role_based",
|
|
2235
2320
|
maxDelegationDepth: 2,
|
|
2236
|
-
maxChildCalls:
|
|
2237
|
-
maxParallelChild:
|
|
2321
|
+
maxChildCalls: 6,
|
|
2322
|
+
maxParallelChild: 3,
|
|
2238
2323
|
childContextPolicy: "scoped",
|
|
2239
2324
|
requireJsonOutputContract: true
|
|
2240
2325
|
},
|
|
2241
2326
|
toolResponses: {
|
|
2242
|
-
maxToolResponseChars:
|
|
2243
|
-
maxToolResponseTokens:
|
|
2327
|
+
maxToolResponseChars: 32e3,
|
|
2328
|
+
maxToolResponseTokens: 8e3,
|
|
2244
2329
|
defaultPolicy: "summarize_archive",
|
|
2245
2330
|
toolResponseRetentionByTool: {},
|
|
2246
2331
|
criticalTools: [...DEFAULT_CRITICAL_TOOLS],
|
|
@@ -2269,54 +2354,54 @@ function buildProfile(overrides) {
|
|
|
2269
2354
|
}
|
|
2270
2355
|
var DEFAULT_PROFILE_CONFIGS = {
|
|
2271
2356
|
fast: buildProfile({
|
|
2272
|
-
limits: { maxToolCalls:
|
|
2357
|
+
limits: { maxToolCalls: 8, maxParallelTools: 3, maxContextTokens: 32e3 },
|
|
2273
2358
|
summarization: {
|
|
2274
|
-
maxTokens:
|
|
2275
|
-
summaryTriggerTokens:
|
|
2276
|
-
summaryPromptMaxTokens:
|
|
2277
|
-
summaryCompressionRatioTarget: 0.
|
|
2359
|
+
maxTokens: 32e3,
|
|
2360
|
+
summaryTriggerTokens: 24e3,
|
|
2361
|
+
summaryPromptMaxTokens: 6e3,
|
|
2362
|
+
summaryCompressionRatioTarget: 0.5
|
|
2278
2363
|
},
|
|
2279
2364
|
context: {
|
|
2280
|
-
lastTurnsToKeep:
|
|
2365
|
+
lastTurnsToKeep: 8,
|
|
2281
2366
|
toolResponsePolicy: "keep_structured",
|
|
2282
|
-
budget: { systemReserveTokens:
|
|
2367
|
+
budget: { systemReserveTokens: 1500, goalsReserveTokens: 1200, recentTurnsReserveTokens: 6e3, toolResponseReserveTokens: 3500 }
|
|
2283
2368
|
},
|
|
2284
2369
|
memory: { readPolicy: "recent_only" },
|
|
2285
2370
|
delegation: { mode: "off", maxDelegationDepth: 1, maxChildCalls: 2, maxParallelChild: 1, childContextPolicy: "minimal" },
|
|
2286
|
-
toolResponses: { maxToolResponseChars:
|
|
2371
|
+
toolResponses: { maxToolResponseChars: 16e3, maxToolResponseTokens: 4e3 }
|
|
2287
2372
|
}),
|
|
2288
2373
|
balanced: buildProfile({}),
|
|
2289
2374
|
deep: buildProfile({
|
|
2290
|
-
limits: { maxToolCalls:
|
|
2375
|
+
limits: { maxToolCalls: 40, maxParallelTools: 8, maxContextTokens: 2e5 },
|
|
2291
2376
|
summarization: {
|
|
2292
|
-
maxTokens:
|
|
2293
|
-
summaryTriggerTokens:
|
|
2294
|
-
summaryPromptMaxTokens:
|
|
2295
|
-
summaryCompressionRatioTarget: 0.
|
|
2377
|
+
maxTokens: 2e5,
|
|
2378
|
+
summaryTriggerTokens: 15e4,
|
|
2379
|
+
summaryPromptMaxTokens: 16e3,
|
|
2380
|
+
summaryCompressionRatioTarget: 0.4
|
|
2296
2381
|
},
|
|
2297
2382
|
context: {
|
|
2298
|
-
lastTurnsToKeep:
|
|
2299
|
-
budget: { systemReserveTokens:
|
|
2383
|
+
lastTurnsToKeep: 30,
|
|
2384
|
+
budget: { systemReserveTokens: 2500, goalsReserveTokens: 2500, recentTurnsReserveTokens: 36e3, toolResponseReserveTokens: 18e3 }
|
|
2300
2385
|
},
|
|
2301
2386
|
memory: { scope: "workspace" },
|
|
2302
|
-
delegation: { maxDelegationDepth: 3, maxChildCalls:
|
|
2303
|
-
toolResponses: { maxToolResponseChars:
|
|
2387
|
+
delegation: { maxDelegationDepth: 3, maxChildCalls: 10, maxParallelChild: 4 },
|
|
2388
|
+
toolResponses: { maxToolResponseChars: 64e3, maxToolResponseTokens: 16e3 }
|
|
2304
2389
|
}),
|
|
2305
2390
|
research: buildProfile({
|
|
2306
|
-
limits: { maxToolCalls:
|
|
2391
|
+
limits: { maxToolCalls: 80, maxParallelTools: 10, maxContextTokens: 4e5 },
|
|
2307
2392
|
summarization: {
|
|
2308
|
-
maxTokens:
|
|
2309
|
-
summaryTriggerTokens:
|
|
2310
|
-
summaryPromptMaxTokens:
|
|
2311
|
-
summaryCompressionRatioTarget: 0.
|
|
2393
|
+
maxTokens: 4e5,
|
|
2394
|
+
summaryTriggerTokens: 3e5,
|
|
2395
|
+
summaryPromptMaxTokens: 24e3,
|
|
2396
|
+
summaryCompressionRatioTarget: 0.35
|
|
2312
2397
|
},
|
|
2313
2398
|
context: {
|
|
2314
|
-
lastTurnsToKeep:
|
|
2315
|
-
budget: { systemReserveTokens:
|
|
2399
|
+
lastTurnsToKeep: 60,
|
|
2400
|
+
budget: { systemReserveTokens: 3e3, goalsReserveTokens: 3e3, recentTurnsReserveTokens: 72e3, toolResponseReserveTokens: 32e3 }
|
|
2316
2401
|
},
|
|
2317
2402
|
memory: { scope: "workspace" },
|
|
2318
|
-
delegation: { mode: "automatic", maxDelegationDepth: 4, maxChildCalls:
|
|
2319
|
-
toolResponses: { maxToolResponseChars:
|
|
2403
|
+
delegation: { mode: "automatic", maxDelegationDepth: 4, maxChildCalls: 16, maxParallelChild: 6, childContextPolicy: "full" },
|
|
2404
|
+
toolResponses: { maxToolResponseChars: 96e3, maxToolResponseTokens: 24e3 }
|
|
2320
2405
|
})
|
|
2321
2406
|
};
|
|
2322
2407
|
function mergeLimits(base, override) {
|
|
@@ -2406,53 +2491,6 @@ function getResolvedSmartConfig(opts, runtime) {
|
|
|
2406
2491
|
|
|
2407
2492
|
// src/smart/toolResponses.ts
|
|
2408
2493
|
init_utilTokens();
|
|
2409
|
-
|
|
2410
|
-
// src/utils/content.ts
|
|
2411
|
-
function contentToString(content) {
|
|
2412
|
-
try {
|
|
2413
|
-
if (content == null) return "";
|
|
2414
|
-
if (typeof content === "string") return content;
|
|
2415
|
-
if (Array.isArray(content)) {
|
|
2416
|
-
return content.map((p) => {
|
|
2417
|
-
if (!p || typeof p !== "object") return String(p);
|
|
2418
|
-
if (p.type === "text") return String(p.text ?? "");
|
|
2419
|
-
if (p.type === "image_url") {
|
|
2420
|
-
const img = p.image_url;
|
|
2421
|
-
const url = typeof img === "string" ? img : img?.url;
|
|
2422
|
-
const detail = typeof img === "string" ? void 0 : img?.detail;
|
|
2423
|
-
return `[image:${url || "unknown"}${detail ? ` detail=${detail}` : ""}]`;
|
|
2424
|
-
}
|
|
2425
|
-
return JSON.stringify(p);
|
|
2426
|
-
}).join("\n");
|
|
2427
|
-
}
|
|
2428
|
-
return JSON.stringify(content);
|
|
2429
|
-
} catch {
|
|
2430
|
-
return String(content);
|
|
2431
|
-
}
|
|
2432
|
-
}
|
|
2433
|
-
function mergeContentsToString(contents) {
|
|
2434
|
-
return contents.map((c) => contentToString(c)).join("\n");
|
|
2435
|
-
}
|
|
2436
|
-
function safeStringify(value, pretty = false) {
|
|
2437
|
-
if (value == null) return "";
|
|
2438
|
-
if (typeof value === "string") return value;
|
|
2439
|
-
try {
|
|
2440
|
-
return JSON.stringify(value, null, pretty ? 2 : void 0) ?? String(value);
|
|
2441
|
-
} catch {
|
|
2442
|
-
return String(value);
|
|
2443
|
-
}
|
|
2444
|
-
}
|
|
2445
|
-
function extractMessageText2(message) {
|
|
2446
|
-
if (!message) return "";
|
|
2447
|
-
const content = message.content;
|
|
2448
|
-
if (typeof content === "string") return content;
|
|
2449
|
-
if (Array.isArray(content)) {
|
|
2450
|
-
return content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? "").join("");
|
|
2451
|
-
}
|
|
2452
|
-
return "";
|
|
2453
|
-
}
|
|
2454
|
-
|
|
2455
|
-
// src/smart/toolResponses.ts
|
|
2456
2494
|
function summarizeObject(value) {
|
|
2457
2495
|
if (value == null) return "null";
|
|
2458
2496
|
if (typeof value === "string") {
|
|
@@ -2567,6 +2605,97 @@ function normalizeToolCall(call) {
|
|
|
2567
2605
|
args: call.args ?? call.arguments ?? call.input ?? call.function?.arguments ?? call.function_call?.arguments
|
|
2568
2606
|
};
|
|
2569
2607
|
}
|
|
2608
|
+
function normalizeToolSchema(tool, toolName) {
|
|
2609
|
+
const schema = tool.schema;
|
|
2610
|
+
if (!schema) return void 0;
|
|
2611
|
+
if (typeof schema === "object" && schema._def) {
|
|
2612
|
+
try {
|
|
2613
|
+
return sanitizeTracePayload(zodToJsonSchema.zodToJsonSchema(schema, { name: toolName }));
|
|
2614
|
+
} catch {
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
if (schema && typeof schema === "object" && typeof schema.toJSON === "function") {
|
|
2618
|
+
try {
|
|
2619
|
+
return sanitizeTracePayload(schema.toJSON());
|
|
2620
|
+
} catch {
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
return sanitizeTracePayload(schema);
|
|
2624
|
+
}
|
|
2625
|
+
function buildToolDetails(tool, toolName) {
|
|
2626
|
+
if (!tool) return void 0;
|
|
2627
|
+
const details = { name: toolName };
|
|
2628
|
+
if (typeof tool.description === "string" && tool.description.trim().length > 0) {
|
|
2629
|
+
details.description = tool.description;
|
|
2630
|
+
}
|
|
2631
|
+
const inputSchema = normalizeToolSchema(tool, toolName);
|
|
2632
|
+
if (inputSchema !== void 0) details.inputSchema = inputSchema;
|
|
2633
|
+
const needsApproval = typeof tool.needsApproval === "boolean" ? tool.needsApproval : void 0;
|
|
2634
|
+
if (needsApproval !== void 0 || tool.approvalPrompt !== void 0 || tool.approvalDefaults !== void 0) {
|
|
2635
|
+
details.approval = {
|
|
2636
|
+
required: needsApproval,
|
|
2637
|
+
prompt: typeof tool.approvalPrompt === "string" ? tool.approvalPrompt : void 0,
|
|
2638
|
+
defaults: tool.approvalDefaults !== void 0 ? sanitizeTracePayload(tool.approvalDefaults) : void 0
|
|
2639
|
+
};
|
|
2640
|
+
}
|
|
2641
|
+
const cache = tool.cache;
|
|
2642
|
+
if (cache !== void 0) {
|
|
2643
|
+
details.cache = {
|
|
2644
|
+
enabled: Boolean(cache),
|
|
2645
|
+
scope: cache && typeof cache === "object" && typeof cache.scope === "string" ? cache.scope : void 0,
|
|
2646
|
+
ttlMs: cache && typeof cache === "object" && typeof cache.ttlMs === "number" ? cache.ttlMs : void 0,
|
|
2647
|
+
hasKeyFn: Boolean(cache && typeof cache === "object" && typeof cache.keyFn === "function")
|
|
2648
|
+
};
|
|
2649
|
+
}
|
|
2650
|
+
const retry = tool.retry;
|
|
2651
|
+
if (retry && typeof retry === "object") {
|
|
2652
|
+
details.retry = {
|
|
2653
|
+
maxRetries: typeof retry.maxRetries === "number" ? retry.maxRetries : void 0,
|
|
2654
|
+
backoffMs: typeof retry.backoffMs === "number" ? retry.backoffMs : void 0,
|
|
2655
|
+
circuitBreakerThreshold: typeof retry.circuitBreakerThreshold === "number" ? retry.circuitBreakerThreshold : void 0,
|
|
2656
|
+
hasShouldRetry: typeof retry.shouldRetry === "function"
|
|
2657
|
+
};
|
|
2658
|
+
}
|
|
2659
|
+
if (tool.maxExecutionsPerRun !== void 0) {
|
|
2660
|
+
details.limits = { maxExecutionsPerRun: tool.maxExecutionsPerRun };
|
|
2661
|
+
}
|
|
2662
|
+
if (typeof tool.__source === "string") {
|
|
2663
|
+
details.source = tool.__source;
|
|
2664
|
+
}
|
|
2665
|
+
return details;
|
|
2666
|
+
}
|
|
2667
|
+
function buildToolTraceSections(params) {
|
|
2668
|
+
const sanitizedArgs = sanitizeTracePayload(params.args ?? {});
|
|
2669
|
+
const sanitizedOutput = sanitizeTracePayload(params.output);
|
|
2670
|
+
const summary = params.summary ?? summarizeToolOutput(sanitizedOutput);
|
|
2671
|
+
const items = extractToolItems(sanitizedOutput);
|
|
2672
|
+
return [
|
|
2673
|
+
{
|
|
2674
|
+
kind: "tool_call",
|
|
2675
|
+
label: `Tool Call: ${params.toolName}`,
|
|
2676
|
+
tool: params.toolName,
|
|
2677
|
+
arguments: sanitizedArgs,
|
|
2678
|
+
toolDetails: params.toolDetails
|
|
2679
|
+
},
|
|
2680
|
+
{
|
|
2681
|
+
kind: "tool_result",
|
|
2682
|
+
label: `Tool Result: ${params.toolName}`,
|
|
2683
|
+
tool: params.toolName,
|
|
2684
|
+
summary,
|
|
2685
|
+
items,
|
|
2686
|
+
output: sanitizedOutput,
|
|
2687
|
+
toolDetails: params.toolDetails,
|
|
2688
|
+
execution: {
|
|
2689
|
+
id: params.executionId,
|
|
2690
|
+
status: params.status,
|
|
2691
|
+
durationMs: params.durationMs,
|
|
2692
|
+
fromCache: params.fromCache
|
|
2693
|
+
},
|
|
2694
|
+
classification: params.classification,
|
|
2695
|
+
retentionPolicy: params.retentionPolicy
|
|
2696
|
+
}
|
|
2697
|
+
];
|
|
2698
|
+
}
|
|
2570
2699
|
function createToolsNode(initialTools, opts) {
|
|
2571
2700
|
return async (state) => {
|
|
2572
2701
|
const runtime = state.agent || {
|
|
@@ -2675,6 +2804,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2675
2804
|
args = validatedArgs.value;
|
|
2676
2805
|
}
|
|
2677
2806
|
const toolName = tool.name || tc.name;
|
|
2807
|
+
const toolDetails = buildToolDetails(tool, toolName);
|
|
2678
2808
|
const toolStateRef = tool._stateRef && typeof tool._stateRef === "object" ? tool._stateRef : null;
|
|
2679
2809
|
if (toolStateRef) {
|
|
2680
2810
|
toolStateRef.pendingApprovals = pendingApprovals;
|
|
@@ -2695,21 +2825,17 @@ function createToolsNode(initialTools, opts) {
|
|
|
2695
2825
|
label: `Tool Skipped - ${toolName}`,
|
|
2696
2826
|
actor: { scope: "tool", name: toolName, role: "tool" },
|
|
2697
2827
|
status: "skipped",
|
|
2828
|
+
toolDetails,
|
|
2698
2829
|
toolExecutionId: tc.id,
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
function: { name: toolName, arguments: sanitizeTracePayload(args) }
|
|
2709
|
-
}
|
|
2710
|
-
]
|
|
2711
|
-
}
|
|
2712
|
-
]
|
|
2830
|
+
sections: buildToolTraceSections({
|
|
2831
|
+
args,
|
|
2832
|
+
executionId: tc.id,
|
|
2833
|
+
output: limitMessage,
|
|
2834
|
+
status: "skipped",
|
|
2835
|
+
summary: limitMessage,
|
|
2836
|
+
toolDetails,
|
|
2837
|
+
toolName
|
|
2838
|
+
})
|
|
2713
2839
|
});
|
|
2714
2840
|
toolCount += 1;
|
|
2715
2841
|
return { status: "error" };
|
|
@@ -2796,6 +2922,25 @@ function createToolsNode(initialTools, opts) {
|
|
|
2796
2922
|
push({ role: "tool", content: breakerMsg, tool_call_id: toolCallId, name: tc.name });
|
|
2797
2923
|
markToolFailure(breakerMsg, toolName, toolCallId);
|
|
2798
2924
|
onEvent?.({ type: "tool_call", phase: "error", name: toolName, id: tc.id, args, error: { message: breakerMsg } });
|
|
2925
|
+
recordTraceEvent(traceSession, {
|
|
2926
|
+
type: "tool_call",
|
|
2927
|
+
label: `Tool Error - ${toolName}`,
|
|
2928
|
+
actor: { scope: "tool", name: toolName, role: "tool" },
|
|
2929
|
+
status: "error",
|
|
2930
|
+
requestBytes: inputBytes,
|
|
2931
|
+
toolDetails,
|
|
2932
|
+
toolExecutionId: toolCallId,
|
|
2933
|
+
error: { message: breakerMsg },
|
|
2934
|
+
sections: buildToolTraceSections({
|
|
2935
|
+
args,
|
|
2936
|
+
executionId: toolCallId,
|
|
2937
|
+
output: { message: breakerMsg },
|
|
2938
|
+
status: "error",
|
|
2939
|
+
summary: breakerMsg,
|
|
2940
|
+
toolDetails,
|
|
2941
|
+
toolName
|
|
2942
|
+
})
|
|
2943
|
+
});
|
|
2799
2944
|
toolCount += 1;
|
|
2800
2945
|
return { status: "error" };
|
|
2801
2946
|
}
|
|
@@ -2820,6 +2965,38 @@ function createToolsNode(initialTools, opts) {
|
|
|
2820
2965
|
});
|
|
2821
2966
|
push({ role: "tool", content: responsePolicy2.content, tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2822
2967
|
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: cachedHit, durationMs: 0 });
|
|
2968
|
+
const sanitizedCachedHit = sanitizeTracePayload(cachedHit);
|
|
2969
|
+
const outputBytes2 = traceSession?.resolvedConfig.logData ? estimatePayloadBytes(sanitizedCachedHit) : void 0;
|
|
2970
|
+
recordTraceEvent(traceSession, {
|
|
2971
|
+
type: "tool_call",
|
|
2972
|
+
label: `Tool Execution - ${toolName}`,
|
|
2973
|
+
actor: { scope: "tool", name: toolName, role: "tool" },
|
|
2974
|
+
durationMs: 0,
|
|
2975
|
+
requestBytes: inputBytes,
|
|
2976
|
+
responseBytes: outputBytes2,
|
|
2977
|
+
toolDetails,
|
|
2978
|
+
toolExecutionId: executionId2,
|
|
2979
|
+
sections: buildToolTraceSections({
|
|
2980
|
+
args,
|
|
2981
|
+
classification: responsePolicy2.classification,
|
|
2982
|
+
durationMs: 0,
|
|
2983
|
+
executionId: executionId2,
|
|
2984
|
+
fromCache: true,
|
|
2985
|
+
output: sanitizedCachedHit,
|
|
2986
|
+
retentionPolicy: "keep_full",
|
|
2987
|
+
status: "cached",
|
|
2988
|
+
summary: responsePolicy2.content,
|
|
2989
|
+
toolDetails,
|
|
2990
|
+
toolName
|
|
2991
|
+
}),
|
|
2992
|
+
debug: {
|
|
2993
|
+
classification: responsePolicy2.classification,
|
|
2994
|
+
retentionPolicy: "keep_full",
|
|
2995
|
+
originalTokenCount: responsePolicy2.tokenCount,
|
|
2996
|
+
truncated: responsePolicy2.truncated,
|
|
2997
|
+
fromCache: true
|
|
2998
|
+
}
|
|
2999
|
+
});
|
|
2823
3000
|
toolCount += 1;
|
|
2824
3001
|
return { status: "success" };
|
|
2825
3002
|
}
|
|
@@ -2940,28 +3117,6 @@ function createToolsNode(initialTools, opts) {
|
|
|
2940
3117
|
}
|
|
2941
3118
|
const sanitizedOutput = sanitizeTracePayload(output);
|
|
2942
3119
|
const outputBytes = traceSession?.resolvedConfig.logData ? estimatePayloadBytes(sanitizedOutput) : void 0;
|
|
2943
|
-
const messageList = [
|
|
2944
|
-
{
|
|
2945
|
-
role: "assistant",
|
|
2946
|
-
name: toolName,
|
|
2947
|
-
content: "",
|
|
2948
|
-
tool_calls: [
|
|
2949
|
-
{
|
|
2950
|
-
id: tc.id || executionId,
|
|
2951
|
-
type: "function",
|
|
2952
|
-
function: {
|
|
2953
|
-
name: toolName,
|
|
2954
|
-
arguments: sanitizedArgs
|
|
2955
|
-
}
|
|
2956
|
-
}
|
|
2957
|
-
]
|
|
2958
|
-
},
|
|
2959
|
-
{
|
|
2960
|
-
role: "tool",
|
|
2961
|
-
name: toolName,
|
|
2962
|
-
content: responsePolicy.content
|
|
2963
|
-
}
|
|
2964
|
-
];
|
|
2965
3120
|
recordTraceEvent(traceSession, {
|
|
2966
3121
|
type: "tool_call",
|
|
2967
3122
|
label: `Tool Execution - ${toolName}`,
|
|
@@ -2969,8 +3124,20 @@ function createToolsNode(initialTools, opts) {
|
|
|
2969
3124
|
durationMs,
|
|
2970
3125
|
requestBytes: inputBytes,
|
|
2971
3126
|
responseBytes: outputBytes,
|
|
3127
|
+
toolDetails,
|
|
2972
3128
|
toolExecutionId: executionId,
|
|
2973
|
-
|
|
3129
|
+
sections: buildToolTraceSections({
|
|
3130
|
+
args: sanitizedArgs,
|
|
3131
|
+
classification: responsePolicy.classification,
|
|
3132
|
+
durationMs,
|
|
3133
|
+
executionId,
|
|
3134
|
+
output: sanitizedOutput,
|
|
3135
|
+
retentionPolicy: "keep_full",
|
|
3136
|
+
status: "success",
|
|
3137
|
+
summary: responsePolicy.content,
|
|
3138
|
+
toolDetails,
|
|
3139
|
+
toolName
|
|
3140
|
+
}),
|
|
2974
3141
|
debug: {
|
|
2975
3142
|
classification: responsePolicy.classification,
|
|
2976
3143
|
retentionPolicy: "keep_full",
|
|
@@ -2989,6 +3156,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2989
3156
|
markToolFailure(message, toolName, toolCallId);
|
|
2990
3157
|
onEvent?.({ type: "tool_call", phase: "error", name: toolName, id: tc.id, args, error: { message } });
|
|
2991
3158
|
onProgress?.({ stage: "tools", message: `Tool ${tc.name} failed`, detail: { error: message } });
|
|
3159
|
+
const errorOutput = { message, stack: error?.stack };
|
|
2992
3160
|
recordTraceEvent(traceSession, {
|
|
2993
3161
|
type: "tool_call",
|
|
2994
3162
|
label: `Tool Error - ${toolName}`,
|
|
@@ -2996,27 +3164,20 @@ function createToolsNode(initialTools, opts) {
|
|
|
2996
3164
|
status: "error",
|
|
2997
3165
|
durationMs,
|
|
2998
3166
|
requestBytes: inputBytes,
|
|
3167
|
+
responseBytes: traceSession?.resolvedConfig.logData ? estimatePayloadBytes(errorOutput) : void 0,
|
|
3168
|
+
toolDetails,
|
|
2999
3169
|
toolExecutionId: executionId,
|
|
3000
3170
|
error: { message, stack: error?.stack },
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
}
|
|
3012
|
-
]
|
|
3013
|
-
},
|
|
3014
|
-
{
|
|
3015
|
-
role: "tool",
|
|
3016
|
-
name: toolName,
|
|
3017
|
-
content: `Error executing tool: ${message}`
|
|
3018
|
-
}
|
|
3019
|
-
]
|
|
3171
|
+
sections: buildToolTraceSections({
|
|
3172
|
+
args: sanitizedArgs,
|
|
3173
|
+
durationMs,
|
|
3174
|
+
executionId,
|
|
3175
|
+
output: errorOutput,
|
|
3176
|
+
status: "error",
|
|
3177
|
+
summary: `Error executing tool: ${message}`,
|
|
3178
|
+
toolDetails,
|
|
3179
|
+
toolName
|
|
3180
|
+
})
|
|
3020
3181
|
});
|
|
3021
3182
|
toolCount += 1;
|
|
3022
3183
|
return { status: "error", approval: approvalEntry };
|
|
@@ -3093,29 +3254,26 @@ function createToolsNode(initialTools, opts) {
|
|
|
3093
3254
|
}
|
|
3094
3255
|
for (const tc of skipped) {
|
|
3095
3256
|
onEvent?.({ type: "tool_call", phase: "skipped", name: tc.name, id: tc.id, args: tc.args });
|
|
3096
|
-
const
|
|
3257
|
+
const toolDetails = buildToolDetails(toolByName.get(tc.name), tc.name);
|
|
3258
|
+
const skipMessage = `Skipped tool due to tool-call limit: ${tc.name}`;
|
|
3097
3259
|
recordTraceEvent(traceSession, {
|
|
3098
3260
|
type: "tool_call",
|
|
3099
3261
|
label: `Tool Skipped - ${tc.name}`,
|
|
3100
3262
|
actor: { scope: "tool", name: tc.name, role: "tool" },
|
|
3101
3263
|
status: "skipped",
|
|
3264
|
+
toolDetails,
|
|
3102
3265
|
toolExecutionId: tc.id,
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
function: { name: tc.name, arguments: sanitizedArgs }
|
|
3113
|
-
}
|
|
3114
|
-
]
|
|
3115
|
-
}
|
|
3116
|
-
]
|
|
3266
|
+
sections: buildToolTraceSections({
|
|
3267
|
+
args: tc.args,
|
|
3268
|
+
executionId: tc.id,
|
|
3269
|
+
output: skipMessage,
|
|
3270
|
+
status: "skipped",
|
|
3271
|
+
summary: skipMessage,
|
|
3272
|
+
toolDetails,
|
|
3273
|
+
toolName: tc.name
|
|
3274
|
+
})
|
|
3117
3275
|
});
|
|
3118
|
-
appended.push({ role: "tool", content:
|
|
3276
|
+
appended.push({ role: "tool", content: skipMessage, tool_call_id: tc.id || `${tc.name}_${appended.length}`, name: tc.name });
|
|
3119
3277
|
toolCount += 1;
|
|
3120
3278
|
}
|
|
3121
3279
|
if (!awaitingApproval && state.ctx?.__awaitingApproval) {
|
|
@@ -3187,15 +3345,40 @@ function countToolCallsInLastTurn(state) {
|
|
|
3187
3345
|
function stripReflectionAskMessages(messages) {
|
|
3188
3346
|
return messages.filter((m) => !(m?.role === "user" && m?.name === REFLECTION_ASK_NAME));
|
|
3189
3347
|
}
|
|
3348
|
+
function lastTwoToolTurns(state) {
|
|
3349
|
+
const groups = [];
|
|
3350
|
+
let cur = [];
|
|
3351
|
+
let sawTool = false;
|
|
3352
|
+
for (let i = state.messages.length - 1; i >= 0; i--) {
|
|
3353
|
+
const m = state.messages[i];
|
|
3354
|
+
if (m?.role === "tool") {
|
|
3355
|
+
if (m.name) cur.push(m.name);
|
|
3356
|
+
sawTool = true;
|
|
3357
|
+
} else if (m?.role === "assistant") {
|
|
3358
|
+
if (sawTool) {
|
|
3359
|
+
groups.push(cur);
|
|
3360
|
+
cur = [];
|
|
3361
|
+
sawTool = false;
|
|
3362
|
+
if (groups.length >= 2) break;
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
}
|
|
3366
|
+
if (sawTool && cur.length) groups.push(cur);
|
|
3367
|
+
return { current: groups[0] ?? [], previous: groups[1] ?? [] };
|
|
3368
|
+
}
|
|
3190
3369
|
function shouldRunReflection(cadence, state, ranToolsThisTurn) {
|
|
3191
3370
|
if (cadence === "off") return false;
|
|
3192
3371
|
if (cadence === "every_turn") return true;
|
|
3193
3372
|
if (cadence === "after_tool") return ranToolsThisTurn;
|
|
3373
|
+
if (cadence === "initial_then_after_tool") return ranToolsThisTurn;
|
|
3194
3374
|
if (cadence === "on_branch") {
|
|
3195
|
-
const
|
|
3196
|
-
|
|
3197
|
-
const
|
|
3198
|
-
|
|
3375
|
+
const { current, previous } = lastTwoToolTurns(state);
|
|
3376
|
+
if (previous.length === 0) return true;
|
|
3377
|
+
const a = new Set(current);
|
|
3378
|
+
const b = new Set(previous);
|
|
3379
|
+
for (const n of a) if (!b.has(n)) return true;
|
|
3380
|
+
for (const n of b) if (!a.has(n)) return true;
|
|
3381
|
+
return false;
|
|
3199
3382
|
}
|
|
3200
3383
|
return false;
|
|
3201
3384
|
}
|
|
@@ -3212,7 +3395,10 @@ function createReflectionNode(opts, resolved) {
|
|
|
3212
3395
|
const onEvent = state.ctx?.__onEvent;
|
|
3213
3396
|
const traceSession = state.ctx?.__traceSession;
|
|
3214
3397
|
const maxChars = resolved.maxChars;
|
|
3215
|
-
const
|
|
3398
|
+
const turnNow = state.toolCallCount ?? 0;
|
|
3399
|
+
const hookCtx = { state, turn: turnNow, trigger, ranToolsThisTurn: true };
|
|
3400
|
+
const defaultPrompt = (resolved.promptTemplate || DEFAULT_REFLECT_PROMPT).replace(/\$\{maxChars\}/g, String(maxChars));
|
|
3401
|
+
const promptBody = resolved.buildPrompt ? String(resolved.buildPrompt({ ...hookCtx, defaultPrompt, maxChars }) ?? defaultPrompt) : defaultPrompt;
|
|
3216
3402
|
const baseMessages = stripReflectionAskMessages([...state.messages]);
|
|
3217
3403
|
const askMessage = {
|
|
3218
3404
|
role: "user",
|
|
@@ -3246,6 +3432,8 @@ function createReflectionNode(opts, resolved) {
|
|
|
3246
3432
|
const rawText = extractText(response);
|
|
3247
3433
|
const text = trimToChars(String(rawText ?? "").trim(), maxChars);
|
|
3248
3434
|
if (!text) return {};
|
|
3435
|
+
const prevText = (state.reflections?.[state.reflections.length - 1]?.text || "").trim();
|
|
3436
|
+
if (prevText && isNearDuplicate(prevText, text)) return {};
|
|
3249
3437
|
const rawUsage = response?.usage_metadata || response?.response_metadata?.usage || response?.usage || response?.additional_kwargs?.usage;
|
|
3250
3438
|
const usage = normalizeUsage(rawUsage);
|
|
3251
3439
|
const { ids, names } = countToolCallsInLastTurn(state);
|
|
@@ -3294,6 +3482,12 @@ function createReflectionNode(opts, resolved) {
|
|
|
3294
3482
|
} catch (e) {
|
|
3295
3483
|
}
|
|
3296
3484
|
}
|
|
3485
|
+
if (resolved.onReflection) {
|
|
3486
|
+
try {
|
|
3487
|
+
resolved.onReflection(record, hookCtx);
|
|
3488
|
+
} catch {
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
3297
3491
|
const nextMessages = stripReflectionAskMessages([...state.messages]);
|
|
3298
3492
|
const reflections = [...state.reflections || [], record];
|
|
3299
3493
|
const kept = reflections.slice(-Math.max(1, resolved.keepLast));
|
|
@@ -3310,7 +3504,20 @@ ${r.text}
|
|
|
3310
3504
|
metadata: { reflectionId: r.id, reflectionTurn: r.turn, reflectionTrigger: r.trigger }
|
|
3311
3505
|
});
|
|
3312
3506
|
}
|
|
3313
|
-
|
|
3507
|
+
const patch = { messages: prunedMessages, reflections };
|
|
3508
|
+
if (resolved.feedTo === "memory") {
|
|
3509
|
+
const fact = {
|
|
3510
|
+
key: `reflection_turn_${turn}`,
|
|
3511
|
+
value: text,
|
|
3512
|
+
sourceTurn: turn,
|
|
3513
|
+
confidence: 0.3,
|
|
3514
|
+
tags: ["reflection"]
|
|
3515
|
+
};
|
|
3516
|
+
patch.memoryFacts = [...state.memoryFacts || [], fact];
|
|
3517
|
+
} else if (resolved.feedTo === "plan" && state.plan) {
|
|
3518
|
+
patch.plan = { ...state.plan, lastReflection: text };
|
|
3519
|
+
}
|
|
3520
|
+
return patch;
|
|
3314
3521
|
};
|
|
3315
3522
|
}
|
|
3316
3523
|
function extractText(chunk) {
|
|
@@ -3339,24 +3546,75 @@ function safeRandomId() {
|
|
|
3339
3546
|
return `r_${Math.random().toString(36).slice(2, 10)}_${Date.now().toString(36)}`;
|
|
3340
3547
|
}
|
|
3341
3548
|
}
|
|
3549
|
+
function isNearDuplicate(a, b) {
|
|
3550
|
+
const norm = (s) => s.toLowerCase().replace(/\s+/g, " ").trim();
|
|
3551
|
+
const na = norm(a);
|
|
3552
|
+
const nb = norm(b);
|
|
3553
|
+
if (na === nb) return true;
|
|
3554
|
+
const tokensA = new Set(na.split(" ").filter(Boolean));
|
|
3555
|
+
const tokensB = new Set(nb.split(" ").filter(Boolean));
|
|
3556
|
+
if (tokensA.size === 0 || tokensB.size === 0) return false;
|
|
3557
|
+
let inter = 0;
|
|
3558
|
+
for (const t of tokensA) if (tokensB.has(t)) inter++;
|
|
3559
|
+
const union = tokensA.size + tokensB.size - inter;
|
|
3560
|
+
return union > 0 && inter / union >= 0.9;
|
|
3561
|
+
}
|
|
3342
3562
|
|
|
3343
3563
|
// src/smart/reasoning.ts
|
|
3344
3564
|
var LEVEL_DEFAULTS = {
|
|
3565
|
+
minimal: {
|
|
3566
|
+
native: { effort: "minimal" },
|
|
3567
|
+
reflection: { maxTokens: 150, maxChars: 400, cadence: "off" }
|
|
3568
|
+
},
|
|
3345
3569
|
low: {
|
|
3346
3570
|
native: { effort: "low" },
|
|
3347
3571
|
reflection: { maxTokens: 200, maxChars: 600, cadence: "on_branch" }
|
|
3348
3572
|
},
|
|
3349
3573
|
medium: {
|
|
3350
3574
|
native: { effort: "medium" },
|
|
3351
|
-
reflection: { maxTokens: 350, maxChars: 1200, cadence: "
|
|
3575
|
+
reflection: { maxTokens: 350, maxChars: 1200, cadence: "initial_then_after_tool" }
|
|
3352
3576
|
},
|
|
3353
3577
|
high: {
|
|
3354
3578
|
native: { effort: "high" },
|
|
3355
|
-
reflection: { maxTokens: 600, maxChars: 2e3, cadence: "
|
|
3579
|
+
reflection: { maxTokens: 600, maxChars: 2e3, cadence: "initial_then_after_tool" }
|
|
3356
3580
|
}
|
|
3357
3581
|
};
|
|
3582
|
+
var VALID_LEVELS = ["minimal", "low", "medium", "high"];
|
|
3583
|
+
var VALID_CADENCES = ["off", "every_turn", "after_tool", "on_branch", "initial_then_after_tool"];
|
|
3584
|
+
var VALID_EFFORTS = ["minimal", "low", "medium", "high"];
|
|
3585
|
+
function validateReasoningConfig(input) {
|
|
3586
|
+
if (!input) return;
|
|
3587
|
+
if (input.level !== void 0 && !VALID_LEVELS.includes(input.level)) {
|
|
3588
|
+
throw new Error(`reasoning.level must be one of ${VALID_LEVELS.join(", ")} (got "${input.level}")`);
|
|
3589
|
+
}
|
|
3590
|
+
if (input.native) {
|
|
3591
|
+
const n = input.native;
|
|
3592
|
+
if (n.effort !== void 0 && !VALID_EFFORTS.includes(n.effort)) {
|
|
3593
|
+
throw new Error(`reasoning.native.effort must be one of ${VALID_EFFORTS.join(", ")} (got "${n.effort}")`);
|
|
3594
|
+
}
|
|
3595
|
+
if (n.budgetTokens !== void 0 && (!Number.isFinite(n.budgetTokens) || n.budgetTokens < 0)) {
|
|
3596
|
+
throw new Error(`reasoning.native.budgetTokens must be a non-negative number (got ${n.budgetTokens})`);
|
|
3597
|
+
}
|
|
3598
|
+
}
|
|
3599
|
+
if (input.reflection) {
|
|
3600
|
+
const r = input.reflection;
|
|
3601
|
+
if (r.cadence !== void 0 && !VALID_CADENCES.includes(r.cadence)) {
|
|
3602
|
+
throw new Error(`reasoning.reflection.cadence must be one of ${VALID_CADENCES.join(", ")} (got "${r.cadence}")`);
|
|
3603
|
+
}
|
|
3604
|
+
if (r.maxPerRun !== void 0 && (!Number.isFinite(r.maxPerRun) || r.maxPerRun < 0)) {
|
|
3605
|
+
throw new Error(`reasoning.reflection.maxPerRun must be a non-negative number (got ${r.maxPerRun})`);
|
|
3606
|
+
}
|
|
3607
|
+
if (r.everyNTurns !== void 0 && (!Number.isFinite(r.everyNTurns) || r.everyNTurns < 1)) {
|
|
3608
|
+
throw new Error(`reasoning.reflection.everyNTurns must be >= 1 (got ${r.everyNTurns})`);
|
|
3609
|
+
}
|
|
3610
|
+
if (r.feedTo !== void 0 && !["memory", "plan", "none"].includes(r.feedTo)) {
|
|
3611
|
+
throw new Error(`reasoning.reflection.feedTo must be "memory", "plan", or "none" (got "${r.feedTo}")`);
|
|
3612
|
+
}
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3358
3615
|
function resolveReasoning(input) {
|
|
3359
3616
|
if (!input || input.enabled === false) return void 0;
|
|
3617
|
+
validateReasoningConfig(input);
|
|
3360
3618
|
const enabled = input.enabled ?? (input.native !== void 0 || input.reflection !== void 0 || input.level !== void 0);
|
|
3361
3619
|
if (!enabled) return void 0;
|
|
3362
3620
|
const level = input.level ?? "medium";
|
|
@@ -3381,7 +3639,8 @@ function resolveReflection(input, preset) {
|
|
|
3381
3639
|
keepLast: 3,
|
|
3382
3640
|
summarize: false,
|
|
3383
3641
|
emitEvents: true,
|
|
3384
|
-
everyNTurns: 1
|
|
3642
|
+
everyNTurns: 1,
|
|
3643
|
+
feedTo: "none"
|
|
3385
3644
|
};
|
|
3386
3645
|
}
|
|
3387
3646
|
const cfg = input ?? {};
|
|
@@ -3398,7 +3657,11 @@ function resolveReflection(input, preset) {
|
|
|
3398
3657
|
promptTemplate: cfg.promptTemplate,
|
|
3399
3658
|
emitEvents: cfg.emitEvents ?? true,
|
|
3400
3659
|
maxPerRun: typeof cfg.maxPerRun === "number" && cfg.maxPerRun >= 0 ? cfg.maxPerRun : void 0,
|
|
3401
|
-
everyNTurns: Math.max(1, Math.trunc(cfg.everyNTurns ?? 1))
|
|
3660
|
+
everyNTurns: Math.max(1, Math.trunc(cfg.everyNTurns ?? 1)),
|
|
3661
|
+
feedTo: cfg.feedTo ?? "none",
|
|
3662
|
+
shouldReflect: cfg.shouldReflect,
|
|
3663
|
+
buildPrompt: cfg.buildPrompt,
|
|
3664
|
+
onReflection: cfg.onReflection
|
|
3402
3665
|
};
|
|
3403
3666
|
}
|
|
3404
3667
|
function ensureArray(value) {
|
|
@@ -4124,12 +4387,14 @@ function createAgent(opts) {
|
|
|
4124
4387
|
if (summarizationThreshold === void 0) {
|
|
4125
4388
|
state = clearNeedsSummarization(state);
|
|
4126
4389
|
}
|
|
4127
|
-
if (resolvedReasoning
|
|
4390
|
+
if (resolvedReasoning) {
|
|
4128
4391
|
const ctx = { ...state.ctx || {} };
|
|
4129
|
-
if (
|
|
4392
|
+
if (resolvedReasoning.native) {
|
|
4130
4393
|
ctx.__reasoning = resolvedReasoning.native;
|
|
4131
|
-
|
|
4394
|
+
} else {
|
|
4395
|
+
delete ctx.__reasoning;
|
|
4132
4396
|
}
|
|
4397
|
+
state = { ...state, ctx: Object.keys(ctx).length > 0 ? ctx : void 0 };
|
|
4133
4398
|
}
|
|
4134
4399
|
const mergedLimits = {
|
|
4135
4400
|
...opts.limits || {},
|
|
@@ -4177,6 +4442,7 @@ function createAgent(opts) {
|
|
|
4177
4442
|
return { breached: false };
|
|
4178
4443
|
};
|
|
4179
4444
|
let iterations = 0;
|
|
4445
|
+
let reflectionsThisRun = 0;
|
|
4180
4446
|
const onStateChange = config?.onStateChange;
|
|
4181
4447
|
const checkpointReason = config?.checkpointReason;
|
|
4182
4448
|
let pausedStage = null;
|
|
@@ -4222,6 +4488,16 @@ function createAgent(opts) {
|
|
|
4222
4488
|
pausedStage = stage;
|
|
4223
4489
|
return true;
|
|
4224
4490
|
};
|
|
4491
|
+
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")) {
|
|
4492
|
+
try {
|
|
4493
|
+
const patch = await reflectNode(state, "initial_then_after_tool");
|
|
4494
|
+
if (patch && Object.keys(patch).length > 0) {
|
|
4495
|
+
state = { ...state, ...patch };
|
|
4496
|
+
reflectionsThisRun++;
|
|
4497
|
+
}
|
|
4498
|
+
} catch {
|
|
4499
|
+
}
|
|
4500
|
+
}
|
|
4225
4501
|
while (iterations < iterationLimit) {
|
|
4226
4502
|
iterations++;
|
|
4227
4503
|
const budget = checkBudgetBreached();
|
|
@@ -4366,7 +4642,7 @@ function createAgent(opts) {
|
|
|
4366
4642
|
if (toolCalls.length === 0) {
|
|
4367
4643
|
if (soManager && !state.ctx?.__finalizedDueToStructuredOutput && !state.ctx?.__structuredOutputForceFinalize) {
|
|
4368
4644
|
if (soManager.strategy.kind === "native") {
|
|
4369
|
-
const assistantText =
|
|
4645
|
+
const assistantText = extractMessageText(lastMsg);
|
|
4370
4646
|
if (assistantText) {
|
|
4371
4647
|
const parsed = soManager.parseFromContent(assistantText);
|
|
4372
4648
|
if (parsed.success) {
|
|
@@ -4398,16 +4674,18 @@ function createAgent(opts) {
|
|
|
4398
4674
|
if (reflectNode && resolvedReasoning?.reflection.enabled) {
|
|
4399
4675
|
const cadence = resolvedReasoning.reflection.cadence;
|
|
4400
4676
|
const refl = resolvedReasoning.reflection;
|
|
4401
|
-
const reflectionsSoFar = state.reflections?.length ?? 0;
|
|
4402
4677
|
const lastTurn = state.reflections?.at(-1)?.turn ?? -Infinity;
|
|
4403
4678
|
const currentTurn = state.toolCallCount || 0;
|
|
4404
|
-
const budgetExceeded = typeof refl.maxPerRun === "number" &&
|
|
4405
|
-
const
|
|
4406
|
-
|
|
4679
|
+
const budgetExceeded = typeof refl.maxPerRun === "number" && reflectionsThisRun >= refl.maxPerRun;
|
|
4680
|
+
const sinceLast = currentTurn - (Number.isFinite(lastTurn) ? lastTurn : -refl.everyNTurns);
|
|
4681
|
+
const cadenceGap = sinceLast < refl.everyNTurns;
|
|
4682
|
+
const cadenceWantsIt = refl.shouldReflect ? !!refl.shouldReflect({ state, turn: currentTurn, trigger: cadence, ranToolsThisTurn: true }) : shouldRunReflection(cadence, state, true);
|
|
4683
|
+
if (!budgetExceeded && !cadenceGap && cadenceWantsIt) {
|
|
4407
4684
|
try {
|
|
4408
4685
|
const patch = await reflectNode(state, cadence);
|
|
4409
4686
|
if (patch && Object.keys(patch).length > 0) {
|
|
4410
4687
|
state = { ...state, ...patch };
|
|
4688
|
+
reflectionsThisRun++;
|
|
4411
4689
|
}
|
|
4412
4690
|
} catch {
|
|
4413
4691
|
}
|
|
@@ -4417,7 +4695,7 @@ function createAgent(opts) {
|
|
|
4417
4695
|
if (soManager && !state.ctx?.__finalizedDueToStructuredOutput) {
|
|
4418
4696
|
const lastForParse = state.messages[state.messages.length - 1];
|
|
4419
4697
|
if (lastForParse?.role === "assistant") {
|
|
4420
|
-
const assistantText =
|
|
4698
|
+
const assistantText = extractMessageText(lastForParse);
|
|
4421
4699
|
if (assistantText) {
|
|
4422
4700
|
const parsed = soManager.parseFromContent(assistantText);
|
|
4423
4701
|
if (parsed.success) {
|
|
@@ -4570,7 +4848,7 @@ function createAgent(opts) {
|
|
|
4570
4848
|
const isTransientSummarizationExit = !!res.ctx?.__needsSummarization;
|
|
4571
4849
|
const finalAssistantMsg = isTransientSummarizationExit ? void 0 : getLastAssistantMessage(res.messages);
|
|
4572
4850
|
const finalIsSyntheticSummary = !isTransientSummarizationExit && finalAssistantMsg && isSyntheticSummaryMessage(finalAssistantMsg);
|
|
4573
|
-
const content = isTransientSummarizationExit || finalIsSyntheticSummary ? "" :
|
|
4851
|
+
const content = isTransientSummarizationExit || finalIsSyntheticSummary ? "" : extractMessageText(finalAssistantMsg);
|
|
4574
4852
|
let parsed = void 0;
|
|
4575
4853
|
let outputError = void 0;
|
|
4576
4854
|
if (soManager) {
|
|
@@ -4878,7 +5156,7 @@ function renderMemoryBlock(facts) {
|
|
|
4878
5156
|
function clampToBudget(messages, maxContextTokens) {
|
|
4879
5157
|
let working = [...messages];
|
|
4880
5158
|
while (working.length > 2) {
|
|
4881
|
-
const tokenCount = countApproxTokens(working.map(
|
|
5159
|
+
const tokenCount = countApproxTokens(working.map(extractMessageText).join("\n"));
|
|
4882
5160
|
if (tokenCount <= maxContextTokens) return working;
|
|
4883
5161
|
const firstNonSystem = working.findIndex((message, index) => !(index === 0 && message.role === "system"));
|
|
4884
5162
|
if (firstNonSystem < 0) break;
|
|
@@ -5981,7 +6259,7 @@ function createSmartAgent(opts) {
|
|
|
5981
6259
|
].join("\n");
|
|
5982
6260
|
function latestUserPrompt(messages) {
|
|
5983
6261
|
const latest = [...messages].reverse().find((message) => message.role === "user");
|
|
5984
|
-
return latest ?
|
|
6262
|
+
return latest ? extractMessageText(latest) : "";
|
|
5985
6263
|
}
|
|
5986
6264
|
async function syncMemory(state) {
|
|
5987
6265
|
const query = latestUserPrompt(state.messages || []);
|
|
@@ -6670,6 +6948,20 @@ function parseSSEBlock(block) {
|
|
|
6670
6948
|
}
|
|
6671
6949
|
|
|
6672
6950
|
// src/providers/utils/reasoning.ts
|
|
6951
|
+
var ANTHROPIC_EFFORT_BUDGET = {
|
|
6952
|
+
minimal: 1024,
|
|
6953
|
+
low: 2048,
|
|
6954
|
+
medium: 8192,
|
|
6955
|
+
high: 16384
|
|
6956
|
+
};
|
|
6957
|
+
var GEMINI_EFFORT_BUDGET = {
|
|
6958
|
+
minimal: 512,
|
|
6959
|
+
low: 1024,
|
|
6960
|
+
medium: 4096,
|
|
6961
|
+
high: 12e3
|
|
6962
|
+
};
|
|
6963
|
+
var THINKING_OUTPUT_RESERVE = 1024;
|
|
6964
|
+
var THINKING_MIN_MAX_TOKENS = 4096;
|
|
6673
6965
|
function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
|
|
6674
6966
|
if (!reasoning) return;
|
|
6675
6967
|
const effort = normalizeEffort(reasoning.effort);
|
|
@@ -6686,21 +6978,56 @@ function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
|
|
|
6686
6978
|
}
|
|
6687
6979
|
function applyAnthropicReasoning(body, reasoning) {
|
|
6688
6980
|
if (!reasoning) return;
|
|
6689
|
-
|
|
6981
|
+
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
|
|
6690
6982
|
if (!budget) return;
|
|
6983
|
+
const currentMax = typeof body.max_tokens === "number" ? body.max_tokens : 0;
|
|
6984
|
+
const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
|
|
6985
|
+
if (currentMax < requiredMax) {
|
|
6986
|
+
body.max_tokens = requiredMax;
|
|
6987
|
+
}
|
|
6988
|
+
budget = clampBudget(budget, body.max_tokens);
|
|
6691
6989
|
const thinking = { type: "enabled", budget_tokens: budget };
|
|
6692
6990
|
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
6693
6991
|
body.thinking = thinking;
|
|
6992
|
+
stripSamplingParams(body, ["temperature", "top_p", "top_k"]);
|
|
6993
|
+
}
|
|
6994
|
+
function applyBedrockReasoning(body, reasoning) {
|
|
6995
|
+
if (!reasoning) return;
|
|
6996
|
+
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
|
|
6997
|
+
if (!budget) return;
|
|
6998
|
+
const inference = body.inferenceConfig ?? (body.inferenceConfig = {});
|
|
6999
|
+
const currentMax = typeof inference.maxTokens === "number" ? inference.maxTokens : 0;
|
|
7000
|
+
const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
|
|
7001
|
+
if (currentMax < requiredMax) {
|
|
7002
|
+
inference.maxTokens = requiredMax;
|
|
7003
|
+
}
|
|
7004
|
+
budget = clampBudget(budget, inference.maxTokens);
|
|
7005
|
+
const extra = body.additionalModelRequestFields ?? (body.additionalModelRequestFields = {});
|
|
7006
|
+
const thinking = { type: "enabled", budget_tokens: budget };
|
|
7007
|
+
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
7008
|
+
extra.thinking = thinking;
|
|
7009
|
+
stripSamplingParams(inference, ["temperature", "topP"]);
|
|
6694
7010
|
}
|
|
6695
7011
|
function applyGeminiReasoning(generationConfig, reasoning) {
|
|
6696
7012
|
if (!reasoning) return;
|
|
6697
|
-
const budget = resolveBudget(reasoning,
|
|
7013
|
+
const budget = resolveBudget(reasoning, GEMINI_EFFORT_BUDGET);
|
|
6698
7014
|
if (budget == null) return;
|
|
6699
7015
|
const thinkingConfig = { thinkingBudget: budget };
|
|
6700
7016
|
if (reasoning.includeThoughts) thinkingConfig.includeThoughts = true;
|
|
6701
7017
|
if (reasoning.providerExtras) Object.assign(thinkingConfig, reasoning.providerExtras);
|
|
6702
7018
|
generationConfig.thinkingConfig = thinkingConfig;
|
|
6703
7019
|
}
|
|
7020
|
+
function stripSamplingParams(target, keys) {
|
|
7021
|
+
for (const k of keys) {
|
|
7022
|
+
if (k in target) delete target[k];
|
|
7023
|
+
}
|
|
7024
|
+
}
|
|
7025
|
+
function clampBudget(budget, maxTokens) {
|
|
7026
|
+
if (typeof maxTokens !== "number" || maxTokens <= 0) return budget;
|
|
7027
|
+
const ceiling = maxTokens - THINKING_OUTPUT_RESERVE;
|
|
7028
|
+
if (ceiling < 1024) return Math.max(1024, Math.floor(maxTokens / 2));
|
|
7029
|
+
return Math.min(budget, ceiling);
|
|
7030
|
+
}
|
|
6704
7031
|
function normalizeEffort(effort) {
|
|
6705
7032
|
if (!effort) return void 0;
|
|
6706
7033
|
const allowed = ["minimal", "low", "medium", "high"];
|
|
@@ -6729,13 +7056,38 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6729
7056
|
};
|
|
6730
7057
|
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
6731
7058
|
}
|
|
7059
|
+
/** True when the request targets a reasoning model (o-series / gpt-5) so we
|
|
7060
|
+
* should route through the Responses API, which exposes `reasoning.effort`
|
|
7061
|
+
* and reasoning summaries. Chat Completions silently drops these. */
|
|
7062
|
+
useResponsesApi(request) {
|
|
7063
|
+
if (!request.reasoning) return false;
|
|
7064
|
+
return isReasoningModel(request.model || this.defaultModel);
|
|
7065
|
+
}
|
|
6732
7066
|
async complete(request) {
|
|
7067
|
+
if (this.useResponsesApi(request)) {
|
|
7068
|
+
return this.completeResponses(request);
|
|
7069
|
+
}
|
|
6733
7070
|
const body = this.buildRequestBody(request, false);
|
|
6734
7071
|
const res = await this.doFetch(body);
|
|
6735
7072
|
const json = await res.json();
|
|
6736
7073
|
return this.parseResponse(json);
|
|
6737
7074
|
}
|
|
6738
7075
|
async *completeStream(request) {
|
|
7076
|
+
if (this.useResponsesApi(request)) {
|
|
7077
|
+
const response = await this.completeResponses(request);
|
|
7078
|
+
yield {
|
|
7079
|
+
id: response.id,
|
|
7080
|
+
model: response.model,
|
|
7081
|
+
delta: {
|
|
7082
|
+
content: response.content ?? void 0,
|
|
7083
|
+
toolCalls: response.toolCalls.length > 0 ? response.toolCalls : void 0,
|
|
7084
|
+
reasoning: response.reasoning
|
|
7085
|
+
},
|
|
7086
|
+
usage: response.usage,
|
|
7087
|
+
finishReason: response.finishReason
|
|
7088
|
+
};
|
|
7089
|
+
return;
|
|
7090
|
+
}
|
|
6739
7091
|
const body = this.buildRequestBody(request, true);
|
|
6740
7092
|
const res = await this.doFetch(body);
|
|
6741
7093
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
@@ -6834,6 +7186,156 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6834
7186
|
applyOpenAIReasoning(body, request.reasoning, "legacy_effort");
|
|
6835
7187
|
return body;
|
|
6836
7188
|
}
|
|
7189
|
+
// ─── Responses API (reasoning models) ──────────────────────────────────────
|
|
7190
|
+
async completeResponses(request) {
|
|
7191
|
+
const body = this.buildResponsesBody(request);
|
|
7192
|
+
const res = await this.responsesFetch(body);
|
|
7193
|
+
const json = await res.json();
|
|
7194
|
+
return this.parseResponsesResponse(json, request.model || this.defaultModel);
|
|
7195
|
+
}
|
|
7196
|
+
buildResponsesBody(request) {
|
|
7197
|
+
const body = {
|
|
7198
|
+
model: request.model || this.defaultModel,
|
|
7199
|
+
input: request.messages.map((m) => this.toResponsesInput(m))
|
|
7200
|
+
};
|
|
7201
|
+
if (request.maxTokens != null) body.max_output_tokens = request.maxTokens;
|
|
7202
|
+
if (request.topP != null) body.top_p = request.topP;
|
|
7203
|
+
if (request.tools?.length) {
|
|
7204
|
+
body.tools = request.tools.map((t) => ({
|
|
7205
|
+
type: "function",
|
|
7206
|
+
name: t.name,
|
|
7207
|
+
description: t.description,
|
|
7208
|
+
parameters: t.parameters,
|
|
7209
|
+
...t.strict ? { strict: true } : {}
|
|
7210
|
+
}));
|
|
7211
|
+
}
|
|
7212
|
+
if (request.toolChoice != null && request.tools?.length) {
|
|
7213
|
+
if (typeof request.toolChoice === "string") {
|
|
7214
|
+
body.tool_choice = request.toolChoice;
|
|
7215
|
+
} else {
|
|
7216
|
+
body.tool_choice = { type: "function", name: request.toolChoice.name };
|
|
7217
|
+
}
|
|
7218
|
+
}
|
|
7219
|
+
if (request.responseFormat) {
|
|
7220
|
+
if (request.responseFormat.type === "json_schema") {
|
|
7221
|
+
body.text = {
|
|
7222
|
+
format: {
|
|
7223
|
+
type: "json_schema",
|
|
7224
|
+
name: request.responseFormat.name ?? "response",
|
|
7225
|
+
schema: request.responseFormat.schema,
|
|
7226
|
+
strict: true
|
|
7227
|
+
}
|
|
7228
|
+
};
|
|
7229
|
+
} else if (request.responseFormat.type === "json_object") {
|
|
7230
|
+
body.text = { format: { type: "json_object" } };
|
|
7231
|
+
}
|
|
7232
|
+
}
|
|
7233
|
+
if (request.extra) Object.assign(body, request.extra);
|
|
7234
|
+
applyOpenAIReasoning(body, request.reasoning, "responses");
|
|
7235
|
+
return body;
|
|
7236
|
+
}
|
|
7237
|
+
/** Maps a unified message to a Responses API `input` item. */
|
|
7238
|
+
toResponsesInput(m) {
|
|
7239
|
+
if (m.role === "tool" && m.toolCallId) {
|
|
7240
|
+
const output = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
|
|
7241
|
+
return { type: "function_call_output", call_id: m.toolCallId, output };
|
|
7242
|
+
}
|
|
7243
|
+
if (m.role === "assistant" && m.toolCalls?.length) {
|
|
7244
|
+
return {
|
|
7245
|
+
__assistantWithCalls: true,
|
|
7246
|
+
text: typeof m.content === "string" ? m.content : "",
|
|
7247
|
+
calls: m.toolCalls.map((tc) => ({
|
|
7248
|
+
type: "function_call",
|
|
7249
|
+
call_id: tc.id,
|
|
7250
|
+
name: tc.name,
|
|
7251
|
+
arguments: tc.arguments
|
|
7252
|
+
}))
|
|
7253
|
+
};
|
|
7254
|
+
}
|
|
7255
|
+
const role = m.role === "system" ? "system" : m.role === "assistant" ? "assistant" : "user";
|
|
7256
|
+
const textType = role === "assistant" ? "output_text" : "input_text";
|
|
7257
|
+
if (typeof m.content === "string") {
|
|
7258
|
+
return { role, content: [{ type: textType, text: m.content }] };
|
|
7259
|
+
}
|
|
7260
|
+
const content = m.content.map((part) => {
|
|
7261
|
+
if (part.type === "text") return { type: textType, text: part.text };
|
|
7262
|
+
if (part.type === "image") {
|
|
7263
|
+
const src = part.source;
|
|
7264
|
+
const url = src.type === "url" ? src.url : `data:${src.mediaType};base64,${src.data}`;
|
|
7265
|
+
return { type: "input_image", image_url: url };
|
|
7266
|
+
}
|
|
7267
|
+
return { type: textType, text: "" };
|
|
7268
|
+
});
|
|
7269
|
+
return { role, content };
|
|
7270
|
+
}
|
|
7271
|
+
async responsesFetch(body) {
|
|
7272
|
+
body.input = expandResponsesInput(body.input);
|
|
7273
|
+
const url = `${this.baseURL}/responses`;
|
|
7274
|
+
const headers = {
|
|
7275
|
+
"Content-Type": "application/json",
|
|
7276
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
7277
|
+
...this.defaultHeaders
|
|
7278
|
+
};
|
|
7279
|
+
const payload = JSON.stringify(body);
|
|
7280
|
+
const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload }));
|
|
7281
|
+
if (!res.ok) {
|
|
7282
|
+
const text = await res.text().catch(() => "");
|
|
7283
|
+
throw new ProviderError(
|
|
7284
|
+
`OpenAI Responses API error ${res.status}: ${text}`,
|
|
7285
|
+
this.providerName,
|
|
7286
|
+
res.status,
|
|
7287
|
+
text
|
|
7288
|
+
);
|
|
7289
|
+
}
|
|
7290
|
+
return res;
|
|
7291
|
+
}
|
|
7292
|
+
parseResponsesResponse(json, modelId) {
|
|
7293
|
+
const textParts = [];
|
|
7294
|
+
const toolCalls = [];
|
|
7295
|
+
const summaryParts = [];
|
|
7296
|
+
for (const item of json.output ?? []) {
|
|
7297
|
+
if (item.type === "message") {
|
|
7298
|
+
for (const c of item.content ?? []) {
|
|
7299
|
+
if (c.type === "output_text" && typeof c.text === "string") textParts.push(c.text);
|
|
7300
|
+
}
|
|
7301
|
+
} else if (item.type === "function_call") {
|
|
7302
|
+
toolCalls.push({
|
|
7303
|
+
id: item.call_id ?? item.id ?? "",
|
|
7304
|
+
name: item.name ?? "",
|
|
7305
|
+
arguments: typeof item.arguments === "string" ? item.arguments : JSON.stringify(item.arguments ?? {})
|
|
7306
|
+
});
|
|
7307
|
+
} else if (item.type === "reasoning") {
|
|
7308
|
+
for (const s of item.summary ?? []) {
|
|
7309
|
+
if (typeof s.text === "string") summaryParts.push(s.text);
|
|
7310
|
+
}
|
|
7311
|
+
}
|
|
7312
|
+
}
|
|
7313
|
+
if (textParts.length === 0 && typeof json.output_text === "string") {
|
|
7314
|
+
textParts.push(json.output_text);
|
|
7315
|
+
}
|
|
7316
|
+
const usage = json.usage ?? {};
|
|
7317
|
+
const reasoningTokens = usage.output_tokens_details?.reasoning_tokens ?? 0;
|
|
7318
|
+
const tokenUsage = {
|
|
7319
|
+
inputTokens: usage.input_tokens ?? 0,
|
|
7320
|
+
outputTokens: usage.output_tokens ?? 0,
|
|
7321
|
+
totalTokens: usage.total_tokens ?? (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),
|
|
7322
|
+
cachedInputTokens: usage.input_tokens_details?.cached_tokens ?? 0,
|
|
7323
|
+
cachedWriteTokens: 0,
|
|
7324
|
+
cachedOutputTokens: 0,
|
|
7325
|
+
reasoningTokens
|
|
7326
|
+
};
|
|
7327
|
+
const finishReason = toolCalls.length > 0 ? "tool_calls" : json.status === "incomplete" ? "length" : "stop";
|
|
7328
|
+
return {
|
|
7329
|
+
id: json.id ?? "",
|
|
7330
|
+
model: json.model ?? modelId,
|
|
7331
|
+
content: textParts.join("") || null,
|
|
7332
|
+
toolCalls,
|
|
7333
|
+
usage: tokenUsage,
|
|
7334
|
+
finishReason,
|
|
7335
|
+
reasoning: summaryParts.length > 0 ? { summary: summaryParts.join("\n").trim() || void 0 } : void 0,
|
|
7336
|
+
raw: json
|
|
7337
|
+
};
|
|
7338
|
+
}
|
|
6837
7339
|
toOpenAIMessage(m) {
|
|
6838
7340
|
const msg = { role: m.role };
|
|
6839
7341
|
if (typeof m.content === "string") {
|
|
@@ -6926,6 +7428,25 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6926
7428
|
};
|
|
6927
7429
|
}
|
|
6928
7430
|
};
|
|
7431
|
+
function isReasoningModel(model) {
|
|
7432
|
+
if (!model) return false;
|
|
7433
|
+
const m = model.toLowerCase();
|
|
7434
|
+
return /(^|[/_-])o[0-9]/.test(m) || m.startsWith("o1") || m.startsWith("o3") || m.startsWith("o4") || m.includes("gpt-5") || m.includes("gpt5");
|
|
7435
|
+
}
|
|
7436
|
+
function expandResponsesInput(input) {
|
|
7437
|
+
const out = [];
|
|
7438
|
+
for (const item of input) {
|
|
7439
|
+
if (item && item.__assistantWithCalls) {
|
|
7440
|
+
if (item.text) {
|
|
7441
|
+
out.push({ role: "assistant", content: [{ type: "output_text", text: item.text }] });
|
|
7442
|
+
}
|
|
7443
|
+
for (const call of item.calls) out.push(call);
|
|
7444
|
+
} else {
|
|
7445
|
+
out.push(item);
|
|
7446
|
+
}
|
|
7447
|
+
}
|
|
7448
|
+
return out;
|
|
7449
|
+
}
|
|
6929
7450
|
function mapFinishReason(reason) {
|
|
6930
7451
|
switch (reason) {
|
|
6931
7452
|
case "stop":
|
|
@@ -6971,6 +7492,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6971
7492
|
let cacheReadInputTokens = 0;
|
|
6972
7493
|
let cacheCreationInputTokens = 0;
|
|
6973
7494
|
const currentToolCalls = /* @__PURE__ */ new Map();
|
|
7495
|
+
const reasoningBlocks = /* @__PURE__ */ new Map();
|
|
6974
7496
|
for await (const event of parseSSEStream(res.body)) {
|
|
6975
7497
|
let data;
|
|
6976
7498
|
try {
|
|
@@ -7000,6 +7522,10 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7000
7522
|
name: block.name ?? "",
|
|
7001
7523
|
arguments: ""
|
|
7002
7524
|
});
|
|
7525
|
+
} else if (block?.type === "thinking") {
|
|
7526
|
+
reasoningBlocks.set(idx, { type: "thinking", text: block.thinking ?? "", signature: block.signature });
|
|
7527
|
+
} else if (block?.type === "redacted_thinking") {
|
|
7528
|
+
reasoningBlocks.set(idx, { type: "redacted_thinking", data: block.data });
|
|
7003
7529
|
}
|
|
7004
7530
|
break;
|
|
7005
7531
|
}
|
|
@@ -7012,6 +7538,19 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7012
7538
|
model,
|
|
7013
7539
|
delta: { content: delta.text }
|
|
7014
7540
|
};
|
|
7541
|
+
} else if (delta?.type === "thinking_delta" && delta.thinking) {
|
|
7542
|
+
const blk = reasoningBlocks.get(idx) ?? { type: "thinking", text: "" };
|
|
7543
|
+
blk.text = (blk.text ?? "") + delta.thinking;
|
|
7544
|
+
reasoningBlocks.set(idx, blk);
|
|
7545
|
+
yield {
|
|
7546
|
+
id,
|
|
7547
|
+
model,
|
|
7548
|
+
delta: { reasoning: { summary: delta.thinking } }
|
|
7549
|
+
};
|
|
7550
|
+
} else if (delta?.type === "signature_delta" && delta.signature) {
|
|
7551
|
+
const blk = reasoningBlocks.get(idx) ?? { type: "thinking", text: "" };
|
|
7552
|
+
blk.signature = (blk.signature ?? "") + delta.signature;
|
|
7553
|
+
reasoningBlocks.set(idx, blk);
|
|
7015
7554
|
} else if (delta?.type === "input_json_delta" && delta.partial_json) {
|
|
7016
7555
|
const tc = currentToolCalls.get(idx);
|
|
7017
7556
|
if (tc) {
|
|
@@ -7044,10 +7583,13 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7044
7583
|
cachedOutputTokens: 0,
|
|
7045
7584
|
reasoningTokens: 0
|
|
7046
7585
|
};
|
|
7586
|
+
const blocks = [...reasoningBlocks.values()].filter(
|
|
7587
|
+
(b) => b.type === "thinking" && b.signature || b.type === "redacted_thinking" && b.data
|
|
7588
|
+
);
|
|
7047
7589
|
yield {
|
|
7048
7590
|
id,
|
|
7049
7591
|
model,
|
|
7050
|
-
delta: {},
|
|
7592
|
+
delta: blocks.length > 0 ? { reasoning: { blocks } } : {},
|
|
7051
7593
|
finishReason,
|
|
7052
7594
|
usage
|
|
7053
7595
|
};
|
|
@@ -7139,6 +7681,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7139
7681
|
}
|
|
7140
7682
|
if (m.role === "assistant" && m.toolCalls?.length) {
|
|
7141
7683
|
const content = [];
|
|
7684
|
+
appendReasoningBlocks(content, m.reasoning?.blocks);
|
|
7142
7685
|
if (typeof m.content === "string" && m.content) {
|
|
7143
7686
|
content.push({ type: "text", text: m.content });
|
|
7144
7687
|
}
|
|
@@ -7152,6 +7695,13 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7152
7695
|
}
|
|
7153
7696
|
return { role: "assistant", content };
|
|
7154
7697
|
}
|
|
7698
|
+
if (m.role === "assistant" && m.reasoning?.blocks?.length) {
|
|
7699
|
+
const content = [];
|
|
7700
|
+
appendReasoningBlocks(content, m.reasoning.blocks);
|
|
7701
|
+
const text = typeof m.content === "string" ? m.content : "";
|
|
7702
|
+
if (text) content.push({ type: "text", text });
|
|
7703
|
+
return { role: "assistant", content };
|
|
7704
|
+
}
|
|
7155
7705
|
const msg = { role: m.role };
|
|
7156
7706
|
if (typeof m.content === "string") {
|
|
7157
7707
|
msg.content = m.content;
|
|
@@ -7207,9 +7757,20 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7207
7757
|
parseResponse(json) {
|
|
7208
7758
|
const textParts = [];
|
|
7209
7759
|
const toolCalls = [];
|
|
7760
|
+
const reasoningBlocks = [];
|
|
7761
|
+
const summaryParts = [];
|
|
7210
7762
|
for (const block of json.content ?? []) {
|
|
7211
7763
|
if (block.type === "text") {
|
|
7212
7764
|
textParts.push(block.text);
|
|
7765
|
+
} else if (block.type === "thinking") {
|
|
7766
|
+
reasoningBlocks.push({
|
|
7767
|
+
type: "thinking",
|
|
7768
|
+
text: block.thinking ?? "",
|
|
7769
|
+
signature: block.signature
|
|
7770
|
+
});
|
|
7771
|
+
if (block.thinking) summaryParts.push(block.thinking);
|
|
7772
|
+
} else if (block.type === "redacted_thinking") {
|
|
7773
|
+
reasoningBlocks.push({ type: "redacted_thinking", data: block.data });
|
|
7213
7774
|
} else if (block.type === "tool_use") {
|
|
7214
7775
|
toolCalls.push({
|
|
7215
7776
|
id: block.id,
|
|
@@ -7226,6 +7787,9 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7226
7787
|
cachedInputTokens: usage.cache_read_input_tokens ?? 0,
|
|
7227
7788
|
cachedWriteTokens: usage.cache_creation_input_tokens ?? 0,
|
|
7228
7789
|
cachedOutputTokens: 0,
|
|
7790
|
+
// Anthropic bills thinking tokens inside `output_tokens` and does not
|
|
7791
|
+
// expose a separate count, so reasoningTokens stays 0 here (cost is still
|
|
7792
|
+
// captured via outputTokens). See docs for the limitation.
|
|
7229
7793
|
reasoningTokens: 0
|
|
7230
7794
|
};
|
|
7231
7795
|
return {
|
|
@@ -7235,6 +7799,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7235
7799
|
toolCalls,
|
|
7236
7800
|
usage: tokenUsage,
|
|
7237
7801
|
finishReason: mapAnthropicStopReason(json.stop_reason),
|
|
7802
|
+
reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
|
|
7238
7803
|
raw: json
|
|
7239
7804
|
};
|
|
7240
7805
|
}
|
|
@@ -7259,6 +7824,18 @@ function safeJsonParse(str) {
|
|
|
7259
7824
|
return {};
|
|
7260
7825
|
}
|
|
7261
7826
|
}
|
|
7827
|
+
function appendReasoningBlocks(content, blocks) {
|
|
7828
|
+
if (!blocks?.length) return;
|
|
7829
|
+
for (const b of blocks) {
|
|
7830
|
+
if (b.type === "redacted_thinking") {
|
|
7831
|
+
if (b.data) content.push({ type: "redacted_thinking", data: b.data });
|
|
7832
|
+
} else if (b.type === "thinking") {
|
|
7833
|
+
if (b.signature) {
|
|
7834
|
+
content.push({ type: "thinking", thinking: b.text ?? "", signature: b.signature });
|
|
7835
|
+
}
|
|
7836
|
+
}
|
|
7837
|
+
}
|
|
7838
|
+
}
|
|
7262
7839
|
|
|
7263
7840
|
// src/providers/azure.ts
|
|
7264
7841
|
var AzureProvider = class extends OpenAIProvider {
|
|
@@ -7302,7 +7879,52 @@ var AzureProvider = class extends OpenAIProvider {
|
|
|
7302
7879
|
}
|
|
7303
7880
|
return res;
|
|
7304
7881
|
}
|
|
7882
|
+
/** Azure exposes the Responses API at /openai/responses with api-key auth.
|
|
7883
|
+
* Reasoning summaries require a preview api-version; callers can override via
|
|
7884
|
+
* the `apiVersion` config. */
|
|
7885
|
+
async responsesFetch(body) {
|
|
7886
|
+
body.input = expandAzureResponsesInput(body.input);
|
|
7887
|
+
const deployment = this.deploymentName ?? body.model;
|
|
7888
|
+
if (!deployment) {
|
|
7889
|
+
throw new ProviderError("Azure requires a deploymentName or model", this.providerName);
|
|
7890
|
+
}
|
|
7891
|
+
const url = `${this.endpoint}/openai/responses?api-version=${this.apiVersion}`;
|
|
7892
|
+
const payload = JSON.stringify({ ...body, model: deployment });
|
|
7893
|
+
const res = await fetch(url, {
|
|
7894
|
+
method: "POST",
|
|
7895
|
+
headers: {
|
|
7896
|
+
"Content-Type": "application/json",
|
|
7897
|
+
"api-key": this.azureApiKey,
|
|
7898
|
+
...this.defaultHeaders
|
|
7899
|
+
},
|
|
7900
|
+
body: payload
|
|
7901
|
+
});
|
|
7902
|
+
if (!res.ok) {
|
|
7903
|
+
const text = await res.text().catch(() => "");
|
|
7904
|
+
throw new ProviderError(
|
|
7905
|
+
`Azure OpenAI Responses API error ${res.status}: ${text}`,
|
|
7906
|
+
this.providerName,
|
|
7907
|
+
res.status,
|
|
7908
|
+
text
|
|
7909
|
+
);
|
|
7910
|
+
}
|
|
7911
|
+
return res;
|
|
7912
|
+
}
|
|
7305
7913
|
};
|
|
7914
|
+
function expandAzureResponsesInput(input) {
|
|
7915
|
+
const out = [];
|
|
7916
|
+
for (const item of input) {
|
|
7917
|
+
if (item && item.__assistantWithCalls) {
|
|
7918
|
+
if (item.text) {
|
|
7919
|
+
out.push({ role: "assistant", content: [{ type: "output_text", text: item.text }] });
|
|
7920
|
+
}
|
|
7921
|
+
for (const call of item.calls) out.push(call);
|
|
7922
|
+
} else {
|
|
7923
|
+
out.push(item);
|
|
7924
|
+
}
|
|
7925
|
+
}
|
|
7926
|
+
return out;
|
|
7927
|
+
}
|
|
7306
7928
|
|
|
7307
7929
|
// src/providers/openaiCompatible.ts
|
|
7308
7930
|
var OpenAICompatibleProvider = class extends OpenAIProvider {
|
|
@@ -7475,6 +8097,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7475
8097
|
if (request.extra) {
|
|
7476
8098
|
Object.assign(body, request.extra);
|
|
7477
8099
|
}
|
|
8100
|
+
applyBedrockReasoning(body, request.reasoning);
|
|
7478
8101
|
return body;
|
|
7479
8102
|
}
|
|
7480
8103
|
splitSystemMessages(messages) {
|
|
@@ -7508,6 +8131,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7508
8131
|
}
|
|
7509
8132
|
if (m.role === "assistant" && m.toolCalls?.length) {
|
|
7510
8133
|
const content2 = [];
|
|
8134
|
+
appendBedrockReasoning(content2, m.reasoning?.blocks);
|
|
7511
8135
|
if (typeof m.content === "string" && m.content) {
|
|
7512
8136
|
content2.push({ text: m.content });
|
|
7513
8137
|
}
|
|
@@ -7588,9 +8212,23 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7588
8212
|
const output = json.output?.message;
|
|
7589
8213
|
const textParts = [];
|
|
7590
8214
|
const toolCalls = [];
|
|
8215
|
+
const reasoningBlocks = [];
|
|
8216
|
+
const summaryParts = [];
|
|
7591
8217
|
for (const block of output?.content ?? []) {
|
|
7592
8218
|
if (block.text) {
|
|
7593
8219
|
textParts.push(block.text);
|
|
8220
|
+
} else if (block.reasoningContent) {
|
|
8221
|
+
const rc = block.reasoningContent;
|
|
8222
|
+
if (rc.reasoningText) {
|
|
8223
|
+
reasoningBlocks.push({
|
|
8224
|
+
type: "thinking",
|
|
8225
|
+
text: rc.reasoningText.text ?? "",
|
|
8226
|
+
signature: rc.reasoningText.signature
|
|
8227
|
+
});
|
|
8228
|
+
if (rc.reasoningText.text) summaryParts.push(rc.reasoningText.text);
|
|
8229
|
+
} else if (rc.redactedContent) {
|
|
8230
|
+
reasoningBlocks.push({ type: "redacted_thinking", data: rc.redactedContent });
|
|
8231
|
+
}
|
|
7594
8232
|
} else if (block.toolUse) {
|
|
7595
8233
|
toolCalls.push({
|
|
7596
8234
|
id: block.toolUse.toolUseId,
|
|
@@ -7607,6 +8245,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7607
8245
|
cachedInputTokens: usage.cacheReadInputTokenCount ?? 0,
|
|
7608
8246
|
cachedWriteTokens: usage.cacheWriteInputTokenCount ?? 0,
|
|
7609
8247
|
cachedOutputTokens: 0,
|
|
8248
|
+
// Bedrock bills thinking tokens inside outputTokens; no separate count.
|
|
7610
8249
|
reasoningTokens: 0
|
|
7611
8250
|
};
|
|
7612
8251
|
return {
|
|
@@ -7616,10 +8255,25 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7616
8255
|
toolCalls,
|
|
7617
8256
|
usage: tokenUsage,
|
|
7618
8257
|
finishReason: mapBedrockStopReason(json.stopReason),
|
|
8258
|
+
reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
|
|
7619
8259
|
raw: json
|
|
7620
8260
|
};
|
|
7621
8261
|
}
|
|
7622
8262
|
};
|
|
8263
|
+
function appendBedrockReasoning(content, blocks) {
|
|
8264
|
+
if (!blocks?.length) return;
|
|
8265
|
+
for (const b of blocks) {
|
|
8266
|
+
if (b.type === "redacted_thinking") {
|
|
8267
|
+
if (b.data) content.push({ reasoningContent: { redactedContent: b.data } });
|
|
8268
|
+
} else if (b.type === "thinking") {
|
|
8269
|
+
if (b.signature) {
|
|
8270
|
+
content.push({
|
|
8271
|
+
reasoningContent: { reasoningText: { text: b.text ?? "", signature: b.signature } }
|
|
8272
|
+
});
|
|
8273
|
+
}
|
|
8274
|
+
}
|
|
8275
|
+
}
|
|
8276
|
+
}
|
|
7623
8277
|
function mapBedrockStopReason(reason) {
|
|
7624
8278
|
switch (reason) {
|
|
7625
8279
|
case "end_turn":
|
|
@@ -7942,10 +8596,15 @@ var VertexProvider = class extends BaseProvider {
|
|
|
7942
8596
|
const parts = candidate?.content?.parts ?? [];
|
|
7943
8597
|
const textParts = [];
|
|
7944
8598
|
const toolCalls = [];
|
|
8599
|
+
const thoughtParts = [];
|
|
7945
8600
|
let toolCallIdx = 0;
|
|
7946
8601
|
for (const part of parts) {
|
|
7947
8602
|
if (part.text) {
|
|
7948
|
-
|
|
8603
|
+
if (part.thought === true) {
|
|
8604
|
+
thoughtParts.push(part.text);
|
|
8605
|
+
} else {
|
|
8606
|
+
textParts.push(part.text);
|
|
8607
|
+
}
|
|
7949
8608
|
} else if (part.functionCall) {
|
|
7950
8609
|
toolCalls.push({
|
|
7951
8610
|
id: `call_${toolCallIdx++}`,
|
|
@@ -7971,6 +8630,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
7971
8630
|
toolCalls,
|
|
7972
8631
|
usage: tokenUsage,
|
|
7973
8632
|
finishReason: mapGeminiFinishReason(candidate?.finishReason),
|
|
8633
|
+
reasoning: thoughtParts.length > 0 ? { summary: thoughtParts.join("\n").trim() || void 0 } : void 0,
|
|
7974
8634
|
raw: json
|
|
7975
8635
|
};
|
|
7976
8636
|
}
|
|
@@ -7980,7 +8640,11 @@ var VertexProvider = class extends BaseProvider {
|
|
|
7980
8640
|
const delta = {};
|
|
7981
8641
|
for (const part of parts) {
|
|
7982
8642
|
if (part.text) {
|
|
7983
|
-
|
|
8643
|
+
if (part.thought === true) {
|
|
8644
|
+
delta.reasoning = { summary: (delta.reasoning?.summary ?? "") + part.text };
|
|
8645
|
+
} else {
|
|
8646
|
+
delta.content = (delta.content ?? "") + part.text;
|
|
8647
|
+
}
|
|
7984
8648
|
} else if (part.functionCall) {
|
|
7985
8649
|
if (!delta.toolCalls) delta.toolCalls = [];
|
|
7986
8650
|
delta.toolCalls.push({
|
|
@@ -8054,12 +8718,16 @@ function fromNativeProvider(provider, options) {
|
|
|
8054
8718
|
let fullContent = "";
|
|
8055
8719
|
let allToolCalls = [];
|
|
8056
8720
|
let lastUsage;
|
|
8721
|
+
let reasoningBlocks;
|
|
8057
8722
|
const toolCallBuffers = /* @__PURE__ */ new Map();
|
|
8058
8723
|
for await (const chunk of provider.completeStream(request)) {
|
|
8059
8724
|
if (chunk.delta.content) {
|
|
8060
8725
|
fullContent += chunk.delta.content;
|
|
8061
8726
|
yield chunk.delta.content;
|
|
8062
8727
|
}
|
|
8728
|
+
if (chunk.delta.reasoning?.blocks?.length) {
|
|
8729
|
+
reasoningBlocks = chunk.delta.reasoning.blocks;
|
|
8730
|
+
}
|
|
8063
8731
|
if (chunk.delta.toolCalls) {
|
|
8064
8732
|
for (const tc of chunk.delta.toolCalls) {
|
|
8065
8733
|
if (tc.id) {
|
|
@@ -8080,6 +8748,9 @@ function fromNativeProvider(provider, options) {
|
|
|
8080
8748
|
}
|
|
8081
8749
|
allToolCalls = [...toolCallBuffers.values()];
|
|
8082
8750
|
const finalMessage = assembleMessage(fullContent, allToolCalls, lastUsage);
|
|
8751
|
+
if (reasoningBlocks?.length) {
|
|
8752
|
+
finalMessage.reasoning = { blocks: reasoningBlocks };
|
|
8753
|
+
}
|
|
8083
8754
|
yield finalMessage;
|
|
8084
8755
|
},
|
|
8085
8756
|
bindTools: (tools, _bindOptions) => {
|
|
@@ -8142,6 +8813,10 @@ function toUnifiedMessage(msg) {
|
|
|
8142
8813
|
arguments: tc.function?.arguments ?? tc.arguments ?? "{}"
|
|
8143
8814
|
}));
|
|
8144
8815
|
}
|
|
8816
|
+
const reasoning = msg.reasoning;
|
|
8817
|
+
if (reasoning && (reasoning.blocks?.length || reasoning.summary)) {
|
|
8818
|
+
unified.reasoning = reasoning;
|
|
8819
|
+
}
|
|
8145
8820
|
return unified;
|
|
8146
8821
|
}
|
|
8147
8822
|
function convertContent(content) {
|
|
@@ -8350,6 +9025,9 @@ function toBaseChatMessage(response) {
|
|
|
8350
9025
|
function: { name: tc.name, arguments: tc.arguments }
|
|
8351
9026
|
}));
|
|
8352
9027
|
}
|
|
9028
|
+
if (response.reasoning && (response.reasoning.blocks?.length || response.reasoning.summary)) {
|
|
9029
|
+
msg.reasoning = response.reasoning;
|
|
9030
|
+
}
|
|
8353
9031
|
return msg;
|
|
8354
9032
|
}
|
|
8355
9033
|
function assembleMessage(content, toolCalls, usage) {
|
|
@@ -8509,6 +9187,7 @@ exports.otlpSink = otlpSink;
|
|
|
8509
9187
|
exports.readMemoryFacts = readMemoryFacts;
|
|
8510
9188
|
exports.regexRule = regexRule;
|
|
8511
9189
|
exports.resolveMemoryStore = resolveMemoryStore;
|
|
9190
|
+
exports.resolveReasoning = resolveReasoning;
|
|
8512
9191
|
exports.resolveStrategy = resolveStrategy;
|
|
8513
9192
|
exports.resolveToolApprovalState = resolveToolApprovalState;
|
|
8514
9193
|
exports.resolveUserQuestionState = resolveUserQuestionState;
|
|
@@ -8517,6 +9196,7 @@ exports.runSmartAgentEvalHarness = runSmartAgentEvalHarness;
|
|
|
8517
9196
|
exports.setTokenCounter = setTokenCounter;
|
|
8518
9197
|
exports.startStreamingSession = startStreamingSession;
|
|
8519
9198
|
exports.traceSessionToOtlp = traceSessionToOtlp;
|
|
9199
|
+
exports.validateReasoningConfig = validateReasoningConfig;
|
|
8520
9200
|
exports.withTools = withTools;
|
|
8521
9201
|
exports.writeSummaryFactsToMemory = writeSummaryFactsToMemory;
|
|
8522
9202
|
//# sourceMappingURL=index.cjs.map
|