@cognipeer/agent-sdk 0.6.4 → 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 +566 -168
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +149 -4
- package/dist/index.d.ts +149 -4
- package/dist/index.mjs +564 -169
- 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) {
|
|
@@ -2299,66 +2403,8 @@ function getResolvedSmartConfig(opts, runtime) {
|
|
|
2299
2403
|
return runtime?.smart || normalizeSmartAgentOptions(opts);
|
|
2300
2404
|
}
|
|
2301
2405
|
|
|
2302
|
-
// src/
|
|
2303
|
-
|
|
2304
|
-
if (!text) return 0;
|
|
2305
|
-
const nonAsciiCount = (text.match(/[^\x00-\x7F]/g) || []).length;
|
|
2306
|
-
const asciiCount = text.length - nonAsciiCount;
|
|
2307
|
-
return Math.ceil(asciiCount / 4 + nonAsciiCount / 1.5);
|
|
2308
|
-
}
|
|
2309
|
-
function extractMessageText(m) {
|
|
2310
|
-
if (!m) return "";
|
|
2311
|
-
const parts = [];
|
|
2312
|
-
parts.push(m.role || "");
|
|
2313
|
-
if (m.name) parts.push(m.name);
|
|
2314
|
-
if (typeof m.content === "string") {
|
|
2315
|
-
parts.push(m.content);
|
|
2316
|
-
} else if (Array.isArray(m.content)) {
|
|
2317
|
-
for (const c of m.content) {
|
|
2318
|
-
if (typeof c === "string") parts.push(c);
|
|
2319
|
-
else if (c?.text) parts.push(c.text);
|
|
2320
|
-
else if (c?.content) parts.push(c.content);
|
|
2321
|
-
else if (c?.type === "tool_use" && c?.input) {
|
|
2322
|
-
parts.push(c.name || "");
|
|
2323
|
-
parts.push(typeof c.input === "string" ? c.input : JSON.stringify(c.input));
|
|
2324
|
-
} else if (c != null && typeof c === "object") {
|
|
2325
|
-
parts.push(JSON.stringify(c));
|
|
2326
|
-
}
|
|
2327
|
-
}
|
|
2328
|
-
} else if (m.content != null && typeof m.content === "object") {
|
|
2329
|
-
parts.push(JSON.stringify(m.content));
|
|
2330
|
-
}
|
|
2331
|
-
if (Array.isArray(m.tool_calls)) {
|
|
2332
|
-
for (const tc of m.tool_calls) {
|
|
2333
|
-
if (tc?.function?.name) parts.push(tc.function.name);
|
|
2334
|
-
if (tc?.function?.arguments) {
|
|
2335
|
-
parts.push(
|
|
2336
|
-
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
2337
|
-
);
|
|
2338
|
-
}
|
|
2339
|
-
if (tc?.name && !tc?.function?.name) parts.push(tc.name);
|
|
2340
|
-
if (tc?.args && !tc?.function?.arguments) {
|
|
2341
|
-
parts.push(typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args));
|
|
2342
|
-
}
|
|
2343
|
-
}
|
|
2344
|
-
}
|
|
2345
|
-
if (Array.isArray(m.additional_kwargs?.tool_calls)) {
|
|
2346
|
-
for (const tc of m.additional_kwargs.tool_calls) {
|
|
2347
|
-
if (tc?.function?.name) parts.push(tc.function.name);
|
|
2348
|
-
if (tc?.function?.arguments) {
|
|
2349
|
-
parts.push(
|
|
2350
|
-
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
2351
|
-
);
|
|
2352
|
-
}
|
|
2353
|
-
}
|
|
2354
|
-
}
|
|
2355
|
-
return parts.join("\n");
|
|
2356
|
-
}
|
|
2357
|
-
function countMessagesTokens(messages) {
|
|
2358
|
-
if (!Array.isArray(messages) || messages.length === 0) return 0;
|
|
2359
|
-
const allText = messages.map(extractMessageText).join("\n");
|
|
2360
|
-
return countApproxTokens(allText) + messages.length * 4;
|
|
2361
|
-
}
|
|
2406
|
+
// src/smart/toolResponses.ts
|
|
2407
|
+
init_utilTokens();
|
|
2362
2408
|
|
|
2363
2409
|
// src/utils/content.ts
|
|
2364
2410
|
function contentToString(content) {
|
|
@@ -2558,6 +2604,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2558
2604
|
anyTool._stateRef.messages = state.messages;
|
|
2559
2605
|
anyTool._stateRef.ctx = state.ctx || (state.ctx = {});
|
|
2560
2606
|
anyTool._stateRef.__onEvent = onEvent;
|
|
2607
|
+
anyTool._stateRef.parentRuntime = runtime;
|
|
2561
2608
|
}
|
|
2562
2609
|
}
|
|
2563
2610
|
const last = state.messages[state.messages.length - 1];
|
|
@@ -2568,6 +2615,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2568
2615
|
const remaining = Math.max(0, limits.maxToolCalls - toolCount);
|
|
2569
2616
|
const planned = toolCalls.slice(0, remaining);
|
|
2570
2617
|
const skipped = toolCalls.slice(remaining);
|
|
2618
|
+
const orderedSlots = planned.map(() => []);
|
|
2571
2619
|
const isCancelled = () => {
|
|
2572
2620
|
if (abortSignal?.aborted) return { cancelled: true, reason: "aborted" };
|
|
2573
2621
|
if (cancellationToken && cancellationToken.isCancellationRequested) return { cancelled: true, reason: "cancelled" };
|
|
@@ -2584,7 +2632,9 @@ function createToolsNode(initialTools, opts) {
|
|
|
2584
2632
|
}
|
|
2585
2633
|
state.ctx = ctx;
|
|
2586
2634
|
};
|
|
2587
|
-
const runOne = async (tc) => {
|
|
2635
|
+
const runOne = async (tc, slot = appended) => {
|
|
2636
|
+
var _a;
|
|
2637
|
+
const push = (msg) => slot.push(msg);
|
|
2588
2638
|
const cancelState = isCancelled();
|
|
2589
2639
|
if (cancelState.cancelled) {
|
|
2590
2640
|
const ctx = state.ctx = state.ctx || {};
|
|
@@ -2595,7 +2645,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2595
2645
|
}
|
|
2596
2646
|
const tool = toolByName.get(tc.name);
|
|
2597
2647
|
if (!tool) {
|
|
2598
|
-
|
|
2648
|
+
push({ role: "tool", content: `Tool not found: ${tc.name}`, tool_call_id: tc.id || `${tc.name}_unknown`, name: tc.name });
|
|
2599
2649
|
onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args: tc.args, error: { message: "Tool not found" } });
|
|
2600
2650
|
toolCount += 1;
|
|
2601
2651
|
return { status: "error" };
|
|
@@ -2611,7 +2661,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2611
2661
|
const validatedArgs = validateToolArgs(tool, args);
|
|
2612
2662
|
if (!validatedArgs.ok && resolved.toolResponses.schemaValidation === "strict") {
|
|
2613
2663
|
const errorMessage = `Tool argument validation failed for ${tc.name}: ${validatedArgs.message}`;
|
|
2614
|
-
|
|
2664
|
+
push({ role: "tool", content: errorMessage, tool_call_id: toolCallId, name: tc.name });
|
|
2615
2665
|
markToolFailure(errorMessage, tc.name, toolCallId);
|
|
2616
2666
|
onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args, error: { message: errorMessage } });
|
|
2617
2667
|
toolCount += 1;
|
|
@@ -2633,7 +2683,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2633
2683
|
const currentExecutions = countSuccessfulToolExecutions(toolHistory, toolName);
|
|
2634
2684
|
if (currentExecutions >= maxExecutionsPerRun) {
|
|
2635
2685
|
const limitMessage = `Skipped tool due to per-tool execution limit: ${toolName} (${maxExecutionsPerRun}/run)`;
|
|
2636
|
-
|
|
2686
|
+
push({ role: "tool", content: limitMessage, tool_call_id: toolCallId, name: tc.name });
|
|
2637
2687
|
onEvent?.({ type: "tool_call", phase: "skipped", name: toolName, id: tc.id, args });
|
|
2638
2688
|
recordTraceEvent(traceSession, {
|
|
2639
2689
|
type: "tool_call",
|
|
@@ -2693,7 +2743,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2693
2743
|
}
|
|
2694
2744
|
if (approvalEntry.status === "rejected") {
|
|
2695
2745
|
const rejectionMessage = approvalEntry.comment || "Tool call rejected by reviewer.";
|
|
2696
|
-
|
|
2746
|
+
push({ role: "tool", content: `Tool call rejected: ${rejectionMessage}`, tool_call_id: toolCallId, name: tc.name });
|
|
2697
2747
|
approvalEntry.metadata = { ...approvalEntry.metadata || {}, resolution: "rejected" };
|
|
2698
2748
|
approvalEntry.status = "executed";
|
|
2699
2749
|
approvalEntry.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2711,23 +2761,102 @@ function createToolsNode(initialTools, opts) {
|
|
|
2711
2761
|
const start = Date.now();
|
|
2712
2762
|
const sanitizedArgs = sanitizeTracePayload(args);
|
|
2713
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
|
+
}
|
|
2714
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
|
+
}
|
|
2715
2821
|
onEvent?.({ type: "tool_call", phase: "start", name: toolName, id: tc.id, args });
|
|
2716
2822
|
onProgress?.({ stage: "tools", message: `Running tool ${tc.name}` });
|
|
2717
2823
|
const anyTool = tool;
|
|
2718
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
|
+
};
|
|
2719
2833
|
let output;
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
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
|
+
}
|
|
2726
2855
|
const durationMs = Date.now() - start;
|
|
2727
2856
|
const executionId = nanoid.nanoid();
|
|
2728
2857
|
if (output && typeof output === "object" && output.__handoff && output.__handoff.runtime) {
|
|
2729
2858
|
toolHistory.push({ executionId, toolName, args, output: "handoff:ok", rawOutput: output, timestamp: (/* @__PURE__ */ new Date()).toISOString(), tool_call_id: tc.id, status: "handoff" });
|
|
2730
|
-
|
|
2859
|
+
push({ role: "tool", content: "ok", tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2731
2860
|
state.agent = output.__handoff.runtime;
|
|
2732
2861
|
onEvent?.({ type: "handoff", from: runtime.name, to: state.agent?.name, toolName });
|
|
2733
2862
|
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: "handoff", durationMs });
|
|
@@ -2779,7 +2908,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2779
2908
|
archiveId: void 0,
|
|
2780
2909
|
status: "success"
|
|
2781
2910
|
});
|
|
2782
|
-
|
|
2911
|
+
push({ role: "tool", content: responsePolicy.content, tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2783
2912
|
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: output, durationMs });
|
|
2784
2913
|
onProgress?.({ stage: "tools", message: `Tool ${tc.name} completed`, detail: { durationMs } });
|
|
2785
2914
|
if (needsApproval && approvalEntry) {
|
|
@@ -2835,7 +2964,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2835
2964
|
const executionId = nanoid.nanoid();
|
|
2836
2965
|
const message = error?.message || String(error);
|
|
2837
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" });
|
|
2838
|
-
|
|
2967
|
+
push({ role: "tool", content: `Error executing tool: ${message}`, tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2839
2968
|
markToolFailure(message, toolName, toolCallId);
|
|
2840
2969
|
onEvent?.({ type: "tool_call", phase: "error", name: toolName, id: tc.id, args, error: { message } });
|
|
2841
2970
|
onProgress?.({ stage: "tools", message: `Tool ${tc.name} failed`, detail: { error: message } });
|
|
@@ -2872,22 +3001,67 @@ function createToolsNode(initialTools, opts) {
|
|
|
2872
3001
|
return { status: "error", approval: approvalEntry };
|
|
2873
3002
|
}
|
|
2874
3003
|
};
|
|
2875
|
-
|
|
2876
|
-
|
|
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 = () => {
|
|
2877
3013
|
const cancelState = isCancelled();
|
|
2878
3014
|
if (cancelState.cancelled) {
|
|
2879
3015
|
const ctx = state.ctx = state.ctx || {};
|
|
2880
3016
|
ctx.__cancelled = { stage: "tools", reason: cancelState.reason, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
2881
3017
|
onEvent?.({ type: "cancelled", stage: "tools", reason: cancelState.reason });
|
|
2882
3018
|
onProgress?.({ stage: "tools", message: "Cancelled", detail: { reason: cancelState.reason } });
|
|
2883
|
-
|
|
3019
|
+
shouldStop = true;
|
|
3020
|
+
return true;
|
|
2884
3021
|
}
|
|
2885
|
-
|
|
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]);
|
|
2886
3028
|
if (result.status === "awaiting_approval") {
|
|
2887
3029
|
awaitingApproval = true;
|
|
2888
3030
|
break;
|
|
2889
3031
|
}
|
|
2890
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
|
+
}
|
|
2891
3065
|
for (const tc of skipped) {
|
|
2892
3066
|
onEvent?.({ type: "tool_call", phase: "skipped", name: tc.name, id: tc.id, args: tc.args });
|
|
2893
3067
|
const sanitizedArgs = sanitizeTracePayload(tc.args);
|
|
@@ -2923,11 +3097,23 @@ function createToolsNode(initialTools, opts) {
|
|
|
2923
3097
|
}
|
|
2924
3098
|
state.ctx = Object.keys(ctx).length > 0 ? ctx : void 0;
|
|
2925
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
|
+
}
|
|
2926
3106
|
return {
|
|
2927
3107
|
messages: [...state.messages, ...appended],
|
|
2928
3108
|
toolCallCount: toolCount,
|
|
2929
3109
|
toolHistory,
|
|
2930
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,
|
|
2931
3117
|
agent: state.agent,
|
|
2932
3118
|
pendingApprovals
|
|
2933
3119
|
};
|
|
@@ -3164,7 +3350,8 @@ function resolveReflection(input, preset) {
|
|
|
3164
3350
|
maxChars: preset.maxChars,
|
|
3165
3351
|
keepLast: 3,
|
|
3166
3352
|
summarize: false,
|
|
3167
|
-
emitEvents: true
|
|
3353
|
+
emitEvents: true,
|
|
3354
|
+
everyNTurns: 1
|
|
3168
3355
|
};
|
|
3169
3356
|
}
|
|
3170
3357
|
const cfg = input ?? {};
|
|
@@ -3179,7 +3366,9 @@ function resolveReflection(input, preset) {
|
|
|
3179
3366
|
keepLast: cfg.keepLast ?? 3,
|
|
3180
3367
|
summarize: cfg.summarize ?? false,
|
|
3181
3368
|
promptTemplate: cfg.promptTemplate,
|
|
3182
|
-
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))
|
|
3183
3372
|
};
|
|
3184
3373
|
}
|
|
3185
3374
|
function ensureArray(value) {
|
|
@@ -3392,6 +3581,9 @@ function resolveToolApprovalState(state, resolution) {
|
|
|
3392
3581
|
};
|
|
3393
3582
|
}
|
|
3394
3583
|
|
|
3584
|
+
// src/agent.ts
|
|
3585
|
+
init_utilTokens();
|
|
3586
|
+
|
|
3395
3587
|
// src/utils/syntheticMessages.ts
|
|
3396
3588
|
function isSyntheticSummaryMessage(message) {
|
|
3397
3589
|
if (!message) return false;
|
|
@@ -3570,6 +3762,21 @@ function getActiveSummarizationThreshold(opts) {
|
|
|
3570
3762
|
}
|
|
3571
3763
|
return summarization.summaryTriggerTokens || summarization.maxTokens || opts.limits?.maxContextTokens || 5e4;
|
|
3572
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
|
+
}
|
|
3573
3780
|
function clearNeedsSummarization(state) {
|
|
3574
3781
|
if (!state.ctx?.__needsSummarization) {
|
|
3575
3782
|
return state;
|
|
@@ -3664,6 +3871,45 @@ function createAgent(opts) {
|
|
|
3664
3871
|
};
|
|
3665
3872
|
const maxToolCalls = mergedLimits?.maxToolCalls === void 0 ? 50 : mergedLimits?.maxToolCalls;
|
|
3666
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
|
+
};
|
|
3667
3913
|
let iterations = 0;
|
|
3668
3914
|
const onStateChange = config?.onStateChange;
|
|
3669
3915
|
const checkpointReason = config?.checkpointReason;
|
|
@@ -3712,6 +3958,13 @@ function createAgent(opts) {
|
|
|
3712
3958
|
};
|
|
3713
3959
|
while (iterations < iterationLimit) {
|
|
3714
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
|
+
}
|
|
3715
3968
|
const traceSession = state.ctx?.__traceSession;
|
|
3716
3969
|
if (traceSession) {
|
|
3717
3970
|
const iterEvent = recordTraceEvent(traceSession, {
|
|
@@ -3767,22 +4020,11 @@ function createAgent(opts) {
|
|
|
3767
4020
|
}
|
|
3768
4021
|
}
|
|
3769
4022
|
if (summarizationThreshold !== void 0) {
|
|
3770
|
-
const
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
const tokenCount = countMessagesTokens(tokCountMessages);
|
|
3776
|
-
if (tokenCount > summarizationThreshold) {
|
|
3777
|
-
const summarizationExhausted = !!state.ctx?.__summarizationExhausted;
|
|
3778
|
-
const hasFreshSummary = (state.messages || []).some(
|
|
3779
|
-
(m) => m.role === "tool" && typeof m.content === "string" && (m.content === "SUMMARIZED" || m.content.startsWith("SUMMARIZED_TOOL_RESPONSE"))
|
|
3780
|
-
);
|
|
3781
|
-
if (hasFreshSummary && tokenCount <= summarizationThreshold * 1.15) ; else if (summarizationExhausted) ; else {
|
|
3782
|
-
const ctx = { ...state.ctx || {}, __needsSummarization: true };
|
|
3783
|
-
state = { ...state, ctx };
|
|
3784
|
-
break;
|
|
3785
|
-
}
|
|
4023
|
+
const verdict = shouldSignalSummarization(state, summarizationThreshold);
|
|
4024
|
+
if (verdict === "trigger") {
|
|
4025
|
+
const ctx = { ...state.ctx || {}, __needsSummarization: true };
|
|
4026
|
+
state = { ...state, ctx };
|
|
4027
|
+
break;
|
|
3786
4028
|
}
|
|
3787
4029
|
}
|
|
3788
4030
|
onProgress?.({ stage: "agent", message: "Invoking model" });
|
|
@@ -3888,7 +4130,13 @@ function createAgent(opts) {
|
|
|
3888
4130
|
if (state.ctx?.__finalizedDueToStructuredOutput) break;
|
|
3889
4131
|
if (reflectNode && resolvedReasoning?.reflection.enabled) {
|
|
3890
4132
|
const cadence = resolvedReasoning.reflection.cadence;
|
|
3891
|
-
|
|
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)) {
|
|
3892
4140
|
try {
|
|
3893
4141
|
const patch = await reflectNode(state, cadence);
|
|
3894
4142
|
if (patch && Object.keys(patch).length > 0) {
|
|
@@ -3948,7 +4196,7 @@ function createAgent(opts) {
|
|
|
3948
4196
|
}
|
|
3949
4197
|
const lastAfterLoop = state.messages[state.messages.length - 1];
|
|
3950
4198
|
if (lastAfterLoop?.role === "tool" && !pausedStage) {
|
|
3951
|
-
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;
|
|
3952
4200
|
if (!isExpectedExit) {
|
|
3953
4201
|
throw new Error(
|
|
3954
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."
|
|
@@ -3961,6 +4209,11 @@ function createAgent(opts) {
|
|
|
3961
4209
|
return state;
|
|
3962
4210
|
}
|
|
3963
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
|
+
}
|
|
3964
4217
|
const onEvent = config?.onEvent;
|
|
3965
4218
|
const onProgress = config?.onProgress;
|
|
3966
4219
|
const onStream = config?.onStream;
|
|
@@ -4018,7 +4271,19 @@ function createAgent(opts) {
|
|
|
4018
4271
|
status: "error",
|
|
4019
4272
|
error: { message: err?.message, stack: err?.stack }
|
|
4020
4273
|
});
|
|
4274
|
+
if (userTokenCounter) {
|
|
4275
|
+
const { setTokenCounter: setTokenCounter2 } = await Promise.resolve().then(() => (init_utilTokens(), utilTokens_exports));
|
|
4276
|
+
setTokenCounter2(void 0);
|
|
4277
|
+
}
|
|
4021
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
|
+
}
|
|
4022
4287
|
}
|
|
4023
4288
|
await finalizeTraceSession(traceSession, {
|
|
4024
4289
|
agentRuntime: res.agent || runtime,
|
|
@@ -4076,12 +4341,58 @@ function createAgent(opts) {
|
|
|
4076
4341
|
resolveToolApproval,
|
|
4077
4342
|
asTool: ({ toolName, description, inputDescription }) => {
|
|
4078
4343
|
const schema = zod.z.object({ input: zod.z.string().describe(inputDescription || "Input for delegated agent") });
|
|
4079
|
-
|
|
4344
|
+
const delegatedTool = createTool({
|
|
4080
4345
|
name: toolName,
|
|
4081
4346
|
description: description || `Delegate task to agent ${opts.name || "Agent"}`,
|
|
4082
4347
|
schema,
|
|
4083
4348
|
func: async ({ input }) => {
|
|
4084
|
-
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 });
|
|
4085
4396
|
return {
|
|
4086
4397
|
content: res.content,
|
|
4087
4398
|
output: res.output,
|
|
@@ -4089,6 +4400,8 @@ function createAgent(opts) {
|
|
|
4089
4400
|
};
|
|
4090
4401
|
}
|
|
4091
4402
|
});
|
|
4403
|
+
delegatedTool._stateRef = {};
|
|
4404
|
+
return delegatedTool;
|
|
4092
4405
|
},
|
|
4093
4406
|
asHandoff: ({ toolName, description, schema }) => {
|
|
4094
4407
|
const finalName = toolName || `handoff_to_${runtime.name || "agent"}`;
|
|
@@ -4228,7 +4541,11 @@ function createAgentNode(opts) {
|
|
|
4228
4541
|
};
|
|
4229
4542
|
}
|
|
4230
4543
|
|
|
4544
|
+
// src/nodes/contextSummarize.ts
|
|
4545
|
+
init_utilTokens();
|
|
4546
|
+
|
|
4231
4547
|
// src/smart/contextPolicy.ts
|
|
4548
|
+
init_utilTokens();
|
|
4232
4549
|
function collectRecentTurns(messages, lastTurnsToKeep) {
|
|
4233
4550
|
if (lastTurnsToKeep <= 0) return [];
|
|
4234
4551
|
const systemPrefix = messages.filter((message, index) => index === 0 && message.role === "system");
|
|
@@ -4531,7 +4848,7 @@ function createContextSummarizeNode(opts) {
|
|
|
4531
4848
|
const resolved = getResolvedSmartConfig(opts, state.agent);
|
|
4532
4849
|
const config = resolved.summarization;
|
|
4533
4850
|
if (!config.enable) return {};
|
|
4534
|
-
const model = opts.model;
|
|
4851
|
+
const model = state.agent?.model || opts.model;
|
|
4535
4852
|
const messages = state.messages || [];
|
|
4536
4853
|
const onEvent = state.ctx?.__onEvent;
|
|
4537
4854
|
const traceSession = state.ctx?.__traceSession;
|
|
@@ -4850,6 +5167,10 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
4850
5167
|
};
|
|
4851
5168
|
};
|
|
4852
5169
|
}
|
|
5170
|
+
|
|
5171
|
+
// src/index.ts
|
|
5172
|
+
init_utilTokens();
|
|
5173
|
+
init_utilTokens();
|
|
4853
5174
|
var TOOL_RESPONSE_RECOVERY_MARKERS = [
|
|
4854
5175
|
/ARCHIVED_TOOL_RESPONSE\s*\[/,
|
|
4855
5176
|
/STRUCTURED_TOOL_RESPONSE\s*\[/,
|
|
@@ -5168,6 +5489,7 @@ function createContextTools(stateRef, opts) {
|
|
|
5168
5489
|
}
|
|
5169
5490
|
|
|
5170
5491
|
// src/graph/decisions.ts
|
|
5492
|
+
init_utilTokens();
|
|
5171
5493
|
function needsSummarization(state, opts, summarizationEnabled) {
|
|
5172
5494
|
if (!summarizationEnabled) {
|
|
5173
5495
|
return false;
|
|
@@ -5330,12 +5652,24 @@ function createSmartAgent(opts) {
|
|
|
5330
5652
|
toolResponses: resolved.toolResponses,
|
|
5331
5653
|
useTodoList: planningEnabled
|
|
5332
5654
|
};
|
|
5333
|
-
const
|
|
5334
|
-
const
|
|
5335
|
-
const
|
|
5336
|
-
const
|
|
5337
|
-
const
|
|
5338
|
-
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 });
|
|
5339
5673
|
base.__runtime.runtimeProfile = resolved.runtimeProfile;
|
|
5340
5674
|
base.__runtime.smart = resolved;
|
|
5341
5675
|
const summarizationEnabled = resolved.summarization.enable !== false;
|
|
@@ -5371,17 +5705,17 @@ function createSmartAgent(opts) {
|
|
|
5371
5705
|
const memoryFacts = await writeSummaryFactsToMemory(memoryStore, resolved, latestSummary, Math.max(1, (state.messages || []).filter((message) => message.role === "user").length));
|
|
5372
5706
|
return { ...state, memoryFacts };
|
|
5373
5707
|
}
|
|
5374
|
-
function
|
|
5375
|
-
if (!Array.isArray(
|
|
5708
|
+
function syncPlanStateWith(ref, state) {
|
|
5709
|
+
if (!Array.isArray(ref.todoList)) return state;
|
|
5376
5710
|
return {
|
|
5377
5711
|
...state,
|
|
5378
5712
|
plan: {
|
|
5379
|
-
version:
|
|
5380
|
-
steps:
|
|
5713
|
+
version: ref.planVersion || state.planVersion || 1,
|
|
5714
|
+
steps: ref.todoList,
|
|
5381
5715
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5382
|
-
adherenceScore:
|
|
5716
|
+
adherenceScore: ref.adherenceScore || 0
|
|
5383
5717
|
},
|
|
5384
|
-
planVersion:
|
|
5718
|
+
planVersion: ref.planVersion || state.planVersion || 1
|
|
5385
5719
|
};
|
|
5386
5720
|
}
|
|
5387
5721
|
function systemMessage2() {
|
|
@@ -5393,9 +5727,9 @@ function createSmartAgent(opts) {
|
|
|
5393
5727
|
);
|
|
5394
5728
|
return { role: "system", content: sys };
|
|
5395
5729
|
}
|
|
5396
|
-
function syncRuntimeTools(currentState, currentMessages) {
|
|
5730
|
+
function syncRuntimeTools(currentState, currentMessages, toolSet) {
|
|
5397
5731
|
const needsRecoveryTool = hasToolResponseRecoveryReference(currentMessages);
|
|
5398
|
-
const nextTools = needsRecoveryTool ? toolsWithRecovery : toolsWithoutRecovery;
|
|
5732
|
+
const nextTools = needsRecoveryTool ? toolSet.toolsWithRecovery : toolSet.toolsWithoutRecovery;
|
|
5399
5733
|
const currentRuntime = currentState.agent || base.__runtime;
|
|
5400
5734
|
if (currentRuntime.tools === nextTools) {
|
|
5401
5735
|
return currentState;
|
|
@@ -5414,7 +5748,7 @@ function createSmartAgent(opts) {
|
|
|
5414
5748
|
const toolCalls = Array.isArray(lastAssistant.tool_calls) ? lastAssistant.tool_calls : [];
|
|
5415
5749
|
return toolCalls.length === 0;
|
|
5416
5750
|
}
|
|
5417
|
-
async function trySummarize(currentState, currentRawMessages) {
|
|
5751
|
+
async function trySummarize(currentState, currentRawMessages, ref) {
|
|
5418
5752
|
if (!summarizer) return { state: currentState, rawMessages: currentRawMessages, compressed: false };
|
|
5419
5753
|
const delta = await summarizer(currentState);
|
|
5420
5754
|
if (!delta || Object.keys(delta).length === 0) {
|
|
@@ -5423,28 +5757,31 @@ function createSmartAgent(opts) {
|
|
|
5423
5757
|
}
|
|
5424
5758
|
const ctx = { ...currentState.ctx || {} };
|
|
5425
5759
|
delete ctx.__summarizationExhausted;
|
|
5426
|
-
const updated = await persistLatestSummary(
|
|
5760
|
+
const updated = await persistLatestSummary(syncPlanStateWith(ref, { ...currentState, ...delta, ctx }));
|
|
5427
5761
|
return { state: updated, rawMessages: [...updated.messages || currentRawMessages], compressed: true };
|
|
5428
5762
|
}
|
|
5429
5763
|
const instance = {
|
|
5430
5764
|
invoke: async (input, config) => {
|
|
5765
|
+
const toolSet = buildInvokeToolSet();
|
|
5766
|
+
const stateRef = toolSet.stateRef;
|
|
5431
5767
|
stateRef.toolHistory = input.toolHistory;
|
|
5432
5768
|
stateRef.toolHistoryArchived = input.toolHistoryArchived;
|
|
5433
5769
|
stateRef.todoList = input.plan?.steps;
|
|
5434
5770
|
stateRef.planVersion = input.planVersion || input.plan?.version || 0;
|
|
5435
5771
|
stateRef.adherenceScore = input.plan?.adherenceScore || 0;
|
|
5772
|
+
const syncPlanFromRef = (state2) => syncPlanStateWith(stateRef, state2);
|
|
5436
5773
|
const alreadyHasSystem = Array.isArray(input.messages) && input.messages[0]?.role === "system";
|
|
5437
5774
|
const seedMessages = alreadyHasSystem ? [...input.messages || []] : [systemMessage2(), ...input.messages || []];
|
|
5438
|
-
let state = syncRuntimeTools(await syncMemory({ ...input, messages: seedMessages }), seedMessages);
|
|
5775
|
+
let state = syncRuntimeTools(await syncMemory({ ...input, messages: seedMessages }), seedMessages, toolSet);
|
|
5439
5776
|
let lastResult = null;
|
|
5440
5777
|
let rawMessages = [...seedMessages];
|
|
5441
5778
|
const effectiveMaxToolCalls = config?.limits?.maxToolCalls ?? resolved.limits.maxToolCalls ?? 10;
|
|
5442
5779
|
const iterationLimit = Math.max(effectiveMaxToolCalls * 3 + 5, 30);
|
|
5443
5780
|
for (let i = 0; i < iterationLimit; i++) {
|
|
5444
|
-
state = syncRuntimeTools({ ...state, messages: rawMessages }, rawMessages);
|
|
5781
|
+
state = syncRuntimeTools({ ...state, messages: rawMessages }, rawMessages, toolSet);
|
|
5445
5782
|
const next = summarizationEnabled ? decideBefore(state) : "agent";
|
|
5446
5783
|
if (next === "contextSummarize" && summarizer) {
|
|
5447
|
-
const result = await trySummarize(state, rawMessages);
|
|
5784
|
+
const result = await trySummarize(state, rawMessages, stateRef);
|
|
5448
5785
|
state = result.state;
|
|
5449
5786
|
rawMessages = result.rawMessages;
|
|
5450
5787
|
if (result.compressed) continue;
|
|
@@ -5468,14 +5805,14 @@ function createSmartAgent(opts) {
|
|
|
5468
5805
|
if (currentPlan && !state.plan) {
|
|
5469
5806
|
state = { ...state, plan: currentPlan };
|
|
5470
5807
|
}
|
|
5471
|
-
state = syncRuntimeTools(
|
|
5808
|
+
state = syncRuntimeTools(syncPlanFromRef(await syncMemory(state)), rawMessages, toolSet);
|
|
5472
5809
|
stateRef.toolHistory = state.toolHistory;
|
|
5473
5810
|
stateRef.toolHistoryArchived = state.toolHistoryArchived;
|
|
5474
5811
|
if (state.ctx?.__needsSummarization && summarizer) {
|
|
5475
5812
|
const ctx = { ...state.ctx || {} };
|
|
5476
5813
|
delete ctx.__needsSummarization;
|
|
5477
5814
|
state = { ...state, ctx };
|
|
5478
|
-
const result = await trySummarize(state, rawMessages);
|
|
5815
|
+
const result = await trySummarize(state, rawMessages, stateRef);
|
|
5479
5816
|
state = result.state;
|
|
5480
5817
|
rawMessages = result.rawMessages;
|
|
5481
5818
|
continue;
|
|
@@ -5486,7 +5823,7 @@ function createSmartAgent(opts) {
|
|
|
5486
5823
|
if (summarizationEnabled) {
|
|
5487
5824
|
const after = decideAfter(state);
|
|
5488
5825
|
if (after === "contextSummarize" && summarizer) {
|
|
5489
|
-
const result = await trySummarize(state, rawMessages);
|
|
5826
|
+
const result = await trySummarize(state, rawMessages, stateRef);
|
|
5490
5827
|
state = result.state;
|
|
5491
5828
|
rawMessages = result.rawMessages;
|
|
5492
5829
|
if (result.compressed) continue;
|
|
@@ -5925,7 +6262,50 @@ var ProviderError = class extends Error {
|
|
|
5925
6262
|
};
|
|
5926
6263
|
|
|
5927
6264
|
// src/providers/base.ts
|
|
6265
|
+
var DEFAULT_RETRY = {
|
|
6266
|
+
maxRetries: 3,
|
|
6267
|
+
baseDelayMs: 500,
|
|
6268
|
+
maxDelayMs: 8e3
|
|
6269
|
+
};
|
|
5928
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
|
+
}
|
|
5929
6309
|
};
|
|
5930
6310
|
|
|
5931
6311
|
// src/providers/utils/sse.ts
|
|
@@ -6052,6 +6432,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6052
6432
|
...config.defaultHeaders,
|
|
6053
6433
|
...config.organization ? { "OpenAI-Organization": config.organization } : {}
|
|
6054
6434
|
};
|
|
6435
|
+
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
6055
6436
|
}
|
|
6056
6437
|
async complete(request) {
|
|
6057
6438
|
const body = this.buildRequestBody(request, false);
|
|
@@ -6199,15 +6580,13 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6199
6580
|
}
|
|
6200
6581
|
async doFetch(body) {
|
|
6201
6582
|
const url = `${this.baseURL}/chat/completions`;
|
|
6202
|
-
const
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
body: JSON.stringify(body)
|
|
6210
|
-
});
|
|
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 }));
|
|
6211
6590
|
if (!res.ok) {
|
|
6212
6591
|
const text = await res.text().catch(() => "");
|
|
6213
6592
|
throw new ProviderError(
|
|
@@ -6277,6 +6656,8 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6277
6656
|
this.defaultModel = config.defaultModel ?? "claude-sonnet-4-20250514";
|
|
6278
6657
|
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
6279
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 };
|
|
6280
6661
|
}
|
|
6281
6662
|
async complete(request) {
|
|
6282
6663
|
const body = this.buildRequestBody(request, false);
|
|
@@ -6395,12 +6776,22 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6395
6776
|
max_tokens: request.maxTokens ?? 4096,
|
|
6396
6777
|
stream
|
|
6397
6778
|
};
|
|
6398
|
-
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
|
+
}
|
|
6399
6786
|
if (request.temperature != null) body.temperature = request.temperature;
|
|
6400
6787
|
if (request.topP != null) body.top_p = request.topP;
|
|
6401
6788
|
if (request.stop) body.stop_sequences = request.stop;
|
|
6402
6789
|
if (request.tools?.length) {
|
|
6403
|
-
|
|
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;
|
|
6404
6795
|
}
|
|
6405
6796
|
if (request.toolChoice != null) {
|
|
6406
6797
|
if (request.toolChoice === "auto") {
|
|
@@ -6499,16 +6890,14 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6499
6890
|
}
|
|
6500
6891
|
async doFetch(body) {
|
|
6501
6892
|
const url = `${this.baseURL}/v1/messages`;
|
|
6502
|
-
const
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
body: JSON.stringify(body)
|
|
6511
|
-
});
|
|
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 }));
|
|
6512
6901
|
if (!res.ok) {
|
|
6513
6902
|
const text = await res.text().catch(() => "");
|
|
6514
6903
|
throw new ProviderError(
|
|
@@ -6720,6 +7109,8 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6720
7109
|
this.region = config.region;
|
|
6721
7110
|
this.defaultModel = config.defaultModel ?? "anthropic.claude-sonnet-4-20250514-v1:0";
|
|
6722
7111
|
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
7112
|
+
this.promptCachingEnabled = config.prompt_caching?.enabled === true;
|
|
7113
|
+
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
6723
7114
|
this.credentials = {
|
|
6724
7115
|
accessKeyId: config.accessKeyId ?? process.env.AWS_ACCESS_KEY_ID ?? "",
|
|
6725
7116
|
secretAccessKey: config.secretAccessKey ?? process.env.AWS_SECRET_ACCESS_KEY ?? "",
|
|
@@ -6758,7 +7149,9 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6758
7149
|
messages: messages.map((m) => this.toBedrockMessage(m))
|
|
6759
7150
|
};
|
|
6760
7151
|
if (system.length > 0) {
|
|
6761
|
-
|
|
7152
|
+
const systemBlocks = system.map((s) => ({ text: s }));
|
|
7153
|
+
if (this.promptCachingEnabled) systemBlocks.push({ cachePoint: { type: "default" } });
|
|
7154
|
+
body.system = systemBlocks;
|
|
6762
7155
|
}
|
|
6763
7156
|
const inferenceConfig = {};
|
|
6764
7157
|
if (request.maxTokens != null) inferenceConfig.maxTokens = request.maxTokens;
|
|
@@ -6767,8 +7160,12 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6767
7160
|
if (request.stop) inferenceConfig.stopSequences = request.stop;
|
|
6768
7161
|
if (Object.keys(inferenceConfig).length > 0) body.inferenceConfig = inferenceConfig;
|
|
6769
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
|
+
}
|
|
6770
7167
|
body.toolConfig = {
|
|
6771
|
-
tools
|
|
7168
|
+
tools
|
|
6772
7169
|
};
|
|
6773
7170
|
if (request.toolChoice != null) {
|
|
6774
7171
|
if (request.toolChoice === "auto") {
|
|
@@ -6865,23 +7262,21 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6865
7262
|
const host = `bedrock-runtime.${this.region}.amazonaws.com`;
|
|
6866
7263
|
const url = `https://${host}/model/${encodeURIComponent(modelId)}/converse`;
|
|
6867
7264
|
const bodyStr = JSON.stringify(body);
|
|
6868
|
-
const
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
method: "POST",
|
|
6883
|
-
headers,
|
|
6884
|
-
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 });
|
|
6885
7280
|
});
|
|
6886
7281
|
if (!res.ok) {
|
|
6887
7282
|
const text = await res.text().catch(() => "");
|
|
@@ -7795,6 +8190,7 @@ exports.createToolLimitFinalizeNode = createToolLimitFinalizeNode;
|
|
|
7795
8190
|
exports.createToolsNode = createToolsNode;
|
|
7796
8191
|
exports.customCallbackRule = customCallbackRule;
|
|
7797
8192
|
exports.customSink = customSink;
|
|
8193
|
+
exports.defaultTokenCounter = defaultTokenCounter;
|
|
7798
8194
|
exports.emptyUsage = emptyUsage;
|
|
7799
8195
|
exports.evaluateGuardrails = evaluateGuardrails;
|
|
7800
8196
|
exports.fileSink = fileSink;
|
|
@@ -7807,6 +8203,7 @@ exports.generateTraceId = generateTraceId;
|
|
|
7807
8203
|
exports.getModelCapabilities = getModelCapabilities;
|
|
7808
8204
|
exports.getNestedValue = getNestedValue;
|
|
7809
8205
|
exports.getResolvedSmartConfig = getResolvedSmartConfig;
|
|
8206
|
+
exports.getTokenCounter = getTokenCounter;
|
|
7810
8207
|
exports.hasToolResponseRecoveryReference = hasToolResponseRecoveryReference;
|
|
7811
8208
|
exports.httpSink = httpSink;
|
|
7812
8209
|
exports.isSmartModel = isSmartModel;
|
|
@@ -7820,6 +8217,7 @@ exports.resolveStrategy = resolveStrategy;
|
|
|
7820
8217
|
exports.resolveToolApprovalState = resolveToolApprovalState;
|
|
7821
8218
|
exports.restoreSnapshot = restoreSnapshot;
|
|
7822
8219
|
exports.runSmartAgentEvalHarness = runSmartAgentEvalHarness;
|
|
8220
|
+
exports.setTokenCounter = setTokenCounter;
|
|
7823
8221
|
exports.startStreamingSession = startStreamingSession;
|
|
7824
8222
|
exports.traceSessionToOtlp = traceSessionToOtlp;
|
|
7825
8223
|
exports.withTools = withTools;
|