@cognipeer/agent-sdk 0.6.3 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -3
- package/dist/index.cjs +571 -171
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +150 -5
- package/dist/index.d.ts +150 -5
- package/dist/index.mjs +569 -172
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -18,7 +18,99 @@ var path__default = /*#__PURE__*/_interopDefault(path);
|
|
|
18
18
|
var crypto__default = /*#__PURE__*/_interopDefault(crypto);
|
|
19
19
|
var AjvModule__default = /*#__PURE__*/_interopDefault(AjvModule);
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
var __defProp = Object.defineProperty;
|
|
22
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
23
|
+
var __esm = (fn, res) => function __init() {
|
|
24
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
25
|
+
};
|
|
26
|
+
var __export = (target, all) => {
|
|
27
|
+
for (var name in all)
|
|
28
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// src/utils/utilTokens.ts
|
|
32
|
+
var utilTokens_exports = {};
|
|
33
|
+
__export(utilTokens_exports, {
|
|
34
|
+
countApproxTokens: () => countApproxTokens,
|
|
35
|
+
countMessagesTokens: () => countMessagesTokens,
|
|
36
|
+
defaultTokenCounter: () => defaultTokenCounter,
|
|
37
|
+
getTokenCounter: () => getTokenCounter,
|
|
38
|
+
setTokenCounter: () => setTokenCounter
|
|
39
|
+
});
|
|
40
|
+
function defaultTokenCounter(text) {
|
|
41
|
+
if (!text) return 0;
|
|
42
|
+
const nonAsciiCount = (text.match(/[^\x00-\x7F]/g) || []).length;
|
|
43
|
+
const asciiCount = text.length - nonAsciiCount;
|
|
44
|
+
return Math.ceil(asciiCount / 4 + nonAsciiCount / 1.5);
|
|
45
|
+
}
|
|
46
|
+
function setTokenCounter(counter) {
|
|
47
|
+
activeTokenCounter = typeof counter === "function" ? counter : defaultTokenCounter;
|
|
48
|
+
}
|
|
49
|
+
function getTokenCounter() {
|
|
50
|
+
return activeTokenCounter;
|
|
51
|
+
}
|
|
52
|
+
function countApproxTokens(text) {
|
|
53
|
+
return activeTokenCounter(text || "");
|
|
54
|
+
}
|
|
55
|
+
function extractMessageText(m) {
|
|
56
|
+
if (!m) return "";
|
|
57
|
+
const parts = [];
|
|
58
|
+
parts.push(m.role || "");
|
|
59
|
+
if (m.name) parts.push(m.name);
|
|
60
|
+
if (typeof m.content === "string") {
|
|
61
|
+
parts.push(m.content);
|
|
62
|
+
} else if (Array.isArray(m.content)) {
|
|
63
|
+
for (const c of m.content) {
|
|
64
|
+
if (typeof c === "string") parts.push(c);
|
|
65
|
+
else if (c?.text) parts.push(c.text);
|
|
66
|
+
else if (c?.content) parts.push(c.content);
|
|
67
|
+
else if (c?.type === "tool_use" && c?.input) {
|
|
68
|
+
parts.push(c.name || "");
|
|
69
|
+
parts.push(typeof c.input === "string" ? c.input : JSON.stringify(c.input));
|
|
70
|
+
} else if (c != null && typeof c === "object") {
|
|
71
|
+
parts.push(JSON.stringify(c));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} else if (m.content != null && typeof m.content === "object") {
|
|
75
|
+
parts.push(JSON.stringify(m.content));
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(m.tool_calls)) {
|
|
78
|
+
for (const tc of m.tool_calls) {
|
|
79
|
+
if (tc?.function?.name) parts.push(tc.function.name);
|
|
80
|
+
if (tc?.function?.arguments) {
|
|
81
|
+
parts.push(
|
|
82
|
+
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
if (tc?.name && !tc?.function?.name) parts.push(tc.name);
|
|
86
|
+
if (tc?.args && !tc?.function?.arguments) {
|
|
87
|
+
parts.push(typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (Array.isArray(m.additional_kwargs?.tool_calls)) {
|
|
92
|
+
for (const tc of m.additional_kwargs.tool_calls) {
|
|
93
|
+
if (tc?.function?.name) parts.push(tc.function.name);
|
|
94
|
+
if (tc?.function?.arguments) {
|
|
95
|
+
parts.push(
|
|
96
|
+
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return parts.join("\n");
|
|
102
|
+
}
|
|
103
|
+
function countMessagesTokens(messages) {
|
|
104
|
+
if (!Array.isArray(messages) || messages.length === 0) return 0;
|
|
105
|
+
const allText = messages.map(extractMessageText).join("\n");
|
|
106
|
+
return countApproxTokens(allText) + messages.length * 4;
|
|
107
|
+
}
|
|
108
|
+
var activeTokenCounter;
|
|
109
|
+
var init_utilTokens = __esm({
|
|
110
|
+
"src/utils/utilTokens.ts"() {
|
|
111
|
+
activeTokenCounter = defaultTokenCounter;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
22
114
|
var moduleName = "@langchain/core/tools";
|
|
23
115
|
var cachedToolFactory;
|
|
24
116
|
var cachedHasAttemptedFactory = false;
|
|
@@ -326,7 +418,9 @@ function createTool({
|
|
|
326
418
|
needsApproval,
|
|
327
419
|
approvalPrompt,
|
|
328
420
|
approvalDefaults,
|
|
329
|
-
maxExecutionsPerRun
|
|
421
|
+
maxExecutionsPerRun,
|
|
422
|
+
cache,
|
|
423
|
+
retry
|
|
330
424
|
}) {
|
|
331
425
|
const execute = async (input) => func(input);
|
|
332
426
|
const toolRecord = {
|
|
@@ -351,6 +445,12 @@ function createTool({
|
|
|
351
445
|
if (maxExecutionsPerRun !== void 0) {
|
|
352
446
|
toolRecord.maxExecutionsPerRun = maxExecutionsPerRun;
|
|
353
447
|
}
|
|
448
|
+
if (cache !== void 0) {
|
|
449
|
+
toolRecord.cache = cache;
|
|
450
|
+
}
|
|
451
|
+
if (retry !== void 0) {
|
|
452
|
+
toolRecord.retry = retry;
|
|
453
|
+
}
|
|
354
454
|
toolRecord.__source = toolRecord.__source || "smart";
|
|
355
455
|
toolRecord.__impl = func;
|
|
356
456
|
return toolRecord;
|
|
@@ -1892,7 +1992,8 @@ function createAgentCoreNode(opts) {
|
|
|
1892
1992
|
todoListPrompt: opts.todoListPrompt,
|
|
1893
1993
|
limits: opts.limits,
|
|
1894
1994
|
outputSchema: opts.outputSchema,
|
|
1895
|
-
tracing: opts.tracing
|
|
1995
|
+
tracing: opts.tracing,
|
|
1996
|
+
responseFormat: void 0
|
|
1896
1997
|
};
|
|
1897
1998
|
const tools = runtime.tools ?? [];
|
|
1898
1999
|
const shouldUseStrictToolCalling = Boolean(
|
|
@@ -2094,7 +2195,7 @@ function createAgentCoreNode(opts) {
|
|
|
2094
2195
|
// src/smart/runtimeConfig.ts
|
|
2095
2196
|
var DEFAULT_CRITICAL_TOOLS = ["response", "manage_todo_list", "get_tool_response"];
|
|
2096
2197
|
var BASE_DEFAULTS = {
|
|
2097
|
-
limits: { maxToolCalls: 8, maxParallelTools: 2, maxContextTokens: 24e3 },
|
|
2198
|
+
limits: { maxToolCalls: 8, maxParallelTools: 2, maxContextTokens: 24e3, maxTotalOutputTokens: 0, maxCostUsd: 0, maxWallClockMs: 0 },
|
|
2098
2199
|
summarization: {
|
|
2099
2200
|
enable: true,
|
|
2100
2201
|
maxTokens: 24e3,
|
|
@@ -2221,7 +2322,10 @@ function mergeLimits(base, override) {
|
|
|
2221
2322
|
return {
|
|
2222
2323
|
maxToolCalls: override?.maxToolCalls ?? base.maxToolCalls,
|
|
2223
2324
|
maxParallelTools: override?.maxParallelTools ?? base.maxParallelTools,
|
|
2224
|
-
maxContextTokens: override?.maxContextTokens ?? base.maxContextTokens
|
|
2325
|
+
maxContextTokens: override?.maxContextTokens ?? base.maxContextTokens,
|
|
2326
|
+
maxTotalOutputTokens: override?.maxTotalOutputTokens ?? base.maxTotalOutputTokens ?? 0,
|
|
2327
|
+
maxCostUsd: override?.maxCostUsd ?? base.maxCostUsd ?? 0,
|
|
2328
|
+
maxWallClockMs: override?.maxWallClockMs ?? base.maxWallClockMs ?? 0
|
|
2225
2329
|
};
|
|
2226
2330
|
}
|
|
2227
2331
|
function resolveBaseProfile(opts, runtimeProfile) {
|
|
@@ -2239,6 +2343,7 @@ function normalizeSmartAgentOptions(opts) {
|
|
|
2239
2343
|
const summarizationOverride = typeof opts.summarization === "object" ? opts.summarization : {};
|
|
2240
2344
|
const planningMode = opts.planning?.mode ?? customProfile.planning?.mode ?? (useTodoList ? "todo" : preset.planning.mode);
|
|
2241
2345
|
const memoryStore = opts.memory?.store ?? customProfile.memory?.store;
|
|
2346
|
+
const contextToolResponsePolicy = opts.context?.toolResponsePolicy ?? customProfile.context?.toolResponsePolicy ?? preset.context.toolResponsePolicy;
|
|
2242
2347
|
return {
|
|
2243
2348
|
runtimeProfile,
|
|
2244
2349
|
baseProfile,
|
|
@@ -2261,7 +2366,7 @@ function normalizeSmartAgentOptions(opts) {
|
|
|
2261
2366
|
...customProfile.context?.budget || {},
|
|
2262
2367
|
...opts.context?.budget || {}
|
|
2263
2368
|
},
|
|
2264
|
-
toolResponsePolicy:
|
|
2369
|
+
toolResponsePolicy: contextToolResponsePolicy
|
|
2265
2370
|
},
|
|
2266
2371
|
planning: {
|
|
2267
2372
|
...preset.planning,
|
|
@@ -2284,6 +2389,7 @@ function normalizeSmartAgentOptions(opts) {
|
|
|
2284
2389
|
...preset.toolResponses,
|
|
2285
2390
|
...customProfile.toolResponses || {},
|
|
2286
2391
|
...opts.toolResponses || {},
|
|
2392
|
+
defaultPolicy: opts.toolResponses?.defaultPolicy ?? customProfile.toolResponses?.defaultPolicy ?? contextToolResponsePolicy,
|
|
2287
2393
|
toolResponseRetentionByTool: {
|
|
2288
2394
|
...preset.toolResponses.toolResponseRetentionByTool,
|
|
2289
2395
|
...customProfile.toolResponses?.toolResponseRetentionByTool || {},
|
|
@@ -2297,66 +2403,8 @@ function getResolvedSmartConfig(opts, runtime) {
|
|
|
2297
2403
|
return runtime?.smart || normalizeSmartAgentOptions(opts);
|
|
2298
2404
|
}
|
|
2299
2405
|
|
|
2300
|
-
// src/
|
|
2301
|
-
|
|
2302
|
-
if (!text) return 0;
|
|
2303
|
-
const nonAsciiCount = (text.match(/[^\x00-\x7F]/g) || []).length;
|
|
2304
|
-
const asciiCount = text.length - nonAsciiCount;
|
|
2305
|
-
return Math.ceil(asciiCount / 4 + nonAsciiCount / 1.5);
|
|
2306
|
-
}
|
|
2307
|
-
function extractMessageText(m) {
|
|
2308
|
-
if (!m) return "";
|
|
2309
|
-
const parts = [];
|
|
2310
|
-
parts.push(m.role || "");
|
|
2311
|
-
if (m.name) parts.push(m.name);
|
|
2312
|
-
if (typeof m.content === "string") {
|
|
2313
|
-
parts.push(m.content);
|
|
2314
|
-
} else if (Array.isArray(m.content)) {
|
|
2315
|
-
for (const c of m.content) {
|
|
2316
|
-
if (typeof c === "string") parts.push(c);
|
|
2317
|
-
else if (c?.text) parts.push(c.text);
|
|
2318
|
-
else if (c?.content) parts.push(c.content);
|
|
2319
|
-
else if (c?.type === "tool_use" && c?.input) {
|
|
2320
|
-
parts.push(c.name || "");
|
|
2321
|
-
parts.push(typeof c.input === "string" ? c.input : JSON.stringify(c.input));
|
|
2322
|
-
} else if (c != null && typeof c === "object") {
|
|
2323
|
-
parts.push(JSON.stringify(c));
|
|
2324
|
-
}
|
|
2325
|
-
}
|
|
2326
|
-
} else if (m.content != null && typeof m.content === "object") {
|
|
2327
|
-
parts.push(JSON.stringify(m.content));
|
|
2328
|
-
}
|
|
2329
|
-
if (Array.isArray(m.tool_calls)) {
|
|
2330
|
-
for (const tc of m.tool_calls) {
|
|
2331
|
-
if (tc?.function?.name) parts.push(tc.function.name);
|
|
2332
|
-
if (tc?.function?.arguments) {
|
|
2333
|
-
parts.push(
|
|
2334
|
-
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
2335
|
-
);
|
|
2336
|
-
}
|
|
2337
|
-
if (tc?.name && !tc?.function?.name) parts.push(tc.name);
|
|
2338
|
-
if (tc?.args && !tc?.function?.arguments) {
|
|
2339
|
-
parts.push(typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args));
|
|
2340
|
-
}
|
|
2341
|
-
}
|
|
2342
|
-
}
|
|
2343
|
-
if (Array.isArray(m.additional_kwargs?.tool_calls)) {
|
|
2344
|
-
for (const tc of m.additional_kwargs.tool_calls) {
|
|
2345
|
-
if (tc?.function?.name) parts.push(tc.function.name);
|
|
2346
|
-
if (tc?.function?.arguments) {
|
|
2347
|
-
parts.push(
|
|
2348
|
-
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
2349
|
-
);
|
|
2350
|
-
}
|
|
2351
|
-
}
|
|
2352
|
-
}
|
|
2353
|
-
return parts.join("\n");
|
|
2354
|
-
}
|
|
2355
|
-
function countMessagesTokens(messages) {
|
|
2356
|
-
if (!Array.isArray(messages) || messages.length === 0) return 0;
|
|
2357
|
-
const allText = messages.map(extractMessageText).join("\n");
|
|
2358
|
-
return countApproxTokens(allText) + messages.length * 4;
|
|
2359
|
-
}
|
|
2406
|
+
// src/smart/toolResponses.ts
|
|
2407
|
+
init_utilTokens();
|
|
2360
2408
|
|
|
2361
2409
|
// src/utils/content.ts
|
|
2362
2410
|
function contentToString(content) {
|
|
@@ -2556,6 +2604,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2556
2604
|
anyTool._stateRef.messages = state.messages;
|
|
2557
2605
|
anyTool._stateRef.ctx = state.ctx || (state.ctx = {});
|
|
2558
2606
|
anyTool._stateRef.__onEvent = onEvent;
|
|
2607
|
+
anyTool._stateRef.parentRuntime = runtime;
|
|
2559
2608
|
}
|
|
2560
2609
|
}
|
|
2561
2610
|
const last = state.messages[state.messages.length - 1];
|
|
@@ -2566,6 +2615,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2566
2615
|
const remaining = Math.max(0, limits.maxToolCalls - toolCount);
|
|
2567
2616
|
const planned = toolCalls.slice(0, remaining);
|
|
2568
2617
|
const skipped = toolCalls.slice(remaining);
|
|
2618
|
+
const orderedSlots = planned.map(() => []);
|
|
2569
2619
|
const isCancelled = () => {
|
|
2570
2620
|
if (abortSignal?.aborted) return { cancelled: true, reason: "aborted" };
|
|
2571
2621
|
if (cancellationToken && cancellationToken.isCancellationRequested) return { cancelled: true, reason: "cancelled" };
|
|
@@ -2582,7 +2632,9 @@ function createToolsNode(initialTools, opts) {
|
|
|
2582
2632
|
}
|
|
2583
2633
|
state.ctx = ctx;
|
|
2584
2634
|
};
|
|
2585
|
-
const runOne = async (tc) => {
|
|
2635
|
+
const runOne = async (tc, slot = appended) => {
|
|
2636
|
+
var _a;
|
|
2637
|
+
const push = (msg) => slot.push(msg);
|
|
2586
2638
|
const cancelState = isCancelled();
|
|
2587
2639
|
if (cancelState.cancelled) {
|
|
2588
2640
|
const ctx = state.ctx = state.ctx || {};
|
|
@@ -2593,7 +2645,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2593
2645
|
}
|
|
2594
2646
|
const tool = toolByName.get(tc.name);
|
|
2595
2647
|
if (!tool) {
|
|
2596
|
-
|
|
2648
|
+
push({ role: "tool", content: `Tool not found: ${tc.name}`, tool_call_id: tc.id || `${tc.name}_unknown`, name: tc.name });
|
|
2597
2649
|
onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args: tc.args, error: { message: "Tool not found" } });
|
|
2598
2650
|
toolCount += 1;
|
|
2599
2651
|
return { status: "error" };
|
|
@@ -2609,7 +2661,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2609
2661
|
const validatedArgs = validateToolArgs(tool, args);
|
|
2610
2662
|
if (!validatedArgs.ok && resolved.toolResponses.schemaValidation === "strict") {
|
|
2611
2663
|
const errorMessage = `Tool argument validation failed for ${tc.name}: ${validatedArgs.message}`;
|
|
2612
|
-
|
|
2664
|
+
push({ role: "tool", content: errorMessage, tool_call_id: toolCallId, name: tc.name });
|
|
2613
2665
|
markToolFailure(errorMessage, tc.name, toolCallId);
|
|
2614
2666
|
onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args, error: { message: errorMessage } });
|
|
2615
2667
|
toolCount += 1;
|
|
@@ -2631,7 +2683,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2631
2683
|
const currentExecutions = countSuccessfulToolExecutions(toolHistory, toolName);
|
|
2632
2684
|
if (currentExecutions >= maxExecutionsPerRun) {
|
|
2633
2685
|
const limitMessage = `Skipped tool due to per-tool execution limit: ${toolName} (${maxExecutionsPerRun}/run)`;
|
|
2634
|
-
|
|
2686
|
+
push({ role: "tool", content: limitMessage, tool_call_id: toolCallId, name: tc.name });
|
|
2635
2687
|
onEvent?.({ type: "tool_call", phase: "skipped", name: toolName, id: tc.id, args });
|
|
2636
2688
|
recordTraceEvent(traceSession, {
|
|
2637
2689
|
type: "tool_call",
|
|
@@ -2691,7 +2743,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2691
2743
|
}
|
|
2692
2744
|
if (approvalEntry.status === "rejected") {
|
|
2693
2745
|
const rejectionMessage = approvalEntry.comment || "Tool call rejected by reviewer.";
|
|
2694
|
-
|
|
2746
|
+
push({ role: "tool", content: `Tool call rejected: ${rejectionMessage}`, tool_call_id: toolCallId, name: tc.name });
|
|
2695
2747
|
approvalEntry.metadata = { ...approvalEntry.metadata || {}, resolution: "rejected" };
|
|
2696
2748
|
approvalEntry.status = "executed";
|
|
2697
2749
|
approvalEntry.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2709,23 +2761,102 @@ function createToolsNode(initialTools, opts) {
|
|
|
2709
2761
|
const start = Date.now();
|
|
2710
2762
|
const sanitizedArgs = sanitizeTracePayload(args);
|
|
2711
2763
|
const inputBytes = traceSession?.resolvedConfig.logData ? estimatePayloadBytes(sanitizedArgs) : void 0;
|
|
2764
|
+
const cacheCfg = tool.cache;
|
|
2765
|
+
const cacheEnabled = cacheCfg === true || cacheCfg && typeof cacheCfg === "object";
|
|
2766
|
+
const cacheKeyFn = cacheEnabled && typeof cacheCfg === "object" ? cacheCfg.keyFn : void 0;
|
|
2767
|
+
const stableJson = (value) => {
|
|
2768
|
+
try {
|
|
2769
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
2770
|
+
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
|
2771
|
+
const keys = Object.keys(value).sort();
|
|
2772
|
+
return `{${keys.map((k) => JSON.stringify(k) + ":" + stableJson(value[k])).join(",")}}`;
|
|
2773
|
+
} catch {
|
|
2774
|
+
return String(value);
|
|
2775
|
+
}
|
|
2776
|
+
};
|
|
2777
|
+
const cacheKey = cacheEnabled ? `${toolName}|${cacheKeyFn ? cacheKeyFn(args) : stableJson(args)}` : void 0;
|
|
2778
|
+
const toolCache = state.toolCache = state.toolCache || {};
|
|
2779
|
+
let cachedHit = void 0;
|
|
2780
|
+
if (cacheKey && Object.prototype.hasOwnProperty.call(toolCache, cacheKey)) {
|
|
2781
|
+
const entry = toolCache[cacheKey];
|
|
2782
|
+
const ttl = cacheEnabled && typeof cacheCfg === "object" ? cacheCfg.ttlMs : void 0;
|
|
2783
|
+
if (!ttl || entry?.timestamp && Date.now() - entry.timestamp <= ttl) {
|
|
2784
|
+
cachedHit = entry?.value;
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
const retryCfg = tool.retry;
|
|
2788
|
+
const failureStats = (_a = state.ctx).__toolFailureCounts || (_a.__toolFailureCounts = {});
|
|
2789
|
+
if (retryCfg?.circuitBreakerThreshold && failureStats[toolName] >= retryCfg.circuitBreakerThreshold) {
|
|
2790
|
+
const breakerMsg = `Tool ${toolName} circuit breaker open after ${failureStats[toolName]} consecutive failures`;
|
|
2791
|
+
push({ role: "tool", content: breakerMsg, tool_call_id: toolCallId, name: tc.name });
|
|
2792
|
+
markToolFailure(breakerMsg, toolName, toolCallId);
|
|
2793
|
+
onEvent?.({ type: "tool_call", phase: "error", name: toolName, id: tc.id, args, error: { message: breakerMsg } });
|
|
2794
|
+
toolCount += 1;
|
|
2795
|
+
return { status: "error" };
|
|
2796
|
+
}
|
|
2712
2797
|
try {
|
|
2798
|
+
if (cachedHit !== void 0) {
|
|
2799
|
+
const executionId2 = nanoid.nanoid();
|
|
2800
|
+
const responsePolicy2 = applyToolResponseHardCap(toolName, cachedHit, executionId2, resolved);
|
|
2801
|
+
toolHistory.push({
|
|
2802
|
+
executionId: executionId2,
|
|
2803
|
+
toolName,
|
|
2804
|
+
args,
|
|
2805
|
+
output: cachedHit,
|
|
2806
|
+
rawOutput: cachedHit,
|
|
2807
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2808
|
+
tool_call_id: tc.id,
|
|
2809
|
+
summarized: false,
|
|
2810
|
+
originalTokenCount: responsePolicy2.tokenCount,
|
|
2811
|
+
classification: responsePolicy2.classification,
|
|
2812
|
+
retentionPolicy: "keep_full",
|
|
2813
|
+
fromCache: true,
|
|
2814
|
+
status: "success"
|
|
2815
|
+
});
|
|
2816
|
+
push({ role: "tool", content: responsePolicy2.content, tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2817
|
+
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: cachedHit, durationMs: 0 });
|
|
2818
|
+
toolCount += 1;
|
|
2819
|
+
return { status: "success" };
|
|
2820
|
+
}
|
|
2713
2821
|
onEvent?.({ type: "tool_call", phase: "start", name: toolName, id: tc.id, args });
|
|
2714
2822
|
onProgress?.({ stage: "tools", message: `Running tool ${tc.name}` });
|
|
2715
2823
|
const anyTool = tool;
|
|
2716
2824
|
const callOptions = { cancellationToken, signal: abortSignal };
|
|
2825
|
+
const invokeOnce = async () => {
|
|
2826
|
+
if (typeof anyTool.func === "function") return anyTool.func(args, callOptions);
|
|
2827
|
+
if (typeof anyTool.invoke === "function") return anyTool.invoke(args, callOptions);
|
|
2828
|
+
if (typeof anyTool.call === "function") return anyTool.call(args, callOptions);
|
|
2829
|
+
if (typeof anyTool._call === "function") return anyTool._call(args, callOptions);
|
|
2830
|
+
if (typeof anyTool.run === "function") return anyTool.run(args, callOptions);
|
|
2831
|
+
throw new Error("Tool is not invokable");
|
|
2832
|
+
};
|
|
2717
2833
|
let output;
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2834
|
+
const maxRetries = Math.max(0, Number(retryCfg?.maxRetries) || 0);
|
|
2835
|
+
const backoffMs = Math.max(0, Number(retryCfg?.backoffMs) || 250);
|
|
2836
|
+
let attempt = 0;
|
|
2837
|
+
while (true) {
|
|
2838
|
+
try {
|
|
2839
|
+
output = await invokeOnce();
|
|
2840
|
+
failureStats[toolName] = 0;
|
|
2841
|
+
break;
|
|
2842
|
+
} catch (retryErr) {
|
|
2843
|
+
attempt += 1;
|
|
2844
|
+
const shouldRetry = retryCfg?.shouldRetry ? retryCfg.shouldRetry(retryErr, attempt) : true;
|
|
2845
|
+
if (attempt > maxRetries || !shouldRetry) {
|
|
2846
|
+
failureStats[toolName] = (failureStats[toolName] || 0) + 1;
|
|
2847
|
+
throw retryErr;
|
|
2848
|
+
}
|
|
2849
|
+
await new Promise((r) => setTimeout(r, backoffMs * Math.pow(2, attempt - 1)));
|
|
2850
|
+
}
|
|
2851
|
+
}
|
|
2852
|
+
if (cacheKey) {
|
|
2853
|
+
toolCache[cacheKey] = { value: output, timestamp: Date.now() };
|
|
2854
|
+
}
|
|
2724
2855
|
const durationMs = Date.now() - start;
|
|
2725
2856
|
const executionId = nanoid.nanoid();
|
|
2726
2857
|
if (output && typeof output === "object" && output.__handoff && output.__handoff.runtime) {
|
|
2727
2858
|
toolHistory.push({ executionId, toolName, args, output: "handoff:ok", rawOutput: output, timestamp: (/* @__PURE__ */ new Date()).toISOString(), tool_call_id: tc.id, status: "handoff" });
|
|
2728
|
-
|
|
2859
|
+
push({ role: "tool", content: "ok", tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2729
2860
|
state.agent = output.__handoff.runtime;
|
|
2730
2861
|
onEvent?.({ type: "handoff", from: runtime.name, to: state.agent?.name, toolName });
|
|
2731
2862
|
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: "handoff", durationMs });
|
|
@@ -2777,7 +2908,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2777
2908
|
archiveId: void 0,
|
|
2778
2909
|
status: "success"
|
|
2779
2910
|
});
|
|
2780
|
-
|
|
2911
|
+
push({ role: "tool", content: responsePolicy.content, tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2781
2912
|
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: output, durationMs });
|
|
2782
2913
|
onProgress?.({ stage: "tools", message: `Tool ${tc.name} completed`, detail: { durationMs } });
|
|
2783
2914
|
if (needsApproval && approvalEntry) {
|
|
@@ -2833,7 +2964,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2833
2964
|
const executionId = nanoid.nanoid();
|
|
2834
2965
|
const message = error?.message || String(error);
|
|
2835
2966
|
toolHistory.push({ executionId, toolName, args, output: `Error executing tool: ${message}`, rawOutput: null, timestamp: (/* @__PURE__ */ new Date()).toISOString(), tool_call_id: tc.id, status: "error" });
|
|
2836
|
-
|
|
2967
|
+
push({ role: "tool", content: `Error executing tool: ${message}`, tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2837
2968
|
markToolFailure(message, toolName, toolCallId);
|
|
2838
2969
|
onEvent?.({ type: "tool_call", phase: "error", name: toolName, id: tc.id, args, error: { message } });
|
|
2839
2970
|
onProgress?.({ stage: "tools", message: `Tool ${tc.name} failed`, detail: { error: message } });
|
|
@@ -2870,22 +3001,67 @@ function createToolsNode(initialTools, opts) {
|
|
|
2870
3001
|
return { status: "error", approval: approvalEntry };
|
|
2871
3002
|
}
|
|
2872
3003
|
};
|
|
2873
|
-
|
|
2874
|
-
|
|
3004
|
+
const approvalIndices = [];
|
|
3005
|
+
const parallelIndices = [];
|
|
3006
|
+
planned.forEach((tc, idx) => {
|
|
3007
|
+
const t = toolByName.get(tc.name);
|
|
3008
|
+
if (t && t.needsApproval) approvalIndices.push(idx);
|
|
3009
|
+
else parallelIndices.push(idx);
|
|
3010
|
+
});
|
|
3011
|
+
let shouldStop = false;
|
|
3012
|
+
const checkCancellationStop = () => {
|
|
2875
3013
|
const cancelState = isCancelled();
|
|
2876
3014
|
if (cancelState.cancelled) {
|
|
2877
3015
|
const ctx = state.ctx = state.ctx || {};
|
|
2878
3016
|
ctx.__cancelled = { stage: "tools", reason: cancelState.reason, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
2879
3017
|
onEvent?.({ type: "cancelled", stage: "tools", reason: cancelState.reason });
|
|
2880
3018
|
onProgress?.({ stage: "tools", message: "Cancelled", detail: { reason: cancelState.reason } });
|
|
2881
|
-
|
|
3019
|
+
shouldStop = true;
|
|
3020
|
+
return true;
|
|
2882
3021
|
}
|
|
2883
|
-
|
|
3022
|
+
return false;
|
|
3023
|
+
};
|
|
3024
|
+
for (const idx of approvalIndices) {
|
|
3025
|
+
if (awaitingApproval || shouldStop) break;
|
|
3026
|
+
if (checkCancellationStop()) break;
|
|
3027
|
+
const result = await runOne(planned[idx], orderedSlots[idx]);
|
|
2884
3028
|
if (result.status === "awaiting_approval") {
|
|
2885
3029
|
awaitingApproval = true;
|
|
2886
3030
|
break;
|
|
2887
3031
|
}
|
|
2888
3032
|
}
|
|
3033
|
+
if (!awaitingApproval && !shouldStop && parallelIndices.length > 0) {
|
|
3034
|
+
const concurrency = Math.max(1, Math.min(limits.maxParallelTools, parallelIndices.length));
|
|
3035
|
+
let cursor = 0;
|
|
3036
|
+
const workerError = {};
|
|
3037
|
+
const workers = [];
|
|
3038
|
+
for (let w = 0; w < concurrency; w++) {
|
|
3039
|
+
workers.push((async () => {
|
|
3040
|
+
while (true) {
|
|
3041
|
+
if (workerError.err || shouldStop || awaitingApproval) return;
|
|
3042
|
+
const i = cursor++;
|
|
3043
|
+
if (i >= parallelIndices.length) return;
|
|
3044
|
+
if (checkCancellationStop()) return;
|
|
3045
|
+
const idx = parallelIndices[i];
|
|
3046
|
+
try {
|
|
3047
|
+
const result = await runOne(planned[idx], orderedSlots[idx]);
|
|
3048
|
+
if (result.status === "awaiting_approval") {
|
|
3049
|
+
awaitingApproval = true;
|
|
3050
|
+
return;
|
|
3051
|
+
}
|
|
3052
|
+
} catch (err) {
|
|
3053
|
+
workerError.err = err;
|
|
3054
|
+
return;
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
})());
|
|
3058
|
+
}
|
|
3059
|
+
await Promise.all(workers);
|
|
3060
|
+
if (workerError.err) throw workerError.err;
|
|
3061
|
+
}
|
|
3062
|
+
for (const slot of orderedSlots) {
|
|
3063
|
+
if (slot.length > 0) appended.push(...slot);
|
|
3064
|
+
}
|
|
2889
3065
|
for (const tc of skipped) {
|
|
2890
3066
|
onEvent?.({ type: "tool_call", phase: "skipped", name: tc.name, id: tc.id, args: tc.args });
|
|
2891
3067
|
const sanitizedArgs = sanitizeTracePayload(tc.args);
|
|
@@ -2921,11 +3097,23 @@ function createToolsNode(initialTools, opts) {
|
|
|
2921
3097
|
}
|
|
2922
3098
|
state.ctx = Object.keys(ctx).length > 0 ? ctx : void 0;
|
|
2923
3099
|
}
|
|
3100
|
+
const appendedHasToolResult = appended.some((m) => m.role === "tool");
|
|
3101
|
+
if (appendedHasToolResult && state.ctx?.__summarizationExhausted) {
|
|
3102
|
+
const ctx = { ...state.ctx };
|
|
3103
|
+
delete ctx.__summarizationExhausted;
|
|
3104
|
+
state.ctx = Object.keys(ctx).length > 0 ? ctx : void 0;
|
|
3105
|
+
}
|
|
2924
3106
|
return {
|
|
2925
3107
|
messages: [...state.messages, ...appended],
|
|
2926
3108
|
toolCallCount: toolCount,
|
|
2927
3109
|
toolHistory,
|
|
2928
3110
|
toolHistoryArchived,
|
|
3111
|
+
toolCache: state.toolCache,
|
|
3112
|
+
// Explicitly propagate ctx so callers using `{ ...state, ...delta }`
|
|
3113
|
+
// do not silently capture a stale ctx reference. Mutations to
|
|
3114
|
+
// __summarizationExhausted / __awaitingApproval / __structuredOutputParsed
|
|
3115
|
+
// are made on this object during execution.
|
|
3116
|
+
ctx: state.ctx,
|
|
2929
3117
|
agent: state.agent,
|
|
2930
3118
|
pendingApprovals
|
|
2931
3119
|
};
|
|
@@ -3162,7 +3350,8 @@ function resolveReflection(input, preset) {
|
|
|
3162
3350
|
maxChars: preset.maxChars,
|
|
3163
3351
|
keepLast: 3,
|
|
3164
3352
|
summarize: false,
|
|
3165
|
-
emitEvents: true
|
|
3353
|
+
emitEvents: true,
|
|
3354
|
+
everyNTurns: 1
|
|
3166
3355
|
};
|
|
3167
3356
|
}
|
|
3168
3357
|
const cfg = input ?? {};
|
|
@@ -3177,7 +3366,9 @@ function resolveReflection(input, preset) {
|
|
|
3177
3366
|
keepLast: cfg.keepLast ?? 3,
|
|
3178
3367
|
summarize: cfg.summarize ?? false,
|
|
3179
3368
|
promptTemplate: cfg.promptTemplate,
|
|
3180
|
-
emitEvents: cfg.emitEvents ?? true
|
|
3369
|
+
emitEvents: cfg.emitEvents ?? true,
|
|
3370
|
+
maxPerRun: typeof cfg.maxPerRun === "number" && cfg.maxPerRun >= 0 ? cfg.maxPerRun : void 0,
|
|
3371
|
+
everyNTurns: Math.max(1, Math.trunc(cfg.everyNTurns ?? 1))
|
|
3181
3372
|
};
|
|
3182
3373
|
}
|
|
3183
3374
|
function ensureArray(value) {
|
|
@@ -3390,6 +3581,9 @@ function resolveToolApprovalState(state, resolution) {
|
|
|
3390
3581
|
};
|
|
3391
3582
|
}
|
|
3392
3583
|
|
|
3584
|
+
// src/agent.ts
|
|
3585
|
+
init_utilTokens();
|
|
3586
|
+
|
|
3393
3587
|
// src/utils/syntheticMessages.ts
|
|
3394
3588
|
function isSyntheticSummaryMessage(message) {
|
|
3395
3589
|
if (!message) return false;
|
|
@@ -3568,6 +3762,21 @@ function getActiveSummarizationThreshold(opts) {
|
|
|
3568
3762
|
}
|
|
3569
3763
|
return summarization.summaryTriggerTokens || summarization.maxTokens || opts.limits?.maxContextTokens || 5e4;
|
|
3570
3764
|
}
|
|
3765
|
+
function shouldSignalSummarization(state, threshold) {
|
|
3766
|
+
const tokCountMessages = (state.messages || []).filter((message) => {
|
|
3767
|
+
if (isSyntheticSummaryMessage(message)) return false;
|
|
3768
|
+
if (message.role === "system" && (message.name === "context_summary" || message.name === "memory_context")) return false;
|
|
3769
|
+
return true;
|
|
3770
|
+
});
|
|
3771
|
+
const tokenCount = countMessagesTokens(tokCountMessages);
|
|
3772
|
+
if (tokenCount <= threshold) return "skip";
|
|
3773
|
+
if (state.ctx?.__summarizationExhausted) return "skip";
|
|
3774
|
+
const hasFreshSummary = (state.messages || []).some(
|
|
3775
|
+
(m) => m.role === "tool" && typeof m.content === "string" && (m.content === "SUMMARIZED" || m.content.startsWith("SUMMARIZED_TOOL_RESPONSE"))
|
|
3776
|
+
);
|
|
3777
|
+
if (hasFreshSummary && tokenCount <= threshold * 1.15) return "skip";
|
|
3778
|
+
return "trigger";
|
|
3779
|
+
}
|
|
3571
3780
|
function clearNeedsSummarization(state) {
|
|
3572
3781
|
if (!state.ctx?.__needsSummarization) {
|
|
3573
3782
|
return state;
|
|
@@ -3662,6 +3871,45 @@ function createAgent(opts) {
|
|
|
3662
3871
|
};
|
|
3663
3872
|
const maxToolCalls = mergedLimits?.maxToolCalls === void 0 ? 50 : mergedLimits?.maxToolCalls;
|
|
3664
3873
|
const iterationLimit = maxToolCalls === Infinity ? 100 : Math.max(maxToolCalls * 3 + 10, 40);
|
|
3874
|
+
const wallClockStart = Date.now();
|
|
3875
|
+
const maxWallClockMs = mergedLimits?.maxWallClockMs && mergedLimits.maxWallClockMs > 0 ? mergedLimits.maxWallClockMs : void 0;
|
|
3876
|
+
const maxTotalOutputTokens = mergedLimits?.maxTotalOutputTokens && mergedLimits.maxTotalOutputTokens > 0 ? mergedLimits.maxTotalOutputTokens : void 0;
|
|
3877
|
+
const maxCostUsd = mergedLimits?.maxCostUsd && mergedLimits.maxCostUsd > 0 ? mergedLimits.maxCostUsd : void 0;
|
|
3878
|
+
const costEstimator = opts.costEstimator;
|
|
3879
|
+
const checkBudgetBreached = () => {
|
|
3880
|
+
if (maxWallClockMs && Date.now() - wallClockStart > maxWallClockMs) {
|
|
3881
|
+
return { breached: true, reason: `maxWallClockMs (${maxWallClockMs}ms) exceeded` };
|
|
3882
|
+
}
|
|
3883
|
+
if (maxTotalOutputTokens) {
|
|
3884
|
+
const totals = state.usage?.totals;
|
|
3885
|
+
if (totals) {
|
|
3886
|
+
let outputSum = 0;
|
|
3887
|
+
for (const v of Object.values(totals)) outputSum += Number(v?.output) || 0;
|
|
3888
|
+
if (outputSum > maxTotalOutputTokens) {
|
|
3889
|
+
return { breached: true, reason: `maxTotalOutputTokens (${maxTotalOutputTokens}) exceeded` };
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
3892
|
+
}
|
|
3893
|
+
if (maxCostUsd && costEstimator) {
|
|
3894
|
+
const perRequest = state.usage?.perRequest;
|
|
3895
|
+
if (perRequest) {
|
|
3896
|
+
let cost = 0;
|
|
3897
|
+
for (const r of perRequest) {
|
|
3898
|
+
cost += costEstimator({
|
|
3899
|
+
modelName: r.modelName,
|
|
3900
|
+
inputTokens: Number(r.usage?.prompt_tokens) || 0,
|
|
3901
|
+
outputTokens: Number(r.usage?.completion_tokens) || 0,
|
|
3902
|
+
cachedInputTokens: Number(r.usage?.prompt_tokens_details?.cached_tokens) || 0,
|
|
3903
|
+
reasoningTokens: Number(r.usage?.completion_tokens_details?.reasoning_tokens) || 0
|
|
3904
|
+
}) || 0;
|
|
3905
|
+
}
|
|
3906
|
+
if (cost > maxCostUsd) {
|
|
3907
|
+
return { breached: true, reason: `maxCostUsd ($${maxCostUsd}) exceeded (actual: $${cost.toFixed(4)})` };
|
|
3908
|
+
}
|
|
3909
|
+
}
|
|
3910
|
+
}
|
|
3911
|
+
return { breached: false };
|
|
3912
|
+
};
|
|
3665
3913
|
let iterations = 0;
|
|
3666
3914
|
const onStateChange = config?.onStateChange;
|
|
3667
3915
|
const checkpointReason = config?.checkpointReason;
|
|
@@ -3710,6 +3958,13 @@ function createAgent(opts) {
|
|
|
3710
3958
|
};
|
|
3711
3959
|
while (iterations < iterationLimit) {
|
|
3712
3960
|
iterations++;
|
|
3961
|
+
const budget = checkBudgetBreached();
|
|
3962
|
+
if (budget.breached) {
|
|
3963
|
+
emit?.({ type: "metadata", limitBreached: budget.reason });
|
|
3964
|
+
const ctx = { ...state.ctx || {}, __limitBreached: budget.reason };
|
|
3965
|
+
state = { ...state, ctx };
|
|
3966
|
+
break;
|
|
3967
|
+
}
|
|
3713
3968
|
const traceSession = state.ctx?.__traceSession;
|
|
3714
3969
|
if (traceSession) {
|
|
3715
3970
|
const iterEvent = recordTraceEvent(traceSession, {
|
|
@@ -3765,22 +4020,11 @@ function createAgent(opts) {
|
|
|
3765
4020
|
}
|
|
3766
4021
|
}
|
|
3767
4022
|
if (summarizationThreshold !== void 0) {
|
|
3768
|
-
const
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
const tokenCount = countMessagesTokens(tokCountMessages);
|
|
3774
|
-
if (tokenCount > summarizationThreshold) {
|
|
3775
|
-
const summarizationExhausted = !!state.ctx?.__summarizationExhausted;
|
|
3776
|
-
const hasFreshSummary = (state.messages || []).some(
|
|
3777
|
-
(m) => m.role === "tool" && typeof m.content === "string" && (m.content === "SUMMARIZED" || m.content.startsWith("SUMMARIZED_TOOL_RESPONSE"))
|
|
3778
|
-
);
|
|
3779
|
-
if (hasFreshSummary && tokenCount <= summarizationThreshold * 1.15) ; else if (summarizationExhausted) ; else {
|
|
3780
|
-
const ctx = { ...state.ctx || {}, __needsSummarization: true };
|
|
3781
|
-
state = { ...state, ctx };
|
|
3782
|
-
break;
|
|
3783
|
-
}
|
|
4023
|
+
const verdict = shouldSignalSummarization(state, summarizationThreshold);
|
|
4024
|
+
if (verdict === "trigger") {
|
|
4025
|
+
const ctx = { ...state.ctx || {}, __needsSummarization: true };
|
|
4026
|
+
state = { ...state, ctx };
|
|
4027
|
+
break;
|
|
3784
4028
|
}
|
|
3785
4029
|
}
|
|
3786
4030
|
onProgress?.({ stage: "agent", message: "Invoking model" });
|
|
@@ -3886,7 +4130,13 @@ function createAgent(opts) {
|
|
|
3886
4130
|
if (state.ctx?.__finalizedDueToStructuredOutput) break;
|
|
3887
4131
|
if (reflectNode && resolvedReasoning?.reflection.enabled) {
|
|
3888
4132
|
const cadence = resolvedReasoning.reflection.cadence;
|
|
3889
|
-
|
|
4133
|
+
const refl = resolvedReasoning.reflection;
|
|
4134
|
+
const reflectionsSoFar = state.reflections?.length ?? 0;
|
|
4135
|
+
const lastTurn = state.reflections?.at(-1)?.turn ?? -Infinity;
|
|
4136
|
+
const currentTurn = state.toolCallCount || 0;
|
|
4137
|
+
const budgetExceeded = typeof refl.maxPerRun === "number" && reflectionsSoFar >= refl.maxPerRun;
|
|
4138
|
+
const cadenceGap = currentTurn - (Number.isFinite(lastTurn) ? lastTurn : -refl.everyNTurns) < refl.everyNTurns;
|
|
4139
|
+
if (!budgetExceeded && !cadenceGap && shouldRunReflection(cadence, state, true)) {
|
|
3890
4140
|
try {
|
|
3891
4141
|
const patch = await reflectNode(state, cadence);
|
|
3892
4142
|
if (patch && Object.keys(patch).length > 0) {
|
|
@@ -3946,7 +4196,7 @@ function createAgent(opts) {
|
|
|
3946
4196
|
}
|
|
3947
4197
|
const lastAfterLoop = state.messages[state.messages.length - 1];
|
|
3948
4198
|
if (lastAfterLoop?.role === "tool" && !pausedStage) {
|
|
3949
|
-
const isExpectedExit = state.ctx?.__awaitingApproval || state.ctx?.__cancelled || state.ctx?.__finalizedDueToStructuredOutput || state.ctx?.__finalizedDueToToolLimit || state.ctx?.__needsSummarization;
|
|
4199
|
+
const isExpectedExit = state.ctx?.__awaitingApproval || state.ctx?.__cancelled || state.ctx?.__finalizedDueToStructuredOutput || state.ctx?.__finalizedDueToToolLimit || state.ctx?.__needsSummarization || state.ctx?.__limitBreached;
|
|
3950
4200
|
if (!isExpectedExit) {
|
|
3951
4201
|
throw new Error(
|
|
3952
4202
|
"Agent loop terminated with a pending tool response but no subsequent model invocation. This usually indicates a model provider error or exhausted iteration budget."
|
|
@@ -3959,6 +4209,11 @@ function createAgent(opts) {
|
|
|
3959
4209
|
return state;
|
|
3960
4210
|
}
|
|
3961
4211
|
const invokeAgent = async (input, config) => {
|
|
4212
|
+
const userTokenCounter = opts.tokenCounter;
|
|
4213
|
+
if (userTokenCounter) {
|
|
4214
|
+
const { setTokenCounter: setTokenCounter2 } = await Promise.resolve().then(() => (init_utilTokens(), utilTokens_exports));
|
|
4215
|
+
setTokenCounter2(userTokenCounter);
|
|
4216
|
+
}
|
|
3962
4217
|
const onEvent = config?.onEvent;
|
|
3963
4218
|
const onProgress = config?.onProgress;
|
|
3964
4219
|
const onStream = config?.onStream;
|
|
@@ -4016,7 +4271,19 @@ function createAgent(opts) {
|
|
|
4016
4271
|
status: "error",
|
|
4017
4272
|
error: { message: err?.message, stack: err?.stack }
|
|
4018
4273
|
});
|
|
4274
|
+
if (userTokenCounter) {
|
|
4275
|
+
const { setTokenCounter: setTokenCounter2 } = await Promise.resolve().then(() => (init_utilTokens(), utilTokens_exports));
|
|
4276
|
+
setTokenCounter2(void 0);
|
|
4277
|
+
}
|
|
4019
4278
|
throw err;
|
|
4279
|
+
} finally {
|
|
4280
|
+
if (userTokenCounter) {
|
|
4281
|
+
try {
|
|
4282
|
+
const { setTokenCounter: setTokenCounter2 } = await Promise.resolve().then(() => (init_utilTokens(), utilTokens_exports));
|
|
4283
|
+
setTokenCounter2(void 0);
|
|
4284
|
+
} catch {
|
|
4285
|
+
}
|
|
4286
|
+
}
|
|
4020
4287
|
}
|
|
4021
4288
|
await finalizeTraceSession(traceSession, {
|
|
4022
4289
|
agentRuntime: res.agent || runtime,
|
|
@@ -4074,12 +4341,58 @@ function createAgent(opts) {
|
|
|
4074
4341
|
resolveToolApproval,
|
|
4075
4342
|
asTool: ({ toolName, description, inputDescription }) => {
|
|
4076
4343
|
const schema = zod.z.object({ input: zod.z.string().describe(inputDescription || "Input for delegated agent") });
|
|
4077
|
-
|
|
4344
|
+
const delegatedTool = createTool({
|
|
4078
4345
|
name: toolName,
|
|
4079
4346
|
description: description || `Delegate task to agent ${opts.name || "Agent"}`,
|
|
4080
4347
|
schema,
|
|
4081
4348
|
func: async ({ input }) => {
|
|
4082
|
-
const
|
|
4349
|
+
const ref = delegatedTool._stateRef;
|
|
4350
|
+
const parentCtx = ref.ctx || {};
|
|
4351
|
+
const parentMessages = Array.isArray(ref.messages) ? ref.messages : [];
|
|
4352
|
+
const parentRuntime = ref.parentRuntime;
|
|
4353
|
+
const resolvedSmart = parentRuntime?.smart || opts.__resolvedSmart;
|
|
4354
|
+
const delegationPolicy = resolvedSmart?.delegation || {
|
|
4355
|
+
mode: "role_based",
|
|
4356
|
+
maxDelegationDepth: 2,
|
|
4357
|
+
maxChildCalls: 4,
|
|
4358
|
+
childContextPolicy: "scoped"
|
|
4359
|
+
};
|
|
4360
|
+
const currentDepth = Number(parentCtx.__delegationDepth) || 0;
|
|
4361
|
+
if (delegationPolicy.mode === "off") {
|
|
4362
|
+
return { error: "Delegation disabled by runtime policy." };
|
|
4363
|
+
}
|
|
4364
|
+
if (currentDepth >= delegationPolicy.maxDelegationDepth) {
|
|
4365
|
+
return {
|
|
4366
|
+
error: `Delegation depth limit reached (${delegationPolicy.maxDelegationDepth}). Refusing nested call.`
|
|
4367
|
+
};
|
|
4368
|
+
}
|
|
4369
|
+
parentCtx.__delegatedCallCount = (parentCtx.__delegatedCallCount || 0) + 1;
|
|
4370
|
+
if (parentCtx.__delegatedCallCount > delegationPolicy.maxChildCalls) {
|
|
4371
|
+
return {
|
|
4372
|
+
error: `Child-call budget exhausted (${delegationPolicy.maxChildCalls}).`
|
|
4373
|
+
};
|
|
4374
|
+
}
|
|
4375
|
+
let childMessages;
|
|
4376
|
+
switch (delegationPolicy.childContextPolicy) {
|
|
4377
|
+
case "full":
|
|
4378
|
+
childMessages = [...parentMessages, { role: "user", content: input }];
|
|
4379
|
+
break;
|
|
4380
|
+
case "scoped": {
|
|
4381
|
+
const systemPrefix = parentMessages[0]?.role === "system" ? [parentMessages[0]] : [];
|
|
4382
|
+
const lastUser = [...parentMessages].reverse().find((m) => m?.role === "user");
|
|
4383
|
+
childMessages = [
|
|
4384
|
+
...systemPrefix,
|
|
4385
|
+
...lastUser ? [lastUser] : [],
|
|
4386
|
+
{ role: "user", content: input }
|
|
4387
|
+
];
|
|
4388
|
+
break;
|
|
4389
|
+
}
|
|
4390
|
+
case "minimal":
|
|
4391
|
+
default:
|
|
4392
|
+
childMessages = [{ role: "user", content: input }];
|
|
4393
|
+
}
|
|
4394
|
+
const childCtx = { __delegationDepth: currentDepth + 1 };
|
|
4395
|
+
const res = await instance.invoke({ messages: childMessages, ctx: childCtx });
|
|
4083
4396
|
return {
|
|
4084
4397
|
content: res.content,
|
|
4085
4398
|
output: res.output,
|
|
@@ -4087,6 +4400,8 @@ function createAgent(opts) {
|
|
|
4087
4400
|
};
|
|
4088
4401
|
}
|
|
4089
4402
|
});
|
|
4403
|
+
delegatedTool._stateRef = {};
|
|
4404
|
+
return delegatedTool;
|
|
4090
4405
|
},
|
|
4091
4406
|
asHandoff: ({ toolName, description, schema }) => {
|
|
4092
4407
|
const finalName = toolName || `handoff_to_${runtime.name || "agent"}`;
|
|
@@ -4226,7 +4541,11 @@ function createAgentNode(opts) {
|
|
|
4226
4541
|
};
|
|
4227
4542
|
}
|
|
4228
4543
|
|
|
4544
|
+
// src/nodes/contextSummarize.ts
|
|
4545
|
+
init_utilTokens();
|
|
4546
|
+
|
|
4229
4547
|
// src/smart/contextPolicy.ts
|
|
4548
|
+
init_utilTokens();
|
|
4230
4549
|
function collectRecentTurns(messages, lastTurnsToKeep) {
|
|
4231
4550
|
if (lastTurnsToKeep <= 0) return [];
|
|
4232
4551
|
const systemPrefix = messages.filter((message, index) => index === 0 && message.role === "system");
|
|
@@ -4529,7 +4848,7 @@ function createContextSummarizeNode(opts) {
|
|
|
4529
4848
|
const resolved = getResolvedSmartConfig(opts, state.agent);
|
|
4530
4849
|
const config = resolved.summarization;
|
|
4531
4850
|
if (!config.enable) return {};
|
|
4532
|
-
const model = opts.model;
|
|
4851
|
+
const model = state.agent?.model || opts.model;
|
|
4533
4852
|
const messages = state.messages || [];
|
|
4534
4853
|
const onEvent = state.ctx?.__onEvent;
|
|
4535
4854
|
const traceSession = state.ctx?.__traceSession;
|
|
@@ -4848,6 +5167,10 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
4848
5167
|
};
|
|
4849
5168
|
};
|
|
4850
5169
|
}
|
|
5170
|
+
|
|
5171
|
+
// src/index.ts
|
|
5172
|
+
init_utilTokens();
|
|
5173
|
+
init_utilTokens();
|
|
4851
5174
|
var TOOL_RESPONSE_RECOVERY_MARKERS = [
|
|
4852
5175
|
/ARCHIVED_TOOL_RESPONSE\s*\[/,
|
|
4853
5176
|
/STRUCTURED_TOOL_RESPONSE\s*\[/,
|
|
@@ -5166,6 +5489,7 @@ function createContextTools(stateRef, opts) {
|
|
|
5166
5489
|
}
|
|
5167
5490
|
|
|
5168
5491
|
// src/graph/decisions.ts
|
|
5492
|
+
init_utilTokens();
|
|
5169
5493
|
function needsSummarization(state, opts, summarizationEnabled) {
|
|
5170
5494
|
if (!summarizationEnabled) {
|
|
5171
5495
|
return false;
|
|
@@ -5328,12 +5652,24 @@ function createSmartAgent(opts) {
|
|
|
5328
5652
|
toolResponses: resolved.toolResponses,
|
|
5329
5653
|
useTodoList: planningEnabled
|
|
5330
5654
|
};
|
|
5331
|
-
const
|
|
5332
|
-
const
|
|
5333
|
-
const
|
|
5334
|
-
const
|
|
5335
|
-
const
|
|
5336
|
-
const
|
|
5655
|
+
const userTools = opts.tools ?? [];
|
|
5656
|
+
const factoryStateRef = { toolHistory: void 0, toolHistoryArchived: void 0, todoList: void 0, planVersion: 0, adherenceScore: 0 };
|
|
5657
|
+
const factoryContextTools = createContextTools(factoryStateRef, { planningEnabled, includeGetToolResponse: false });
|
|
5658
|
+
const factoryToolsWithoutRecovery = [...userTools, ...factoryContextTools];
|
|
5659
|
+
const soManagerFactory = opts.outputSchema ? new StructuredOutputManager(opts.outputSchema, resolveStrategy(opts.model)) : void 0;
|
|
5660
|
+
const modelCapabilities = opts.outputSchema ? getModelCapabilities(opts.model) : void 0;
|
|
5661
|
+
const responseFinalizeTool = soManagerFactory && modelCapabilities?.structuredOutput !== "native" ? soManagerFactory.getResponseTool() : void 0;
|
|
5662
|
+
const buildInvokeToolSet = () => {
|
|
5663
|
+
const ref = { toolHistory: void 0, toolHistoryArchived: void 0, todoList: void 0, planVersion: 0, adherenceScore: 0 };
|
|
5664
|
+
const ctxTools = createContextTools(ref, { planningEnabled, includeGetToolResponse: false });
|
|
5665
|
+
const recoveryTool = createGetToolResponseTool(ref);
|
|
5666
|
+
const base2 = [...userTools, ...ctxTools];
|
|
5667
|
+
if (responseFinalizeTool) base2.push(responseFinalizeTool);
|
|
5668
|
+
const without = base2;
|
|
5669
|
+
const withRec = [...without, recoveryTool];
|
|
5670
|
+
return { stateRef: ref, toolsWithoutRecovery: without, toolsWithRecovery: withRec };
|
|
5671
|
+
};
|
|
5672
|
+
const base = createAgent({ ...runtimeOpts, tools: factoryToolsWithoutRecovery });
|
|
5337
5673
|
base.__runtime.runtimeProfile = resolved.runtimeProfile;
|
|
5338
5674
|
base.__runtime.smart = resolved;
|
|
5339
5675
|
const summarizationEnabled = resolved.summarization.enable !== false;
|
|
@@ -5369,17 +5705,17 @@ function createSmartAgent(opts) {
|
|
|
5369
5705
|
const memoryFacts = await writeSummaryFactsToMemory(memoryStore, resolved, latestSummary, Math.max(1, (state.messages || []).filter((message) => message.role === "user").length));
|
|
5370
5706
|
return { ...state, memoryFacts };
|
|
5371
5707
|
}
|
|
5372
|
-
function
|
|
5373
|
-
if (!Array.isArray(
|
|
5708
|
+
function syncPlanStateWith(ref, state) {
|
|
5709
|
+
if (!Array.isArray(ref.todoList)) return state;
|
|
5374
5710
|
return {
|
|
5375
5711
|
...state,
|
|
5376
5712
|
plan: {
|
|
5377
|
-
version:
|
|
5378
|
-
steps:
|
|
5713
|
+
version: ref.planVersion || state.planVersion || 1,
|
|
5714
|
+
steps: ref.todoList,
|
|
5379
5715
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5380
|
-
adherenceScore:
|
|
5716
|
+
adherenceScore: ref.adherenceScore || 0
|
|
5381
5717
|
},
|
|
5382
|
-
planVersion:
|
|
5718
|
+
planVersion: ref.planVersion || state.planVersion || 1
|
|
5383
5719
|
};
|
|
5384
5720
|
}
|
|
5385
5721
|
function systemMessage2() {
|
|
@@ -5391,9 +5727,9 @@ function createSmartAgent(opts) {
|
|
|
5391
5727
|
);
|
|
5392
5728
|
return { role: "system", content: sys };
|
|
5393
5729
|
}
|
|
5394
|
-
function syncRuntimeTools(currentState, currentMessages) {
|
|
5730
|
+
function syncRuntimeTools(currentState, currentMessages, toolSet) {
|
|
5395
5731
|
const needsRecoveryTool = hasToolResponseRecoveryReference(currentMessages);
|
|
5396
|
-
const nextTools = needsRecoveryTool ? toolsWithRecovery : toolsWithoutRecovery;
|
|
5732
|
+
const nextTools = needsRecoveryTool ? toolSet.toolsWithRecovery : toolSet.toolsWithoutRecovery;
|
|
5397
5733
|
const currentRuntime = currentState.agent || base.__runtime;
|
|
5398
5734
|
if (currentRuntime.tools === nextTools) {
|
|
5399
5735
|
return currentState;
|
|
@@ -5412,7 +5748,7 @@ function createSmartAgent(opts) {
|
|
|
5412
5748
|
const toolCalls = Array.isArray(lastAssistant.tool_calls) ? lastAssistant.tool_calls : [];
|
|
5413
5749
|
return toolCalls.length === 0;
|
|
5414
5750
|
}
|
|
5415
|
-
async function trySummarize(currentState, currentRawMessages) {
|
|
5751
|
+
async function trySummarize(currentState, currentRawMessages, ref) {
|
|
5416
5752
|
if (!summarizer) return { state: currentState, rawMessages: currentRawMessages, compressed: false };
|
|
5417
5753
|
const delta = await summarizer(currentState);
|
|
5418
5754
|
if (!delta || Object.keys(delta).length === 0) {
|
|
@@ -5421,28 +5757,31 @@ function createSmartAgent(opts) {
|
|
|
5421
5757
|
}
|
|
5422
5758
|
const ctx = { ...currentState.ctx || {} };
|
|
5423
5759
|
delete ctx.__summarizationExhausted;
|
|
5424
|
-
const updated = await persistLatestSummary(
|
|
5760
|
+
const updated = await persistLatestSummary(syncPlanStateWith(ref, { ...currentState, ...delta, ctx }));
|
|
5425
5761
|
return { state: updated, rawMessages: [...updated.messages || currentRawMessages], compressed: true };
|
|
5426
5762
|
}
|
|
5427
5763
|
const instance = {
|
|
5428
5764
|
invoke: async (input, config) => {
|
|
5765
|
+
const toolSet = buildInvokeToolSet();
|
|
5766
|
+
const stateRef = toolSet.stateRef;
|
|
5429
5767
|
stateRef.toolHistory = input.toolHistory;
|
|
5430
5768
|
stateRef.toolHistoryArchived = input.toolHistoryArchived;
|
|
5431
5769
|
stateRef.todoList = input.plan?.steps;
|
|
5432
5770
|
stateRef.planVersion = input.planVersion || input.plan?.version || 0;
|
|
5433
5771
|
stateRef.adherenceScore = input.plan?.adherenceScore || 0;
|
|
5772
|
+
const syncPlanFromRef = (state2) => syncPlanStateWith(stateRef, state2);
|
|
5434
5773
|
const alreadyHasSystem = Array.isArray(input.messages) && input.messages[0]?.role === "system";
|
|
5435
5774
|
const seedMessages = alreadyHasSystem ? [...input.messages || []] : [systemMessage2(), ...input.messages || []];
|
|
5436
|
-
let state = syncRuntimeTools(await syncMemory({ ...input, messages: seedMessages }), seedMessages);
|
|
5775
|
+
let state = syncRuntimeTools(await syncMemory({ ...input, messages: seedMessages }), seedMessages, toolSet);
|
|
5437
5776
|
let lastResult = null;
|
|
5438
5777
|
let rawMessages = [...seedMessages];
|
|
5439
5778
|
const effectiveMaxToolCalls = config?.limits?.maxToolCalls ?? resolved.limits.maxToolCalls ?? 10;
|
|
5440
5779
|
const iterationLimit = Math.max(effectiveMaxToolCalls * 3 + 5, 30);
|
|
5441
5780
|
for (let i = 0; i < iterationLimit; i++) {
|
|
5442
|
-
state = syncRuntimeTools({ ...state, messages: rawMessages }, rawMessages);
|
|
5781
|
+
state = syncRuntimeTools({ ...state, messages: rawMessages }, rawMessages, toolSet);
|
|
5443
5782
|
const next = summarizationEnabled ? decideBefore(state) : "agent";
|
|
5444
5783
|
if (next === "contextSummarize" && summarizer) {
|
|
5445
|
-
const result = await trySummarize(state, rawMessages);
|
|
5784
|
+
const result = await trySummarize(state, rawMessages, stateRef);
|
|
5446
5785
|
state = result.state;
|
|
5447
5786
|
rawMessages = result.rawMessages;
|
|
5448
5787
|
if (result.compressed) continue;
|
|
@@ -5466,14 +5805,14 @@ function createSmartAgent(opts) {
|
|
|
5466
5805
|
if (currentPlan && !state.plan) {
|
|
5467
5806
|
state = { ...state, plan: currentPlan };
|
|
5468
5807
|
}
|
|
5469
|
-
state = syncRuntimeTools(
|
|
5808
|
+
state = syncRuntimeTools(syncPlanFromRef(await syncMemory(state)), rawMessages, toolSet);
|
|
5470
5809
|
stateRef.toolHistory = state.toolHistory;
|
|
5471
5810
|
stateRef.toolHistoryArchived = state.toolHistoryArchived;
|
|
5472
5811
|
if (state.ctx?.__needsSummarization && summarizer) {
|
|
5473
5812
|
const ctx = { ...state.ctx || {} };
|
|
5474
5813
|
delete ctx.__needsSummarization;
|
|
5475
5814
|
state = { ...state, ctx };
|
|
5476
|
-
const result = await trySummarize(state, rawMessages);
|
|
5815
|
+
const result = await trySummarize(state, rawMessages, stateRef);
|
|
5477
5816
|
state = result.state;
|
|
5478
5817
|
rawMessages = result.rawMessages;
|
|
5479
5818
|
continue;
|
|
@@ -5484,7 +5823,7 @@ function createSmartAgent(opts) {
|
|
|
5484
5823
|
if (summarizationEnabled) {
|
|
5485
5824
|
const after = decideAfter(state);
|
|
5486
5825
|
if (after === "contextSummarize" && summarizer) {
|
|
5487
|
-
const result = await trySummarize(state, rawMessages);
|
|
5826
|
+
const result = await trySummarize(state, rawMessages, stateRef);
|
|
5488
5827
|
state = result.state;
|
|
5489
5828
|
rawMessages = result.rawMessages;
|
|
5490
5829
|
if (result.compressed) continue;
|
|
@@ -5923,7 +6262,50 @@ var ProviderError = class extends Error {
|
|
|
5923
6262
|
};
|
|
5924
6263
|
|
|
5925
6264
|
// src/providers/base.ts
|
|
6265
|
+
var DEFAULT_RETRY = {
|
|
6266
|
+
maxRetries: 3,
|
|
6267
|
+
baseDelayMs: 500,
|
|
6268
|
+
maxDelayMs: 8e3
|
|
6269
|
+
};
|
|
5926
6270
|
var BaseProvider = class {
|
|
6271
|
+
constructor() {
|
|
6272
|
+
this.retryPolicy = DEFAULT_RETRY;
|
|
6273
|
+
}
|
|
6274
|
+
/**
|
|
6275
|
+
* Helper concrete providers can wrap their fetch with. Retries 429/5xx
|
|
6276
|
+
* with exponential backoff and respects Retry-After if the response
|
|
6277
|
+
* carries one.
|
|
6278
|
+
*/
|
|
6279
|
+
async doFetchWithRetry(execute) {
|
|
6280
|
+
const policy = this.retryPolicy;
|
|
6281
|
+
const maxRetries = Math.max(0, policy.maxRetries ?? DEFAULT_RETRY.maxRetries);
|
|
6282
|
+
const baseDelay = Math.max(0, policy.baseDelayMs ?? DEFAULT_RETRY.baseDelayMs);
|
|
6283
|
+
const maxDelay = Math.max(baseDelay, policy.maxDelayMs ?? DEFAULT_RETRY.maxDelayMs);
|
|
6284
|
+
let lastResp;
|
|
6285
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
6286
|
+
const res = await execute();
|
|
6287
|
+
const isRetryable = res.status === 429 || res.status >= 500 && res.status < 600;
|
|
6288
|
+
if (!isRetryable) return res;
|
|
6289
|
+
const predicate = policy.shouldRetry;
|
|
6290
|
+
if (predicate && !predicate({ status: res.status }, attempt)) return res;
|
|
6291
|
+
if (attempt === maxRetries) {
|
|
6292
|
+
lastResp = res;
|
|
6293
|
+
break;
|
|
6294
|
+
}
|
|
6295
|
+
const retryAfter = res.headers.get("retry-after");
|
|
6296
|
+
let delay = Math.min(maxDelay, baseDelay * Math.pow(2, attempt));
|
|
6297
|
+
if (retryAfter) {
|
|
6298
|
+
const asNumber = Number(retryAfter);
|
|
6299
|
+
if (!Number.isNaN(asNumber)) delay = Math.min(maxDelay, Math.max(delay, asNumber * 1e3));
|
|
6300
|
+
}
|
|
6301
|
+
try {
|
|
6302
|
+
await res.text();
|
|
6303
|
+
} catch {
|
|
6304
|
+
}
|
|
6305
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
6306
|
+
}
|
|
6307
|
+
return lastResp;
|
|
6308
|
+
}
|
|
5927
6309
|
};
|
|
5928
6310
|
|
|
5929
6311
|
// src/providers/utils/sse.ts
|
|
@@ -6050,6 +6432,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6050
6432
|
...config.defaultHeaders,
|
|
6051
6433
|
...config.organization ? { "OpenAI-Organization": config.organization } : {}
|
|
6052
6434
|
};
|
|
6435
|
+
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
6053
6436
|
}
|
|
6054
6437
|
async complete(request) {
|
|
6055
6438
|
const body = this.buildRequestBody(request, false);
|
|
@@ -6129,7 +6512,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6129
6512
|
if (request.tools?.length) {
|
|
6130
6513
|
body.tools = request.tools.map((t) => this.toOpenAITool(t));
|
|
6131
6514
|
}
|
|
6132
|
-
if (request.toolChoice != null) {
|
|
6515
|
+
if (request.toolChoice != null && request.tools?.length) {
|
|
6133
6516
|
if (typeof request.toolChoice === "string") {
|
|
6134
6517
|
body.tool_choice = request.toolChoice;
|
|
6135
6518
|
} else {
|
|
@@ -6197,15 +6580,13 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6197
6580
|
}
|
|
6198
6581
|
async doFetch(body) {
|
|
6199
6582
|
const url = `${this.baseURL}/chat/completions`;
|
|
6200
|
-
const
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
body: JSON.stringify(body)
|
|
6208
|
-
});
|
|
6583
|
+
const headers = {
|
|
6584
|
+
"Content-Type": "application/json",
|
|
6585
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
6586
|
+
...this.defaultHeaders
|
|
6587
|
+
};
|
|
6588
|
+
const payload = JSON.stringify(body);
|
|
6589
|
+
const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload }));
|
|
6209
6590
|
if (!res.ok) {
|
|
6210
6591
|
const text = await res.text().catch(() => "");
|
|
6211
6592
|
throw new ProviderError(
|
|
@@ -6275,6 +6656,8 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6275
6656
|
this.defaultModel = config.defaultModel ?? "claude-sonnet-4-20250514";
|
|
6276
6657
|
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
6277
6658
|
this.anthropicVersion = config.anthropicVersion ?? "2023-06-01";
|
|
6659
|
+
this.promptCachingEnabled = config.prompt_caching?.enabled === true;
|
|
6660
|
+
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
6278
6661
|
}
|
|
6279
6662
|
async complete(request) {
|
|
6280
6663
|
const body = this.buildRequestBody(request, false);
|
|
@@ -6393,12 +6776,22 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6393
6776
|
max_tokens: request.maxTokens ?? 4096,
|
|
6394
6777
|
stream
|
|
6395
6778
|
};
|
|
6396
|
-
if (system)
|
|
6779
|
+
if (system) {
|
|
6780
|
+
if (this.promptCachingEnabled) {
|
|
6781
|
+
body.system = [{ type: "text", text: system, cache_control: { type: "ephemeral" } }];
|
|
6782
|
+
} else {
|
|
6783
|
+
body.system = system;
|
|
6784
|
+
}
|
|
6785
|
+
}
|
|
6397
6786
|
if (request.temperature != null) body.temperature = request.temperature;
|
|
6398
6787
|
if (request.topP != null) body.top_p = request.topP;
|
|
6399
6788
|
if (request.stop) body.stop_sequences = request.stop;
|
|
6400
6789
|
if (request.tools?.length) {
|
|
6401
|
-
|
|
6790
|
+
const tools = request.tools.map((t) => this.toAnthropicTool(t));
|
|
6791
|
+
if (this.promptCachingEnabled && tools.length > 0) {
|
|
6792
|
+
tools[tools.length - 1] = { ...tools[tools.length - 1], cache_control: { type: "ephemeral" } };
|
|
6793
|
+
}
|
|
6794
|
+
body.tools = tools;
|
|
6402
6795
|
}
|
|
6403
6796
|
if (request.toolChoice != null) {
|
|
6404
6797
|
if (request.toolChoice === "auto") {
|
|
@@ -6497,16 +6890,14 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6497
6890
|
}
|
|
6498
6891
|
async doFetch(body) {
|
|
6499
6892
|
const url = `${this.baseURL}/v1/messages`;
|
|
6500
|
-
const
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
body: JSON.stringify(body)
|
|
6509
|
-
});
|
|
6893
|
+
const headers = {
|
|
6894
|
+
"Content-Type": "application/json",
|
|
6895
|
+
"x-api-key": this.apiKey,
|
|
6896
|
+
"anthropic-version": this.anthropicVersion,
|
|
6897
|
+
...this.defaultHeaders
|
|
6898
|
+
};
|
|
6899
|
+
const payload = JSON.stringify(body);
|
|
6900
|
+
const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload }));
|
|
6510
6901
|
if (!res.ok) {
|
|
6511
6902
|
const text = await res.text().catch(() => "");
|
|
6512
6903
|
throw new ProviderError(
|
|
@@ -6718,6 +7109,8 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6718
7109
|
this.region = config.region;
|
|
6719
7110
|
this.defaultModel = config.defaultModel ?? "anthropic.claude-sonnet-4-20250514-v1:0";
|
|
6720
7111
|
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
7112
|
+
this.promptCachingEnabled = config.prompt_caching?.enabled === true;
|
|
7113
|
+
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
6721
7114
|
this.credentials = {
|
|
6722
7115
|
accessKeyId: config.accessKeyId ?? process.env.AWS_ACCESS_KEY_ID ?? "",
|
|
6723
7116
|
secretAccessKey: config.secretAccessKey ?? process.env.AWS_SECRET_ACCESS_KEY ?? "",
|
|
@@ -6756,7 +7149,9 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6756
7149
|
messages: messages.map((m) => this.toBedrockMessage(m))
|
|
6757
7150
|
};
|
|
6758
7151
|
if (system.length > 0) {
|
|
6759
|
-
|
|
7152
|
+
const systemBlocks = system.map((s) => ({ text: s }));
|
|
7153
|
+
if (this.promptCachingEnabled) systemBlocks.push({ cachePoint: { type: "default" } });
|
|
7154
|
+
body.system = systemBlocks;
|
|
6760
7155
|
}
|
|
6761
7156
|
const inferenceConfig = {};
|
|
6762
7157
|
if (request.maxTokens != null) inferenceConfig.maxTokens = request.maxTokens;
|
|
@@ -6765,8 +7160,12 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6765
7160
|
if (request.stop) inferenceConfig.stopSequences = request.stop;
|
|
6766
7161
|
if (Object.keys(inferenceConfig).length > 0) body.inferenceConfig = inferenceConfig;
|
|
6767
7162
|
if (request.tools?.length) {
|
|
7163
|
+
const tools = request.tools.map((t) => this.toBedrockTool(t));
|
|
7164
|
+
if (this.promptCachingEnabled && tools.length > 0) {
|
|
7165
|
+
tools.push({ cachePoint: { type: "default" } });
|
|
7166
|
+
}
|
|
6768
7167
|
body.toolConfig = {
|
|
6769
|
-
tools
|
|
7168
|
+
tools
|
|
6770
7169
|
};
|
|
6771
7170
|
if (request.toolChoice != null) {
|
|
6772
7171
|
if (request.toolChoice === "auto") {
|
|
@@ -6863,23 +7262,21 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6863
7262
|
const host = `bedrock-runtime.${this.region}.amazonaws.com`;
|
|
6864
7263
|
const url = `https://${host}/model/${encodeURIComponent(modelId)}/converse`;
|
|
6865
7264
|
const bodyStr = JSON.stringify(body);
|
|
6866
|
-
const
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
method: "POST",
|
|
6881
|
-
headers,
|
|
6882
|
-
body: bodyStr
|
|
7265
|
+
const res = await this.doFetchWithRetry(() => {
|
|
7266
|
+
const headers = signRequest({
|
|
7267
|
+
method: "POST",
|
|
7268
|
+
url,
|
|
7269
|
+
headers: {
|
|
7270
|
+
"Content-Type": "application/json",
|
|
7271
|
+
Accept: "application/json",
|
|
7272
|
+
...this.defaultHeaders
|
|
7273
|
+
},
|
|
7274
|
+
body: bodyStr,
|
|
7275
|
+
region: this.region,
|
|
7276
|
+
service: "bedrock",
|
|
7277
|
+
credentials: this.credentials
|
|
7278
|
+
});
|
|
7279
|
+
return fetch(url, { method: "POST", headers, body: bodyStr });
|
|
6883
7280
|
});
|
|
6884
7281
|
if (!res.ok) {
|
|
6885
7282
|
const text = await res.text().catch(() => "");
|
|
@@ -7410,7 +7807,7 @@ function fromNativeProvider(provider, options) {
|
|
|
7410
7807
|
const reasoningCfg = reasoningOverride ?? opts?.reasoning;
|
|
7411
7808
|
if (reasoningCfg) req.reasoning = reasoningCfg;
|
|
7412
7809
|
const tc = invokeOptions?.tool_choice ?? invokeOptions?.toolChoice;
|
|
7413
|
-
if (tc) {
|
|
7810
|
+
if (tc && tools?.length) {
|
|
7414
7811
|
req.toolChoice = tc;
|
|
7415
7812
|
}
|
|
7416
7813
|
const rf = invokeOptions?.response_format;
|
|
@@ -7793,6 +8190,7 @@ exports.createToolLimitFinalizeNode = createToolLimitFinalizeNode;
|
|
|
7793
8190
|
exports.createToolsNode = createToolsNode;
|
|
7794
8191
|
exports.customCallbackRule = customCallbackRule;
|
|
7795
8192
|
exports.customSink = customSink;
|
|
8193
|
+
exports.defaultTokenCounter = defaultTokenCounter;
|
|
7796
8194
|
exports.emptyUsage = emptyUsage;
|
|
7797
8195
|
exports.evaluateGuardrails = evaluateGuardrails;
|
|
7798
8196
|
exports.fileSink = fileSink;
|
|
@@ -7805,6 +8203,7 @@ exports.generateTraceId = generateTraceId;
|
|
|
7805
8203
|
exports.getModelCapabilities = getModelCapabilities;
|
|
7806
8204
|
exports.getNestedValue = getNestedValue;
|
|
7807
8205
|
exports.getResolvedSmartConfig = getResolvedSmartConfig;
|
|
8206
|
+
exports.getTokenCounter = getTokenCounter;
|
|
7808
8207
|
exports.hasToolResponseRecoveryReference = hasToolResponseRecoveryReference;
|
|
7809
8208
|
exports.httpSink = httpSink;
|
|
7810
8209
|
exports.isSmartModel = isSmartModel;
|
|
@@ -7818,6 +8217,7 @@ exports.resolveStrategy = resolveStrategy;
|
|
|
7818
8217
|
exports.resolveToolApprovalState = resolveToolApprovalState;
|
|
7819
8218
|
exports.restoreSnapshot = restoreSnapshot;
|
|
7820
8219
|
exports.runSmartAgentEvalHarness = runSmartAgentEvalHarness;
|
|
8220
|
+
exports.setTokenCounter = setTokenCounter;
|
|
7821
8221
|
exports.startStreamingSession = startStreamingSession;
|
|
7822
8222
|
exports.traceSessionToOtlp = traceSessionToOtlp;
|
|
7823
8223
|
exports.withTools = withTools;
|