@cognipeer/agent-sdk 0.6.3 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -3
- package/dist/index.cjs +571 -171
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +150 -5
- package/dist/index.d.ts +150 -5
- package/dist/index.mjs +569 -172
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.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) {
|
|
@@ -2229,6 +2333,7 @@ function normalizeSmartAgentOptions(opts) {
|
|
|
2229
2333
|
const summarizationOverride = typeof opts.summarization === "object" ? opts.summarization : {};
|
|
2230
2334
|
const planningMode = opts.planning?.mode ?? customProfile.planning?.mode ?? (useTodoList ? "todo" : preset.planning.mode);
|
|
2231
2335
|
const memoryStore = opts.memory?.store ?? customProfile.memory?.store;
|
|
2336
|
+
const contextToolResponsePolicy = opts.context?.toolResponsePolicy ?? customProfile.context?.toolResponsePolicy ?? preset.context.toolResponsePolicy;
|
|
2232
2337
|
return {
|
|
2233
2338
|
runtimeProfile,
|
|
2234
2339
|
baseProfile,
|
|
@@ -2251,7 +2356,7 @@ function normalizeSmartAgentOptions(opts) {
|
|
|
2251
2356
|
...customProfile.context?.budget || {},
|
|
2252
2357
|
...opts.context?.budget || {}
|
|
2253
2358
|
},
|
|
2254
|
-
toolResponsePolicy:
|
|
2359
|
+
toolResponsePolicy: contextToolResponsePolicy
|
|
2255
2360
|
},
|
|
2256
2361
|
planning: {
|
|
2257
2362
|
...preset.planning,
|
|
@@ -2274,6 +2379,7 @@ function normalizeSmartAgentOptions(opts) {
|
|
|
2274
2379
|
...preset.toolResponses,
|
|
2275
2380
|
...customProfile.toolResponses || {},
|
|
2276
2381
|
...opts.toolResponses || {},
|
|
2382
|
+
defaultPolicy: opts.toolResponses?.defaultPolicy ?? customProfile.toolResponses?.defaultPolicy ?? contextToolResponsePolicy,
|
|
2277
2383
|
toolResponseRetentionByTool: {
|
|
2278
2384
|
...preset.toolResponses.toolResponseRetentionByTool,
|
|
2279
2385
|
...customProfile.toolResponses?.toolResponseRetentionByTool || {},
|
|
@@ -2287,66 +2393,8 @@ function getResolvedSmartConfig(opts, runtime) {
|
|
|
2287
2393
|
return runtime?.smart || normalizeSmartAgentOptions(opts);
|
|
2288
2394
|
}
|
|
2289
2395
|
|
|
2290
|
-
// src/
|
|
2291
|
-
|
|
2292
|
-
if (!text) return 0;
|
|
2293
|
-
const nonAsciiCount = (text.match(/[^\x00-\x7F]/g) || []).length;
|
|
2294
|
-
const asciiCount = text.length - nonAsciiCount;
|
|
2295
|
-
return Math.ceil(asciiCount / 4 + nonAsciiCount / 1.5);
|
|
2296
|
-
}
|
|
2297
|
-
function extractMessageText(m) {
|
|
2298
|
-
if (!m) return "";
|
|
2299
|
-
const parts = [];
|
|
2300
|
-
parts.push(m.role || "");
|
|
2301
|
-
if (m.name) parts.push(m.name);
|
|
2302
|
-
if (typeof m.content === "string") {
|
|
2303
|
-
parts.push(m.content);
|
|
2304
|
-
} else if (Array.isArray(m.content)) {
|
|
2305
|
-
for (const c of m.content) {
|
|
2306
|
-
if (typeof c === "string") parts.push(c);
|
|
2307
|
-
else if (c?.text) parts.push(c.text);
|
|
2308
|
-
else if (c?.content) parts.push(c.content);
|
|
2309
|
-
else if (c?.type === "tool_use" && c?.input) {
|
|
2310
|
-
parts.push(c.name || "");
|
|
2311
|
-
parts.push(typeof c.input === "string" ? c.input : JSON.stringify(c.input));
|
|
2312
|
-
} else if (c != null && typeof c === "object") {
|
|
2313
|
-
parts.push(JSON.stringify(c));
|
|
2314
|
-
}
|
|
2315
|
-
}
|
|
2316
|
-
} else if (m.content != null && typeof m.content === "object") {
|
|
2317
|
-
parts.push(JSON.stringify(m.content));
|
|
2318
|
-
}
|
|
2319
|
-
if (Array.isArray(m.tool_calls)) {
|
|
2320
|
-
for (const tc of m.tool_calls) {
|
|
2321
|
-
if (tc?.function?.name) parts.push(tc.function.name);
|
|
2322
|
-
if (tc?.function?.arguments) {
|
|
2323
|
-
parts.push(
|
|
2324
|
-
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
2325
|
-
);
|
|
2326
|
-
}
|
|
2327
|
-
if (tc?.name && !tc?.function?.name) parts.push(tc.name);
|
|
2328
|
-
if (tc?.args && !tc?.function?.arguments) {
|
|
2329
|
-
parts.push(typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args));
|
|
2330
|
-
}
|
|
2331
|
-
}
|
|
2332
|
-
}
|
|
2333
|
-
if (Array.isArray(m.additional_kwargs?.tool_calls)) {
|
|
2334
|
-
for (const tc of m.additional_kwargs.tool_calls) {
|
|
2335
|
-
if (tc?.function?.name) parts.push(tc.function.name);
|
|
2336
|
-
if (tc?.function?.arguments) {
|
|
2337
|
-
parts.push(
|
|
2338
|
-
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
2339
|
-
);
|
|
2340
|
-
}
|
|
2341
|
-
}
|
|
2342
|
-
}
|
|
2343
|
-
return parts.join("\n");
|
|
2344
|
-
}
|
|
2345
|
-
function countMessagesTokens(messages) {
|
|
2346
|
-
if (!Array.isArray(messages) || messages.length === 0) return 0;
|
|
2347
|
-
const allText = messages.map(extractMessageText).join("\n");
|
|
2348
|
-
return countApproxTokens(allText) + messages.length * 4;
|
|
2349
|
-
}
|
|
2396
|
+
// src/smart/toolResponses.ts
|
|
2397
|
+
init_utilTokens();
|
|
2350
2398
|
|
|
2351
2399
|
// src/utils/content.ts
|
|
2352
2400
|
function contentToString(content) {
|
|
@@ -2546,6 +2594,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2546
2594
|
anyTool._stateRef.messages = state.messages;
|
|
2547
2595
|
anyTool._stateRef.ctx = state.ctx || (state.ctx = {});
|
|
2548
2596
|
anyTool._stateRef.__onEvent = onEvent;
|
|
2597
|
+
anyTool._stateRef.parentRuntime = runtime;
|
|
2549
2598
|
}
|
|
2550
2599
|
}
|
|
2551
2600
|
const last = state.messages[state.messages.length - 1];
|
|
@@ -2556,6 +2605,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2556
2605
|
const remaining = Math.max(0, limits.maxToolCalls - toolCount);
|
|
2557
2606
|
const planned = toolCalls.slice(0, remaining);
|
|
2558
2607
|
const skipped = toolCalls.slice(remaining);
|
|
2608
|
+
const orderedSlots = planned.map(() => []);
|
|
2559
2609
|
const isCancelled = () => {
|
|
2560
2610
|
if (abortSignal?.aborted) return { cancelled: true, reason: "aborted" };
|
|
2561
2611
|
if (cancellationToken && cancellationToken.isCancellationRequested) return { cancelled: true, reason: "cancelled" };
|
|
@@ -2572,7 +2622,9 @@ function createToolsNode(initialTools, opts) {
|
|
|
2572
2622
|
}
|
|
2573
2623
|
state.ctx = ctx;
|
|
2574
2624
|
};
|
|
2575
|
-
const runOne = async (tc) => {
|
|
2625
|
+
const runOne = async (tc, slot = appended) => {
|
|
2626
|
+
var _a;
|
|
2627
|
+
const push = (msg) => slot.push(msg);
|
|
2576
2628
|
const cancelState = isCancelled();
|
|
2577
2629
|
if (cancelState.cancelled) {
|
|
2578
2630
|
const ctx = state.ctx = state.ctx || {};
|
|
@@ -2583,7 +2635,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2583
2635
|
}
|
|
2584
2636
|
const tool = toolByName.get(tc.name);
|
|
2585
2637
|
if (!tool) {
|
|
2586
|
-
|
|
2638
|
+
push({ role: "tool", content: `Tool not found: ${tc.name}`, tool_call_id: tc.id || `${tc.name}_unknown`, name: tc.name });
|
|
2587
2639
|
onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args: tc.args, error: { message: "Tool not found" } });
|
|
2588
2640
|
toolCount += 1;
|
|
2589
2641
|
return { status: "error" };
|
|
@@ -2599,7 +2651,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2599
2651
|
const validatedArgs = validateToolArgs(tool, args);
|
|
2600
2652
|
if (!validatedArgs.ok && resolved.toolResponses.schemaValidation === "strict") {
|
|
2601
2653
|
const errorMessage = `Tool argument validation failed for ${tc.name}: ${validatedArgs.message}`;
|
|
2602
|
-
|
|
2654
|
+
push({ role: "tool", content: errorMessage, tool_call_id: toolCallId, name: tc.name });
|
|
2603
2655
|
markToolFailure(errorMessage, tc.name, toolCallId);
|
|
2604
2656
|
onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args, error: { message: errorMessage } });
|
|
2605
2657
|
toolCount += 1;
|
|
@@ -2621,7 +2673,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2621
2673
|
const currentExecutions = countSuccessfulToolExecutions(toolHistory, toolName);
|
|
2622
2674
|
if (currentExecutions >= maxExecutionsPerRun) {
|
|
2623
2675
|
const limitMessage = `Skipped tool due to per-tool execution limit: ${toolName} (${maxExecutionsPerRun}/run)`;
|
|
2624
|
-
|
|
2676
|
+
push({ role: "tool", content: limitMessage, tool_call_id: toolCallId, name: tc.name });
|
|
2625
2677
|
onEvent?.({ type: "tool_call", phase: "skipped", name: toolName, id: tc.id, args });
|
|
2626
2678
|
recordTraceEvent(traceSession, {
|
|
2627
2679
|
type: "tool_call",
|
|
@@ -2681,7 +2733,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2681
2733
|
}
|
|
2682
2734
|
if (approvalEntry.status === "rejected") {
|
|
2683
2735
|
const rejectionMessage = approvalEntry.comment || "Tool call rejected by reviewer.";
|
|
2684
|
-
|
|
2736
|
+
push({ role: "tool", content: `Tool call rejected: ${rejectionMessage}`, tool_call_id: toolCallId, name: tc.name });
|
|
2685
2737
|
approvalEntry.metadata = { ...approvalEntry.metadata || {}, resolution: "rejected" };
|
|
2686
2738
|
approvalEntry.status = "executed";
|
|
2687
2739
|
approvalEntry.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2699,23 +2751,102 @@ function createToolsNode(initialTools, opts) {
|
|
|
2699
2751
|
const start = Date.now();
|
|
2700
2752
|
const sanitizedArgs = sanitizeTracePayload(args);
|
|
2701
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
|
+
}
|
|
2702
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
|
+
}
|
|
2703
2811
|
onEvent?.({ type: "tool_call", phase: "start", name: toolName, id: tc.id, args });
|
|
2704
2812
|
onProgress?.({ stage: "tools", message: `Running tool ${tc.name}` });
|
|
2705
2813
|
const anyTool = tool;
|
|
2706
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
|
+
};
|
|
2707
2823
|
let output;
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
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
|
+
}
|
|
2714
2845
|
const durationMs = Date.now() - start;
|
|
2715
2846
|
const executionId = nanoid();
|
|
2716
2847
|
if (output && typeof output === "object" && output.__handoff && output.__handoff.runtime) {
|
|
2717
2848
|
toolHistory.push({ executionId, toolName, args, output: "handoff:ok", rawOutput: output, timestamp: (/* @__PURE__ */ new Date()).toISOString(), tool_call_id: tc.id, status: "handoff" });
|
|
2718
|
-
|
|
2849
|
+
push({ role: "tool", content: "ok", tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2719
2850
|
state.agent = output.__handoff.runtime;
|
|
2720
2851
|
onEvent?.({ type: "handoff", from: runtime.name, to: state.agent?.name, toolName });
|
|
2721
2852
|
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: "handoff", durationMs });
|
|
@@ -2767,7 +2898,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2767
2898
|
archiveId: void 0,
|
|
2768
2899
|
status: "success"
|
|
2769
2900
|
});
|
|
2770
|
-
|
|
2901
|
+
push({ role: "tool", content: responsePolicy.content, tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2771
2902
|
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: output, durationMs });
|
|
2772
2903
|
onProgress?.({ stage: "tools", message: `Tool ${tc.name} completed`, detail: { durationMs } });
|
|
2773
2904
|
if (needsApproval && approvalEntry) {
|
|
@@ -2823,7 +2954,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
2823
2954
|
const executionId = nanoid();
|
|
2824
2955
|
const message = error?.message || String(error);
|
|
2825
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" });
|
|
2826
|
-
|
|
2957
|
+
push({ role: "tool", content: `Error executing tool: ${message}`, tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
2827
2958
|
markToolFailure(message, toolName, toolCallId);
|
|
2828
2959
|
onEvent?.({ type: "tool_call", phase: "error", name: toolName, id: tc.id, args, error: { message } });
|
|
2829
2960
|
onProgress?.({ stage: "tools", message: `Tool ${tc.name} failed`, detail: { error: message } });
|
|
@@ -2860,22 +2991,67 @@ function createToolsNode(initialTools, opts) {
|
|
|
2860
2991
|
return { status: "error", approval: approvalEntry };
|
|
2861
2992
|
}
|
|
2862
2993
|
};
|
|
2863
|
-
|
|
2864
|
-
|
|
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 = () => {
|
|
2865
3003
|
const cancelState = isCancelled();
|
|
2866
3004
|
if (cancelState.cancelled) {
|
|
2867
3005
|
const ctx = state.ctx = state.ctx || {};
|
|
2868
3006
|
ctx.__cancelled = { stage: "tools", reason: cancelState.reason, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
2869
3007
|
onEvent?.({ type: "cancelled", stage: "tools", reason: cancelState.reason });
|
|
2870
3008
|
onProgress?.({ stage: "tools", message: "Cancelled", detail: { reason: cancelState.reason } });
|
|
2871
|
-
|
|
3009
|
+
shouldStop = true;
|
|
3010
|
+
return true;
|
|
2872
3011
|
}
|
|
2873
|
-
|
|
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]);
|
|
2874
3018
|
if (result.status === "awaiting_approval") {
|
|
2875
3019
|
awaitingApproval = true;
|
|
2876
3020
|
break;
|
|
2877
3021
|
}
|
|
2878
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
|
+
}
|
|
2879
3055
|
for (const tc of skipped) {
|
|
2880
3056
|
onEvent?.({ type: "tool_call", phase: "skipped", name: tc.name, id: tc.id, args: tc.args });
|
|
2881
3057
|
const sanitizedArgs = sanitizeTracePayload(tc.args);
|
|
@@ -2911,11 +3087,23 @@ function createToolsNode(initialTools, opts) {
|
|
|
2911
3087
|
}
|
|
2912
3088
|
state.ctx = Object.keys(ctx).length > 0 ? ctx : void 0;
|
|
2913
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
|
+
}
|
|
2914
3096
|
return {
|
|
2915
3097
|
messages: [...state.messages, ...appended],
|
|
2916
3098
|
toolCallCount: toolCount,
|
|
2917
3099
|
toolHistory,
|
|
2918
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,
|
|
2919
3107
|
agent: state.agent,
|
|
2920
3108
|
pendingApprovals
|
|
2921
3109
|
};
|
|
@@ -3152,7 +3340,8 @@ function resolveReflection(input, preset) {
|
|
|
3152
3340
|
maxChars: preset.maxChars,
|
|
3153
3341
|
keepLast: 3,
|
|
3154
3342
|
summarize: false,
|
|
3155
|
-
emitEvents: true
|
|
3343
|
+
emitEvents: true,
|
|
3344
|
+
everyNTurns: 1
|
|
3156
3345
|
};
|
|
3157
3346
|
}
|
|
3158
3347
|
const cfg = input ?? {};
|
|
@@ -3167,7 +3356,9 @@ function resolveReflection(input, preset) {
|
|
|
3167
3356
|
keepLast: cfg.keepLast ?? 3,
|
|
3168
3357
|
summarize: cfg.summarize ?? false,
|
|
3169
3358
|
promptTemplate: cfg.promptTemplate,
|
|
3170
|
-
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))
|
|
3171
3362
|
};
|
|
3172
3363
|
}
|
|
3173
3364
|
function ensureArray(value) {
|
|
@@ -3380,6 +3571,9 @@ function resolveToolApprovalState(state, resolution) {
|
|
|
3380
3571
|
};
|
|
3381
3572
|
}
|
|
3382
3573
|
|
|
3574
|
+
// src/agent.ts
|
|
3575
|
+
init_utilTokens();
|
|
3576
|
+
|
|
3383
3577
|
// src/utils/syntheticMessages.ts
|
|
3384
3578
|
function isSyntheticSummaryMessage(message) {
|
|
3385
3579
|
if (!message) return false;
|
|
@@ -3558,6 +3752,21 @@ function getActiveSummarizationThreshold(opts) {
|
|
|
3558
3752
|
}
|
|
3559
3753
|
return summarization.summaryTriggerTokens || summarization.maxTokens || opts.limits?.maxContextTokens || 5e4;
|
|
3560
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
|
+
}
|
|
3561
3770
|
function clearNeedsSummarization(state) {
|
|
3562
3771
|
if (!state.ctx?.__needsSummarization) {
|
|
3563
3772
|
return state;
|
|
@@ -3652,6 +3861,45 @@ function createAgent(opts) {
|
|
|
3652
3861
|
};
|
|
3653
3862
|
const maxToolCalls = mergedLimits?.maxToolCalls === void 0 ? 50 : mergedLimits?.maxToolCalls;
|
|
3654
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
|
+
};
|
|
3655
3903
|
let iterations = 0;
|
|
3656
3904
|
const onStateChange = config?.onStateChange;
|
|
3657
3905
|
const checkpointReason = config?.checkpointReason;
|
|
@@ -3700,6 +3948,13 @@ function createAgent(opts) {
|
|
|
3700
3948
|
};
|
|
3701
3949
|
while (iterations < iterationLimit) {
|
|
3702
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
|
+
}
|
|
3703
3958
|
const traceSession = state.ctx?.__traceSession;
|
|
3704
3959
|
if (traceSession) {
|
|
3705
3960
|
const iterEvent = recordTraceEvent(traceSession, {
|
|
@@ -3755,22 +4010,11 @@ function createAgent(opts) {
|
|
|
3755
4010
|
}
|
|
3756
4011
|
}
|
|
3757
4012
|
if (summarizationThreshold !== void 0) {
|
|
3758
|
-
const
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
const tokenCount = countMessagesTokens(tokCountMessages);
|
|
3764
|
-
if (tokenCount > summarizationThreshold) {
|
|
3765
|
-
const summarizationExhausted = !!state.ctx?.__summarizationExhausted;
|
|
3766
|
-
const hasFreshSummary = (state.messages || []).some(
|
|
3767
|
-
(m) => m.role === "tool" && typeof m.content === "string" && (m.content === "SUMMARIZED" || m.content.startsWith("SUMMARIZED_TOOL_RESPONSE"))
|
|
3768
|
-
);
|
|
3769
|
-
if (hasFreshSummary && tokenCount <= summarizationThreshold * 1.15) ; else if (summarizationExhausted) ; else {
|
|
3770
|
-
const ctx = { ...state.ctx || {}, __needsSummarization: true };
|
|
3771
|
-
state = { ...state, ctx };
|
|
3772
|
-
break;
|
|
3773
|
-
}
|
|
4013
|
+
const verdict = shouldSignalSummarization(state, summarizationThreshold);
|
|
4014
|
+
if (verdict === "trigger") {
|
|
4015
|
+
const ctx = { ...state.ctx || {}, __needsSummarization: true };
|
|
4016
|
+
state = { ...state, ctx };
|
|
4017
|
+
break;
|
|
3774
4018
|
}
|
|
3775
4019
|
}
|
|
3776
4020
|
onProgress?.({ stage: "agent", message: "Invoking model" });
|
|
@@ -3876,7 +4120,13 @@ function createAgent(opts) {
|
|
|
3876
4120
|
if (state.ctx?.__finalizedDueToStructuredOutput) break;
|
|
3877
4121
|
if (reflectNode && resolvedReasoning?.reflection.enabled) {
|
|
3878
4122
|
const cadence = resolvedReasoning.reflection.cadence;
|
|
3879
|
-
|
|
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)) {
|
|
3880
4130
|
try {
|
|
3881
4131
|
const patch = await reflectNode(state, cadence);
|
|
3882
4132
|
if (patch && Object.keys(patch).length > 0) {
|
|
@@ -3936,7 +4186,7 @@ function createAgent(opts) {
|
|
|
3936
4186
|
}
|
|
3937
4187
|
const lastAfterLoop = state.messages[state.messages.length - 1];
|
|
3938
4188
|
if (lastAfterLoop?.role === "tool" && !pausedStage) {
|
|
3939
|
-
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;
|
|
3940
4190
|
if (!isExpectedExit) {
|
|
3941
4191
|
throw new Error(
|
|
3942
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."
|
|
@@ -3949,6 +4199,11 @@ function createAgent(opts) {
|
|
|
3949
4199
|
return state;
|
|
3950
4200
|
}
|
|
3951
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
|
+
}
|
|
3952
4207
|
const onEvent = config?.onEvent;
|
|
3953
4208
|
const onProgress = config?.onProgress;
|
|
3954
4209
|
const onStream = config?.onStream;
|
|
@@ -4006,7 +4261,19 @@ function createAgent(opts) {
|
|
|
4006
4261
|
status: "error",
|
|
4007
4262
|
error: { message: err?.message, stack: err?.stack }
|
|
4008
4263
|
});
|
|
4264
|
+
if (userTokenCounter) {
|
|
4265
|
+
const { setTokenCounter: setTokenCounter2 } = await Promise.resolve().then(() => (init_utilTokens(), utilTokens_exports));
|
|
4266
|
+
setTokenCounter2(void 0);
|
|
4267
|
+
}
|
|
4009
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
|
+
}
|
|
4010
4277
|
}
|
|
4011
4278
|
await finalizeTraceSession(traceSession, {
|
|
4012
4279
|
agentRuntime: res.agent || runtime,
|
|
@@ -4064,12 +4331,58 @@ function createAgent(opts) {
|
|
|
4064
4331
|
resolveToolApproval,
|
|
4065
4332
|
asTool: ({ toolName, description, inputDescription }) => {
|
|
4066
4333
|
const schema = z.object({ input: z.string().describe(inputDescription || "Input for delegated agent") });
|
|
4067
|
-
|
|
4334
|
+
const delegatedTool = createTool({
|
|
4068
4335
|
name: toolName,
|
|
4069
4336
|
description: description || `Delegate task to agent ${opts.name || "Agent"}`,
|
|
4070
4337
|
schema,
|
|
4071
4338
|
func: async ({ input }) => {
|
|
4072
|
-
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 });
|
|
4073
4386
|
return {
|
|
4074
4387
|
content: res.content,
|
|
4075
4388
|
output: res.output,
|
|
@@ -4077,6 +4390,8 @@ function createAgent(opts) {
|
|
|
4077
4390
|
};
|
|
4078
4391
|
}
|
|
4079
4392
|
});
|
|
4393
|
+
delegatedTool._stateRef = {};
|
|
4394
|
+
return delegatedTool;
|
|
4080
4395
|
},
|
|
4081
4396
|
asHandoff: ({ toolName, description, schema }) => {
|
|
4082
4397
|
const finalName = toolName || `handoff_to_${runtime.name || "agent"}`;
|
|
@@ -4216,7 +4531,11 @@ function createAgentNode(opts) {
|
|
|
4216
4531
|
};
|
|
4217
4532
|
}
|
|
4218
4533
|
|
|
4534
|
+
// src/nodes/contextSummarize.ts
|
|
4535
|
+
init_utilTokens();
|
|
4536
|
+
|
|
4219
4537
|
// src/smart/contextPolicy.ts
|
|
4538
|
+
init_utilTokens();
|
|
4220
4539
|
function collectRecentTurns(messages, lastTurnsToKeep) {
|
|
4221
4540
|
if (lastTurnsToKeep <= 0) return [];
|
|
4222
4541
|
const systemPrefix = messages.filter((message, index) => index === 0 && message.role === "system");
|
|
@@ -4519,7 +4838,7 @@ function createContextSummarizeNode(opts) {
|
|
|
4519
4838
|
const resolved = getResolvedSmartConfig(opts, state.agent);
|
|
4520
4839
|
const config = resolved.summarization;
|
|
4521
4840
|
if (!config.enable) return {};
|
|
4522
|
-
const model = opts.model;
|
|
4841
|
+
const model = state.agent?.model || opts.model;
|
|
4523
4842
|
const messages = state.messages || [];
|
|
4524
4843
|
const onEvent = state.ctx?.__onEvent;
|
|
4525
4844
|
const traceSession = state.ctx?.__traceSession;
|
|
@@ -4838,6 +5157,10 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
4838
5157
|
};
|
|
4839
5158
|
};
|
|
4840
5159
|
}
|
|
5160
|
+
|
|
5161
|
+
// src/index.ts
|
|
5162
|
+
init_utilTokens();
|
|
5163
|
+
init_utilTokens();
|
|
4841
5164
|
var TOOL_RESPONSE_RECOVERY_MARKERS = [
|
|
4842
5165
|
/ARCHIVED_TOOL_RESPONSE\s*\[/,
|
|
4843
5166
|
/STRUCTURED_TOOL_RESPONSE\s*\[/,
|
|
@@ -5156,6 +5479,7 @@ function createContextTools(stateRef, opts) {
|
|
|
5156
5479
|
}
|
|
5157
5480
|
|
|
5158
5481
|
// src/graph/decisions.ts
|
|
5482
|
+
init_utilTokens();
|
|
5159
5483
|
function needsSummarization(state, opts, summarizationEnabled) {
|
|
5160
5484
|
if (!summarizationEnabled) {
|
|
5161
5485
|
return false;
|
|
@@ -5318,12 +5642,24 @@ function createSmartAgent(opts) {
|
|
|
5318
5642
|
toolResponses: resolved.toolResponses,
|
|
5319
5643
|
useTodoList: planningEnabled
|
|
5320
5644
|
};
|
|
5321
|
-
const
|
|
5322
|
-
const
|
|
5323
|
-
const
|
|
5324
|
-
const
|
|
5325
|
-
const
|
|
5326
|
-
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 });
|
|
5327
5663
|
base.__runtime.runtimeProfile = resolved.runtimeProfile;
|
|
5328
5664
|
base.__runtime.smart = resolved;
|
|
5329
5665
|
const summarizationEnabled = resolved.summarization.enable !== false;
|
|
@@ -5359,17 +5695,17 @@ function createSmartAgent(opts) {
|
|
|
5359
5695
|
const memoryFacts = await writeSummaryFactsToMemory(memoryStore, resolved, latestSummary, Math.max(1, (state.messages || []).filter((message) => message.role === "user").length));
|
|
5360
5696
|
return { ...state, memoryFacts };
|
|
5361
5697
|
}
|
|
5362
|
-
function
|
|
5363
|
-
if (!Array.isArray(
|
|
5698
|
+
function syncPlanStateWith(ref, state) {
|
|
5699
|
+
if (!Array.isArray(ref.todoList)) return state;
|
|
5364
5700
|
return {
|
|
5365
5701
|
...state,
|
|
5366
5702
|
plan: {
|
|
5367
|
-
version:
|
|
5368
|
-
steps:
|
|
5703
|
+
version: ref.planVersion || state.planVersion || 1,
|
|
5704
|
+
steps: ref.todoList,
|
|
5369
5705
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5370
|
-
adherenceScore:
|
|
5706
|
+
adherenceScore: ref.adherenceScore || 0
|
|
5371
5707
|
},
|
|
5372
|
-
planVersion:
|
|
5708
|
+
planVersion: ref.planVersion || state.planVersion || 1
|
|
5373
5709
|
};
|
|
5374
5710
|
}
|
|
5375
5711
|
function systemMessage2() {
|
|
@@ -5381,9 +5717,9 @@ function createSmartAgent(opts) {
|
|
|
5381
5717
|
);
|
|
5382
5718
|
return { role: "system", content: sys };
|
|
5383
5719
|
}
|
|
5384
|
-
function syncRuntimeTools(currentState, currentMessages) {
|
|
5720
|
+
function syncRuntimeTools(currentState, currentMessages, toolSet) {
|
|
5385
5721
|
const needsRecoveryTool = hasToolResponseRecoveryReference(currentMessages);
|
|
5386
|
-
const nextTools = needsRecoveryTool ? toolsWithRecovery : toolsWithoutRecovery;
|
|
5722
|
+
const nextTools = needsRecoveryTool ? toolSet.toolsWithRecovery : toolSet.toolsWithoutRecovery;
|
|
5387
5723
|
const currentRuntime = currentState.agent || base.__runtime;
|
|
5388
5724
|
if (currentRuntime.tools === nextTools) {
|
|
5389
5725
|
return currentState;
|
|
@@ -5402,7 +5738,7 @@ function createSmartAgent(opts) {
|
|
|
5402
5738
|
const toolCalls = Array.isArray(lastAssistant.tool_calls) ? lastAssistant.tool_calls : [];
|
|
5403
5739
|
return toolCalls.length === 0;
|
|
5404
5740
|
}
|
|
5405
|
-
async function trySummarize(currentState, currentRawMessages) {
|
|
5741
|
+
async function trySummarize(currentState, currentRawMessages, ref) {
|
|
5406
5742
|
if (!summarizer) return { state: currentState, rawMessages: currentRawMessages, compressed: false };
|
|
5407
5743
|
const delta = await summarizer(currentState);
|
|
5408
5744
|
if (!delta || Object.keys(delta).length === 0) {
|
|
@@ -5411,28 +5747,31 @@ function createSmartAgent(opts) {
|
|
|
5411
5747
|
}
|
|
5412
5748
|
const ctx = { ...currentState.ctx || {} };
|
|
5413
5749
|
delete ctx.__summarizationExhausted;
|
|
5414
|
-
const updated = await persistLatestSummary(
|
|
5750
|
+
const updated = await persistLatestSummary(syncPlanStateWith(ref, { ...currentState, ...delta, ctx }));
|
|
5415
5751
|
return { state: updated, rawMessages: [...updated.messages || currentRawMessages], compressed: true };
|
|
5416
5752
|
}
|
|
5417
5753
|
const instance = {
|
|
5418
5754
|
invoke: async (input, config) => {
|
|
5755
|
+
const toolSet = buildInvokeToolSet();
|
|
5756
|
+
const stateRef = toolSet.stateRef;
|
|
5419
5757
|
stateRef.toolHistory = input.toolHistory;
|
|
5420
5758
|
stateRef.toolHistoryArchived = input.toolHistoryArchived;
|
|
5421
5759
|
stateRef.todoList = input.plan?.steps;
|
|
5422
5760
|
stateRef.planVersion = input.planVersion || input.plan?.version || 0;
|
|
5423
5761
|
stateRef.adherenceScore = input.plan?.adherenceScore || 0;
|
|
5762
|
+
const syncPlanFromRef = (state2) => syncPlanStateWith(stateRef, state2);
|
|
5424
5763
|
const alreadyHasSystem = Array.isArray(input.messages) && input.messages[0]?.role === "system";
|
|
5425
5764
|
const seedMessages = alreadyHasSystem ? [...input.messages || []] : [systemMessage2(), ...input.messages || []];
|
|
5426
|
-
let state = syncRuntimeTools(await syncMemory({ ...input, messages: seedMessages }), seedMessages);
|
|
5765
|
+
let state = syncRuntimeTools(await syncMemory({ ...input, messages: seedMessages }), seedMessages, toolSet);
|
|
5427
5766
|
let lastResult = null;
|
|
5428
5767
|
let rawMessages = [...seedMessages];
|
|
5429
5768
|
const effectiveMaxToolCalls = config?.limits?.maxToolCalls ?? resolved.limits.maxToolCalls ?? 10;
|
|
5430
5769
|
const iterationLimit = Math.max(effectiveMaxToolCalls * 3 + 5, 30);
|
|
5431
5770
|
for (let i = 0; i < iterationLimit; i++) {
|
|
5432
|
-
state = syncRuntimeTools({ ...state, messages: rawMessages }, rawMessages);
|
|
5771
|
+
state = syncRuntimeTools({ ...state, messages: rawMessages }, rawMessages, toolSet);
|
|
5433
5772
|
const next = summarizationEnabled ? decideBefore(state) : "agent";
|
|
5434
5773
|
if (next === "contextSummarize" && summarizer) {
|
|
5435
|
-
const result = await trySummarize(state, rawMessages);
|
|
5774
|
+
const result = await trySummarize(state, rawMessages, stateRef);
|
|
5436
5775
|
state = result.state;
|
|
5437
5776
|
rawMessages = result.rawMessages;
|
|
5438
5777
|
if (result.compressed) continue;
|
|
@@ -5456,14 +5795,14 @@ function createSmartAgent(opts) {
|
|
|
5456
5795
|
if (currentPlan && !state.plan) {
|
|
5457
5796
|
state = { ...state, plan: currentPlan };
|
|
5458
5797
|
}
|
|
5459
|
-
state = syncRuntimeTools(
|
|
5798
|
+
state = syncRuntimeTools(syncPlanFromRef(await syncMemory(state)), rawMessages, toolSet);
|
|
5460
5799
|
stateRef.toolHistory = state.toolHistory;
|
|
5461
5800
|
stateRef.toolHistoryArchived = state.toolHistoryArchived;
|
|
5462
5801
|
if (state.ctx?.__needsSummarization && summarizer) {
|
|
5463
5802
|
const ctx = { ...state.ctx || {} };
|
|
5464
5803
|
delete ctx.__needsSummarization;
|
|
5465
5804
|
state = { ...state, ctx };
|
|
5466
|
-
const result = await trySummarize(state, rawMessages);
|
|
5805
|
+
const result = await trySummarize(state, rawMessages, stateRef);
|
|
5467
5806
|
state = result.state;
|
|
5468
5807
|
rawMessages = result.rawMessages;
|
|
5469
5808
|
continue;
|
|
@@ -5474,7 +5813,7 @@ function createSmartAgent(opts) {
|
|
|
5474
5813
|
if (summarizationEnabled) {
|
|
5475
5814
|
const after = decideAfter(state);
|
|
5476
5815
|
if (after === "contextSummarize" && summarizer) {
|
|
5477
|
-
const result = await trySummarize(state, rawMessages);
|
|
5816
|
+
const result = await trySummarize(state, rawMessages, stateRef);
|
|
5478
5817
|
state = result.state;
|
|
5479
5818
|
rawMessages = result.rawMessages;
|
|
5480
5819
|
if (result.compressed) continue;
|
|
@@ -5913,7 +6252,50 @@ var ProviderError = class extends Error {
|
|
|
5913
6252
|
};
|
|
5914
6253
|
|
|
5915
6254
|
// src/providers/base.ts
|
|
6255
|
+
var DEFAULT_RETRY = {
|
|
6256
|
+
maxRetries: 3,
|
|
6257
|
+
baseDelayMs: 500,
|
|
6258
|
+
maxDelayMs: 8e3
|
|
6259
|
+
};
|
|
5916
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
|
+
}
|
|
5917
6299
|
};
|
|
5918
6300
|
|
|
5919
6301
|
// src/providers/utils/sse.ts
|
|
@@ -6040,6 +6422,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6040
6422
|
...config.defaultHeaders,
|
|
6041
6423
|
...config.organization ? { "OpenAI-Organization": config.organization } : {}
|
|
6042
6424
|
};
|
|
6425
|
+
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
6043
6426
|
}
|
|
6044
6427
|
async complete(request) {
|
|
6045
6428
|
const body = this.buildRequestBody(request, false);
|
|
@@ -6119,7 +6502,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6119
6502
|
if (request.tools?.length) {
|
|
6120
6503
|
body.tools = request.tools.map((t) => this.toOpenAITool(t));
|
|
6121
6504
|
}
|
|
6122
|
-
if (request.toolChoice != null) {
|
|
6505
|
+
if (request.toolChoice != null && request.tools?.length) {
|
|
6123
6506
|
if (typeof request.toolChoice === "string") {
|
|
6124
6507
|
body.tool_choice = request.toolChoice;
|
|
6125
6508
|
} else {
|
|
@@ -6187,15 +6570,13 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6187
6570
|
}
|
|
6188
6571
|
async doFetch(body) {
|
|
6189
6572
|
const url = `${this.baseURL}/chat/completions`;
|
|
6190
|
-
const
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
body: JSON.stringify(body)
|
|
6198
|
-
});
|
|
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 }));
|
|
6199
6580
|
if (!res.ok) {
|
|
6200
6581
|
const text = await res.text().catch(() => "");
|
|
6201
6582
|
throw new ProviderError(
|
|
@@ -6265,6 +6646,8 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6265
6646
|
this.defaultModel = config.defaultModel ?? "claude-sonnet-4-20250514";
|
|
6266
6647
|
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
6267
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 };
|
|
6268
6651
|
}
|
|
6269
6652
|
async complete(request) {
|
|
6270
6653
|
const body = this.buildRequestBody(request, false);
|
|
@@ -6383,12 +6766,22 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6383
6766
|
max_tokens: request.maxTokens ?? 4096,
|
|
6384
6767
|
stream
|
|
6385
6768
|
};
|
|
6386
|
-
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
|
+
}
|
|
6387
6776
|
if (request.temperature != null) body.temperature = request.temperature;
|
|
6388
6777
|
if (request.topP != null) body.top_p = request.topP;
|
|
6389
6778
|
if (request.stop) body.stop_sequences = request.stop;
|
|
6390
6779
|
if (request.tools?.length) {
|
|
6391
|
-
|
|
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;
|
|
6392
6785
|
}
|
|
6393
6786
|
if (request.toolChoice != null) {
|
|
6394
6787
|
if (request.toolChoice === "auto") {
|
|
@@ -6487,16 +6880,14 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6487
6880
|
}
|
|
6488
6881
|
async doFetch(body) {
|
|
6489
6882
|
const url = `${this.baseURL}/v1/messages`;
|
|
6490
|
-
const
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
body: JSON.stringify(body)
|
|
6499
|
-
});
|
|
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 }));
|
|
6500
6891
|
if (!res.ok) {
|
|
6501
6892
|
const text = await res.text().catch(() => "");
|
|
6502
6893
|
throw new ProviderError(
|
|
@@ -6708,6 +7099,8 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6708
7099
|
this.region = config.region;
|
|
6709
7100
|
this.defaultModel = config.defaultModel ?? "anthropic.claude-sonnet-4-20250514-v1:0";
|
|
6710
7101
|
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
7102
|
+
this.promptCachingEnabled = config.prompt_caching?.enabled === true;
|
|
7103
|
+
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
6711
7104
|
this.credentials = {
|
|
6712
7105
|
accessKeyId: config.accessKeyId ?? process.env.AWS_ACCESS_KEY_ID ?? "",
|
|
6713
7106
|
secretAccessKey: config.secretAccessKey ?? process.env.AWS_SECRET_ACCESS_KEY ?? "",
|
|
@@ -6746,7 +7139,9 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6746
7139
|
messages: messages.map((m) => this.toBedrockMessage(m))
|
|
6747
7140
|
};
|
|
6748
7141
|
if (system.length > 0) {
|
|
6749
|
-
|
|
7142
|
+
const systemBlocks = system.map((s) => ({ text: s }));
|
|
7143
|
+
if (this.promptCachingEnabled) systemBlocks.push({ cachePoint: { type: "default" } });
|
|
7144
|
+
body.system = systemBlocks;
|
|
6750
7145
|
}
|
|
6751
7146
|
const inferenceConfig = {};
|
|
6752
7147
|
if (request.maxTokens != null) inferenceConfig.maxTokens = request.maxTokens;
|
|
@@ -6755,8 +7150,12 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6755
7150
|
if (request.stop) inferenceConfig.stopSequences = request.stop;
|
|
6756
7151
|
if (Object.keys(inferenceConfig).length > 0) body.inferenceConfig = inferenceConfig;
|
|
6757
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
|
+
}
|
|
6758
7157
|
body.toolConfig = {
|
|
6759
|
-
tools
|
|
7158
|
+
tools
|
|
6760
7159
|
};
|
|
6761
7160
|
if (request.toolChoice != null) {
|
|
6762
7161
|
if (request.toolChoice === "auto") {
|
|
@@ -6853,23 +7252,21 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
6853
7252
|
const host = `bedrock-runtime.${this.region}.amazonaws.com`;
|
|
6854
7253
|
const url = `https://${host}/model/${encodeURIComponent(modelId)}/converse`;
|
|
6855
7254
|
const bodyStr = JSON.stringify(body);
|
|
6856
|
-
const
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
method: "POST",
|
|
6871
|
-
headers,
|
|
6872
|
-
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 });
|
|
6873
7270
|
});
|
|
6874
7271
|
if (!res.ok) {
|
|
6875
7272
|
const text = await res.text().catch(() => "");
|
|
@@ -7400,7 +7797,7 @@ function fromNativeProvider(provider, options) {
|
|
|
7400
7797
|
const reasoningCfg = reasoningOverride ?? opts?.reasoning;
|
|
7401
7798
|
if (reasoningCfg) req.reasoning = reasoningCfg;
|
|
7402
7799
|
const tc = invokeOptions?.tool_choice ?? invokeOptions?.toolChoice;
|
|
7403
|
-
if (tc) {
|
|
7800
|
+
if (tc && tools?.length) {
|
|
7404
7801
|
req.toolChoice = tc;
|
|
7405
7802
|
}
|
|
7406
7803
|
const rf = invokeOptions?.response_format;
|
|
@@ -7744,6 +8141,6 @@ function createProvider(config) {
|
|
|
7744
8141
|
}
|
|
7745
8142
|
}
|
|
7746
8143
|
|
|
7747
|
-
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 };
|
|
7748
8145
|
//# sourceMappingURL=index.mjs.map
|
|
7749
8146
|
//# sourceMappingURL=index.mjs.map
|