@trigger.dev/sdk 4.5.0-rc.7 → 4.5.1
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/v3/ai-shared.js +1 -4
- package/dist/commonjs/v3/ai-shared.js.map +1 -1
- package/dist/commonjs/v3/ai.d.ts +13 -10
- package/dist/commonjs/v3/ai.js +121 -66
- package/dist/commonjs/v3/ai.js.map +1 -1
- package/dist/commonjs/v3/auth.d.ts +1 -1
- package/dist/commonjs/v3/auth.js +3 -4
- package/dist/commonjs/v3/auth.js.map +1 -1
- package/dist/commonjs/v3/batch.d.ts +1 -1
- package/dist/commonjs/v3/batch.js.map +1 -1
- package/dist/commonjs/v3/chat-client.js +18 -14
- package/dist/commonjs/v3/chat-client.js.map +1 -1
- package/dist/commonjs/v3/chat-react.js +2 -4
- package/dist/commonjs/v3/chat-react.js.map +1 -1
- package/dist/commonjs/v3/chat-server.d.ts +69 -1
- package/dist/commonjs/v3/chat-server.js +162 -14
- package/dist/commonjs/v3/chat-server.js.map +1 -1
- package/dist/commonjs/v3/chat-server.test.js +156 -12
- package/dist/commonjs/v3/chat-server.test.js.map +1 -1
- package/dist/commonjs/v3/chat.js +4 -3
- package/dist/commonjs/v3/chat.js.map +1 -1
- package/dist/commonjs/v3/chat.test.js +9 -48
- package/dist/commonjs/v3/chat.test.js.map +1 -1
- package/dist/commonjs/v3/deployments.d.ts +2 -3
- package/dist/commonjs/v3/deployments.js.map +1 -1
- package/dist/commonjs/v3/envvars.js.map +1 -1
- package/dist/commonjs/v3/idempotencyKeys.js.map +1 -1
- package/dist/commonjs/v3/metadata.d.ts +2 -2
- package/dist/commonjs/v3/prompt.js +2 -6
- package/dist/commonjs/v3/prompt.js.map +1 -1
- package/dist/commonjs/v3/promptManagement.js.map +1 -1
- package/dist/commonjs/v3/query.js.map +1 -1
- package/dist/commonjs/v3/queues.d.ts +1 -1
- package/dist/commonjs/v3/queues.js.map +1 -1
- package/dist/commonjs/v3/retry.d.ts +1 -1
- package/dist/commonjs/v3/retry.js +1 -1
- package/dist/commonjs/v3/retry.js.map +1 -1
- package/dist/commonjs/v3/runs.d.ts +3 -4
- package/dist/commonjs/v3/runs.js.map +1 -1
- package/dist/commonjs/v3/schedules/index.d.ts +3 -3
- package/dist/commonjs/v3/schedules/index.js.map +1 -1
- package/dist/commonjs/v3/sessions.d.ts +3 -4
- package/dist/commonjs/v3/sessions.js +2 -1
- package/dist/commonjs/v3/sessions.js.map +1 -1
- package/dist/commonjs/v3/shared.d.ts +3 -4
- package/dist/commonjs/v3/shared.js +0 -12
- package/dist/commonjs/v3/shared.js.map +1 -1
- package/dist/commonjs/v3/skill.js.map +1 -1
- package/dist/commonjs/v3/streams.d.ts +1 -1
- package/dist/commonjs/v3/streams.js +4 -5
- package/dist/commonjs/v3/streams.js.map +1 -1
- package/dist/commonjs/v3/streams.test.js +3 -3
- package/dist/commonjs/v3/streams.test.js.map +1 -1
- package/dist/commonjs/v3/test/mock-chat-agent.js +1 -4
- package/dist/commonjs/v3/test/mock-chat-agent.js.map +1 -1
- package/dist/commonjs/v3/test/test-session-handle.d.ts +2 -1
- package/dist/commonjs/v3/test/test-session-handle.js.map +1 -1
- package/dist/commonjs/v3/triggerClient.test.js +1 -1
- package/dist/commonjs/v3/triggerClient.test.js.map +1 -1
- package/dist/commonjs/v3/triggerClient.types.test.js +11 -11
- package/dist/commonjs/v3/triggerClient.types.test.js.map +1 -1
- package/dist/commonjs/v3/wait.d.ts +2 -1
- package/dist/commonjs/v3/wait.js.map +1 -1
- package/dist/commonjs/v3/webhooks.js +1 -1
- package/dist/commonjs/v3/webhooks.js.map +1 -1
- package/dist/commonjs/version.js +1 -1
- package/dist/esm/v3/ai-shared.js +1 -4
- package/dist/esm/v3/ai-shared.js.map +1 -1
- package/dist/esm/v3/ai.d.ts +13 -10
- package/dist/esm/v3/ai.js +119 -54
- package/dist/esm/v3/ai.js.map +1 -1
- package/dist/esm/v3/auth.d.ts +1 -1
- package/dist/esm/v3/auth.js +1 -2
- package/dist/esm/v3/auth.js.map +1 -1
- package/dist/esm/v3/batch.d.ts +1 -1
- package/dist/esm/v3/batch.js +1 -1
- package/dist/esm/v3/batch.js.map +1 -1
- package/dist/esm/v3/chat-client.js +18 -14
- package/dist/esm/v3/chat-client.js.map +1 -1
- package/dist/esm/v3/chat-react.js +2 -4
- package/dist/esm/v3/chat-react.js.map +1 -1
- package/dist/esm/v3/chat-server.d.ts +69 -1
- package/dist/esm/v3/chat-server.js +162 -14
- package/dist/esm/v3/chat-server.js.map +1 -1
- package/dist/esm/v3/chat-server.test.js +156 -12
- package/dist/esm/v3/chat-server.test.js.map +1 -1
- package/dist/esm/v3/chat.js +4 -3
- package/dist/esm/v3/chat.js.map +1 -1
- package/dist/esm/v3/chat.test.js +9 -48
- package/dist/esm/v3/chat.test.js.map +1 -1
- package/dist/esm/v3/deployments.d.ts +2 -3
- package/dist/esm/v3/deployments.js +1 -1
- package/dist/esm/v3/deployments.js.map +1 -1
- package/dist/esm/v3/envvars.js.map +1 -1
- package/dist/esm/v3/idempotencyKeys.js +1 -1
- package/dist/esm/v3/idempotencyKeys.js.map +1 -1
- package/dist/esm/v3/metadata.d.ts +2 -2
- package/dist/esm/v3/prompt.js +2 -6
- package/dist/esm/v3/prompt.js.map +1 -1
- package/dist/esm/v3/promptManagement.js.map +1 -1
- package/dist/esm/v3/query.js.map +1 -1
- package/dist/esm/v3/queues.d.ts +1 -1
- package/dist/esm/v3/queues.js.map +1 -1
- package/dist/esm/v3/retry.d.ts +1 -1
- package/dist/esm/v3/retry.js +1 -1
- package/dist/esm/v3/retry.js.map +1 -1
- package/dist/esm/v3/runs.d.ts +2 -3
- package/dist/esm/v3/runs.js.map +1 -1
- package/dist/esm/v3/schedules/index.d.ts +3 -3
- package/dist/esm/v3/schedules/index.js.map +1 -1
- package/dist/esm/v3/sessions.d.ts +3 -4
- package/dist/esm/v3/sessions.js +2 -1
- package/dist/esm/v3/sessions.js.map +1 -1
- package/dist/esm/v3/shared.d.ts +3 -4
- package/dist/esm/v3/shared.js +1 -13
- package/dist/esm/v3/shared.js.map +1 -1
- package/dist/esm/v3/skill.js.map +1 -1
- package/dist/esm/v3/streams.d.ts +1 -1
- package/dist/esm/v3/streams.js +4 -5
- package/dist/esm/v3/streams.js.map +1 -1
- package/dist/esm/v3/streams.test.js +4 -4
- package/dist/esm/v3/streams.test.js.map +1 -1
- package/dist/esm/v3/test/mock-chat-agent.js +4 -7
- package/dist/esm/v3/test/mock-chat-agent.js.map +1 -1
- package/dist/esm/v3/test/test-session-handle.d.ts +2 -1
- package/dist/esm/v3/test/test-session-handle.js +1 -1
- package/dist/esm/v3/test/test-session-handle.js.map +1 -1
- package/dist/esm/v3/triggerClient.test.js +1 -1
- package/dist/esm/v3/triggerClient.test.js.map +1 -1
- package/dist/esm/v3/triggerClient.types.test.js +11 -11
- package/dist/esm/v3/triggerClient.types.test.js.map +1 -1
- package/dist/esm/v3/wait.d.ts +2 -1
- package/dist/esm/v3/wait.js.map +1 -1
- package/dist/esm/v3/webhooks.js +1 -1
- package/dist/esm/v3/webhooks.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/docs/ai/prompts.mdx +0 -4
- package/docs/ai-chat/actions.mdx +0 -4
- package/docs/ai-chat/anatomy.mdx +0 -4
- package/docs/ai-chat/backend.mdx +0 -4
- package/docs/ai-chat/background-injection.mdx +0 -4
- package/docs/ai-chat/changelog.mdx +109 -1
- package/docs/ai-chat/chat-local.mdx +0 -4
- package/docs/ai-chat/client-protocol.mdx +0 -4
- package/docs/ai-chat/compaction.mdx +0 -4
- package/docs/ai-chat/custom-agents.mdx +32 -4
- package/docs/ai-chat/error-handling.mdx +0 -4
- package/docs/ai-chat/fast-starts.mdx +86 -4
- package/docs/ai-chat/frontend.mdx +0 -4
- package/docs/ai-chat/how-it-works.mdx +0 -4
- package/docs/ai-chat/lifecycle-hooks.mdx +0 -4
- package/docs/ai-chat/mcp.mdx +0 -4
- package/docs/ai-chat/overview.mdx +0 -4
- package/docs/ai-chat/patterns/branching-conversations.mdx +0 -4
- package/docs/ai-chat/patterns/code-sandbox.mdx +0 -4
- package/docs/ai-chat/patterns/database-persistence.mdx +0 -4
- package/docs/ai-chat/patterns/human-in-the-loop.mdx +9 -5
- package/docs/ai-chat/patterns/large-payloads.mdx +0 -4
- package/docs/ai-chat/patterns/oom-resilience.mdx +0 -4
- package/docs/ai-chat/patterns/persistence-and-replay.mdx +0 -4
- package/docs/ai-chat/patterns/recovery-boot.mdx +0 -4
- package/docs/ai-chat/patterns/skills.mdx +0 -4
- package/docs/ai-chat/patterns/sub-agents.mdx +0 -4
- package/docs/ai-chat/patterns/tool-result-auditing.mdx +0 -4
- package/docs/ai-chat/patterns/trusted-edge-signals.mdx +0 -4
- package/docs/ai-chat/patterns/version-upgrades.mdx +0 -4
- package/docs/ai-chat/pending-messages.mdx +0 -4
- package/docs/ai-chat/prompt-caching.mdx +4 -4
- package/docs/ai-chat/quick-start.mdx +0 -4
- package/docs/ai-chat/reference.mdx +1 -5
- package/docs/ai-chat/server-chat.mdx +0 -4
- package/docs/ai-chat/sessions.mdx +0 -4
- package/docs/ai-chat/testing.mdx +0 -4
- package/docs/ai-chat/tools.mdx +0 -4
- package/docs/ai-chat/types.mdx +0 -4
- package/docs/ai-chat/upgrade-guide.mdx +0 -4
- package/docs/building-with-ai.mdx +1 -1
- package/docs/deploy-environment-variables.mdx +1 -1
- package/docs/deployment/dev-branches.mdx +92 -0
- package/docs/deployment/overview.mdx +1 -1
- package/docs/help-slack.mdx +1 -0
- package/docs/how-to-reduce-your-spend.mdx +14 -7
- package/docs/introduction.mdx +13 -13
- package/docs/mcp-agent-rules.mdx +1 -1
- package/docs/open-source-self-hosting.mdx +1 -1
- package/docs/self-hosting/kubernetes.mdx +8 -8
- package/docs/self-hosting/overview.mdx +2 -1
- package/docs/tasks/scheduled.mdx +2 -2
- package/docs/troubleshooting-debugging-in-vscode.mdx +1 -0
- package/docs/troubleshooting-github-issues.mdx +1 -1
- package/docs/troubleshooting-uptime-status.mdx +1 -0
- package/docs/video-walkthrough.mdx +1 -1
- package/docs/wait-for.mdx +1 -1
- package/package.json +2 -2
- package/docs/cli-dev.mdx +0 -8
package/dist/esm/v3/ai.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { accessoryAttributes, apiClientManager, controlSubtype, getSchemaParseFn, headerValue, InputStreamOncePromise, isSchemaZodEsque, logger, ManualWaitpointPromise, OutOfMemoryError,
|
|
1
|
+
import { accessoryAttributes, apiClientManager, controlSubtype, generateJWT, getSchemaParseFn, headerValue, InputStreamOncePromise, isSchemaZodEsque, logger, ManualWaitpointPromise, OutOfMemoryError, resourceCatalog, SemanticInternalAttributes, SESSION_IN_EVENT_ID_HEADER, sessionStreams, taskContext, TRIGGER_CONTROL_SUBTYPE, } from "@trigger.dev/core/v3";
|
|
2
2
|
// Runtime VALUES go through the ESM/CJS shim so the CJS build can `require`
|
|
3
3
|
// ESM-only `ai@7` (see ../imports/ai-runtime.ts).
|
|
4
|
-
import { convertToModelMessages, dynamicTool, generateId as generateMessageId, getToolName, isToolUIPart, jsonSchema, readUIMessageStream, tool as aiTool, zodSchema, } from "../imports/ai-runtime.js";
|
|
5
4
|
import { trace } from "@opentelemetry/api";
|
|
5
|
+
import { tool as aiTool, convertToModelMessages, dynamicTool, generateId as generateMessageId, getToolName, isToolUIPart, jsonSchema, readUIMessageStream, zodSchema, } from "../imports/ai-runtime.js";
|
|
6
|
+
import { PENDING_MESSAGE_INJECTED_TYPE, upsertIncomingMessage, } from "./ai-shared.js";
|
|
6
7
|
import { auth } from "./auth.js";
|
|
7
8
|
import { locals } from "./locals.js";
|
|
8
9
|
import { metadata } from "./metadata.js";
|
|
@@ -14,12 +15,11 @@ import { metadata } from "./metadata.js";
|
|
|
14
15
|
// that wants those primitives imports `./ai-shared.js` directly and
|
|
15
16
|
// never touches `ai.ts`'s module graph, so the `node:*` builtins
|
|
16
17
|
// pulled in transitively here never reach a client chunk.
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
18
|
+
import { readFileInSkill, runBashInSkill } from "./agentSkillsRuntime.js";
|
|
19
|
+
import { ensureAiSdkTelemetry } from "./aiAutoTelemetry.js";
|
|
19
20
|
import { sessions, } from "./sessions.js";
|
|
20
21
|
import { createTask } from "./shared.js";
|
|
21
|
-
import {
|
|
22
|
-
import { resourceCatalog } from "@trigger.dev/core/v3";
|
|
22
|
+
import { markChatAgentRunForStreamsWarning } from "./streams.js";
|
|
23
23
|
import { tracer } from "./tracer.js";
|
|
24
24
|
const METADATA_KEY = "tool.execute.options";
|
|
25
25
|
/**
|
|
@@ -141,7 +141,9 @@ async function seedSessionInResumeCursorForCustomLoop(payload) {
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
catch (error) {
|
|
144
|
-
logger.warn("chat session: session.in resume cursor lookup failed; old messages may replay", {
|
|
144
|
+
logger.warn("chat session: session.in resume cursor lookup failed; old messages may replay", {
|
|
145
|
+
error: error instanceof Error ? error.message : String(error),
|
|
146
|
+
});
|
|
145
147
|
}
|
|
146
148
|
}
|
|
147
149
|
let readChatSnapshotImpl;
|
|
@@ -1227,8 +1229,7 @@ const handoverInput = {
|
|
|
1227
1229
|
const result = await getChatSession().in.waitWithIdleTimeout(options);
|
|
1228
1230
|
if (!result.ok)
|
|
1229
1231
|
return result;
|
|
1230
|
-
if (result.output.kind === "handover" ||
|
|
1231
|
-
result.output.kind === "handover-skip") {
|
|
1232
|
+
if (result.output.kind === "handover" || result.output.kind === "handover-skip") {
|
|
1232
1233
|
return { ok: true, output: result.output };
|
|
1233
1234
|
}
|
|
1234
1235
|
// Other kinds (message, stop) are not expected during handover-prepare.
|
|
@@ -1893,8 +1894,7 @@ const chatAgentCompactionKey = locals.create("chat.agentCompaction");
|
|
|
1893
1894
|
// React hooks (`@trigger.dev/sdk/chat/react`) can import it without
|
|
1894
1895
|
// dragging `ai.ts` into the browser graph. Re-exported here so
|
|
1895
1896
|
// `@trigger.dev/sdk/ai` consumers still see it.
|
|
1896
|
-
export { PENDING_MESSAGE_INJECTED_TYPE, upsertIncomingMessage }
|
|
1897
|
-
import { PENDING_MESSAGE_INJECTED_TYPE } from "./ai-shared.js";
|
|
1897
|
+
export { PENDING_MESSAGE_INJECTED_TYPE, upsertIncomingMessage };
|
|
1898
1898
|
/** @internal */
|
|
1899
1899
|
const chatPendingMessagesKey = locals.create("chat.pendingMessages");
|
|
1900
1900
|
/** @internal */
|
|
@@ -1939,6 +1939,55 @@ function isStepBoundarySafe(step) {
|
|
|
1939
1939
|
.map((p) => p.toolCallId));
|
|
1940
1940
|
return ![...callIds].some((id) => !settledIds.has(id));
|
|
1941
1941
|
}
|
|
1942
|
+
/**
|
|
1943
|
+
* True when a model message is a `tool` message carrying a
|
|
1944
|
+
* `tool-approval-response` part — the trailing row a head-start handover
|
|
1945
|
+
* reshapes a pending first-turn tool call into. AI SDK's `collectToolApprovals`
|
|
1946
|
+
* only inspects the conversation's last message, so this row must survive to
|
|
1947
|
+
* `streamText` intact for the agent to execute the handed-over call.
|
|
1948
|
+
* @internal
|
|
1949
|
+
*/
|
|
1950
|
+
function hasToolApprovalResponse(message) {
|
|
1951
|
+
return (message?.role === "tool" &&
|
|
1952
|
+
Array.isArray(message.content) &&
|
|
1953
|
+
message.content.some((part) => part != null &&
|
|
1954
|
+
typeof part === "object" &&
|
|
1955
|
+
part.type === "tool-approval-response"));
|
|
1956
|
+
}
|
|
1957
|
+
/**
|
|
1958
|
+
* Keep a head-start handover's tool-approval tail intact across `prepareMessages`.
|
|
1959
|
+
*
|
|
1960
|
+
* The handover reshapes the warm step-1's pending tool call into AI SDK's
|
|
1961
|
+
* tool-approval round: a `tool-approval-request` on the assistant plus a
|
|
1962
|
+
* trailing `tool` message with `tool-approval-response { approved: true }`. The
|
|
1963
|
+
* agent's next `streamText` runs `collectToolApprovals`, which ONLY looks at the
|
|
1964
|
+
* last message — so that tool row must stay last and unmodified for the pending
|
|
1965
|
+
* call to execute. A user `prepareMessages` hook that rewrites or drops the last
|
|
1966
|
+
* message (e.g. rolling a provider cache breakpoint onto it) silently breaks the
|
|
1967
|
+
* resume: the agent sends a bare `tool_use` and the turn dies with
|
|
1968
|
+
* "tool_use ids were found without tool_result". If the hook's input ended with
|
|
1969
|
+
* that approval tail, re-assert the original tail as the last message.
|
|
1970
|
+
*
|
|
1971
|
+
* No-op for every normal turn — only fires when the input genuinely ended with a
|
|
1972
|
+
* pending tool-approval response (i.e. a head-start resume).
|
|
1973
|
+
* @internal
|
|
1974
|
+
*/
|
|
1975
|
+
function preserveToolApprovalTail(original, prepared) {
|
|
1976
|
+
const originalTail = original[original.length - 1];
|
|
1977
|
+
if (!hasToolApprovalResponse(originalTail))
|
|
1978
|
+
return prepared;
|
|
1979
|
+
// Hook left the exact tail object in place — nothing to do.
|
|
1980
|
+
if (prepared[prepared.length - 1] === originalTail)
|
|
1981
|
+
return prepared;
|
|
1982
|
+
// Otherwise drop only the trailing approval tail the hook produced (the
|
|
1983
|
+
// original moved, or a rewritten copy) and re-append the original so it is
|
|
1984
|
+
// last and intact. Older approval rounds deeper in history must survive.
|
|
1985
|
+
const withoutMovedOriginal = prepared.filter((m) => m !== originalTail);
|
|
1986
|
+
while (hasToolApprovalResponse(withoutMovedOriginal[withoutMovedOriginal.length - 1])) {
|
|
1987
|
+
withoutMovedOriginal.pop();
|
|
1988
|
+
}
|
|
1989
|
+
return [...withoutMovedOriginal, originalTail];
|
|
1990
|
+
}
|
|
1942
1991
|
/**
|
|
1943
1992
|
* Apply the prepareMessages hook if one is set in locals.
|
|
1944
1993
|
* @internal
|
|
@@ -1948,7 +1997,7 @@ async function applyPrepareMessages(messages, reason) {
|
|
|
1948
1997
|
if (!hook)
|
|
1949
1998
|
return messages;
|
|
1950
1999
|
const turnCtx = locals.get(chatTurnContextKey);
|
|
1951
|
-
|
|
2000
|
+
const prepared = await tracer.startActiveSpan("prepareMessages()", async () => {
|
|
1952
2001
|
return hook({
|
|
1953
2002
|
messages,
|
|
1954
2003
|
reason,
|
|
@@ -1964,6 +2013,9 @@ async function applyPrepareMessages(messages, reason) {
|
|
|
1964
2013
|
"chat.prepareMessages.messageCount": messages.length,
|
|
1965
2014
|
},
|
|
1966
2015
|
});
|
|
2016
|
+
// A user hook must never be able to break the head-start handover resume by
|
|
2017
|
+
// disturbing the trailing tool-approval row (see preserveToolApprovalTail).
|
|
2018
|
+
return preserveToolApprovalTail(messages, prepared);
|
|
1967
2019
|
}
|
|
1968
2020
|
/**
|
|
1969
2021
|
* Resolve the `tools` option into a concrete `ToolSet` and cache it in locals so
|
|
@@ -2234,7 +2286,7 @@ async function drainSteeringQueue(config, messages, steps, queueOverride) {
|
|
|
2234
2286
|
.filter((p) => p.type === "text")
|
|
2235
2287
|
.map((p) => p.text)
|
|
2236
2288
|
.join("") || "");
|
|
2237
|
-
const
|
|
2289
|
+
const _previewText = messageTexts.length === 1 ? messageTexts[0].slice(0, 80) : `${queue.length} messages`;
|
|
2238
2290
|
return tracer.startActiveSpan("pending message injected", async () => {
|
|
2239
2291
|
// Transform the batch — default: concatenate all pre-converted model messages
|
|
2240
2292
|
const injected = config.prepare
|
|
@@ -2912,7 +2964,9 @@ function chatAgent(options) {
|
|
|
2912
2964
|
const replayOutPhase = async () => {
|
|
2913
2965
|
const replayOutStart = Date.now();
|
|
2914
2966
|
try {
|
|
2915
|
-
const replayResult = await replaySessionOutTail(sessionIdForSnapshot, {
|
|
2967
|
+
const replayResult = await replaySessionOutTail(sessionIdForSnapshot, {
|
|
2968
|
+
lastEventId: bootSnapshot?.lastOutEventId,
|
|
2969
|
+
});
|
|
2916
2970
|
replayedSettled = replayResult.settled;
|
|
2917
2971
|
replayedPartial = replayResult.partial;
|
|
2918
2972
|
replayedPartialRaw = replayResult.partialRaw;
|
|
@@ -3009,9 +3063,7 @@ function chatAgent(options) {
|
|
|
3009
3063
|
// crashed / was canceled / requested upgrade
|
|
3010
3064
|
// - Snapshot exists at all (catches edge cases where the wire
|
|
3011
3065
|
// didn't set `continuation` but a snapshot indicates prior turns)
|
|
3012
|
-
const needsResumeCursor = ctx.attempt.number > 1 ||
|
|
3013
|
-
payload.continuation === true ||
|
|
3014
|
-
bootSnapshot !== undefined;
|
|
3066
|
+
const needsResumeCursor = ctx.attempt.number > 1 || payload.continuation === true || bootSnapshot !== undefined;
|
|
3015
3067
|
if (needsResumeCursor) {
|
|
3016
3068
|
try {
|
|
3017
3069
|
// Reuse the cursor the boot block already resolved (snapshot
|
|
@@ -3358,9 +3410,7 @@ function chatAgent(options) {
|
|
|
3358
3410
|
// Wait for the first real message — task-level idle settings win over
|
|
3359
3411
|
// `transport.preload(..., { idleTimeoutInSeconds })` / wire payload so
|
|
3360
3412
|
// `chat.agent({ idleTimeoutInSeconds, preloadIdleTimeoutInSeconds })` is authoritative.
|
|
3361
|
-
const effectivePreloadIdleTimeout = preloadIdleTimeoutInSeconds ??
|
|
3362
|
-
idleTimeoutInSeconds ??
|
|
3363
|
-
payload.idleTimeoutInSeconds;
|
|
3413
|
+
const effectivePreloadIdleTimeout = preloadIdleTimeoutInSeconds ?? idleTimeoutInSeconds ?? payload.idleTimeoutInSeconds;
|
|
3364
3414
|
const effectivePreloadTimeout = metadata.get(TURN_TIMEOUT_METADATA_KEY) ??
|
|
3365
3415
|
preloadTimeout ??
|
|
3366
3416
|
turnTimeout;
|
|
@@ -3605,7 +3655,9 @@ function chatAgent(options) {
|
|
|
3605
3655
|
if (lastUserMessage) {
|
|
3606
3656
|
turnAttributes["chat.user_message"] = lastUserMessage;
|
|
3607
3657
|
// Show a truncated preview of the user message as an accessory
|
|
3608
|
-
const preview = lastUserMessage.length > 80
|
|
3658
|
+
const preview = lastUserMessage.length > 80
|
|
3659
|
+
? lastUserMessage.slice(0, 80) + "..."
|
|
3660
|
+
: lastUserMessage;
|
|
3609
3661
|
Object.assign(turnAttributes, accessoryAttributes({
|
|
3610
3662
|
items: [{ text: preview, variant: "normal" }],
|
|
3611
3663
|
style: "codepath",
|
|
@@ -3892,8 +3944,7 @@ function chatAgent(options) {
|
|
|
3892
3944
|
if (currentWirePayload.trigger === "submit-message" &&
|
|
3893
3945
|
cleanedUIMessages.length > 0) {
|
|
3894
3946
|
const lastUI = cleanedUIMessages[cleanedUIMessages.length - 1];
|
|
3895
|
-
const matchedExisting = lastUI.id !== undefined &&
|
|
3896
|
-
previouslyKnownMessageIds.has(lastUI.id);
|
|
3947
|
+
const matchedExisting = lastUI.id !== undefined && previouslyKnownMessageIds.has(lastUI.id);
|
|
3897
3948
|
if (!matchedExisting) {
|
|
3898
3949
|
turnNewUIMessages.push(lastUI);
|
|
3899
3950
|
const lastModel = (await toModelMessages([lastUI]))[0];
|
|
@@ -4228,7 +4279,8 @@ function chatAgent(options) {
|
|
|
4228
4279
|
// We call toUIMessageStream ourselves to attach onFinish for response capture.
|
|
4229
4280
|
// Pass originalMessages so the AI SDK reuses message IDs across turns
|
|
4230
4281
|
// (e.g. for tool approval continuations / HITL flows).
|
|
4231
|
-
if ((locals.get(chatPipeCountKey) ?? 0) === 0 &&
|
|
4282
|
+
if ((locals.get(chatPipeCountKey) ?? 0) === 0 &&
|
|
4283
|
+
isUIMessageStreamable(runResult)) {
|
|
4232
4284
|
onFinishAttached = true;
|
|
4233
4285
|
const resolvedOptions = resolveUIMessageStreamOptions();
|
|
4234
4286
|
// For action turns, don't pass originalMessages: the response
|
|
@@ -4241,9 +4293,7 @@ function chatAgent(options) {
|
|
|
4241
4293
|
// Pass originalMessages so the AI SDK reuses message IDs across
|
|
4242
4294
|
// turns (e.g. for tool approval continuations / HITL flows).
|
|
4243
4295
|
// Omit for action turns to force a fresh response ID.
|
|
4244
|
-
...(isActionTurn
|
|
4245
|
-
? {}
|
|
4246
|
-
: { originalMessages: accumulatedUIMessages }),
|
|
4296
|
+
...(isActionTurn ? {} : { originalMessages: accumulatedUIMessages }),
|
|
4247
4297
|
// Always provide generateMessageId so the start chunk carries a
|
|
4248
4298
|
// messageId. Without this, the frontend and backend generate IDs
|
|
4249
4299
|
// independently and they won't match for ID-based dedup.
|
|
@@ -4254,7 +4304,10 @@ function chatAgent(options) {
|
|
|
4254
4304
|
resolveOnFinish();
|
|
4255
4305
|
},
|
|
4256
4306
|
});
|
|
4257
|
-
await pipeChat(uiStream, {
|
|
4307
|
+
await pipeChat(uiStream, {
|
|
4308
|
+
signal: combinedSignal,
|
|
4309
|
+
spanName: "stream response",
|
|
4310
|
+
});
|
|
4258
4311
|
}
|
|
4259
4312
|
}
|
|
4260
4313
|
catch (error) {
|
|
@@ -4289,7 +4342,8 @@ function chatAgent(options) {
|
|
|
4289
4342
|
// never reports final usage), which would block the turn loop
|
|
4290
4343
|
// from ever firing onTurnComplete / writeTurnComplete.
|
|
4291
4344
|
let turnUsage;
|
|
4292
|
-
if (runResult != null &&
|
|
4345
|
+
if (runResult != null &&
|
|
4346
|
+
typeof runResult.totalUsage?.then === "function") {
|
|
4293
4347
|
try {
|
|
4294
4348
|
turnUsage = (await Promise.race([
|
|
4295
4349
|
runResult.totalUsage,
|
|
@@ -4375,7 +4429,10 @@ function chatAgent(options) {
|
|
|
4375
4429
|
// may produce a message with an empty ID since IDs are normally
|
|
4376
4430
|
// assigned by the frontend's useChat).
|
|
4377
4431
|
if (!capturedResponseMessage.id) {
|
|
4378
|
-
capturedResponseMessage = {
|
|
4432
|
+
capturedResponseMessage = {
|
|
4433
|
+
...capturedResponseMessage,
|
|
4434
|
+
id: generateMessageId(),
|
|
4435
|
+
};
|
|
4379
4436
|
}
|
|
4380
4437
|
// Append any non-transient data parts queued via chat.response or writer.write()
|
|
4381
4438
|
const queuedParts = locals.get(chatResponsePartsKey);
|
|
@@ -4676,7 +4733,9 @@ function chatAgent(options) {
|
|
|
4676
4733
|
? { "gen_ai.usage.total_tokens": turnUsage.totalTokens }
|
|
4677
4734
|
: {}),
|
|
4678
4735
|
...(cumulativeUsage.totalTokens != null
|
|
4679
|
-
? {
|
|
4736
|
+
? {
|
|
4737
|
+
"gen_ai.usage.cumulative_total_tokens": cumulativeUsage.totalTokens,
|
|
4738
|
+
}
|
|
4680
4739
|
: {}),
|
|
4681
4740
|
},
|
|
4682
4741
|
});
|
|
@@ -4708,9 +4767,7 @@ function chatAgent(options) {
|
|
|
4708
4767
|
savedAt: Date.now(),
|
|
4709
4768
|
messages: accumulatedUIMessages,
|
|
4710
4769
|
lastOutEventId: turnCompleteResult?.lastEventId,
|
|
4711
|
-
lastInEventId: snapshotInCursor !== undefined
|
|
4712
|
-
? String(snapshotInCursor)
|
|
4713
|
-
: undefined,
|
|
4770
|
+
lastInEventId: snapshotInCursor !== undefined ? String(snapshotInCursor) : undefined,
|
|
4714
4771
|
});
|
|
4715
4772
|
}, {
|
|
4716
4773
|
attributes: {
|
|
@@ -4752,8 +4809,7 @@ function chatAgent(options) {
|
|
|
4752
4809
|
// chat.requestUpgrade() was called — exit the loop so the
|
|
4753
4810
|
// transport triggers a new run on the latest version.
|
|
4754
4811
|
// chat.endRun() — same exit, no upgrade semantics.
|
|
4755
|
-
if (locals.get(chatUpgradeRequestedKey) ||
|
|
4756
|
-
locals.get(chatEndRunRequestedKey)) {
|
|
4812
|
+
if (locals.get(chatUpgradeRequestedKey) || locals.get(chatEndRunRequestedKey)) {
|
|
4757
4813
|
return "exit";
|
|
4758
4814
|
}
|
|
4759
4815
|
// Wait for the next message — stay idle briefly, then suspend
|
|
@@ -4833,7 +4889,9 @@ function chatAgent(options) {
|
|
|
4833
4889
|
// Turn error handler: write an error chunk + turn-complete to the stream
|
|
4834
4890
|
// so the client sees the error, then wait for the next message instead
|
|
4835
4891
|
// of killing the entire run. This keeps the conversation alive.
|
|
4836
|
-
if (turnError instanceof Error &&
|
|
4892
|
+
if (turnError instanceof Error &&
|
|
4893
|
+
turnError.name === "AbortError" &&
|
|
4894
|
+
runSignal.aborted) {
|
|
4837
4895
|
// Full run cancellation — exit immediately
|
|
4838
4896
|
throw turnError;
|
|
4839
4897
|
}
|
|
@@ -4929,9 +4987,7 @@ function chatAgent(options) {
|
|
|
4929
4987
|
savedAt: Date.now(),
|
|
4930
4988
|
messages: erroredUIMessages,
|
|
4931
4989
|
lastOutEventId: errorTurnCompleteResult?.lastEventId,
|
|
4932
|
-
lastInEventId: errorSnapshotInCursor !== undefined
|
|
4933
|
-
? String(errorSnapshotInCursor)
|
|
4934
|
-
: undefined,
|
|
4990
|
+
lastInEventId: errorSnapshotInCursor !== undefined ? String(errorSnapshotInCursor) : undefined,
|
|
4935
4991
|
});
|
|
4936
4992
|
}
|
|
4937
4993
|
catch (error) {
|
|
@@ -4942,8 +4998,7 @@ function chatAgent(options) {
|
|
|
4942
4998
|
}
|
|
4943
4999
|
}
|
|
4944
5000
|
// chat.requestUpgrade() / chat.endRun() — exit after error turn too
|
|
4945
|
-
if (locals.get(chatUpgradeRequestedKey) ||
|
|
4946
|
-
locals.get(chatEndRunRequestedKey)) {
|
|
5001
|
+
if (locals.get(chatUpgradeRequestedKey) || locals.get(chatEndRunRequestedKey)) {
|
|
4947
5002
|
return;
|
|
4948
5003
|
}
|
|
4949
5004
|
// Drain remaining recovered turns before idling — a thrown
|
|
@@ -4976,7 +5031,7 @@ function chatAgent(options) {
|
|
|
4976
5031
|
// cleanup so a missing subscription doesn't throw.
|
|
4977
5032
|
stopSub?.off();
|
|
4978
5033
|
}
|
|
4979
|
-
}
|
|
5034
|
+
},
|
|
4980
5035
|
});
|
|
4981
5036
|
// Register clientDataSchema so the CLI converts it to JSONSchema
|
|
4982
5037
|
// and stores it as payloadSchema — used by the Playground UI
|
|
@@ -5068,7 +5123,7 @@ function createChatBuilder(config) {
|
|
|
5068
5123
|
agent(options) {
|
|
5069
5124
|
const mergedUiStream = config.uiStreamOptions && options.uiMessageStreamOptions
|
|
5070
5125
|
? { ...config.uiStreamOptions, ...options.uiMessageStreamOptions }
|
|
5071
|
-
: options.uiMessageStreamOptions ?? config.uiStreamOptions;
|
|
5126
|
+
: (options.uiMessageStreamOptions ?? config.uiStreamOptions);
|
|
5072
5127
|
return chatAgent({
|
|
5073
5128
|
...options,
|
|
5074
5129
|
...(config.clientDataSchema ? { clientDataSchema: config.clientDataSchema } : {}),
|
|
@@ -5896,7 +5951,9 @@ function createChatSession(payload, options) {
|
|
|
5896
5951
|
if (turn === 0 && currentPayload.trigger === "handover-prepare") {
|
|
5897
5952
|
const signal = await waitForHandover({
|
|
5898
5953
|
payload: currentPayload,
|
|
5899
|
-
idleTimeoutInSeconds: sessionIdleTimeoutOpt ??
|
|
5954
|
+
idleTimeoutInSeconds: sessionIdleTimeoutOpt ??
|
|
5955
|
+
currentPayload.idleTimeoutInSeconds ??
|
|
5956
|
+
idleTimeoutInSeconds,
|
|
5900
5957
|
timeout,
|
|
5901
5958
|
});
|
|
5902
5959
|
if (!signal || signal.kind === "handover-skip" || runSignal.aborted) {
|
|
@@ -5915,7 +5972,8 @@ function createChatSession(payload, options) {
|
|
|
5915
5972
|
// arrive with the sticky boot-payload fields stripped, so running
|
|
5916
5973
|
// a turn immediately would invoke the model with no user input.
|
|
5917
5974
|
const isMessagelessContinuationBoot = currentPayload.continuation === true && !currentPayload.message;
|
|
5918
|
-
if (turn === 0 &&
|
|
5975
|
+
if (turn === 0 &&
|
|
5976
|
+
(currentPayload.trigger === "preload" || isMessagelessContinuationBoot)) {
|
|
5919
5977
|
const result = await messagesInput.waitWithIdleTimeout({
|
|
5920
5978
|
idleTimeoutInSeconds: sessionIdleTimeoutOpt ?? currentPayload.idleTimeoutInSeconds ?? 30,
|
|
5921
5979
|
timeout,
|
|
@@ -5939,8 +5997,7 @@ function createChatSession(payload, options) {
|
|
|
5939
5997
|
// Subsequent turns: wait for the next message
|
|
5940
5998
|
if (turn > 0) {
|
|
5941
5999
|
// chat.requestUpgrade() / chat.endRun() — exit before waiting
|
|
5942
|
-
if (locals.get(chatUpgradeRequestedKey) ||
|
|
5943
|
-
locals.get(chatEndRunRequestedKey)) {
|
|
6000
|
+
if (locals.get(chatUpgradeRequestedKey) || locals.get(chatEndRunRequestedKey)) {
|
|
5944
6001
|
stop.cleanup();
|
|
5945
6002
|
return { done: true, value: undefined };
|
|
5946
6003
|
}
|
|
@@ -6014,7 +6071,7 @@ function createChatSession(payload, options) {
|
|
|
6014
6071
|
const incomingForAccumulator = currentPayload.message
|
|
6015
6072
|
? [currentPayload.message]
|
|
6016
6073
|
: [];
|
|
6017
|
-
const
|
|
6074
|
+
const _messages = await accumulator.addIncoming(incomingForAccumulator, currentPayload.trigger, turn);
|
|
6018
6075
|
// Apply the head-start handover AFTER addIncoming — turn-0 addIncoming
|
|
6019
6076
|
// replaces accumulator state, which would wipe a pre-applied splice.
|
|
6020
6077
|
// Seed prior history first, then splice the warm step-1 partial.
|
|
@@ -6187,7 +6244,8 @@ function createChatSession(payload, options) {
|
|
|
6187
6244
|
},
|
|
6188
6245
|
];
|
|
6189
6246
|
if (sessionCompaction.compactUIMessages) {
|
|
6190
|
-
accumulator.uiMessages =
|
|
6247
|
+
accumulator.uiMessages =
|
|
6248
|
+
await sessionCompaction.compactUIMessages(compactEvent);
|
|
6191
6249
|
}
|
|
6192
6250
|
}
|
|
6193
6251
|
}
|
|
@@ -6199,7 +6257,10 @@ function createChatSession(payload, options) {
|
|
|
6199
6257
|
// Append any non-transient data parts queued via chat.response or writer.write()
|
|
6200
6258
|
const queuedParts = locals.get(chatResponsePartsKey);
|
|
6201
6259
|
if (queuedParts && queuedParts.length > 0) {
|
|
6202
|
-
response = {
|
|
6260
|
+
response = {
|
|
6261
|
+
...response,
|
|
6262
|
+
parts: [...(response.parts ?? []), ...queuedParts],
|
|
6263
|
+
};
|
|
6203
6264
|
locals.set(chatResponsePartsKey, []);
|
|
6204
6265
|
}
|
|
6205
6266
|
await accumulator.addResponse(response);
|
|
@@ -6468,6 +6529,12 @@ function createChatStartSessionAction(taskId, options) {
|
|
|
6468
6529
|
if (!params.chatId) {
|
|
6469
6530
|
throw new Error("chat.createStartSessionAction: params.chatId is required — used as the session externalId.");
|
|
6470
6531
|
}
|
|
6532
|
+
// Scope the action to `apiClient`'s env: re-enter without it so the body
|
|
6533
|
+
// runs once, under that config (read via apiClientManager.accessToken/.baseURL).
|
|
6534
|
+
if (options?.apiClient) {
|
|
6535
|
+
const { apiClient, ...rest } = options;
|
|
6536
|
+
return apiClientManager.runWithConfig(apiClient, () => createChatStartSessionAction(taskId, rest)(params));
|
|
6537
|
+
}
|
|
6471
6538
|
// The first run boots before the user's first message lands on
|
|
6472
6539
|
// `.in/append`, so it sees an empty `messages` array and `trigger:
|
|
6473
6540
|
// "preload"`. This matches the pre-Sessions preload semantics:
|
|
@@ -6575,9 +6642,7 @@ function createChatStartSessionAction(taskId, options) {
|
|
|
6575
6642
|
}
|
|
6576
6643
|
function resolveChatStartBaseURL(endpoint, chatId, option) {
|
|
6577
6644
|
const fallback = apiClientManager.baseURL ?? "https://api.trigger.dev";
|
|
6578
|
-
const raw = typeof option === "function"
|
|
6579
|
-
? option({ endpoint, chatId })
|
|
6580
|
-
: option ?? fallback;
|
|
6645
|
+
const raw = typeof option === "function" ? option({ endpoint, chatId }) : (option ?? fallback);
|
|
6581
6646
|
return raw.replace(/\/$/, "");
|
|
6582
6647
|
}
|
|
6583
6648
|
function overrideRequestHeaders(accessToken) {
|