@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.mjs
CHANGED
|
@@ -8,7 +8,99 @@ import { nanoid } from 'nanoid';
|
|
|
8
8
|
import crypto, { randomUUID, createHash, createHmac } from 'crypto';
|
|
9
9
|
import AjvModule from 'ajv';
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __esm = (fn, res) => function __init() {
|
|
14
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
15
|
+
};
|
|
16
|
+
var __export = (target, all) => {
|
|
17
|
+
for (var name in all)
|
|
18
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// src/utils/utilTokens.ts
|
|
22
|
+
var utilTokens_exports = {};
|
|
23
|
+
__export(utilTokens_exports, {
|
|
24
|
+
countApproxTokens: () => countApproxTokens,
|
|
25
|
+
countMessagesTokens: () => countMessagesTokens,
|
|
26
|
+
defaultTokenCounter: () => defaultTokenCounter,
|
|
27
|
+
getTokenCounter: () => getTokenCounter,
|
|
28
|
+
setTokenCounter: () => setTokenCounter
|
|
29
|
+
});
|
|
30
|
+
function defaultTokenCounter(text) {
|
|
31
|
+
if (!text) return 0;
|
|
32
|
+
const nonAsciiCount = (text.match(/[^\x00-\x7F]/g) || []).length;
|
|
33
|
+
const asciiCount = text.length - nonAsciiCount;
|
|
34
|
+
return Math.ceil(asciiCount / 4 + nonAsciiCount / 1.5);
|
|
35
|
+
}
|
|
36
|
+
function setTokenCounter(counter) {
|
|
37
|
+
activeTokenCounter = typeof counter === "function" ? counter : defaultTokenCounter;
|
|
38
|
+
}
|
|
39
|
+
function getTokenCounter() {
|
|
40
|
+
return activeTokenCounter;
|
|
41
|
+
}
|
|
42
|
+
function countApproxTokens(text) {
|
|
43
|
+
return activeTokenCounter(text || "");
|
|
44
|
+
}
|
|
45
|
+
function extractMessageText(m) {
|
|
46
|
+
if (!m) return "";
|
|
47
|
+
const parts = [];
|
|
48
|
+
parts.push(m.role || "");
|
|
49
|
+
if (m.name) parts.push(m.name);
|
|
50
|
+
if (typeof m.content === "string") {
|
|
51
|
+
parts.push(m.content);
|
|
52
|
+
} else if (Array.isArray(m.content)) {
|
|
53
|
+
for (const c of m.content) {
|
|
54
|
+
if (typeof c === "string") parts.push(c);
|
|
55
|
+
else if (c?.text) parts.push(c.text);
|
|
56
|
+
else if (c?.content) parts.push(c.content);
|
|
57
|
+
else if (c?.type === "tool_use" && c?.input) {
|
|
58
|
+
parts.push(c.name || "");
|
|
59
|
+
parts.push(typeof c.input === "string" ? c.input : JSON.stringify(c.input));
|
|
60
|
+
} else if (c != null && typeof c === "object") {
|
|
61
|
+
parts.push(JSON.stringify(c));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} else if (m.content != null && typeof m.content === "object") {
|
|
65
|
+
parts.push(JSON.stringify(m.content));
|
|
66
|
+
}
|
|
67
|
+
if (Array.isArray(m.tool_calls)) {
|
|
68
|
+
for (const tc of m.tool_calls) {
|
|
69
|
+
if (tc?.function?.name) parts.push(tc.function.name);
|
|
70
|
+
if (tc?.function?.arguments) {
|
|
71
|
+
parts.push(
|
|
72
|
+
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
if (tc?.name && !tc?.function?.name) parts.push(tc.name);
|
|
76
|
+
if (tc?.args && !tc?.function?.arguments) {
|
|
77
|
+
parts.push(typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (Array.isArray(m.additional_kwargs?.tool_calls)) {
|
|
82
|
+
for (const tc of m.additional_kwargs.tool_calls) {
|
|
83
|
+
if (tc?.function?.name) parts.push(tc.function.name);
|
|
84
|
+
if (tc?.function?.arguments) {
|
|
85
|
+
parts.push(
|
|
86
|
+
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return parts.join("\n");
|
|
92
|
+
}
|
|
93
|
+
function countMessagesTokens(messages) {
|
|
94
|
+
if (!Array.isArray(messages) || messages.length === 0) return 0;
|
|
95
|
+
const allText = messages.map(extractMessageText).join("\n");
|
|
96
|
+
return countApproxTokens(allText) + messages.length * 4;
|
|
97
|
+
}
|
|
98
|
+
var activeTokenCounter;
|
|
99
|
+
var init_utilTokens = __esm({
|
|
100
|
+
"src/utils/utilTokens.ts"() {
|
|
101
|
+
activeTokenCounter = defaultTokenCounter;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
12
104
|
var moduleName = "@langchain/core/tools";
|
|
13
105
|
var cachedToolFactory;
|
|
14
106
|
var cachedHasAttemptedFactory = false;
|
|
@@ -316,7 +408,9 @@ function createTool({
|
|
|
316
408
|
needsApproval,
|
|
317
409
|
approvalPrompt,
|
|
318
410
|
approvalDefaults,
|
|
319
|
-
maxExecutionsPerRun
|
|
411
|
+
maxExecutionsPerRun,
|
|
412
|
+
cache,
|
|
413
|
+
retry
|
|
320
414
|
}) {
|
|
321
415
|
const execute = async (input) => func(input);
|
|
322
416
|
const toolRecord = {
|
|
@@ -341,6 +435,12 @@ function createTool({
|
|
|
341
435
|
if (maxExecutionsPerRun !== void 0) {
|
|
342
436
|
toolRecord.maxExecutionsPerRun = maxExecutionsPerRun;
|
|
343
437
|
}
|
|
438
|
+
if (cache !== void 0) {
|
|
439
|
+
toolRecord.cache = cache;
|
|
440
|
+
}
|
|
441
|
+
if (retry !== void 0) {
|
|
442
|
+
toolRecord.retry = retry;
|
|
443
|
+
}
|
|
344
444
|
toolRecord.__source = toolRecord.__source || "smart";
|
|
345
445
|
toolRecord.__impl = func;
|
|
346
446
|
return toolRecord;
|
|
@@ -1882,7 +1982,8 @@ function createAgentCoreNode(opts) {
|
|
|
1882
1982
|
todoListPrompt: opts.todoListPrompt,
|
|
1883
1983
|
limits: opts.limits,
|
|
1884
1984
|
outputSchema: opts.outputSchema,
|
|
1885
|
-
tracing: opts.tracing
|
|
1985
|
+
tracing: opts.tracing,
|
|
1986
|
+
responseFormat: void 0
|
|
1886
1987
|
};
|
|
1887
1988
|
const tools = runtime.tools ?? [];
|
|
1888
1989
|
const shouldUseStrictToolCalling = Boolean(
|
|
@@ -2084,7 +2185,7 @@ function createAgentCoreNode(opts) {
|
|
|
2084
2185
|
// src/smart/runtimeConfig.ts
|
|
2085
2186
|
var DEFAULT_CRITICAL_TOOLS = ["response", "manage_todo_list", "get_tool_response"];
|
|
2086
2187
|
var BASE_DEFAULTS = {
|
|
2087
|
-
limits: { maxToolCalls: 8, maxParallelTools: 2, maxContextTokens: 24e3 },
|
|
2188
|
+
limits: { maxToolCalls: 8, maxParallelTools: 2, maxContextTokens: 24e3, maxTotalOutputTokens: 0, maxCostUsd: 0, maxWallClockMs: 0 },
|
|
2088
2189
|
summarization: {
|
|
2089
2190
|
enable: true,
|
|
2090
2191
|
maxTokens: 24e3,
|
|
@@ -2211,7 +2312,10 @@ function mergeLimits(base, override) {
|
|
|
2211
2312
|
return {
|
|
2212
2313
|
maxToolCalls: override?.maxToolCalls ?? base.maxToolCalls,
|
|
2213
2314
|
maxParallelTools: override?.maxParallelTools ?? base.maxParallelTools,
|
|
2214
|
-
maxContextTokens: override?.maxContextTokens ?? base.maxContextTokens
|
|
2315
|
+
maxContextTokens: override?.maxContextTokens ?? base.maxContextTokens,
|
|
2316
|
+
maxTotalOutputTokens: override?.maxTotalOutputTokens ?? base.maxTotalOutputTokens ?? 0,
|
|
2317
|
+
maxCostUsd: override?.maxCostUsd ?? base.maxCostUsd ?? 0,
|
|
2318
|
+
maxWallClockMs: override?.maxWallClockMs ?? base.maxWallClockMs ?? 0
|
|
2215
2319
|
};
|
|
2216
2320
|
}
|
|
2217
2321
|
function resolveBaseProfile(opts, runtimeProfile) {
|
|
@@ -2289,66 +2393,8 @@ function getResolvedSmartConfig(opts, runtime) {
|
|
|
2289
2393
|
return runtime?.smart || normalizeSmartAgentOptions(opts);
|
|
2290
2394
|
}
|
|
2291
2395
|
|
|
2292
|
-
// src/
|
|
2293
|
-
|
|
2294
|
-
if (!text) return 0;
|
|
2295
|
-
const nonAsciiCount = (text.match(/[^\x00-\x7F]/g) || []).length;
|
|
2296
|
-
const asciiCount = text.length - nonAsciiCount;
|
|
2297
|
-
return Math.ceil(asciiCount / 4 + nonAsciiCount / 1.5);
|
|
2298
|
-
}
|
|
2299
|
-
function extractMessageText(m) {
|
|
2300
|
-
if (!m) return "";
|
|
2301
|
-
const parts = [];
|
|
2302
|
-
parts.push(m.role || "");
|
|
2303
|
-
if (m.name) parts.push(m.name);
|
|
2304
|
-
if (typeof m.content === "string") {
|
|
2305
|
-
parts.push(m.content);
|
|
2306
|
-
} else if (Array.isArray(m.content)) {
|
|
2307
|
-
for (const c of m.content) {
|
|
2308
|
-
if (typeof c === "string") parts.push(c);
|
|
2309
|
-
else if (c?.text) parts.push(c.text);
|
|
2310
|
-
else if (c?.content) parts.push(c.content);
|
|
2311
|
-
else if (c?.type === "tool_use" && c?.input) {
|
|
2312
|
-
parts.push(c.name || "");
|
|
2313
|
-
parts.push(typeof c.input === "string" ? c.input : JSON.stringify(c.input));
|
|
2314
|
-
} else if (c != null && typeof c === "object") {
|
|
2315
|
-
parts.push(JSON.stringify(c));
|
|
2316
|
-
}
|
|
2317
|
-
}
|
|
2318
|
-
} else if (m.content != null && typeof m.content === "object") {
|
|
2319
|
-
parts.push(JSON.stringify(m.content));
|
|
2320
|
-
}
|
|
2321
|
-
if (Array.isArray(m.tool_calls)) {
|
|
2322
|
-
for (const tc of m.tool_calls) {
|
|
2323
|
-
if (tc?.function?.name) parts.push(tc.function.name);
|
|
2324
|
-
if (tc?.function?.arguments) {
|
|
2325
|
-
parts.push(
|
|
2326
|
-
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
2327
|
-
);
|
|
2328
|
-
}
|
|
2329
|
-
if (tc?.name && !tc?.function?.name) parts.push(tc.name);
|
|
2330
|
-
if (tc?.args && !tc?.function?.arguments) {
|
|
2331
|
-
parts.push(typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args));
|
|
2332
|
-
}
|
|
2333
|
-
}
|
|
2334
|
-
}
|
|
2335
|
-
if (Array.isArray(m.additional_kwargs?.tool_calls)) {
|
|
2336
|
-
for (const tc of m.additional_kwargs.tool_calls) {
|
|
2337
|
-
if (tc?.function?.name) parts.push(tc.function.name);
|
|
2338
|
-
if (tc?.function?.arguments) {
|
|
2339
|
-
parts.push(
|
|
2340
|
-
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
2341
|
-
);
|
|
2342
|
-
}
|
|
2343
|
-
}
|
|
2344
|
-
}
|
|
2345
|
-
return parts.join("\n");
|
|
2346
|
-
}
|
|
2347
|
-
function countMessagesTokens(messages) {
|
|
2348
|
-
if (!Array.isArray(messages) || messages.length === 0) return 0;
|
|
2349
|
-
const allText = messages.map(extractMessageText).join("\n");
|
|
2350
|
-
return countApproxTokens(allText) + messages.length * 4;
|
|
2351
|
-
}
|
|
2396
|
+
// src/smart/toolResponses.ts
|
|
2397
|
+
init_utilTokens();
|
|
2352
2398
|
|
|
2353
2399
|
// src/utils/content.ts
|
|
2354
2400
|
function contentToString(content) {
|
|
@@ -2548,6 +2594,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2548
2594
|
anyTool._stateRef.messages = state.messages;
|
|
2549
2595
|
anyTool._stateRef.ctx = state.ctx || (state.ctx = {});
|
|
2550
2596
|
anyTool._stateRef.__onEvent = onEvent;
|
|
2597
|
+
anyTool._stateRef.parentRuntime = runtime;
|
|
2551
2598
|
}
|
|
2552
2599
|
}
|
|
2553
2600
|
const last = state.messages[state.messages.length - 1];
|
|
@@ -2558,6 +2605,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2558
2605
|
const remaining = Math.max(0, limits.maxToolCalls - toolCount);
|
|
2559
2606
|
const planned = toolCalls.slice(0, remaining);
|
|
2560
2607
|
const skipped = toolCalls.slice(remaining);
|
|
2608
|
+
const orderedSlots = planned.map(() => []);
|
|
2561
2609
|
const isCancelled = () => {
|
|
2562
2610
|
if (abortSignal?.aborted) return { cancelled: true, reason: "aborted" };
|
|
2563
2611
|
if (cancellationToken && cancellationToken.isCancellationRequested) return { cancelled: true, reason: "cancelled" };
|
|
@@ -2574,7 +2622,9 @@ function createToolsNode(initialTools, opts) {
|
|
|
2574
2622
|
}
|
|
2575
2623
|
state.ctx = ctx;
|
|
2576
2624
|
};
|
|
2577
|
-
const runOne = async (tc) => {
|
|
2625
|
+
const runOne = async (tc, slot = appended) => {
|
|
2626
|
+
var _a;
|
|
2627
|
+
const push = (msg) => slot.push(msg);
|
|
2578
2628
|
const cancelState = isCancelled();
|
|
2579
2629
|
if (cancelState.cancelled) {
|
|
2580
2630
|
const ctx = state.ctx = state.ctx || {};
|
|
@@ -2585,7 +2635,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2585
2635
|
}
|
|
2586
2636
|
const tool = toolByName.get(tc.name);
|
|
2587
2637
|
if (!tool) {
|
|
2588
|
-
|
|
2638
|
+
push({ role: "tool", content: `Tool not found: ${tc.name}`, tool_call_id: tc.id || `${tc.name}_unknown`, name: tc.name });
|
|
2589
2639
|
onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args: tc.args, error: { message: "Tool not found" } });
|
|
2590
2640
|
toolCount += 1;
|
|
2591
2641
|
return { status: "error" };
|
|
@@ -2601,7 +2651,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2601
2651
|
const validatedArgs = validateToolArgs(tool, args);
|
|
2602
2652
|
if (!validatedArgs.ok && resolved.toolResponses.schemaValidation === "strict") {
|
|
2603
2653
|
const errorMessage = `Tool argument validation failed for ${tc.name}: ${validatedArgs.message}`;
|
|
2604
|
-
|
|
2654
|
+
push({ role: "tool", content: errorMessage, tool_call_id: toolCallId, name: tc.name });
|
|
2605
2655
|
markToolFailure(errorMessage, tc.name, toolCallId);
|
|
2606
2656
|
onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args, error: { message: errorMessage } });
|
|
2607
2657
|
toolCount += 1;
|
|
@@ -2623,7 +2673,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2623
2673
|
const currentExecutions = countSuccessfulToolExecutions(toolHistory, toolName);
|
|
2624
2674
|
if (currentExecutions >= maxExecutionsPerRun) {
|
|
2625
2675
|
const limitMessage = `Skipped tool due to per-tool execution limit: ${toolName} (${maxExecutionsPerRun}/run)`;
|
|
2626
|
-
|
|
2676
|
+
push({ role: "tool", content: limitMessage, tool_call_id: toolCallId, name: tc.name });
|
|
2627
2677
|
onEvent?.({ type: "tool_call", phase: "skipped", name: toolName, id: tc.id, args });
|
|
2628
2678
|
recordTraceEvent(traceSession, {
|
|
2629
2679
|
type: "tool_call",
|
|
@@ -2683,7 +2733,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2683
2733
|
}
|
|
2684
2734
|
if (approvalEntry.status === "rejected") {
|
|
2685
2735
|
const rejectionMessage = approvalEntry.comment || "Tool call rejected by reviewer.";
|
|
2686
|
-
|
|
2736
|
+
push({ role: "tool", content: `Tool call rejected: ${rejectionMessage}`, tool_call_id: toolCallId, name: tc.name });
|
|
2687
2737
|
approvalEntry.metadata = { ...approvalEntry.metadata || {}, resolution: "rejected" };
|
|
2688
2738
|
approvalEntry.status = "executed";
|
|
2689
2739
|
approvalEntry.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2701,23 +2751,102 @@ function createToolsNode(initialTools, opts) {
|
|
|
2701
2751
|
const start = Date.now();
|
|
2702
2752
|
const sanitizedArgs = sanitizeTracePayload(args);
|
|
2703
2753
|
const inputBytes = traceSession?.resolvedConfig.logData ? estimatePayloadBytes(sanitizedArgs) : void 0;
|
|
2754
|
+
const cacheCfg = tool.cache;
|
|
2755
|
+
const cacheEnabled = cacheCfg === true || cacheCfg && typeof cacheCfg === "object";
|
|
2756
|
+
const cacheKeyFn = cacheEnabled && typeof cacheCfg === "object" ? cacheCfg.keyFn : void 0;
|
|
2757
|
+
const stableJson = (value) => {
|
|
2758
|
+
try {
|
|
2759
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
2760
|
+
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
|
2761
|
+
const keys = Object.keys(value).sort();
|
|
2762
|
+
return `{${keys.map((k) => JSON.stringify(k) + ":" + stableJson(value[k])).join(",")}}`;
|
|
2763
|
+
} catch {
|
|
2764
|
+
return String(value);
|
|
2765
|
+
}
|
|
2766
|
+
};
|
|
2767
|
+
const cacheKey = cacheEnabled ? `${toolName}|${cacheKeyFn ? cacheKeyFn(args) : stableJson(args)}` : void 0;
|
|
2768
|
+
const toolCache = state.toolCache = state.toolCache || {};
|
|
2769
|
+
let cachedHit = void 0;
|
|
2770
|
+
if (cacheKey && Object.prototype.hasOwnProperty.call(toolCache, cacheKey)) {
|
|
2771
|
+
const entry = toolCache[cacheKey];
|
|
2772
|
+
const ttl = cacheEnabled && typeof cacheCfg === "object" ? cacheCfg.ttlMs : void 0;
|
|
2773
|
+
if (!ttl || entry?.timestamp && Date.now() - entry.timestamp <= ttl) {
|
|
2774
|
+
cachedHit = entry?.value;
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
const retryCfg = tool.retry;
|
|
2778
|
+
const failureStats = (_a = state.ctx).__toolFailureCounts || (_a.__toolFailureCounts = {});
|
|
2779
|
+
if (retryCfg?.circuitBreakerThreshold && failureStats[toolName] >= retryCfg.circuitBreakerThreshold) {
|
|
2780
|
+
const breakerMsg = `Tool ${toolName} circuit breaker open after ${failureStats[toolName]} consecutive failures`;
|
|
2781
|
+
push({ role: "tool", content: breakerMsg, tool_call_id: toolCallId, name: tc.name });
|
|
2782
|
+
markToolFailure(breakerMsg, toolName, toolCallId);
|
|
2783
|
+
onEvent?.({ type: "tool_call", phase: "error", name: toolName, id: tc.id, args, error: { message: breakerMsg } });
|
|
2784
|
+
toolCount += 1;
|
|
2785
|
+
return { status: "error" };
|
|
2786
|
+
}
|
|
2704
2787
|
try {
|
|
2788
|
+
if (cachedHit !== void 0) {
|
|
2789
|
+
const executionId2 = nanoid();
|
|
2790
|
+
const responsePolicy2 = applyToolResponseHardCap(toolName, cachedHit, executionId2, resolved);
|
|
2791
|
+
toolHistory.push({
|
|
2792
|
+
executionId: executionId2,
|
|
2793
|
+
toolName,
|
|
2794
|
+
args,
|
|
2795
|
+
output: cachedHit,
|
|
2796
|
+
rawOutput: cachedHit,
|
|
2797
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2798
|
+
tool_call_id: tc.id,
|
|
2799
|
+
summarized: false,
|
|
2800
|
+
originalTokenCount: responsePolicy2.tokenCount,
|
|
2801
|
+
classification: responsePolicy2.classification,
|
|
2802
|
+
retentionPolicy: "keep_full",
|
|
2803
|
+
fromCache: true,
|
|
2804
|
+
status: "success"
|
|
2805
|
+
});
|
|
2806
|
+
push({ role: "tool", content: responsePolicy2.content, tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2807
|
+
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: cachedHit, durationMs: 0 });
|
|
2808
|
+
toolCount += 1;
|
|
2809
|
+
return { status: "success" };
|
|
2810
|
+
}
|
|
2705
2811
|
onEvent?.({ type: "tool_call", phase: "start", name: toolName, id: tc.id, args });
|
|
2706
2812
|
onProgress?.({ stage: "tools", message: `Running tool ${tc.name}` });
|
|
2707
2813
|
const anyTool = tool;
|
|
2708
2814
|
const callOptions = { cancellationToken, signal: abortSignal };
|
|
2815
|
+
const invokeOnce = async () => {
|
|
2816
|
+
if (typeof anyTool.func === "function") return anyTool.func(args, callOptions);
|
|
2817
|
+
if (typeof anyTool.invoke === "function") return anyTool.invoke(args, callOptions);
|
|
2818
|
+
if (typeof anyTool.call === "function") return anyTool.call(args, callOptions);
|
|
2819
|
+
if (typeof anyTool._call === "function") return anyTool._call(args, callOptions);
|
|
2820
|
+
if (typeof anyTool.run === "function") return anyTool.run(args, callOptions);
|
|
2821
|
+
throw new Error("Tool is not invokable");
|
|
2822
|
+
};
|
|
2709
2823
|
let output;
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2824
|
+
const maxRetries = Math.max(0, Number(retryCfg?.maxRetries) || 0);
|
|
2825
|
+
const backoffMs = Math.max(0, Number(retryCfg?.backoffMs) || 250);
|
|
2826
|
+
let attempt = 0;
|
|
2827
|
+
while (true) {
|
|
2828
|
+
try {
|
|
2829
|
+
output = await invokeOnce();
|
|
2830
|
+
failureStats[toolName] = 0;
|
|
2831
|
+
break;
|
|
2832
|
+
} catch (retryErr) {
|
|
2833
|
+
attempt += 1;
|
|
2834
|
+
const shouldRetry = retryCfg?.shouldRetry ? retryCfg.shouldRetry(retryErr, attempt) : true;
|
|
2835
|
+
if (attempt > maxRetries || !shouldRetry) {
|
|
2836
|
+
failureStats[toolName] = (failureStats[toolName] || 0) + 1;
|
|
2837
|
+
throw retryErr;
|
|
2838
|
+
}
|
|
2839
|
+
await new Promise((r) => setTimeout(r, backoffMs * Math.pow(2, attempt - 1)));
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
if (cacheKey) {
|
|
2843
|
+
toolCache[cacheKey] = { value: output, timestamp: Date.now() };
|
|
2844
|
+
}
|
|
2716
2845
|
const durationMs = Date.now() - start;
|
|
2717
2846
|
const executionId = nanoid();
|
|
2718
2847
|
if (output && typeof output === "object" && output.__handoff && output.__handoff.runtime) {
|
|
2719
2848
|
toolHistory.push({ executionId, toolName, args, output: "handoff:ok", rawOutput: output, timestamp: (/* @__PURE__ */ new Date()).toISOString(), tool_call_id: tc.id, status: "handoff" });
|
|
2720
|
-
|
|
2849
|
+
push({ role: "tool", content: "ok", tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2721
2850
|
state.agent = output.__handoff.runtime;
|
|
2722
2851
|
onEvent?.({ type: "handoff", from: runtime.name, to: state.agent?.name, toolName });
|
|
2723
2852
|
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: "handoff", durationMs });
|
|
@@ -2769,7 +2898,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2769
2898
|
archiveId: void 0,
|
|
2770
2899
|
status: "success"
|
|
2771
2900
|
});
|
|
2772
|
-
|
|
2901
|
+
push({ role: "tool", content: responsePolicy.content, tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2773
2902
|
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: output, durationMs });
|
|
2774
2903
|
onProgress?.({ stage: "tools", message: `Tool ${tc.name} completed`, detail: { durationMs } });
|
|
2775
2904
|
if (needsApproval && approvalEntry) {
|
|
@@ -2825,7 +2954,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2825
2954
|
const executionId = nanoid();
|
|
2826
2955
|
const message = error?.message || String(error);
|
|
2827
2956
|
toolHistory.push({ executionId, toolName, args, output: `Error executing tool: ${message}`, rawOutput: null, timestamp: (/* @__PURE__ */ new Date()).toISOString(), tool_call_id: tc.id, status: "error" });
|
|
2828
|
-
|
|
2957
|
+
push({ role: "tool", content: `Error executing tool: ${message}`, tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2829
2958
|
markToolFailure(message, toolName, toolCallId);
|
|
2830
2959
|
onEvent?.({ type: "tool_call", phase: "error", name: toolName, id: tc.id, args, error: { message } });
|
|
2831
2960
|
onProgress?.({ stage: "tools", message: `Tool ${tc.name} failed`, detail: { error: message } });
|
|
@@ -2862,22 +2991,67 @@ function createToolsNode(initialTools, opts) {
|
|
|
2862
2991
|
return { status: "error", approval: approvalEntry };
|
|
2863
2992
|
}
|
|
2864
2993
|
};
|
|
2865
|
-
|
|
2866
|
-
|
|
2994
|
+
const approvalIndices = [];
|
|
2995
|
+
const parallelIndices = [];
|
|
2996
|
+
planned.forEach((tc, idx) => {
|
|
2997
|
+
const t = toolByName.get(tc.name);
|
|
2998
|
+
if (t && t.needsApproval) approvalIndices.push(idx);
|
|
2999
|
+
else parallelIndices.push(idx);
|
|
3000
|
+
});
|
|
3001
|
+
let shouldStop = false;
|
|
3002
|
+
const checkCancellationStop = () => {
|
|
2867
3003
|
const cancelState = isCancelled();
|
|
2868
3004
|
if (cancelState.cancelled) {
|
|
2869
3005
|
const ctx = state.ctx = state.ctx || {};
|
|
2870
3006
|
ctx.__cancelled = { stage: "tools", reason: cancelState.reason, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
2871
3007
|
onEvent?.({ type: "cancelled", stage: "tools", reason: cancelState.reason });
|
|
2872
3008
|
onProgress?.({ stage: "tools", message: "Cancelled", detail: { reason: cancelState.reason } });
|
|
2873
|
-
|
|
3009
|
+
shouldStop = true;
|
|
3010
|
+
return true;
|
|
2874
3011
|
}
|
|
2875
|
-
|
|
3012
|
+
return false;
|
|
3013
|
+
};
|
|
3014
|
+
for (const idx of approvalIndices) {
|
|
3015
|
+
if (awaitingApproval || shouldStop) break;
|
|
3016
|
+
if (checkCancellationStop()) break;
|
|
3017
|
+
const result = await runOne(planned[idx], orderedSlots[idx]);
|
|
2876
3018
|
if (result.status === "awaiting_approval") {
|
|
2877
3019
|
awaitingApproval = true;
|
|
2878
3020
|
break;
|
|
2879
3021
|
}
|
|
2880
3022
|
}
|
|
3023
|
+
if (!awaitingApproval && !shouldStop && parallelIndices.length > 0) {
|
|
3024
|
+
const concurrency = Math.max(1, Math.min(limits.maxParallelTools, parallelIndices.length));
|
|
3025
|
+
let cursor = 0;
|
|
3026
|
+
const workerError = {};
|
|
3027
|
+
const workers = [];
|
|
3028
|
+
for (let w = 0; w < concurrency; w++) {
|
|
3029
|
+
workers.push((async () => {
|
|
3030
|
+
while (true) {
|
|
3031
|
+
if (workerError.err || shouldStop || awaitingApproval) return;
|
|
3032
|
+
const i = cursor++;
|
|
3033
|
+
if (i >= parallelIndices.length) return;
|
|
3034
|
+
if (checkCancellationStop()) return;
|
|
3035
|
+
const idx = parallelIndices[i];
|
|
3036
|
+
try {
|
|
3037
|
+
const result = await runOne(planned[idx], orderedSlots[idx]);
|
|
3038
|
+
if (result.status === "awaiting_approval") {
|
|
3039
|
+
awaitingApproval = true;
|
|
3040
|
+
return;
|
|
3041
|
+
}
|
|
3042
|
+
} catch (err) {
|
|
3043
|
+
workerError.err = err;
|
|
3044
|
+
return;
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
})());
|
|
3048
|
+
}
|
|
3049
|
+
await Promise.all(workers);
|
|
3050
|
+
if (workerError.err) throw workerError.err;
|
|
3051
|
+
}
|
|
3052
|
+
for (const slot of orderedSlots) {
|
|
3053
|
+
if (slot.length > 0) appended.push(...slot);
|
|
3054
|
+
}
|
|
2881
3055
|
for (const tc of skipped) {
|
|
2882
3056
|
onEvent?.({ type: "tool_call", phase: "skipped", name: tc.name, id: tc.id, args: tc.args });
|
|
2883
3057
|
const sanitizedArgs = sanitizeTracePayload(tc.args);
|
|
@@ -2913,11 +3087,23 @@ function createToolsNode(initialTools, opts) {
|
|
|
2913
3087
|
}
|
|
2914
3088
|
state.ctx = Object.keys(ctx).length > 0 ? ctx : void 0;
|
|
2915
3089
|
}
|
|
3090
|
+
const appendedHasToolResult = appended.some((m) => m.role === "tool");
|
|
3091
|
+
if (appendedHasToolResult && state.ctx?.__summarizationExhausted) {
|
|
3092
|
+
const ctx = { ...state.ctx };
|
|
3093
|
+
delete ctx.__summarizationExhausted;
|
|
3094
|
+
state.ctx = Object.keys(ctx).length > 0 ? ctx : void 0;
|
|
3095
|
+
}
|
|
2916
3096
|
return {
|
|
2917
3097
|
messages: [...state.messages, ...appended],
|
|
2918
3098
|
toolCallCount: toolCount,
|
|
2919
3099
|
toolHistory,
|
|
2920
3100
|
toolHistoryArchived,
|
|
3101
|
+
toolCache: state.toolCache,
|
|
3102
|
+
// Explicitly propagate ctx so callers using `{ ...state, ...delta }`
|
|
3103
|
+
// do not silently capture a stale ctx reference. Mutations to
|
|
3104
|
+
// __summarizationExhausted / __awaitingApproval / __structuredOutputParsed
|
|
3105
|
+
// are made on this object during execution.
|
|
3106
|
+
ctx: state.ctx,
|
|
2921
3107
|
agent: state.agent,
|
|
2922
3108
|
pendingApprovals
|
|
2923
3109
|
};
|
|
@@ -3154,7 +3340,8 @@ function resolveReflection(input, preset) {
|
|
|
3154
3340
|
maxChars: preset.maxChars,
|
|
3155
3341
|
keepLast: 3,
|
|
3156
3342
|
summarize: false,
|
|
3157
|
-
emitEvents: true
|
|
3343
|
+
emitEvents: true,
|
|
3344
|
+
everyNTurns: 1
|
|
3158
3345
|
};
|
|
3159
3346
|
}
|
|
3160
3347
|
const cfg = input ?? {};
|
|
@@ -3169,7 +3356,9 @@ function resolveReflection(input, preset) {
|
|
|
3169
3356
|
keepLast: cfg.keepLast ?? 3,
|
|
3170
3357
|
summarize: cfg.summarize ?? false,
|
|
3171
3358
|
promptTemplate: cfg.promptTemplate,
|
|
3172
|
-
emitEvents: cfg.emitEvents ?? true
|
|
3359
|
+
emitEvents: cfg.emitEvents ?? true,
|
|
3360
|
+
maxPerRun: typeof cfg.maxPerRun === "number" && cfg.maxPerRun >= 0 ? cfg.maxPerRun : void 0,
|
|
3361
|
+
everyNTurns: Math.max(1, Math.trunc(cfg.everyNTurns ?? 1))
|
|
3173
3362
|
};
|
|
3174
3363
|
}
|
|
3175
3364
|
function ensureArray(value) {
|
|
@@ -3382,6 +3571,9 @@ function resolveToolApprovalState(state, resolution) {
|
|
|
3382
3571
|
};
|
|
3383
3572
|
}
|
|
3384
3573
|
|
|
3574
|
+
// src/agent.ts
|
|
3575
|
+
init_utilTokens();
|
|
3576
|
+
|
|
3385
3577
|
// src/utils/syntheticMessages.ts
|
|
3386
3578
|
function isSyntheticSummaryMessage(message) {
|
|
3387
3579
|
if (!message) return false;
|
|
@@ -3560,6 +3752,21 @@ function getActiveSummarizationThreshold(opts) {
|
|
|
3560
3752
|
}
|
|
3561
3753
|
return summarization.summaryTriggerTokens || summarization.maxTokens || opts.limits?.maxContextTokens || 5e4;
|
|
3562
3754
|
}
|
|
3755
|
+
function shouldSignalSummarization(state, threshold) {
|
|
3756
|
+
const tokCountMessages = (state.messages || []).filter((message) => {
|
|
3757
|
+
if (isSyntheticSummaryMessage(message)) return false;
|
|
3758
|
+
if (message.role === "system" && (message.name === "context_summary" || message.name === "memory_context")) return false;
|
|
3759
|
+
return true;
|
|
3760
|
+
});
|
|
3761
|
+
const tokenCount = countMessagesTokens(tokCountMessages);
|
|
3762
|
+
if (tokenCount <= threshold) return "skip";
|
|
3763
|
+
if (state.ctx?.__summarizationExhausted) return "skip";
|
|
3764
|
+
const hasFreshSummary = (state.messages || []).some(
|
|
3765
|
+
(m) => m.role === "tool" && typeof m.content === "string" && (m.content === "SUMMARIZED" || m.content.startsWith("SUMMARIZED_TOOL_RESPONSE"))
|
|
3766
|
+
);
|
|
3767
|
+
if (hasFreshSummary && tokenCount <= threshold * 1.15) return "skip";
|
|
3768
|
+
return "trigger";
|
|
3769
|
+
}
|
|
3563
3770
|
function clearNeedsSummarization(state) {
|
|
3564
3771
|
if (!state.ctx?.__needsSummarization) {
|
|
3565
3772
|
return state;
|
|
@@ -3654,6 +3861,45 @@ function createAgent(opts) {
|
|
|
3654
3861
|
};
|
|
3655
3862
|
const maxToolCalls = mergedLimits?.maxToolCalls === void 0 ? 50 : mergedLimits?.maxToolCalls;
|
|
3656
3863
|
const iterationLimit = maxToolCalls === Infinity ? 100 : Math.max(maxToolCalls * 3 + 10, 40);
|
|
3864
|
+
const wallClockStart = Date.now();
|
|
3865
|
+
const maxWallClockMs = mergedLimits?.maxWallClockMs && mergedLimits.maxWallClockMs > 0 ? mergedLimits.maxWallClockMs : void 0;
|
|
3866
|
+
const maxTotalOutputTokens = mergedLimits?.maxTotalOutputTokens && mergedLimits.maxTotalOutputTokens > 0 ? mergedLimits.maxTotalOutputTokens : void 0;
|
|
3867
|
+
const maxCostUsd = mergedLimits?.maxCostUsd && mergedLimits.maxCostUsd > 0 ? mergedLimits.maxCostUsd : void 0;
|
|
3868
|
+
const costEstimator = opts.costEstimator;
|
|
3869
|
+
const checkBudgetBreached = () => {
|
|
3870
|
+
if (maxWallClockMs && Date.now() - wallClockStart > maxWallClockMs) {
|
|
3871
|
+
return { breached: true, reason: `maxWallClockMs (${maxWallClockMs}ms) exceeded` };
|
|
3872
|
+
}
|
|
3873
|
+
if (maxTotalOutputTokens) {
|
|
3874
|
+
const totals = state.usage?.totals;
|
|
3875
|
+
if (totals) {
|
|
3876
|
+
let outputSum = 0;
|
|
3877
|
+
for (const v of Object.values(totals)) outputSum += Number(v?.output) || 0;
|
|
3878
|
+
if (outputSum > maxTotalOutputTokens) {
|
|
3879
|
+
return { breached: true, reason: `maxTotalOutputTokens (${maxTotalOutputTokens}) exceeded` };
|
|
3880
|
+
}
|
|
3881
|
+
}
|
|
3882
|
+
}
|
|
3883
|
+
if (maxCostUsd && costEstimator) {
|
|
3884
|
+
const perRequest = state.usage?.perRequest;
|
|
3885
|
+
if (perRequest) {
|
|
3886
|
+
let cost = 0;
|
|
3887
|
+
for (const r of perRequest) {
|
|
3888
|
+
cost += costEstimator({
|
|
3889
|
+
modelName: r.modelName,
|
|
3890
|
+
inputTokens: Number(r.usage?.prompt_tokens) || 0,
|
|
3891
|
+
outputTokens: Number(r.usage?.completion_tokens) || 0,
|
|
3892
|
+
cachedInputTokens: Number(r.usage?.prompt_tokens_details?.cached_tokens) || 0,
|
|
3893
|
+
reasoningTokens: Number(r.usage?.completion_tokens_details?.reasoning_tokens) || 0
|
|
3894
|
+
}) || 0;
|
|
3895
|
+
}
|
|
3896
|
+
if (cost > maxCostUsd) {
|
|
3897
|
+
return { breached: true, reason: `maxCostUsd ($${maxCostUsd}) exceeded (actual: $${cost.toFixed(4)})` };
|
|
3898
|
+
}
|
|
3899
|
+
}
|
|
3900
|
+
}
|
|
3901
|
+
return { breached: false };
|
|
3902
|
+
};
|
|
3657
3903
|
let iterations = 0;
|
|
3658
3904
|
const onStateChange = config?.onStateChange;
|
|
3659
3905
|
const checkpointReason = config?.checkpointReason;
|
|
@@ -3702,6 +3948,13 @@ function createAgent(opts) {
|
|
|
3702
3948
|
};
|
|
3703
3949
|
while (iterations < iterationLimit) {
|
|
3704
3950
|
iterations++;
|
|
3951
|
+
const budget = checkBudgetBreached();
|
|
3952
|
+
if (budget.breached) {
|
|
3953
|
+
emit?.({ type: "metadata", limitBreached: budget.reason });
|
|
3954
|
+
const ctx = { ...state.ctx || {}, __limitBreached: budget.reason };
|
|
3955
|
+
state = { ...state, ctx };
|
|
3956
|
+
break;
|
|
3957
|
+
}
|
|
3705
3958
|
const traceSession = state.ctx?.__traceSession;
|
|
3706
3959
|
if (traceSession) {
|
|
3707
3960
|
const iterEvent = recordTraceEvent(traceSession, {
|
|
@@ -3757,22 +4010,11 @@ function createAgent(opts) {
|
|
|
3757
4010
|
}
|
|
3758
4011
|
}
|
|
3759
4012
|
if (summarizationThreshold !== void 0) {
|
|
3760
|
-
const
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
const tokenCount = countMessagesTokens(tokCountMessages);
|
|
3766
|
-
if (tokenCount > summarizationThreshold) {
|
|
3767
|
-
const summarizationExhausted = !!state.ctx?.__summarizationExhausted;
|
|
3768
|
-
const hasFreshSummary = (state.messages || []).some(
|
|
3769
|
-
(m) => m.role === "tool" && typeof m.content === "string" && (m.content === "SUMMARIZED" || m.content.startsWith("SUMMARIZED_TOOL_RESPONSE"))
|
|
3770
|
-
);
|
|
3771
|
-
if (hasFreshSummary && tokenCount <= summarizationThreshold * 1.15) ; else if (summarizationExhausted) ; else {
|
|
3772
|
-
const ctx = { ...state.ctx || {}, __needsSummarization: true };
|
|
3773
|
-
state = { ...state, ctx };
|
|
3774
|
-
break;
|
|
3775
|
-
}
|
|
4013
|
+
const verdict = shouldSignalSummarization(state, summarizationThreshold);
|
|
4014
|
+
if (verdict === "trigger") {
|
|
4015
|
+
const ctx = { ...state.ctx || {}, __needsSummarization: true };
|
|
4016
|
+
state = { ...state, ctx };
|
|
4017
|
+
break;
|
|
3776
4018
|
}
|
|
3777
4019
|
}
|
|
3778
4020
|
onProgress?.({ stage: "agent", message: "Invoking model" });
|
|
@@ -3878,7 +4120,13 @@ function createAgent(opts) {
|
|
|
3878
4120
|
if (state.ctx?.__finalizedDueToStructuredOutput) break;
|
|
3879
4121
|
if (reflectNode && resolvedReasoning?.reflection.enabled) {
|
|
3880
4122
|
const cadence = resolvedReasoning.reflection.cadence;
|
|
3881
|
-
|
|
4123
|
+
const refl = resolvedReasoning.reflection;
|
|
4124
|
+
const reflectionsSoFar = state.reflections?.length ?? 0;
|
|
4125
|
+
const lastTurn = state.reflections?.at(-1)?.turn ?? -Infinity;
|
|
4126
|
+
const currentTurn = state.toolCallCount || 0;
|
|
4127
|
+
const budgetExceeded = typeof refl.maxPerRun === "number" && reflectionsSoFar >= refl.maxPerRun;
|
|
4128
|
+
const cadenceGap = currentTurn - (Number.isFinite(lastTurn) ? lastTurn : -refl.everyNTurns) < refl.everyNTurns;
|
|
4129
|
+
if (!budgetExceeded && !cadenceGap && shouldRunReflection(cadence, state, true)) {
|
|
3882
4130
|
try {
|
|
3883
4131
|
const patch = await reflectNode(state, cadence);
|
|
3884
4132
|
if (patch && Object.keys(patch).length > 0) {
|
|
@@ -3938,7 +4186,7 @@ function createAgent(opts) {
|
|
|
3938
4186
|
}
|
|
3939
4187
|
const lastAfterLoop = state.messages[state.messages.length - 1];
|
|
3940
4188
|
if (lastAfterLoop?.role === "tool" && !pausedStage) {
|
|
3941
|
-
const isExpectedExit = state.ctx?.__awaitingApproval || state.ctx?.__cancelled || state.ctx?.__finalizedDueToStructuredOutput || state.ctx?.__finalizedDueToToolLimit || state.ctx?.__needsSummarization;
|
|
4189
|
+
const isExpectedExit = state.ctx?.__awaitingApproval || state.ctx?.__cancelled || state.ctx?.__finalizedDueToStructuredOutput || state.ctx?.__finalizedDueToToolLimit || state.ctx?.__needsSummarization || state.ctx?.__limitBreached;
|
|
3942
4190
|
if (!isExpectedExit) {
|
|
3943
4191
|
throw new Error(
|
|
3944
4192
|
"Agent loop terminated with a pending tool response but no subsequent model invocation. This usually indicates a model provider error or exhausted iteration budget."
|
|
@@ -3951,6 +4199,11 @@ function createAgent(opts) {
|
|
|
3951
4199
|
return state;
|
|
3952
4200
|
}
|
|
3953
4201
|
const invokeAgent = async (input, config) => {
|
|
4202
|
+
const userTokenCounter = opts.tokenCounter;
|
|
4203
|
+
if (userTokenCounter) {
|
|
4204
|
+
const { setTokenCounter: setTokenCounter2 } = await Promise.resolve().then(() => (init_utilTokens(), utilTokens_exports));
|
|
4205
|
+
setTokenCounter2(userTokenCounter);
|
|
4206
|
+
}
|
|
3954
4207
|
const onEvent = config?.onEvent;
|
|
3955
4208
|
const onProgress = config?.onProgress;
|
|
3956
4209
|
const onStream = config?.onStream;
|
|
@@ -4008,7 +4261,19 @@ function createAgent(opts) {
|
|
|
4008
4261
|
status: "error",
|
|
4009
4262
|
error: { message: err?.message, stack: err?.stack }
|
|
4010
4263
|
});
|
|
4264
|
+
if (userTokenCounter) {
|
|
4265
|
+
const { setTokenCounter: setTokenCounter2 } = await Promise.resolve().then(() => (init_utilTokens(), utilTokens_exports));
|
|
4266
|
+
setTokenCounter2(void 0);
|
|
4267
|
+
}
|
|
4011
4268
|
throw err;
|
|
4269
|
+
} finally {
|
|
4270
|
+
if (userTokenCounter) {
|
|
4271
|
+
try {
|
|
4272
|
+
const { setTokenCounter: setTokenCounter2 } = await Promise.resolve().then(() => (init_utilTokens(), utilTokens_exports));
|
|
4273
|
+
setTokenCounter2(void 0);
|
|
4274
|
+
} catch {
|
|
4275
|
+
}
|
|
4276
|
+
}
|
|
4012
4277
|
}
|
|
4013
4278
|
await finalizeTraceSession(traceSession, {
|
|
4014
4279
|
agentRuntime: res.agent || runtime,
|
|
@@ -4066,12 +4331,58 @@ function createAgent(opts) {
|
|
|
4066
4331
|
resolveToolApproval,
|
|
4067
4332
|
asTool: ({ toolName, description, inputDescription }) => {
|
|
4068
4333
|
const schema = z.object({ input: z.string().describe(inputDescription || "Input for delegated agent") });
|
|
4069
|
-
|
|
4334
|
+
const delegatedTool = createTool({
|
|
4070
4335
|
name: toolName,
|
|
4071
4336
|
description: description || `Delegate task to agent ${opts.name || "Agent"}`,
|
|
4072
4337
|
schema,
|
|
4073
4338
|
func: async ({ input }) => {
|
|
4074
|
-
const
|
|
4339
|
+
const ref = delegatedTool._stateRef;
|
|
4340
|
+
const parentCtx = ref.ctx || {};
|
|
4341
|
+
const parentMessages = Array.isArray(ref.messages) ? ref.messages : [];
|
|
4342
|
+
const parentRuntime = ref.parentRuntime;
|
|
4343
|
+
const resolvedSmart = parentRuntime?.smart || opts.__resolvedSmart;
|
|
4344
|
+
const delegationPolicy = resolvedSmart?.delegation || {
|
|
4345
|
+
mode: "role_based",
|
|
4346
|
+
maxDelegationDepth: 2,
|
|
4347
|
+
maxChildCalls: 4,
|
|
4348
|
+
childContextPolicy: "scoped"
|
|
4349
|
+
};
|
|
4350
|
+
const currentDepth = Number(parentCtx.__delegationDepth) || 0;
|
|
4351
|
+
if (delegationPolicy.mode === "off") {
|
|
4352
|
+
return { error: "Delegation disabled by runtime policy." };
|
|
4353
|
+
}
|
|
4354
|
+
if (currentDepth >= delegationPolicy.maxDelegationDepth) {
|
|
4355
|
+
return {
|
|
4356
|
+
error: `Delegation depth limit reached (${delegationPolicy.maxDelegationDepth}). Refusing nested call.`
|
|
4357
|
+
};
|
|
4358
|
+
}
|
|
4359
|
+
parentCtx.__delegatedCallCount = (parentCtx.__delegatedCallCount || 0) + 1;
|
|
4360
|
+
if (parentCtx.__delegatedCallCount > delegationPolicy.maxChildCalls) {
|
|
4361
|
+
return {
|
|
4362
|
+
error: `Child-call budget exhausted (${delegationPolicy.maxChildCalls}).`
|
|
4363
|
+
};
|
|
4364
|
+
}
|
|
4365
|
+
let childMessages;
|
|
4366
|
+
switch (delegationPolicy.childContextPolicy) {
|
|
4367
|
+
case "full":
|
|
4368
|
+
childMessages = [...parentMessages, { role: "user", content: input }];
|
|
4369
|
+
break;
|
|
4370
|
+
case "scoped": {
|
|
4371
|
+
const systemPrefix = parentMessages[0]?.role === "system" ? [parentMessages[0]] : [];
|
|
4372
|
+
const lastUser = [...parentMessages].reverse().find((m) => m?.role === "user");
|
|
4373
|
+
childMessages = [
|
|
4374
|
+
...systemPrefix,
|
|
4375
|
+
...lastUser ? [lastUser] : [],
|
|
4376
|
+
{ role: "user", content: input }
|
|
4377
|
+
];
|
|
4378
|
+
break;
|
|
4379
|
+
}
|
|
4380
|
+
case "minimal":
|
|
4381
|
+
default:
|
|
4382
|
+
childMessages = [{ role: "user", content: input }];
|
|
4383
|
+
}
|
|
4384
|
+
const childCtx = { __delegationDepth: currentDepth + 1 };
|
|
4385
|
+
const res = await instance.invoke({ messages: childMessages, ctx: childCtx });
|
|
4075
4386
|
return {
|
|
4076
4387
|
content: res.content,
|
|
4077
4388
|
output: res.output,
|
|
@@ -4079,6 +4390,8 @@ function createAgent(opts) {
|
|
|
4079
4390
|
};
|
|
4080
4391
|
}
|
|
4081
4392
|
});
|
|
4393
|
+
delegatedTool._stateRef = {};
|
|
4394
|
+
return delegatedTool;
|
|
4082
4395
|
},
|
|
4083
4396
|
asHandoff: ({ toolName, description, schema }) => {
|
|
4084
4397
|
const finalName = toolName || `handoff_to_${runtime.name || "agent"}`;
|
|
@@ -4218,7 +4531,11 @@ function createAgentNode(opts) {
|
|
|
4218
4531
|
};
|
|
4219
4532
|
}
|
|
4220
4533
|
|
|
4534
|
+
// src/nodes/contextSummarize.ts
|
|
4535
|
+
init_utilTokens();
|
|
4536
|
+
|
|
4221
4537
|
// src/smart/contextPolicy.ts
|
|
4538
|
+
init_utilTokens();
|
|
4222
4539
|
function collectRecentTurns(messages, lastTurnsToKeep) {
|
|
4223
4540
|
if (lastTurnsToKeep <= 0) return [];
|
|
4224
4541
|
const systemPrefix = messages.filter((message, index) => index === 0 && message.role === "system");
|
|
@@ -4521,7 +4838,7 @@ function createContextSummarizeNode(opts) {
|
|
|
4521
4838
|
const resolved = getResolvedSmartConfig(opts, state.agent);
|
|
4522
4839
|
const config = resolved.summarization;
|
|
4523
4840
|
if (!config.enable) return {};
|
|
4524
|
-
const model = opts.model;
|
|
4841
|
+
const model = state.agent?.model || opts.model;
|
|
4525
4842
|
const messages = state.messages || [];
|
|
4526
4843
|
const onEvent = state.ctx?.__onEvent;
|
|
4527
4844
|
const traceSession = state.ctx?.__traceSession;
|
|
@@ -4840,6 +5157,10 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
4840
5157
|
};
|
|
4841
5158
|
};
|
|
4842
5159
|
}
|
|
5160
|
+
|
|
5161
|
+
// src/index.ts
|
|
5162
|
+
init_utilTokens();
|
|
5163
|
+
init_utilTokens();
|
|
4843
5164
|
var TOOL_RESPONSE_RECOVERY_MARKERS = [
|
|
4844
5165
|
/ARCHIVED_TOOL_RESPONSE\s*\[/,
|
|
4845
5166
|
/STRUCTURED_TOOL_RESPONSE\s*\[/,
|
|
@@ -5158,6 +5479,7 @@ function createContextTools(stateRef, opts) {
|
|
|
5158
5479
|
}
|
|
5159
5480
|
|
|
5160
5481
|
// src/graph/decisions.ts
|
|
5482
|
+
init_utilTokens();
|
|
5161
5483
|
function needsSummarization(state, opts, summarizationEnabled) {
|
|
5162
5484
|
if (!summarizationEnabled) {
|
|
5163
5485
|
return false;
|
|
@@ -5320,12 +5642,24 @@ function createSmartAgent(opts) {
|
|
|
5320
5642
|
toolResponses: resolved.toolResponses,
|
|
5321
5643
|
useTodoList: planningEnabled
|
|
5322
5644
|
};
|
|
5323
|
-
const
|
|
5324
|
-
const
|
|
5325
|
-
const
|
|
5326
|
-
const
|
|
5327
|
-
const
|
|
5328
|
-
const
|
|
5645
|
+
const userTools = opts.tools ?? [];
|
|
5646
|
+
const factoryStateRef = { toolHistory: void 0, toolHistoryArchived: void 0, todoList: void 0, planVersion: 0, adherenceScore: 0 };
|
|
5647
|
+
const factoryContextTools = createContextTools(factoryStateRef, { planningEnabled, includeGetToolResponse: false });
|
|
5648
|
+
const factoryToolsWithoutRecovery = [...userTools, ...factoryContextTools];
|
|
5649
|
+
const soManagerFactory = opts.outputSchema ? new StructuredOutputManager(opts.outputSchema, resolveStrategy(opts.model)) : void 0;
|
|
5650
|
+
const modelCapabilities = opts.outputSchema ? getModelCapabilities(opts.model) : void 0;
|
|
5651
|
+
const responseFinalizeTool = soManagerFactory && modelCapabilities?.structuredOutput !== "native" ? soManagerFactory.getResponseTool() : void 0;
|
|
5652
|
+
const buildInvokeToolSet = () => {
|
|
5653
|
+
const ref = { toolHistory: void 0, toolHistoryArchived: void 0, todoList: void 0, planVersion: 0, adherenceScore: 0 };
|
|
5654
|
+
const ctxTools = createContextTools(ref, { planningEnabled, includeGetToolResponse: false });
|
|
5655
|
+
const recoveryTool = createGetToolResponseTool(ref);
|
|
5656
|
+
const base2 = [...userTools, ...ctxTools];
|
|
5657
|
+
if (responseFinalizeTool) base2.push(responseFinalizeTool);
|
|
5658
|
+
const without = base2;
|
|
5659
|
+
const withRec = [...without, recoveryTool];
|
|
5660
|
+
return { stateRef: ref, toolsWithoutRecovery: without, toolsWithRecovery: withRec };
|
|
5661
|
+
};
|
|
5662
|
+
const base = createAgent({ ...runtimeOpts, tools: factoryToolsWithoutRecovery });
|
|
5329
5663
|
base.__runtime.runtimeProfile = resolved.runtimeProfile;
|
|
5330
5664
|
base.__runtime.smart = resolved;
|
|
5331
5665
|
const summarizationEnabled = resolved.summarization.enable !== false;
|
|
@@ -5361,17 +5695,17 @@ function createSmartAgent(opts) {
|
|
|
5361
5695
|
const memoryFacts = await writeSummaryFactsToMemory(memoryStore, resolved, latestSummary, Math.max(1, (state.messages || []).filter((message) => message.role === "user").length));
|
|
5362
5696
|
return { ...state, memoryFacts };
|
|
5363
5697
|
}
|
|
5364
|
-
function
|
|
5365
|
-
if (!Array.isArray(
|
|
5698
|
+
function syncPlanStateWith(ref, state) {
|
|
5699
|
+
if (!Array.isArray(ref.todoList)) return state;
|
|
5366
5700
|
return {
|
|
5367
5701
|
...state,
|
|
5368
5702
|
plan: {
|
|
5369
|
-
version:
|
|
5370
|
-
steps:
|
|
5703
|
+
version: ref.planVersion || state.planVersion || 1,
|
|
5704
|
+
steps: ref.todoList,
|
|
5371
5705
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5372
|
-
adherenceScore:
|
|
5706
|
+
adherenceScore: ref.adherenceScore || 0
|
|
5373
5707
|
},
|
|
5374
|
-
planVersion:
|
|
5708
|
+
planVersion: ref.planVersion || state.planVersion || 1
|
|
5375
5709
|
};
|
|
5376
5710
|
}
|
|
5377
5711
|
function systemMessage2() {
|
|
@@ -5383,9 +5717,9 @@ function createSmartAgent(opts) {
|
|
|
5383
5717
|
);
|
|
5384
5718
|
return { role: "system", content: sys };
|
|
5385
5719
|
}
|
|
5386
|
-
function syncRuntimeTools(currentState, currentMessages) {
|
|
5720
|
+
function syncRuntimeTools(currentState, currentMessages, toolSet) {
|
|
5387
5721
|
const needsRecoveryTool = hasToolResponseRecoveryReference(currentMessages);
|
|
5388
|
-
const nextTools = needsRecoveryTool ? toolsWithRecovery : toolsWithoutRecovery;
|
|
5722
|
+
const nextTools = needsRecoveryTool ? toolSet.toolsWithRecovery : toolSet.toolsWithoutRecovery;
|
|
5389
5723
|
const currentRuntime = currentState.agent || base.__runtime;
|
|
5390
5724
|
if (currentRuntime.tools === nextTools) {
|
|
5391
5725
|
return currentState;
|
|
@@ -5404,7 +5738,7 @@ function createSmartAgent(opts) {
|
|
|
5404
5738
|
const toolCalls = Array.isArray(lastAssistant.tool_calls) ? lastAssistant.tool_calls : [];
|
|
5405
5739
|
return toolCalls.length === 0;
|
|
5406
5740
|
}
|
|
5407
|
-
async function trySummarize(currentState, currentRawMessages) {
|
|
5741
|
+
async function trySummarize(currentState, currentRawMessages, ref) {
|
|
5408
5742
|
if (!summarizer) return { state: currentState, rawMessages: currentRawMessages, compressed: false };
|
|
5409
5743
|
const delta = await summarizer(currentState);
|
|
5410
5744
|
if (!delta || Object.keys(delta).length === 0) {
|
|
@@ -5413,28 +5747,31 @@ function createSmartAgent(opts) {
|
|
|
5413
5747
|
}
|
|
5414
5748
|
const ctx = { ...currentState.ctx || {} };
|
|
5415
5749
|
delete ctx.__summarizationExhausted;
|
|
5416
|
-
const updated = await persistLatestSummary(
|
|
5750
|
+
const updated = await persistLatestSummary(syncPlanStateWith(ref, { ...currentState, ...delta, ctx }));
|
|
5417
5751
|
return { state: updated, rawMessages: [...updated.messages || currentRawMessages], compressed: true };
|
|
5418
5752
|
}
|
|
5419
5753
|
const instance = {
|
|
5420
5754
|
invoke: async (input, config) => {
|
|
5755
|
+
const toolSet = buildInvokeToolSet();
|
|
5756
|
+
const stateRef = toolSet.stateRef;
|
|
5421
5757
|
stateRef.toolHistory = input.toolHistory;
|
|
5422
5758
|
stateRef.toolHistoryArchived = input.toolHistoryArchived;
|
|
5423
5759
|
stateRef.todoList = input.plan?.steps;
|
|
5424
5760
|
stateRef.planVersion = input.planVersion || input.plan?.version || 0;
|
|
5425
5761
|
stateRef.adherenceScore = input.plan?.adherenceScore || 0;
|
|
5762
|
+
const syncPlanFromRef = (state2) => syncPlanStateWith(stateRef, state2);
|
|
5426
5763
|
const alreadyHasSystem = Array.isArray(input.messages) && input.messages[0]?.role === "system";
|
|
5427
5764
|
const seedMessages = alreadyHasSystem ? [...input.messages || []] : [systemMessage2(), ...input.messages || []];
|
|
5428
|
-
let state = syncRuntimeTools(await syncMemory({ ...input, messages: seedMessages }), seedMessages);
|
|
5765
|
+
let state = syncRuntimeTools(await syncMemory({ ...input, messages: seedMessages }), seedMessages, toolSet);
|
|
5429
5766
|
let lastResult = null;
|
|
5430
5767
|
let rawMessages = [...seedMessages];
|
|
5431
5768
|
const effectiveMaxToolCalls = config?.limits?.maxToolCalls ?? resolved.limits.maxToolCalls ?? 10;
|
|
5432
5769
|
const iterationLimit = Math.max(effectiveMaxToolCalls * 3 + 5, 30);
|
|
5433
5770
|
for (let i = 0; i < iterationLimit; i++) {
|
|
5434
|
-
state = syncRuntimeTools({ ...state, messages: rawMessages }, rawMessages);
|
|
5771
|
+
state = syncRuntimeTools({ ...state, messages: rawMessages }, rawMessages, toolSet);
|
|
5435
5772
|
const next = summarizationEnabled ? decideBefore(state) : "agent";
|
|
5436
5773
|
if (next === "contextSummarize" && summarizer) {
|
|
5437
|
-
const result = await trySummarize(state, rawMessages);
|
|
5774
|
+
const result = await trySummarize(state, rawMessages, stateRef);
|
|
5438
5775
|
state = result.state;
|
|
5439
5776
|
rawMessages = result.rawMessages;
|
|
5440
5777
|
if (result.compressed) continue;
|
|
@@ -5458,14 +5795,14 @@ function createSmartAgent(opts) {
|
|
|
5458
5795
|
if (currentPlan && !state.plan) {
|
|
5459
5796
|
state = { ...state, plan: currentPlan };
|
|
5460
5797
|
}
|
|
5461
|
-
state = syncRuntimeTools(
|
|
5798
|
+
state = syncRuntimeTools(syncPlanFromRef(await syncMemory(state)), rawMessages, toolSet);
|
|
5462
5799
|
stateRef.toolHistory = state.toolHistory;
|
|
5463
5800
|
stateRef.toolHistoryArchived = state.toolHistoryArchived;
|
|
5464
5801
|
if (state.ctx?.__needsSummarization && summarizer) {
|
|
5465
5802
|
const ctx = { ...state.ctx || {} };
|
|
5466
5803
|
delete ctx.__needsSummarization;
|
|
5467
5804
|
state = { ...state, ctx };
|
|
5468
|
-
const result = await trySummarize(state, rawMessages);
|
|
5805
|
+
const result = await trySummarize(state, rawMessages, stateRef);
|
|
5469
5806
|
state = result.state;
|
|
5470
5807
|
rawMessages = result.rawMessages;
|
|
5471
5808
|
continue;
|
|
@@ -5476,7 +5813,7 @@ function createSmartAgent(opts) {
|
|
|
5476
5813
|
if (summarizationEnabled) {
|
|
5477
5814
|
const after = decideAfter(state);
|
|
5478
5815
|
if (after === "contextSummarize" && summarizer) {
|
|
5479
|
-
const result = await trySummarize(state, rawMessages);
|
|
5816
|
+
const result = await trySummarize(state, rawMessages, stateRef);
|
|
5480
5817
|
state = result.state;
|
|
5481
5818
|
rawMessages = result.rawMessages;
|
|
5482
5819
|
if (result.compressed) continue;
|
|
@@ -5915,7 +6252,50 @@ var ProviderError = class extends Error {
|
|
|
5915
6252
|
};
|
|
5916
6253
|
|
|
5917
6254
|
// src/providers/base.ts
|
|
6255
|
+
var DEFAULT_RETRY = {
|
|
6256
|
+
maxRetries: 3,
|
|
6257
|
+
baseDelayMs: 500,
|
|
6258
|
+
maxDelayMs: 8e3
|
|
6259
|
+
};
|
|
5918
6260
|
var BaseProvider = class {
|
|
6261
|
+
constructor() {
|
|
6262
|
+
this.retryPolicy = DEFAULT_RETRY;
|
|
6263
|
+
}
|
|
6264
|
+
/**
|
|
6265
|
+
* Helper concrete providers can wrap their fetch with. Retries 429/5xx
|
|
6266
|
+
* with exponential backoff and respects Retry-After if the response
|
|
6267
|
+
* carries one.
|
|
6268
|
+
*/
|
|
6269
|
+
async doFetchWithRetry(execute) {
|
|
6270
|
+
const policy = this.retryPolicy;
|
|
6271
|
+
const maxRetries = Math.max(0, policy.maxRetries ?? DEFAULT_RETRY.maxRetries);
|
|
6272
|
+
const baseDelay = Math.max(0, policy.baseDelayMs ?? DEFAULT_RETRY.baseDelayMs);
|
|
6273
|
+
const maxDelay = Math.max(baseDelay, policy.maxDelayMs ?? DEFAULT_RETRY.maxDelayMs);
|
|
6274
|
+
let lastResp;
|
|
6275
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
6276
|
+
const res = await execute();
|
|
6277
|
+
const isRetryable = res.status === 429 || res.status >= 500 && res.status < 600;
|
|
6278
|
+
if (!isRetryable) return res;
|
|
6279
|
+
const predicate = policy.shouldRetry;
|
|
6280
|
+
if (predicate && !predicate({ status: res.status }, attempt)) return res;
|
|
6281
|
+
if (attempt === maxRetries) {
|
|
6282
|
+
lastResp = res;
|
|
6283
|
+
break;
|
|
6284
|
+
}
|
|
6285
|
+
const retryAfter = res.headers.get("retry-after");
|
|
6286
|
+
let delay = Math.min(maxDelay, baseDelay * Math.pow(2, attempt));
|
|
6287
|
+
if (retryAfter) {
|
|
6288
|
+
const asNumber = Number(retryAfter);
|
|
6289
|
+
if (!Number.isNaN(asNumber)) delay = Math.min(maxDelay, Math.max(delay, asNumber * 1e3));
|
|
6290
|
+
}
|
|
6291
|
+
try {
|
|
6292
|
+
await res.text();
|
|
6293
|
+
} catch {
|
|
6294
|
+
}
|
|
6295
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
6296
|
+
}
|
|
6297
|
+
return lastResp;
|
|
6298
|
+
}
|
|
5919
6299
|
};
|
|
5920
6300
|
|
|
5921
6301
|
// src/providers/utils/sse.ts
|
|
@@ -6042,6 +6422,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6042
6422
|
...config.defaultHeaders,
|
|
6043
6423
|
...config.organization ? { "OpenAI-Organization": config.organization } : {}
|
|
6044
6424
|
};
|
|
6425
|
+
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
6045
6426
|
}
|
|
6046
6427
|
async complete(request) {
|
|
6047
6428
|
const body = this.buildRequestBody(request, false);
|
|
@@ -6189,15 +6570,13 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6189
6570
|
}
|
|
6190
6571
|
async doFetch(body) {
|
|
6191
6572
|
const url = `${this.baseURL}/chat/completions`;
|
|
6192
|
-
const
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
body: JSON.stringify(body)
|
|
6200
|
-
});
|
|
6573
|
+
const headers = {
|
|
6574
|
+
"Content-Type": "application/json",
|
|
6575
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
6576
|
+
...this.defaultHeaders
|
|
6577
|
+
};
|
|
6578
|
+
const payload = JSON.stringify(body);
|
|
6579
|
+
const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload }));
|
|
6201
6580
|
if (!res.ok) {
|
|
6202
6581
|
const text = await res.text().catch(() => "");
|
|
6203
6582
|
throw new ProviderError(
|
|
@@ -6267,6 +6646,8 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6267
6646
|
this.defaultModel = config.defaultModel ?? "claude-sonnet-4-20250514";
|
|
6268
6647
|
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
6269
6648
|
this.anthropicVersion = config.anthropicVersion ?? "2023-06-01";
|
|
6649
|
+
this.promptCachingEnabled = config.prompt_caching?.enabled === true;
|
|
6650
|
+
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
6270
6651
|
}
|
|
6271
6652
|
async complete(request) {
|
|
6272
6653
|
const body = this.buildRequestBody(request, false);
|
|
@@ -6385,12 +6766,22 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6385
6766
|
max_tokens: request.maxTokens ?? 4096,
|
|
6386
6767
|
stream
|
|
6387
6768
|
};
|
|
6388
|
-
if (system)
|
|
6769
|
+
if (system) {
|
|
6770
|
+
if (this.promptCachingEnabled) {
|
|
6771
|
+
body.system = [{ type: "text", text: system, cache_control: { type: "ephemeral" } }];
|
|
6772
|
+
} else {
|
|
6773
|
+
body.system = system;
|
|
6774
|
+
}
|
|
6775
|
+
}
|
|
6389
6776
|
if (request.temperature != null) body.temperature = request.temperature;
|
|
6390
6777
|
if (request.topP != null) body.top_p = request.topP;
|
|
6391
6778
|
if (request.stop) body.stop_sequences = request.stop;
|
|
6392
6779
|
if (request.tools?.length) {
|
|
6393
|
-
|
|
6780
|
+
const tools = request.tools.map((t) => this.toAnthropicTool(t));
|
|
6781
|
+
if (this.promptCachingEnabled && tools.length > 0) {
|
|
6782
|
+
tools[tools.length - 1] = { ...tools[tools.length - 1], cache_control: { type: "ephemeral" } };
|
|
6783
|
+
}
|
|
6784
|
+
body.tools = tools;
|
|
6394
6785
|
}
|
|
6395
6786
|
if (request.toolChoice != null) {
|
|
6396
6787
|
if (request.toolChoice === "auto") {
|
|
@@ -6489,16 +6880,14 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6489
6880
|
}
|
|
6490
6881
|
async doFetch(body) {
|
|
6491
6882
|
const url = `${this.baseURL}/v1/messages`;
|
|
6492
|
-
const
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
body: JSON.stringify(body)
|
|
6501
|
-
});
|
|
6883
|
+
const headers = {
|
|
6884
|
+
"Content-Type": "application/json",
|
|
6885
|
+
"x-api-key": this.apiKey,
|
|
6886
|
+
"anthropic-version": this.anthropicVersion,
|
|
6887
|
+
...this.defaultHeaders
|
|
6888
|
+
};
|
|
6889
|
+
const payload = JSON.stringify(body);
|
|
6890
|
+
const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload }));
|
|
6502
6891
|
if (!res.ok) {
|
|
6503
6892
|
const text = await res.text().catch(() => "");
|
|
6504
6893
|
throw new ProviderError(
|
|
@@ -6710,6 +7099,8 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6710
7099
|
this.region = config.region;
|
|
6711
7100
|
this.defaultModel = config.defaultModel ?? "anthropic.claude-sonnet-4-20250514-v1:0";
|
|
6712
7101
|
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
7102
|
+
this.promptCachingEnabled = config.prompt_caching?.enabled === true;
|
|
7103
|
+
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
6713
7104
|
this.credentials = {
|
|
6714
7105
|
accessKeyId: config.accessKeyId ?? process.env.AWS_ACCESS_KEY_ID ?? "",
|
|
6715
7106
|
secretAccessKey: config.secretAccessKey ?? process.env.AWS_SECRET_ACCESS_KEY ?? "",
|
|
@@ -6748,7 +7139,9 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6748
7139
|
messages: messages.map((m) => this.toBedrockMessage(m))
|
|
6749
7140
|
};
|
|
6750
7141
|
if (system.length > 0) {
|
|
6751
|
-
|
|
7142
|
+
const systemBlocks = system.map((s) => ({ text: s }));
|
|
7143
|
+
if (this.promptCachingEnabled) systemBlocks.push({ cachePoint: { type: "default" } });
|
|
7144
|
+
body.system = systemBlocks;
|
|
6752
7145
|
}
|
|
6753
7146
|
const inferenceConfig = {};
|
|
6754
7147
|
if (request.maxTokens != null) inferenceConfig.maxTokens = request.maxTokens;
|
|
@@ -6757,8 +7150,12 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6757
7150
|
if (request.stop) inferenceConfig.stopSequences = request.stop;
|
|
6758
7151
|
if (Object.keys(inferenceConfig).length > 0) body.inferenceConfig = inferenceConfig;
|
|
6759
7152
|
if (request.tools?.length) {
|
|
7153
|
+
const tools = request.tools.map((t) => this.toBedrockTool(t));
|
|
7154
|
+
if (this.promptCachingEnabled && tools.length > 0) {
|
|
7155
|
+
tools.push({ cachePoint: { type: "default" } });
|
|
7156
|
+
}
|
|
6760
7157
|
body.toolConfig = {
|
|
6761
|
-
tools
|
|
7158
|
+
tools
|
|
6762
7159
|
};
|
|
6763
7160
|
if (request.toolChoice != null) {
|
|
6764
7161
|
if (request.toolChoice === "auto") {
|
|
@@ -6855,23 +7252,21 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6855
7252
|
const host = `bedrock-runtime.${this.region}.amazonaws.com`;
|
|
6856
7253
|
const url = `https://${host}/model/${encodeURIComponent(modelId)}/converse`;
|
|
6857
7254
|
const bodyStr = JSON.stringify(body);
|
|
6858
|
-
const
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
method: "POST",
|
|
6873
|
-
headers,
|
|
6874
|
-
body: bodyStr
|
|
7255
|
+
const res = await this.doFetchWithRetry(() => {
|
|
7256
|
+
const headers = signRequest({
|
|
7257
|
+
method: "POST",
|
|
7258
|
+
url,
|
|
7259
|
+
headers: {
|
|
7260
|
+
"Content-Type": "application/json",
|
|
7261
|
+
Accept: "application/json",
|
|
7262
|
+
...this.defaultHeaders
|
|
7263
|
+
},
|
|
7264
|
+
body: bodyStr,
|
|
7265
|
+
region: this.region,
|
|
7266
|
+
service: "bedrock",
|
|
7267
|
+
credentials: this.credentials
|
|
7268
|
+
});
|
|
7269
|
+
return fetch(url, { method: "POST", headers, body: bodyStr });
|
|
6875
7270
|
});
|
|
6876
7271
|
if (!res.ok) {
|
|
6877
7272
|
const text = await res.text().catch(() => "");
|
|
@@ -7746,6 +8141,6 @@ function createProvider(config) {
|
|
|
7746
8141
|
}
|
|
7747
8142
|
}
|
|
7748
8143
|
|
|
7749
|
-
export { AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, DEFAULT_PROFILE_CONFIGS, GuardrailPhase, InMemoryMemoryStore, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, ProviderError, StructuredOutputManager, ToolBasedStrategy, VertexProvider, agentVerdictRule, buildSystemPrompt, captureSnapshot, codePresenceRule, cognipeerSink, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createCodeGuardrail, createContextSummarizeNode, createContextTools, createGetToolResponseTool, createGuardrail, createJsonGuardrail, createManageTodoTool, createProvider, createRegexGuardrail, createResolverNode, createSmartAgent, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customSink, emptyUsage, evaluateGuardrails, fileSink, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getModelCapabilities, getNestedValue, getResolvedSmartConfig, hasToolResponseRecoveryReference, httpSink, isSmartModel, jsonSchemaRule, normalizeSmartAgentOptions, otlpSink, readMemoryFacts, regexRule, resolveMemoryStore, resolveStrategy, resolveToolApprovalState, restoreSnapshot, runSmartAgentEvalHarness, startStreamingSession, traceSessionToOtlp, withTools, writeSummaryFactsToMemory };
|
|
8144
|
+
export { AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, DEFAULT_PROFILE_CONFIGS, GuardrailPhase, InMemoryMemoryStore, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, ProviderError, StructuredOutputManager, ToolBasedStrategy, VertexProvider, agentVerdictRule, buildSystemPrompt, captureSnapshot, codePresenceRule, cognipeerSink, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createCodeGuardrail, createContextSummarizeNode, createContextTools, createGetToolResponseTool, createGuardrail, createJsonGuardrail, createManageTodoTool, createProvider, createRegexGuardrail, createResolverNode, createSmartAgent, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customSink, defaultTokenCounter, emptyUsage, evaluateGuardrails, fileSink, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasToolResponseRecoveryReference, httpSink, isSmartModel, jsonSchemaRule, normalizeSmartAgentOptions, otlpSink, readMemoryFacts, regexRule, resolveMemoryStore, resolveStrategy, resolveToolApprovalState, restoreSnapshot, runSmartAgentEvalHarness, setTokenCounter, startStreamingSession, traceSessionToOtlp, withTools, writeSummaryFactsToMemory };
|
|
7750
8145
|
//# sourceMappingURL=index.mjs.map
|
|
7751
8146
|
//# sourceMappingURL=index.mjs.map
|