@trigger.dev/sdk 4.5.0-rc.3 → 4.5.0-rc.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/dist/commonjs/imports/ai-runtime-cjs.cjs.map +1 -0
- package/dist/commonjs/imports/ai-runtime.d.ts +1 -0
- package/dist/commonjs/imports/ai-runtime.js +27 -0
- package/dist/commonjs/v3/ai-shared.d.ts +16 -1
- package/dist/commonjs/v3/ai-shared.js.map +1 -1
- package/dist/commonjs/v3/ai.d.ts +81 -8
- package/dist/commonjs/v3/ai.js +138 -34
- package/dist/commonjs/v3/ai.js.map +1 -1
- package/dist/commonjs/v3/aiAutoTelemetry.d.ts +2 -0
- package/dist/commonjs/v3/aiAutoTelemetry.js +81 -0
- package/dist/commonjs/v3/aiAutoTelemetry.js.map +1 -0
- package/dist/commonjs/v3/chat-client.js +5 -3
- package/dist/commonjs/v3/chat-client.js.map +1 -1
- package/dist/commonjs/v3/chat-server.d.ts +29 -6
- package/dist/commonjs/v3/chat-server.js +6 -4
- package/dist/commonjs/v3/chat-server.js.map +1 -1
- package/dist/commonjs/v3/chat.d.ts +11 -0
- package/dist/commonjs/v3/chat.js +61 -1
- package/dist/commonjs/v3/chat.js.map +1 -1
- package/dist/commonjs/v3/shared.js +17 -9
- package/dist/commonjs/v3/shared.js.map +1 -1
- package/dist/commonjs/version.js +1 -1
- package/dist/esm/imports/ai-runtime.d.ts +2 -0
- package/dist/esm/imports/ai-runtime.js +16 -0
- package/dist/esm/imports/ai-runtime.js.map +1 -0
- package/dist/esm/v3/ai-shared.d.ts +16 -1
- package/dist/esm/v3/ai-shared.js.map +1 -1
- package/dist/esm/v3/ai.d.ts +81 -8
- package/dist/esm/v3/ai.js +109 -5
- package/dist/esm/v3/ai.js.map +1 -1
- package/dist/esm/v3/aiAutoTelemetry.d.ts +2 -0
- package/dist/esm/v3/aiAutoTelemetry.js +78 -0
- package/dist/esm/v3/aiAutoTelemetry.js.map +1 -0
- package/dist/esm/v3/chat-client.js +3 -1
- package/dist/esm/v3/chat-client.js.map +1 -1
- package/dist/esm/v3/chat-server.d.ts +29 -6
- package/dist/esm/v3/chat-server.js +3 -1
- package/dist/esm/v3/chat-server.js.map +1 -1
- package/dist/esm/v3/chat.d.ts +11 -0
- package/dist/esm/v3/chat.js +61 -1
- package/dist/esm/v3/chat.js.map +1 -1
- package/dist/esm/v3/shared.js +18 -10
- package/dist/esm/v3/shared.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +11 -6
package/dist/commonjs/v3/ai.js
CHANGED
|
@@ -12,7 +12,9 @@ exports.__setReplaySessionInTailImplForTests = __setReplaySessionInTailImplForTe
|
|
|
12
12
|
exports.__replaySessionInTailProductionPathForTests = __replaySessionInTailProductionPathForTests;
|
|
13
13
|
exports.buildSkillTools = buildSkillTools;
|
|
14
14
|
const v3_1 = require("@trigger.dev/core/v3");
|
|
15
|
-
|
|
15
|
+
// Runtime VALUES go through the ESM/CJS shim so the CJS build can `require`
|
|
16
|
+
// ESM-only `ai@7` (see ../imports/ai-runtime.ts).
|
|
17
|
+
const ai_runtime_js_1 = require("../imports/ai-runtime.js");
|
|
16
18
|
const api_1 = require("@opentelemetry/api");
|
|
17
19
|
const auth_js_1 = require("./auth.js");
|
|
18
20
|
const locals_js_1 = require("./locals.js");
|
|
@@ -29,6 +31,7 @@ const agentSkillsRuntime_js_1 = require("./agentSkillsRuntime.js");
|
|
|
29
31
|
const streams_js_1 = require("./streams.js");
|
|
30
32
|
const sessions_js_1 = require("./sessions.js");
|
|
31
33
|
const shared_js_1 = require("./shared.js");
|
|
34
|
+
const aiAutoTelemetry_js_1 = require("./aiAutoTelemetry.js");
|
|
32
35
|
const v3_2 = require("@trigger.dev/core/v3");
|
|
33
36
|
const tracer_js_1 = require("./tracer.js");
|
|
34
37
|
const METADATA_KEY = "tool.execute.options";
|
|
@@ -38,7 +41,16 @@ const METADATA_KEY = "tool.execute.options";
|
|
|
38
41
|
* stopped/aborted conversations with partial tool parts.
|
|
39
42
|
*/
|
|
40
43
|
function toModelMessages(messages) {
|
|
41
|
-
|
|
44
|
+
// Pass the resolved per-turn `tools` (if any) so the AI SDK can look up each
|
|
45
|
+
// tool's `toModelOutput` and re-apply it to prior-turn tool results. Without
|
|
46
|
+
// `tools` it falls back to JSON-stringifying the raw output (TRI-10149). The
|
|
47
|
+
// conditional spread keeps the options object byte-identical to the no-tools
|
|
48
|
+
// path when nothing was declared.
|
|
49
|
+
const tools = locals_js_1.locals.get(chatResolvedToolsKey);
|
|
50
|
+
return (0, ai_runtime_js_1.convertToModelMessages)(messages, {
|
|
51
|
+
ignoreIncompleteToolCalls: true,
|
|
52
|
+
...(tools ? { tools } : {}),
|
|
53
|
+
});
|
|
42
54
|
}
|
|
43
55
|
const chatTurnContextKey = locals_js_1.locals.create("chat.turnContext");
|
|
44
56
|
/**
|
|
@@ -442,7 +454,7 @@ async function replaySessionOutTail(sessionId, options) {
|
|
|
442
454
|
});
|
|
443
455
|
let last;
|
|
444
456
|
try {
|
|
445
|
-
for await (const snapshot of (0,
|
|
457
|
+
for await (const snapshot of (0, ai_runtime_js_1.readUIMessageStream)({ stream: segmentStream })) {
|
|
446
458
|
last = snapshot;
|
|
447
459
|
}
|
|
448
460
|
}
|
|
@@ -645,9 +657,14 @@ function createTaskToolExecuteHandler(task) {
|
|
|
645
657
|
const toolMeta = {
|
|
646
658
|
toolCallId: toolOpts?.toolCallId ?? "",
|
|
647
659
|
};
|
|
648
|
-
|
|
660
|
+
// v6 passes user context as `experimental_context`, v7 as `context`. Read
|
|
661
|
+
// whichever is set and stamp both so subtasks reading either name work.
|
|
662
|
+
const toolContext = toolOpts?.context ?? toolOpts?.experimental_context;
|
|
663
|
+
if (toolContext !== undefined) {
|
|
649
664
|
try {
|
|
650
|
-
|
|
665
|
+
const serialized = JSON.parse(JSON.stringify(toolContext));
|
|
666
|
+
toolMeta.experimental_context = serialized;
|
|
667
|
+
toolMeta.context = serialized;
|
|
651
668
|
}
|
|
652
669
|
catch {
|
|
653
670
|
/* non-serializable */
|
|
@@ -690,9 +707,9 @@ function toolFromTask(task, options) {
|
|
|
690
707
|
// Zod-backed tasks: use static `tool()` so runtime shape matches `ToolSet`. Generic task context
|
|
691
708
|
// prevents `tool()` overloads from inferring input; `as any` is localized to this call only.
|
|
692
709
|
if ("schema" in task && task.schema && (0, v3_1.isSchemaZodEsque)(task.schema)) {
|
|
693
|
-
const staticTool = (0,
|
|
710
|
+
const staticTool = (0, ai_runtime_js_1.tool)({
|
|
694
711
|
description: task.description ?? "",
|
|
695
|
-
inputSchema: (0,
|
|
712
|
+
inputSchema: (0, ai_runtime_js_1.zodSchema)(task.schema),
|
|
696
713
|
execute: async (input, toolOpts) => executeFromTaskInput(input, toolOpts),
|
|
697
714
|
...(options?.experimental_toToolResultContent !== undefined
|
|
698
715
|
? { experimental_toToolResultContent: options.experimental_toToolResultContent }
|
|
@@ -700,7 +717,7 @@ function toolFromTask(task, options) {
|
|
|
700
717
|
});
|
|
701
718
|
return staticTool;
|
|
702
719
|
}
|
|
703
|
-
const toolDefinition = (0,
|
|
720
|
+
const toolDefinition = (0, ai_runtime_js_1.dynamicTool)({
|
|
704
721
|
description: task.description,
|
|
705
722
|
inputSchema: convertTaskSchemaToToolParameters(task),
|
|
706
723
|
...(options?.experimental_toToolResultContent !== undefined
|
|
@@ -768,15 +785,15 @@ function convertTaskSchemaToToolParameters(task) {
|
|
|
768
785
|
if ("schema" in task) {
|
|
769
786
|
// If TaskSchema is ArkTypeEsque, use ai.jsonSchema to convert it to a Schema
|
|
770
787
|
if ("toJsonSchema" in task.schema && typeof task.schema.toJsonSchema === "function") {
|
|
771
|
-
return (0,
|
|
788
|
+
return (0, ai_runtime_js_1.jsonSchema)(task.schema.toJsonSchema());
|
|
772
789
|
}
|
|
773
790
|
// If TaskSchema is ZodEsque, use ai.zodSchema to convert it to a Schema
|
|
774
791
|
if ((0, v3_1.isSchemaZodEsque)(task.schema)) {
|
|
775
|
-
return (0,
|
|
792
|
+
return (0, ai_runtime_js_1.zodSchema)(task.schema);
|
|
776
793
|
}
|
|
777
794
|
}
|
|
778
795
|
if ("jsonSchema" in task) {
|
|
779
|
-
return (0,
|
|
796
|
+
return (0, ai_runtime_js_1.jsonSchema)(task.jsonSchema);
|
|
780
797
|
}
|
|
781
798
|
throw new Error("Cannot convert task to a tool. Make sure to use a task with a schema or jsonSchema.");
|
|
782
799
|
}
|
|
@@ -1260,7 +1277,7 @@ function synthesizeHandoverUIMessage(partial, messageId) {
|
|
|
1260
1277
|
// browser). Fall back to a fresh id only if the handover signal
|
|
1261
1278
|
// didn't carry one.
|
|
1262
1279
|
return {
|
|
1263
|
-
id: messageId ?? (0,
|
|
1280
|
+
id: messageId ?? (0, ai_runtime_js_1.generateId)(),
|
|
1264
1281
|
role: "assistant",
|
|
1265
1282
|
parts,
|
|
1266
1283
|
};
|
|
@@ -1416,7 +1433,7 @@ function* iterateToolParts(message) {
|
|
|
1416
1433
|
if (message.role !== "assistant")
|
|
1417
1434
|
return;
|
|
1418
1435
|
for (const part of (message.parts ?? [])) {
|
|
1419
|
-
if (!(0,
|
|
1436
|
+
if (!(0, ai_runtime_js_1.isToolUIPart)(part))
|
|
1420
1437
|
continue;
|
|
1421
1438
|
const toolCallId = part.toolCallId;
|
|
1422
1439
|
if (typeof toolCallId !== "string" || toolCallId.length === 0)
|
|
@@ -1424,7 +1441,7 @@ function* iterateToolParts(message) {
|
|
|
1424
1441
|
yield {
|
|
1425
1442
|
part,
|
|
1426
1443
|
toolCallId,
|
|
1427
|
-
toolName: (0,
|
|
1444
|
+
toolName: (0, ai_runtime_js_1.getToolName)(part),
|
|
1428
1445
|
state: part.state,
|
|
1429
1446
|
};
|
|
1430
1447
|
}
|
|
@@ -1448,7 +1465,7 @@ function extractPendingToolCallsFromPartial(partial) {
|
|
|
1448
1465
|
const parts = (partial.parts ?? []);
|
|
1449
1466
|
for (let i = 0; i < parts.length; i++) {
|
|
1450
1467
|
const part = parts[i];
|
|
1451
|
-
if (!(0,
|
|
1468
|
+
if (!(0, ai_runtime_js_1.isToolUIPart)(part))
|
|
1452
1469
|
continue;
|
|
1453
1470
|
if (!isPendingToolState(part.state))
|
|
1454
1471
|
continue;
|
|
@@ -1457,7 +1474,7 @@ function extractPendingToolCallsFromPartial(partial) {
|
|
|
1457
1474
|
continue;
|
|
1458
1475
|
out.push({
|
|
1459
1476
|
toolCallId,
|
|
1460
|
-
toolName: (0,
|
|
1477
|
+
toolName: (0, ai_runtime_js_1.getToolName)(part),
|
|
1461
1478
|
input: part.input,
|
|
1462
1479
|
partIndex: i,
|
|
1463
1480
|
});
|
|
@@ -1560,7 +1577,7 @@ function extractNewToolResultsFromHistory(message, messages) {
|
|
|
1560
1577
|
function mergeIncomingIntoHydrated(hydrated, incoming) {
|
|
1561
1578
|
const incomingAdvancedByCallId = new Map();
|
|
1562
1579
|
for (const part of (incoming.parts ?? [])) {
|
|
1563
|
-
if (!(0,
|
|
1580
|
+
if (!(0, ai_runtime_js_1.isToolUIPart)(part))
|
|
1564
1581
|
continue;
|
|
1565
1582
|
const toolCallId = part.toolCallId;
|
|
1566
1583
|
if (typeof toolCallId !== "string" || toolCallId.length === 0)
|
|
@@ -1574,7 +1591,7 @@ function mergeIncomingIntoHydrated(hydrated, incoming) {
|
|
|
1574
1591
|
let mutated = false;
|
|
1575
1592
|
const hydratedParts = (hydrated.parts ?? []);
|
|
1576
1593
|
const mergedParts = hydratedParts.map((part) => {
|
|
1577
|
-
if (!(0,
|
|
1594
|
+
if (!(0, ai_runtime_js_1.isToolUIPart)(part))
|
|
1578
1595
|
return part;
|
|
1579
1596
|
const toolCallId = part.toolCallId;
|
|
1580
1597
|
if (typeof toolCallId !== "string" || toolCallId.length === 0)
|
|
@@ -1743,6 +1760,18 @@ const chatOnCompactedKey = locals_js_1.locals.create("chat.onCompacted");
|
|
|
1743
1760
|
/** @internal Full task `ctx` for the active `chat.agent` run (for hooks invoked from nested compaction). */
|
|
1744
1761
|
const chatAgentRunContextKey = locals_js_1.locals.create("chat.agentRunContext");
|
|
1745
1762
|
const chatPrepareMessagesKey = locals_js_1.locals.create("chat.prepareMessages");
|
|
1763
|
+
/**
|
|
1764
|
+
* @internal The raw `tools` option from `chat.agent({ tools })`, either a
|
|
1765
|
+
* static `ToolSet` or a per-turn function. Set once at boot.
|
|
1766
|
+
*/
|
|
1767
|
+
const chatToolsOptionKey = locals_js_1.locals.create("chat.toolsOption");
|
|
1768
|
+
/**
|
|
1769
|
+
* @internal The concrete `ToolSet` resolved for the current turn. Read by
|
|
1770
|
+
* `toModelMessages` so `convertToModelMessages` can re-run `toModelOutput` on
|
|
1771
|
+
* prior-turn tool results. Unset when no `tools` were declared (preserves the
|
|
1772
|
+
* exact pre-feature conversion behavior).
|
|
1773
|
+
*/
|
|
1774
|
+
const chatResolvedToolsKey = locals_js_1.locals.create("chat.resolvedTools");
|
|
1746
1775
|
/** @internal Flag set by `chat.requestUpgrade()` to exit the loop after the current turn. */
|
|
1747
1776
|
const chatUpgradeRequestedKey = locals_js_1.locals.create("chat.upgradeRequested");
|
|
1748
1777
|
/**
|
|
@@ -1836,6 +1865,37 @@ async function applyPrepareMessages(messages, reason) {
|
|
|
1836
1865
|
},
|
|
1837
1866
|
});
|
|
1838
1867
|
}
|
|
1868
|
+
/**
|
|
1869
|
+
* Resolve the `tools` option into a concrete `ToolSet` and cache it in locals so
|
|
1870
|
+
* `toModelMessages` can pass it to `convertToModelMessages`. For the function
|
|
1871
|
+
* form, invokes the user function with the given context (or the current turn
|
|
1872
|
+
* context when no override is passed). Pass an `override` for the boot-time
|
|
1873
|
+
* history conversion, which runs before the per-turn context exists and uses
|
|
1874
|
+
* the run/continuation payload's `clientData`.
|
|
1875
|
+
*
|
|
1876
|
+
* Fails closed: a throwing resolver propagates rather than carrying a prior
|
|
1877
|
+
* turn's set forward. The function form can gate capabilities by user or flag,
|
|
1878
|
+
* so reusing stale tools would leak capabilities. No-op when no `tools` were
|
|
1879
|
+
* declared.
|
|
1880
|
+
* @internal
|
|
1881
|
+
*/
|
|
1882
|
+
async function resolveTurnTools(override) {
|
|
1883
|
+
const option = locals_js_1.locals.get(chatToolsOptionKey);
|
|
1884
|
+
if (!option)
|
|
1885
|
+
return;
|
|
1886
|
+
if (typeof option !== "function") {
|
|
1887
|
+
locals_js_1.locals.set(chatResolvedToolsKey, option);
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1890
|
+
const ctx = override ?? locals_js_1.locals.get(chatTurnContextKey);
|
|
1891
|
+
const resolved = await option({
|
|
1892
|
+
chatId: ctx?.chatId ?? "",
|
|
1893
|
+
turn: ctx?.turn ?? 0,
|
|
1894
|
+
continuation: ctx?.continuation ?? false,
|
|
1895
|
+
clientData: ctx?.clientData,
|
|
1896
|
+
});
|
|
1897
|
+
locals_js_1.locals.set(chatResolvedToolsKey, resolved);
|
|
1898
|
+
}
|
|
1839
1899
|
/**
|
|
1840
1900
|
* Read the current compaction state. Returns the summary and base message count
|
|
1841
1901
|
* if compaction has occurred in this turn, or `undefined` if not.
|
|
@@ -1921,7 +1981,7 @@ async function chatCompact(messages, steps, options) {
|
|
|
1921
1981
|
return { type: "skipped" };
|
|
1922
1982
|
}
|
|
1923
1983
|
const result = await tracer_js_1.tracer.startActiveSpan("context compaction", async (span) => {
|
|
1924
|
-
const compactionId = (0,
|
|
1984
|
+
const compactionId = (0, ai_runtime_js_1.generateId)();
|
|
1925
1985
|
let summary;
|
|
1926
1986
|
const { waitUntilComplete } = chatStream.writer({
|
|
1927
1987
|
spanName: "stream compaction chunks",
|
|
@@ -2096,7 +2156,7 @@ async function drainSteeringQueue(config, messages, steps, queueOverride) {
|
|
|
2096
2156
|
execute: ({ write }) => {
|
|
2097
2157
|
write({
|
|
2098
2158
|
type: ai_shared_js_2.PENDING_MESSAGE_INJECTED_TYPE,
|
|
2099
|
-
id: (0,
|
|
2159
|
+
id: (0, ai_runtime_js_1.generateId)(),
|
|
2100
2160
|
data: {
|
|
2101
2161
|
messageIds: uiMessages.map((m) => m.id),
|
|
2102
2162
|
messages: uiMessages.map((m, idx) => ({
|
|
@@ -2250,9 +2310,9 @@ function findSkillByName(skills, name) {
|
|
|
2250
2310
|
* (e.g. in a `chat.createSession` loop with custom streamText).
|
|
2251
2311
|
*/
|
|
2252
2312
|
function buildSkillTools(skills) {
|
|
2253
|
-
const loadSkill = (0,
|
|
2313
|
+
const loadSkill = (0, ai_runtime_js_1.tool)({
|
|
2254
2314
|
description: "Load the full instructions for a skill by its name. Call this first before using a skill.",
|
|
2255
|
-
inputSchema: (0,
|
|
2315
|
+
inputSchema: (0, ai_runtime_js_1.jsonSchema)({
|
|
2256
2316
|
type: "object",
|
|
2257
2317
|
properties: {
|
|
2258
2318
|
name: {
|
|
@@ -2280,9 +2340,9 @@ function buildSkillTools(skills) {
|
|
|
2280
2340
|
};
|
|
2281
2341
|
},
|
|
2282
2342
|
});
|
|
2283
|
-
const readFile = (0,
|
|
2343
|
+
const readFile = (0, ai_runtime_js_1.tool)({
|
|
2284
2344
|
description: "Read a file from a skill's bundled folder. Paths must be relative to the skill's root.",
|
|
2285
|
-
inputSchema: (0,
|
|
2345
|
+
inputSchema: (0, ai_runtime_js_1.jsonSchema)({
|
|
2286
2346
|
type: "object",
|
|
2287
2347
|
properties: {
|
|
2288
2348
|
skill: { type: "string", description: "The skill's name (from frontmatter)." },
|
|
@@ -2310,9 +2370,9 @@ function buildSkillTools(skills) {
|
|
|
2310
2370
|
}
|
|
2311
2371
|
},
|
|
2312
2372
|
});
|
|
2313
|
-
const bash = (0,
|
|
2373
|
+
const bash = (0, ai_runtime_js_1.tool)({
|
|
2314
2374
|
description: "Run a bash command inside a skill's bundled folder. Use this to invoke the skill's scripts. The working directory is the skill's root.",
|
|
2315
|
-
inputSchema: (0,
|
|
2375
|
+
inputSchema: (0, ai_runtime_js_1.jsonSchema)({
|
|
2316
2376
|
type: "object",
|
|
2317
2377
|
properties: {
|
|
2318
2378
|
skill: { type: "string", description: "The skill's name (from frontmatter)." },
|
|
@@ -2561,7 +2621,7 @@ function chatCustomAgent(options) {
|
|
|
2561
2621
|
return task;
|
|
2562
2622
|
}
|
|
2563
2623
|
function chatAgent(options) {
|
|
2564
|
-
const { run: userRun, clientDataSchema, onBoot, onRecoveryBoot, onPreload, onChatStart, onValidateMessages, hydrateMessages, actionSchema, onAction, onTurnStart, onBeforeTurnComplete, onCompacted, compaction, pendingMessages: pendingMessagesConfig, prepareMessages, onTurnComplete, maxTurns = 100, turnTimeout = "1h", idleTimeoutInSeconds = 30, chatAccessTokenTTL = "1h", preloadIdleTimeoutInSeconds, preloadTimeout, uiMessageStreamOptions, onChatSuspend, onChatResume, exitAfterPreloadIdle = false, oomMachine, ...restOptions } = options;
|
|
2624
|
+
const { run: userRun, clientDataSchema, onBoot, onRecoveryBoot, onPreload, onChatStart, onValidateMessages, hydrateMessages, actionSchema, onAction, onTurnStart, onBeforeTurnComplete, onCompacted, compaction, pendingMessages: pendingMessagesConfig, prepareMessages, tools: toolsOption, onTurnComplete, maxTurns = 100, turnTimeout = "1h", idleTimeoutInSeconds = 30, chatAccessTokenTTL = "1h", preloadIdleTimeoutInSeconds, preloadTimeout, uiMessageStreamOptions, onChatSuspend, onChatResume, exitAfterPreloadIdle = false, oomMachine, ...restOptions } = options;
|
|
2565
2625
|
const parseClientData = clientDataSchema ? (0, v3_1.getSchemaParseFn)(clientDataSchema) : undefined;
|
|
2566
2626
|
const parseAction = actionSchema ? (0, v3_1.getSchemaParseFn)(actionSchema) : undefined;
|
|
2567
2627
|
// chat.agent does not expose generic retry options (see docstring on
|
|
@@ -2578,6 +2638,11 @@ function chatAgent(options) {
|
|
|
2578
2638
|
agentConfig: { type: "ai-sdk-chat" },
|
|
2579
2639
|
run: async (payload, { signal: runSignal, ctx }) => {
|
|
2580
2640
|
locals_js_1.locals.set(chatAgentRunContextKey, ctx);
|
|
2641
|
+
// On AI SDK 7, register the `@ai-sdk/otel` integration (once per process)
|
|
2642
|
+
// so `experimental_telemetry` spans flow into the run trace. Awaited here
|
|
2643
|
+
// at run boot — before any `streamText` — and a no-op on v5/v6 or when the
|
|
2644
|
+
// optional `@ai-sdk/otel` peer isn't installed. See ./aiAutoTelemetry.ts.
|
|
2645
|
+
await (0, aiAutoTelemetry_js_1.ensureAiSdkTelemetry)();
|
|
2581
2646
|
// Bind the run to its backing Session so every module-level helper
|
|
2582
2647
|
// (chat.stream, chat.messages, chat.stopSignal) resolves to this
|
|
2583
2648
|
// chat's `.in` / `.out` channels.
|
|
@@ -2610,6 +2675,19 @@ function chatAgent(options) {
|
|
|
2610
2675
|
if (prepareMessages) {
|
|
2611
2676
|
locals_js_1.locals.set(chatPrepareMessagesKey, prepareMessages);
|
|
2612
2677
|
}
|
|
2678
|
+
if (toolsOption) {
|
|
2679
|
+
// Cast: the option's function form is typed against the parsed
|
|
2680
|
+
// `clientData` (`ResolveToolsEvent<inferSchemaOut<...>>`), but the
|
|
2681
|
+
// locals key uses the erased `ResolveToolsEvent<unknown>`. The runtime
|
|
2682
|
+
// value is identical; this mirrors how `prepareMessages` is stored.
|
|
2683
|
+
locals_js_1.locals.set(chatToolsOptionKey, toolsOption);
|
|
2684
|
+
// Static tools are usable immediately. The function form is resolved
|
|
2685
|
+
// just before the boot history conversion (with the payload's
|
|
2686
|
+
// clientData) and again per-turn (see resolveTurnTools).
|
|
2687
|
+
if (typeof toolsOption !== "function") {
|
|
2688
|
+
locals_js_1.locals.set(chatResolvedToolsKey, toolsOption);
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2613
2691
|
if (compaction) {
|
|
2614
2692
|
locals_js_1.locals.set(chatAgentCompactionKey, compaction);
|
|
2615
2693
|
}
|
|
@@ -2940,6 +3018,27 @@ function chatAgent(options) {
|
|
|
2940
3018
|
accumulatedUIMessages = [...payload.headStartMessages];
|
|
2941
3019
|
}
|
|
2942
3020
|
if (accumulatedUIMessages.length > 0) {
|
|
3021
|
+
// Resolve a function-form `tools` with the run/continuation payload's
|
|
3022
|
+
// clientData so this conversion of the restored history applies each
|
|
3023
|
+
// tool's toModelOutput (static tools were already seeded above). This
|
|
3024
|
+
// only re-renders saved history, so it fails open: a resolver hiccup
|
|
3025
|
+
// logs and converts without tools rather than blocking the resume.
|
|
3026
|
+
// Per-turn resolveTurnTools still fails closed for live turns.
|
|
3027
|
+
if (typeof toolsOption === "function") {
|
|
3028
|
+
try {
|
|
3029
|
+
await resolveTurnTools({
|
|
3030
|
+
chatId: payload.chatId,
|
|
3031
|
+
turn: 0,
|
|
3032
|
+
continuation: payload.continuation ?? false,
|
|
3033
|
+
clientData: parseClientData
|
|
3034
|
+
? await parseClientData(payload.metadata)
|
|
3035
|
+
: payload.metadata,
|
|
3036
|
+
});
|
|
3037
|
+
}
|
|
3038
|
+
catch (error) {
|
|
3039
|
+
v3_1.logger.warn("chat.agent: tools() resolver threw at boot; restored history converted without toModelOutput", { error: error instanceof Error ? error.message : String(error) });
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
2943
3042
|
try {
|
|
2944
3043
|
accumulatedMessages = await toModelMessages(accumulatedUIMessages);
|
|
2945
3044
|
}
|
|
@@ -3361,6 +3460,10 @@ function chatAgent(options) {
|
|
|
3361
3460
|
continuation,
|
|
3362
3461
|
clientData,
|
|
3363
3462
|
});
|
|
3463
|
+
// Resolve the per-turn `tools` set now that turn context
|
|
3464
|
+
// (incl. parsed clientData) exists, so every toModelMessages
|
|
3465
|
+
// call this turn can re-apply tool `toModelOutput`.
|
|
3466
|
+
await resolveTurnTools();
|
|
3364
3467
|
// Per-turn stop controller (reset each turn)
|
|
3365
3468
|
const stopController = new AbortController();
|
|
3366
3469
|
currentStopController = stopController;
|
|
@@ -3736,7 +3839,7 @@ function chatAgent(options) {
|
|
|
3736
3839
|
const resolvedOptions = resolveUIMessageStreamOptions();
|
|
3737
3840
|
const uiStream = actionStreamResult.toUIMessageStream({
|
|
3738
3841
|
...resolvedOptions,
|
|
3739
|
-
generateMessageId: resolvedOptions.generateMessageId ??
|
|
3842
|
+
generateMessageId: resolvedOptions.generateMessageId ?? ai_runtime_js_1.generateId,
|
|
3740
3843
|
});
|
|
3741
3844
|
await pipeChat(uiStream, {
|
|
3742
3845
|
signal: combinedSignal,
|
|
@@ -3930,6 +4033,7 @@ function chatAgent(options) {
|
|
|
3930
4033
|
previousTurnUsage,
|
|
3931
4034
|
totalUsage: cumulativeUsage,
|
|
3932
4035
|
ctx,
|
|
4036
|
+
tools: locals_js_1.locals.get(chatResolvedToolsKey) ?? {},
|
|
3933
4037
|
signal: combinedSignal,
|
|
3934
4038
|
cancelSignal,
|
|
3935
4039
|
stopSignal,
|
|
@@ -3959,7 +4063,7 @@ function chatAgent(options) {
|
|
|
3959
4063
|
// Always provide generateMessageId so the start chunk carries a
|
|
3960
4064
|
// messageId. Without this, the frontend and backend generate IDs
|
|
3961
4065
|
// independently and they won't match for ID-based dedup.
|
|
3962
|
-
generateMessageId: resolvedOptions.generateMessageId ??
|
|
4066
|
+
generateMessageId: resolvedOptions.generateMessageId ?? ai_runtime_js_1.generateId,
|
|
3963
4067
|
onFinish: ({ responseMessage, finishReason, }) => {
|
|
3964
4068
|
capturedResponseMessage = responseMessage;
|
|
3965
4069
|
capturedFinishReason = finishReason;
|
|
@@ -4087,7 +4191,7 @@ function chatAgent(options) {
|
|
|
4087
4191
|
// may produce a message with an empty ID since IDs are normally
|
|
4088
4192
|
// assigned by the frontend's useChat).
|
|
4089
4193
|
if (!capturedResponseMessage.id) {
|
|
4090
|
-
capturedResponseMessage = { ...capturedResponseMessage, id: (0,
|
|
4194
|
+
capturedResponseMessage = { ...capturedResponseMessage, id: (0, ai_runtime_js_1.generateId)() };
|
|
4091
4195
|
}
|
|
4092
4196
|
// Append any non-transient data parts queued via chat.response or writer.write()
|
|
4093
4197
|
const queuedParts = locals_js_1.locals.get(chatResponsePartsKey);
|
|
@@ -4143,7 +4247,7 @@ function chatAgent(options) {
|
|
|
4143
4247
|
const remainingParts = locals_js_1.locals.get(chatResponsePartsKey);
|
|
4144
4248
|
if (remainingParts && remainingParts.length > 0) {
|
|
4145
4249
|
capturedResponseMessage = {
|
|
4146
|
-
id: (0,
|
|
4250
|
+
id: (0, ai_runtime_js_1.generateId)(),
|
|
4147
4251
|
role: "assistant",
|
|
4148
4252
|
parts: [...remainingParts],
|
|
4149
4253
|
};
|
|
@@ -4185,7 +4289,7 @@ function chatAgent(options) {
|
|
|
4185
4289
|
});
|
|
4186
4290
|
if (shouldTrigger) {
|
|
4187
4291
|
await tracer_js_1.tracer.startActiveSpan("context compaction (outer loop)", async (compactionSpan) => {
|
|
4188
|
-
const compactionId = (0,
|
|
4292
|
+
const compactionId = (0, ai_runtime_js_1.generateId)();
|
|
4189
4293
|
const { waitUntilComplete } = chatStream.writer({
|
|
4190
4294
|
spanName: "stream compaction chunks",
|
|
4191
4295
|
collapsed: true,
|
|
@@ -5259,7 +5363,7 @@ class ChatMessageAccumulator {
|
|
|
5259
5363
|
}
|
|
5260
5364
|
async addResponse(response) {
|
|
5261
5365
|
if (!response.id) {
|
|
5262
|
-
response = { ...response, id: (0,
|
|
5366
|
+
response = { ...response, id: (0, ai_runtime_js_1.generateId)() };
|
|
5263
5367
|
}
|
|
5264
5368
|
this.uiMessages.push(response);
|
|
5265
5369
|
try {
|
|
@@ -5588,7 +5692,7 @@ function createChatSession(payload, options) {
|
|
|
5588
5692
|
const queuedParts = locals_js_1.locals.get(chatResponsePartsKey);
|
|
5589
5693
|
if (queuedParts && queuedParts.length > 0) {
|
|
5590
5694
|
await accumulator.addResponse({
|
|
5591
|
-
id: (0,
|
|
5695
|
+
id: (0, ai_runtime_js_1.generateId)(),
|
|
5592
5696
|
role: "assistant",
|
|
5593
5697
|
parts: queuedParts,
|
|
5594
5698
|
});
|