@trigger.dev/sdk 0.0.0-chat-prerelease-20260507131256 → 0.0.0-chat-prerelease-20260519091352

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.
Files changed (81) hide show
  1. package/dist/commonjs/v3/agentSkillsRuntime.js +53 -13
  2. package/dist/commonjs/v3/agentSkillsRuntime.js.map +1 -1
  3. package/dist/commonjs/v3/ai-shared.d.ts +24 -12
  4. package/dist/commonjs/v3/ai.d.ts +212 -130
  5. package/dist/commonjs/v3/ai.js +1153 -328
  6. package/dist/commonjs/v3/ai.js.map +1 -1
  7. package/dist/commonjs/v3/chat-client.d.ts +37 -1
  8. package/dist/commonjs/v3/chat-client.js +121 -63
  9. package/dist/commonjs/v3/chat-client.js.map +1 -1
  10. package/dist/commonjs/v3/chat-react.js +0 -2
  11. package/dist/commonjs/v3/chat-react.js.map +1 -1
  12. package/dist/commonjs/v3/chat-server.d.ts +16 -1
  13. package/dist/commonjs/v3/chat-server.js +65 -15
  14. package/dist/commonjs/v3/chat-server.js.map +1 -1
  15. package/dist/commonjs/v3/chat-server.test.js +6 -3
  16. package/dist/commonjs/v3/chat-server.test.js.map +1 -1
  17. package/dist/commonjs/v3/chat.d.ts +76 -7
  18. package/dist/commonjs/v3/chat.js +126 -51
  19. package/dist/commonjs/v3/chat.js.map +1 -1
  20. package/dist/commonjs/v3/chat.test.js +173 -10
  21. package/dist/commonjs/v3/chat.test.js.map +1 -1
  22. package/dist/commonjs/v3/runs.d.ts +4 -0
  23. package/dist/commonjs/v3/sessions.d.ts +40 -0
  24. package/dist/commonjs/v3/sessions.js +100 -2
  25. package/dist/commonjs/v3/sessions.js.map +1 -1
  26. package/dist/commonjs/v3/sessions.test.d.ts +1 -0
  27. package/dist/commonjs/v3/sessions.test.js +154 -0
  28. package/dist/commonjs/v3/sessions.test.js.map +1 -0
  29. package/dist/commonjs/v3/shared.d.ts +1 -1
  30. package/dist/commonjs/v3/shared.js +57 -32
  31. package/dist/commonjs/v3/shared.js.map +1 -1
  32. package/dist/commonjs/v3/streams.js +43 -2
  33. package/dist/commonjs/v3/streams.js.map +1 -1
  34. package/dist/commonjs/v3/test/mock-chat-agent.d.ts +96 -9
  35. package/dist/commonjs/v3/test/mock-chat-agent.js +137 -10
  36. package/dist/commonjs/v3/test/mock-chat-agent.js.map +1 -1
  37. package/dist/commonjs/v3/test/test-session-handle.d.ts +16 -1
  38. package/dist/commonjs/v3/test/test-session-handle.js +28 -0
  39. package/dist/commonjs/v3/test/test-session-handle.js.map +1 -1
  40. package/dist/commonjs/version.js +1 -1
  41. package/dist/esm/v3/agentSkillsRuntime.js +53 -13
  42. package/dist/esm/v3/agentSkillsRuntime.js.map +1 -1
  43. package/dist/esm/v3/ai-shared.d.ts +24 -12
  44. package/dist/esm/v3/ai.d.ts +212 -130
  45. package/dist/esm/v3/ai.js +1148 -330
  46. package/dist/esm/v3/ai.js.map +1 -1
  47. package/dist/esm/v3/chat-client.d.ts +37 -1
  48. package/dist/esm/v3/chat-client.js +122 -64
  49. package/dist/esm/v3/chat-client.js.map +1 -1
  50. package/dist/esm/v3/chat-react.js +0 -2
  51. package/dist/esm/v3/chat-react.js.map +1 -1
  52. package/dist/esm/v3/chat-server.d.ts +16 -1
  53. package/dist/esm/v3/chat-server.js +66 -16
  54. package/dist/esm/v3/chat-server.js.map +1 -1
  55. package/dist/esm/v3/chat-server.test.js +6 -3
  56. package/dist/esm/v3/chat-server.test.js.map +1 -1
  57. package/dist/esm/v3/chat.d.ts +76 -7
  58. package/dist/esm/v3/chat.js +127 -52
  59. package/dist/esm/v3/chat.js.map +1 -1
  60. package/dist/esm/v3/chat.test.js +173 -10
  61. package/dist/esm/v3/chat.test.js.map +1 -1
  62. package/dist/esm/v3/runs.d.ts +4 -0
  63. package/dist/esm/v3/sessions.d.ts +40 -0
  64. package/dist/esm/v3/sessions.js +101 -3
  65. package/dist/esm/v3/sessions.js.map +1 -1
  66. package/dist/esm/v3/sessions.test.d.ts +1 -0
  67. package/dist/esm/v3/sessions.test.js +152 -0
  68. package/dist/esm/v3/sessions.test.js.map +1 -0
  69. package/dist/esm/v3/shared.d.ts +1 -1
  70. package/dist/esm/v3/shared.js +57 -32
  71. package/dist/esm/v3/shared.js.map +1 -1
  72. package/dist/esm/v3/streams.js +43 -3
  73. package/dist/esm/v3/streams.js.map +1 -1
  74. package/dist/esm/v3/test/mock-chat-agent.d.ts +96 -9
  75. package/dist/esm/v3/test/mock-chat-agent.js +137 -10
  76. package/dist/esm/v3/test/mock-chat-agent.js.map +1 -1
  77. package/dist/esm/v3/test/test-session-handle.d.ts +16 -1
  78. package/dist/esm/v3/test/test-session-handle.js +28 -0
  79. package/dist/esm/v3/test/test-session-handle.js.map +1 -1
  80. package/dist/esm/version.js +1 -1
  81. package/package.json +2 -2
@@ -56,25 +56,42 @@ function truncate(s, limit) {
56
56
  return s.slice(0, limit) + `\n…[truncated ${s.length - limit} bytes]`;
57
57
  }
58
58
  /**
59
- * Path-traversal guard: confirm `relative` resolves inside `root`.
60
- * Throws if it escapes via `..` or an absolute prefix. Returns the
61
- * absolute resolved path.
59
+ * Path-traversal guard: confirm `relative` resolves inside `root`,
60
+ * even after symlinks are followed. Throws if it escapes via `..`, an
61
+ * absolute prefix, or a symlink that points outside. Returns the
62
+ * resolved real path.
63
+ *
64
+ * `fs.realpath` only works on paths that exist, so when the resolved
65
+ * path doesn't exist yet (e.g. writing a new file) we fall back to
66
+ * the lexical check — a non-existent path can't traverse a symlink
67
+ * to escape since the symlink doesn't exist either.
62
68
  */
63
- function safeJoinInside(root, relative) {
69
+ async function safeJoinInside(root, relative) {
64
70
  if (nodePath.isAbsolute(relative)) {
65
71
  throw new Error(`Path must be relative to the skill directory: ${relative}`);
66
72
  }
67
- const resolved = nodePath.resolve(root, relative);
68
- const normalized = nodePath.resolve(root) + nodePath.sep;
69
- if (resolved !== nodePath.resolve(root) && !resolved.startsWith(normalized)) {
73
+ const realRoot = await fs.realpath(nodePath.resolve(root));
74
+ const resolved = nodePath.resolve(realRoot, relative);
75
+ let real = resolved;
76
+ try {
77
+ real = await fs.realpath(resolved);
78
+ }
79
+ catch (err) {
80
+ if (err.code !== "ENOENT") {
81
+ throw err;
82
+ }
83
+ // Path doesn't exist yet; fall through with the lexical resolve.
84
+ }
85
+ const normalized = realRoot + nodePath.sep;
86
+ if (real !== realRoot && !real.startsWith(normalized)) {
70
87
  throw new Error(`Path escapes the skill directory: ${relative}`);
71
88
  }
72
- return resolved;
89
+ return real;
73
90
  }
74
91
  async function readFileInSkill({ skillPath, relativePath, }) {
75
92
  let absolute;
76
93
  try {
77
- absolute = safeJoinInside(skillPath, relativePath);
94
+ absolute = await safeJoinInside(skillPath, relativePath);
78
95
  }
79
96
  catch (err) {
80
97
  return { error: err.message };
@@ -100,19 +117,42 @@ async function runBashInSkill({ skillPath, command, abortSignal, }) {
100
117
  resolvePromise({ error: err.message });
101
118
  return;
102
119
  }
120
+ // Cap stdout/stderr accumulation at the byte budget so an
121
+ // LLM-generated command (`cat /dev/zero`, `yes`) can't OOM the
122
+ // worker. Track total seen length separately so the truncation
123
+ // notice still reports how much was dropped.
103
124
  let stdout = "";
104
125
  let stderr = "";
126
+ let stdoutSeen = 0;
127
+ let stderrSeen = 0;
128
+ const limit = DEFAULT_BASH_OUTPUT_BYTES;
105
129
  child.stdout?.on("data", (chunk) => {
106
- stdout += chunk.toString();
130
+ const text = chunk.toString();
131
+ stdoutSeen += text.length;
132
+ if (stdout.length >= limit)
133
+ return;
134
+ const remaining = limit - stdout.length;
135
+ stdout += text.length > remaining ? text.slice(0, remaining) : text;
107
136
  });
108
137
  child.stderr?.on("data", (chunk) => {
109
- stderr += chunk.toString();
138
+ const text = chunk.toString();
139
+ stderrSeen += text.length;
140
+ if (stderr.length >= limit)
141
+ return;
142
+ const remaining = limit - stderr.length;
143
+ stderr += text.length > remaining ? text.slice(0, remaining) : text;
110
144
  });
111
145
  child.once("close", (code) => {
146
+ const stdoutFinal = stdoutSeen > stdout.length
147
+ ? `${stdout}\n…[truncated ${stdoutSeen - stdout.length} bytes]`
148
+ : stdout;
149
+ const stderrFinal = stderrSeen > stderr.length
150
+ ? `${stderr}\n…[truncated ${stderrSeen - stderr.length} bytes]`
151
+ : stderr;
112
152
  resolvePromise({
113
153
  exitCode: code,
114
- stdout: truncate(stdout, DEFAULT_BASH_OUTPUT_BYTES),
115
- stderr: truncate(stderr, DEFAULT_BASH_OUTPUT_BYTES),
154
+ stdout: stdoutFinal,
155
+ stderr: stderrFinal,
116
156
  });
117
157
  });
118
158
  child.once("error", (err) => {
@@ -1 +1 @@
1
- {"version":3,"file":"agentSkillsRuntime.js","sourceRoot":"","sources":["../../../src/v3/agentSkillsRuntime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agentSkillsRuntime.js","sourceRoot":"","sources":["../../../src/v3/agentSkillsRuntime.ts"],"names":[],"mappings":"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"}
@@ -24,9 +24,31 @@ export declare const PENDING_MESSAGE_INJECTED_TYPE: "data-pending-message-inject
24
24
  /**
25
25
  * The wire payload shape sent by `TriggerChatTransport`.
26
26
  * Uses `metadata` to match the AI SDK's `ChatRequestOptions` field name.
27
+ *
28
+ * Slim wire: at most ONE message per record. The agent runtime
29
+ * reconstructs prior history at run boot from a durable S3 snapshot +
30
+ * `session.out` replay (or `hydrateMessages` if registered). The wire is
31
+ * delta-only — see plan `vivid-humming-bonbon.md`.
27
32
  */
28
33
  export type ChatTaskWirePayload<TMessage extends UIMessage = UIMessage, TMetadata = unknown> = {
29
- messages: TMessage[];
34
+ /**
35
+ * The single message being delivered on this trigger. Set for:
36
+ * - `submit-message`: the new user message OR a tool-approval-responded
37
+ * assistant message (with `state: "approval-responded"` tool parts).
38
+ * - `regenerate-message`: omitted (the agent slices its own history).
39
+ * - `preload` / `close` / `action`: omitted.
40
+ * - `handover-prepare`: omitted (use `headStartMessages` instead).
41
+ */
42
+ message?: TMessage;
43
+ /**
44
+ * Bespoke escape hatch for `chat.headStart`. The customer's HTTP route
45
+ * handler ships full `UIMessage[]` history at the very first turn — before
46
+ * any snapshot exists. The route handler isn't subject to the
47
+ * `MAX_APPEND_BODY_BYTES` cap on `/in/append` because it goes through the
48
+ * customer's own HTTP endpoint. Used ONLY by `trigger: "handover-prepare"`.
49
+ * Ignored on every other trigger.
50
+ */
51
+ headStartMessages?: TMessage[];
30
52
  chatId: string;
31
53
  trigger: "submit-message" | "regenerate-message" | "preload" | "close" | "action"
32
54
  /**
@@ -58,16 +80,6 @@ export type ChatTaskWirePayload<TMessage extends UIMessage = UIMessage, TMetadat
58
80
  * required once the legacy run-scoped stream path is removed.
59
81
  */
60
82
  sessionId?: string;
61
- /**
62
- * Client-side `chat.store` value sent by the transport. Applied at turn
63
- * start before `run()` fires, overwriting any in-memory store value on the
64
- * agent (last-write-wins).
65
- *
66
- * The transport queues this via `setStore` / `applyStorePatch` and flushes
67
- * it with the next `sendMessage`. On the agent you typically don't read
68
- * this directly — it's applied into `chat.store` transparently.
69
- */
70
- incomingStore?: unknown;
71
83
  };
72
84
  /**
73
85
  * One chunk on the chat input stream. `kind` discriminates the variants —
@@ -148,7 +160,7 @@ export type ChatInputChunk<TMessage extends UIMessage = UIMessage, TMetadata = u
148
160
  */
149
161
  export type InferChatClientData<TTask extends AnyTask> = TTask extends Task<string, ChatTaskWirePayload<any, infer TMetadata>, any> ? TMetadata : unknown;
150
162
  /**
151
- * Extracts the UI message type from a chat task (wire payload `messages` items).
163
+ * Extracts the UI message type from a chat task (wire payload `message` items).
152
164
  *
153
165
  * @example
154
166
  * ```ts
@@ -1,4 +1,4 @@
1
- import { AnyTask, type RealtimeDefinedInputStream, type RealtimeDefinedStream, Task, type inferSchemaIn, type inferSchemaOut, type TaskIdentifier, type TaskOptions, type TaskSchema, type TaskRunContext, type TaskWithSchema } from "@trigger.dev/core/v3";
1
+ import { AnyTask, type MachinePresetName, type RealtimeDefinedInputStream, type RealtimeDefinedStream, Task, type inferSchemaIn, type inferSchemaOut, type TaskIdentifier, type TaskOptions, type TaskSchema, type TaskRunContext, type TaskWithSchema } from "@trigger.dev/core/v3";
2
2
  import type { FinishReason, ModelMessage, ToolSet, UIMessage, UIMessageChunk, UIMessageStreamOptions, LanguageModelUsage } from "ai";
3
3
  import { Tool, ToolCallOptions } from "ai";
4
4
  import { locals } from "./locals.js";
@@ -7,7 +7,6 @@ import type { ResolvedSkill } from "./skill.js";
7
7
  import { type SessionTriggerConfig } from "@trigger.dev/core/v3";
8
8
  /** Re-export for typing `ctx` in `chat.agent` hooks without importing `@trigger.dev/core`. */
9
9
  export type { TaskRunContext } from "@trigger.dev/core/v3";
10
- import { type ChatStorePatchOperation } from "@trigger.dev/core/v3/chat-client";
11
10
  export type ToolCallExecutionOptions = {
12
11
  toolCallId: string;
13
12
  experimental_context?: unknown;
@@ -24,6 +23,9 @@ type ChatTurnContext<TClientData = unknown> = {
24
23
  continuation: boolean;
25
24
  clientData?: TClientData;
26
25
  };
26
+ export declare function __setReadChatSnapshotImplForTests(impl: ReadChatSnapshotImpl | undefined): void;
27
+ export declare function __setWriteChatSnapshotImplForTests(impl: WriteChatSnapshotImpl | undefined): void;
28
+ export declare function __setReplaySessionOutTailImplForTests(impl: ReplaySessionOutTailImpl | undefined): void;
27
29
  type ToolResultContent = Array<{
28
30
  type: "text";
29
31
  text: string;
@@ -132,29 +134,6 @@ export declare const ai: {
132
134
  * ```
133
135
  */
134
136
  declare function createChatAccessToken<TTask extends AnyTask>(taskId: TaskIdentifier<TTask>): Promise<string>;
135
- /**
136
- * Listener fired when the store value changes. `operations` is present for
137
- * `patch()` updates and absent for `set()` (which is a full snapshot).
138
- */
139
- export type ChatStoreChangeListener<TStore = unknown> = (value: TStore, operations?: ChatStorePatchOperation[]) => void;
140
- /**
141
- * Replace the entire store value with `value`. Emits a `store-snapshot`
142
- * chunk on the chat output stream and fires all `onChange` listeners.
143
- */
144
- declare function chatStoreSet<TStore = unknown>(value: TStore): void;
145
- /**
146
- * Apply RFC 6902 JSON Patch operations to the current store value.
147
- * Emits a `store-delta` chunk on the chat output stream and fires all
148
- * `onChange` listeners with the new value and the operations.
149
- */
150
- declare function chatStorePatch(operations: ChatStorePatchOperation[]): void;
151
- /** Get the current store value. Returns `undefined` if no value has been set. */
152
- declare function chatStoreGet<TStore = unknown>(): TStore | undefined;
153
- /**
154
- * Subscribe to store changes for the current run. Returns an
155
- * unsubscribe function.
156
- */
157
- declare function chatStoreOnChange<TStore = unknown>(listener: ChatStoreChangeListener<TStore>): () => void;
158
137
  /**
159
138
  * A stream writer passed to chat lifecycle callbacks (`onPreload`, `onChatStart`,
160
139
  * `onTurnStart`, `onTurnComplete`, `onCompacted`).
@@ -874,15 +853,68 @@ export type PreloadEvent<TClientData = unknown> = {
874
853
  /** Stream writer — write custom `UIMessageChunk` parts to the chat stream. Lazy: no overhead if unused. */
875
854
  writer: ChatWriter;
876
855
  };
856
+ /**
857
+ * Event passed to the `onBoot` callback.
858
+ *
859
+ * Fires once at the start of every run boot — for the initial first-message
860
+ * run, for preloaded runs, AND for reactive continuation runs (post-cancel,
861
+ * post-crash, post-`endRun`, `chat.requestUpgrade`, OOM-retry attempts).
862
+ * Does NOT fire when the SAME run resumes from snapshot via the
863
+ * idle-window suspend/resume path — use `onChatResume` for that.
864
+ *
865
+ * Use this for per-process setup that needs to run every time a fresh
866
+ * worker picks up the chat: initialize `chat.local` state, open
867
+ * per-process resources (DB connections, sandboxes, etc.), or
868
+ * re-hydrate customer state from your DB on continuation.
869
+ *
870
+ * Ordering:
871
+ * - First message of a chat: `onBoot` → `onChatStart` → `onTurnStart` → `run()`
872
+ * - Preloaded run: `onBoot` → `onPreload` → (wait) → `onChatStart` → ...
873
+ * - Continuation run: `onBoot` → (wait for first message) → `onTurnStart` → `run()`
874
+ * (`onChatStart` does NOT fire on continuation runs)
875
+ */
876
+ export type BootEvent<TClientData = unknown> = {
877
+ /** Task run context — same as `task({ run })` second-argument `ctx`. */
878
+ ctx: TaskRunContext;
879
+ /** The unique identifier for the chat session. */
880
+ chatId: string;
881
+ /** The Trigger.dev run ID for this run boot. */
882
+ runId: string;
883
+ /** A scoped access token for this chat run. Persist this for frontend reconnection. */
884
+ chatAccessToken: string;
885
+ /** Custom data from the frontend (passed via `metadata` on `sendMessage()` or the transport). */
886
+ clientData: TClientData;
887
+ /**
888
+ * True when this run is a reactive continuation — the prior run died
889
+ * (cancel / crash / `endRun` / `requestUpgrade` / OOM retry) and this
890
+ * fresh worker is taking over the chat. Branch on this to re-load
891
+ * customer-owned state from your DB.
892
+ */
893
+ continuation: boolean;
894
+ /** Public id of the prior run when `continuation` is true. */
895
+ previousRunId?: string;
896
+ /** Whether this run was triggered as a preload. */
897
+ preloaded: boolean;
898
+ };
877
899
  /**
878
900
  * Event passed to the `onChatStart` callback.
901
+ *
902
+ * Fires exactly once per chat, on the very first user message of the chat's
903
+ * lifetime. Does NOT fire on continuation runs (post-`endRun`,
904
+ * post-waitpoint-timeout, `chat.requestUpgrade`) or on OOM-retry attempts —
905
+ * those are runs of an already-started chat.
879
906
  */
880
907
  export type ChatStartEvent<TClientData = unknown> = {
881
908
  /** Task run context — same as `task({ run })` second-argument `ctx`. */
882
909
  ctx: TaskRunContext;
883
910
  /** The unique identifier for the chat session. */
884
911
  chatId: string;
885
- /** The initial model-ready messages for this conversation. */
912
+ /**
913
+ * The initial model-ready messages for this conversation. Typically just
914
+ * the first user message (or empty if `chat.headStart` is in play and the
915
+ * seed message is supplied elsewhere). Since this hook only fires for the
916
+ * chat's very first message, there's no prior history to load here.
917
+ */
886
918
  messages: ModelMessage[];
887
919
  /** Custom data from the frontend (passed via `metadata` on `sendMessage()` or the transport). */
888
920
  clientData: TClientData;
@@ -890,9 +922,17 @@ export type ChatStartEvent<TClientData = unknown> = {
890
922
  runId: string;
891
923
  /** A scoped access token for this chat run. Persist this for frontend reconnection. */
892
924
  chatAccessToken: string;
893
- /** Whether this run is continuing an existing chat (previous run timed out or was cancelled). False for brand new chats. */
925
+ /**
926
+ * @deprecated Always `false` — `onChatStart` no longer fires on continuation
927
+ * runs. Kept for backward compatibility; remove your `continuation` checks
928
+ * from `onChatStart` and rely on the contract (this hook fires exactly once
929
+ * per chat, on the very first message).
930
+ */
894
931
  continuation: boolean;
895
- /** The run ID of the previous run (only set when `continuation` is true). */
932
+ /**
933
+ * @deprecated Always `undefined` — `onChatStart` no longer fires on
934
+ * continuation runs.
935
+ */
896
936
  previousRunId?: string;
897
937
  /** Whether this run was preloaded before the first message. */
898
938
  preloaded: boolean;
@@ -920,37 +960,6 @@ export type HydrateMessagesEvent<TClientData = unknown, TUIM extends UIMessage =
920
960
  /** The ID of the previous run (if continuation). */
921
961
  previousRunId?: string;
922
962
  };
923
- /**
924
- * Event passed to the `hydrateStore` callback.
925
- *
926
- * Called at turn start — before `run()` fires and before any incoming store
927
- * from the wire payload is applied. Return the authoritative store value
928
- * for this turn; it becomes the initial value `chat.store.get()` sees.
929
- */
930
- export type HydrateStoreEvent<TClientData = unknown, TStore = unknown> = {
931
- /** The unique identifier for the chat session. */
932
- chatId: string;
933
- /** The turn number (0-indexed). */
934
- turn: number;
935
- /** The trigger type for this turn. */
936
- trigger: "submit-message" | "regenerate-message" | "action" | "preload";
937
- /**
938
- * The in-memory store value from the previous turn of this run
939
- * (`undefined` on turn 0 and after continuations).
940
- */
941
- previousStore: TStore | undefined;
942
- /**
943
- * The store value the transport sent with this turn, if any.
944
- * Usually set by client-side `setStore` / `applyStorePatch`.
945
- */
946
- incomingStore: TStore | undefined;
947
- /** Parsed client data from the transport metadata. */
948
- clientData?: TClientData;
949
- /** Whether this run is continuing from a previous run. */
950
- continuation: boolean;
951
- /** The ID of the previous run (if continuation). */
952
- previousRunId?: string;
953
- };
954
963
  /**
955
964
  * Event passed to the `onValidateMessages` callback.
956
965
  */
@@ -1109,6 +1118,23 @@ export type ChatSuspendEvent<TClientData = unknown, TUIM extends UIMessage = UIM
1109
1118
  runId: string;
1110
1119
  /** Custom data from the frontend. */
1111
1120
  clientData?: TClientData;
1121
+ } | {
1122
+ /**
1123
+ * Suspend is happening on a continuation run that booted with no incoming
1124
+ * message (post-`endRun`, post-waitpoint-timeout, etc.) and is waiting
1125
+ * for the next session.in record before running any turn. Distinct from
1126
+ * `phase: "preload"` — the chat already started; `onPreload` has not
1127
+ * fired and will not fire on this run.
1128
+ */
1129
+ phase: "continuation";
1130
+ /** Task run context. */
1131
+ ctx: TaskRunContext;
1132
+ /** The chat session ID. */
1133
+ chatId: string;
1134
+ /** The Trigger.dev run ID. */
1135
+ runId: string;
1136
+ /** Custom data from the frontend. */
1137
+ clientData?: TClientData;
1112
1138
  } | {
1113
1139
  /** Suspend is happening after a completed turn, waiting for the next message. */
1114
1140
  phase: "turn";
@@ -1142,6 +1168,22 @@ export type ChatResumeEvent<TClientData = unknown, TUIM extends UIMessage = UIMe
1142
1168
  runId: string;
1143
1169
  /** Custom data from the frontend. */
1144
1170
  clientData?: TClientData;
1171
+ } | {
1172
+ /**
1173
+ * First message arrived after continuation-wait suspension. Distinct
1174
+ * from `phase: "preload"` — the chat already started; this is a new
1175
+ * run picking up after a prior run ended (`endRun`, waitpoint timeout,
1176
+ * etc.).
1177
+ */
1178
+ phase: "continuation";
1179
+ /** Task run context. */
1180
+ ctx: TaskRunContext;
1181
+ /** The chat session ID. */
1182
+ chatId: string;
1183
+ /** The Trigger.dev run ID. */
1184
+ runId: string;
1185
+ /** Custom data from the frontend. */
1186
+ clientData?: TClientData;
1145
1187
  } | {
1146
1188
  /** Next message arrived after turn suspension. */
1147
1189
  phase: "turn";
@@ -1160,7 +1202,40 @@ export type ChatResumeEvent<TClientData = unknown, TUIM extends UIMessage = UIMe
1160
1202
  /** Custom data from the frontend. */
1161
1203
  clientData?: TClientData;
1162
1204
  };
1163
- export type ChatAgentOptions<TIdentifier extends string, TClientDataSchema extends TaskSchema | undefined = undefined, TUIMessage extends UIMessage = UIMessage, TActionSchema extends TaskSchema | undefined = undefined> = Omit<TaskOptions<TIdentifier, ChatTaskWirePayload<TUIMessage, inferSchemaIn<TClientDataSchema>>, unknown>, "run"> & {
1205
+ export type ChatAgentOptions<TIdentifier extends string, TClientDataSchema extends TaskSchema | undefined = undefined, TUIMessage extends UIMessage = UIMessage, TActionSchema extends TaskSchema | undefined = undefined> = Omit<TaskOptions<TIdentifier, ChatTaskWirePayload<TUIMessage, inferSchemaIn<TClientDataSchema>>, unknown>, "run" | "retry"> & {
1206
+ /**
1207
+ * Fallback machine preset to use when an attempt fails with an
1208
+ * out-of-memory (OOM) error. Setting this enables a single OOM retry:
1209
+ * the next attempt boots on the larger machine, and the chat picks
1210
+ * up via the standard continuation path (same `chatId` / Session,
1211
+ * accumulator rebuilds via `hydrateMessages` or post-`onTurnStart`
1212
+ * persisted state).
1213
+ *
1214
+ * Set `machine` (top-level `TaskOptions`) to control the *default*
1215
+ * machine the agent runs on. `oomMachine` is the *retry-only* swap.
1216
+ *
1217
+ * Note: an OOM retry restarts the entire turn from the top — the
1218
+ * model call and any in-flight tool executes re-run on the larger
1219
+ * machine. Make tool executes idempotent or persist results before
1220
+ * returning if you can't tolerate re-execution.
1221
+ *
1222
+ * Generic `retry` options are not exposed on `chat.agent` because
1223
+ * arbitrary retries against an LLM-driven loop tend to be expensive
1224
+ * and side-effecting. If you need richer retry semantics, drop down
1225
+ * to `chat.task` (the raw primitive).
1226
+ *
1227
+ * @example
1228
+ * ```ts
1229
+ * chat.agent({
1230
+ * id: "my-chat",
1231
+ * machine: "small-1x",
1232
+ * oomMachine: "medium-2x",
1233
+ * run: async ({ messages, signal }) =>
1234
+ * streamText({ model, messages, abortSignal: signal }),
1235
+ * });
1236
+ * ```
1237
+ */
1238
+ oomMachine?: MachinePresetName;
1164
1239
  /**
1165
1240
  * Schema for validating `clientData` from the frontend.
1166
1241
  * Accepts Zod, ArkType, Valibot, or any supported schema library.
@@ -1233,6 +1308,35 @@ export type ChatAgentOptions<TIdentifier extends string, TClientDataSchema exten
1233
1308
  * the stream is automatically piped to the frontend.
1234
1309
  */
1235
1310
  run: (payload: ChatTaskRunPayload<inferSchemaOut<TClientDataSchema>>) => Promise<unknown>;
1311
+ /**
1312
+ * Called once at the start of every run boot — for the initial run, for
1313
+ * preloaded runs, AND for reactive continuation runs (post-cancel /
1314
+ * crash / `endRun` / `requestUpgrade` / OOM retry).
1315
+ *
1316
+ * Use this for per-process setup that needs to run every time a fresh
1317
+ * worker picks up the chat: initialize `chat.local` state, open
1318
+ * per-process resources, or re-hydrate customer state from your DB
1319
+ * on continuation. Branch on `continuation` to decide whether to load
1320
+ * existing state vs. start fresh.
1321
+ *
1322
+ * Fires BEFORE `onPreload` (preloaded path) and `onChatStart`
1323
+ * (first-message path), so `chat.local` is safe to read in those hooks.
1324
+ *
1325
+ * Does NOT fire when the same run resumes from snapshot via the
1326
+ * idle-window suspend/resume path — use `onChatResume` for that.
1327
+ *
1328
+ * @example
1329
+ * ```ts
1330
+ * onBoot: async ({ chatId, clientData, continuation }) => {
1331
+ * const user = await db.user.findFirst({ where: { id: clientData.userId } });
1332
+ * userContext.init({ name: user.name, plan: user.plan });
1333
+ * if (continuation) {
1334
+ * // re-hydrate any per-chat in-memory state from your DB
1335
+ * }
1336
+ * }
1337
+ * ```
1338
+ */
1339
+ onBoot?: (event: BootEvent<inferSchemaOut<TClientDataSchema>>) => Promise<void> | void;
1236
1340
  /**
1237
1341
  * Called when a preloaded run starts, before the first message arrives.
1238
1342
  *
@@ -1249,9 +1353,16 @@ export type ChatAgentOptions<TIdentifier extends string, TClientDataSchema exten
1249
1353
  */
1250
1354
  onPreload?: (event: PreloadEvent<inferSchemaOut<TClientDataSchema>>) => Promise<void> | void;
1251
1355
  /**
1252
- * Called on the first turn (turn 0) of a new run, before the `run` function executes.
1356
+ * Called exactly once per chat, on the very first user message of the
1357
+ * chat's lifetime. Does NOT fire on continuation runs (post-`endRun`,
1358
+ * post-waitpoint-timeout, `chat.requestUpgrade`) or on OOM-retry attempts —
1359
+ * those are runs of an already-started chat.
1253
1360
  *
1254
- * Use this to create the chat record in your database when a new conversation starts.
1361
+ * Use this for one-time chat-setup work creating the Chat DB row,
1362
+ * initializing per-chat in-memory state, minting resources tied to the
1363
+ * chat's lifetime. Safe to assume no prior history exists here.
1364
+ *
1365
+ * For per-turn work, use `onTurnStart`.
1255
1366
  *
1256
1367
  * @example
1257
1368
  * ```ts
@@ -1323,43 +1434,6 @@ export type ChatAgentOptions<TIdentifier extends string, TClientDataSchema exten
1323
1434
  * ```
1324
1435
  */
1325
1436
  hydrateMessages?: (event: HydrateMessagesEvent<inferSchemaOut<TClientDataSchema>, TUIMessage>) => TUIMessage[] | Promise<TUIMessage[]>;
1326
- /**
1327
- * Load the `chat.store` value for this turn from your backend.
1328
- *
1329
- * The store lives in memory on the agent instance for the lifetime of
1330
- * the run. After a continuation (idle timeout, `chat.requestUpgrade`,
1331
- * max turns), a new run starts with an empty store — this hook lets
1332
- * you restore it from your own persistence layer.
1333
- *
1334
- * Runs at turn start, before `run()` fires. The returned value replaces
1335
- * the in-memory store and is emitted as a `store-snapshot` chunk so the
1336
- * frontend sees the initial value.
1337
- *
1338
- * If both `hydrateStore` and `incomingStore` (from the wire payload) are
1339
- * present, `incomingStore` wins — it represents the client's latest
1340
- * local state and follows AG-UI's last-write-wins policy.
1341
- *
1342
- * @example
1343
- * ```ts
1344
- * chat.agent({
1345
- * id: "my-chat",
1346
- * hydrateStore: async ({ chatId, previousRunId }) => {
1347
- * return db.chatStore.findUnique({ where: { chatId } })?.value;
1348
- * },
1349
- * onTurnComplete: async ({ chatId }) => {
1350
- * await db.chatStore.upsert({
1351
- * where: { chatId },
1352
- * update: { value: chat.store.get() },
1353
- * create: { chatId, value: chat.store.get() },
1354
- * });
1355
- * },
1356
- * run: async ({ messages, signal }) => {
1357
- * return streamText({ model: openai("gpt-4o"), messages, abortSignal: signal });
1358
- * },
1359
- * });
1360
- * ```
1361
- */
1362
- hydrateStore?: (event: HydrateStoreEvent<inferSchemaOut<TClientDataSchema>>) => unknown | Promise<unknown>;
1363
1437
  /**
1364
1438
  * Called at the start of every turn, after message accumulation and `onChatStart` (turn 0),
1365
1439
  * but before the `run` function executes.
@@ -1688,6 +1762,8 @@ export interface ChatBuilder<TUIMessage extends UIMessage = UIMessage, TClientDa
1688
1762
  withClientData<TSchema extends TaskSchema>(config: {
1689
1763
  schema: TSchema;
1690
1764
  }): ChatBuilder<TUIMessage, TSchema>;
1765
+ /** Register a builder-level `onBoot` hook. Runs before the task-level hook if both are set. */
1766
+ onBoot(fn: (event: BootEvent<inferSchemaOut<TClientDataSchema>>) => Promise<void> | void): ChatBuilder<TUIMessage, TClientDataSchema>;
1691
1767
  /** Register a builder-level `onPreload` hook. Runs before the task-level hook if both are set. */
1692
1768
  onPreload(fn: (event: PreloadEvent<inferSchemaOut<TClientDataSchema>>) => Promise<void> | void): ChatBuilder<TUIMessage, TClientDataSchema>;
1693
1769
  /** Register a builder-level `onChatStart` hook. Runs before the task-level hook if both are set. */
@@ -2255,8 +2331,11 @@ export type ChatLocal<T extends Record<string, unknown>> = T & {
2255
2331
  /**
2256
2332
  * Creates a per-run typed data object accessible from anywhere during task execution.
2257
2333
  *
2258
- * Declare at module level, then initialize inside a lifecycle hook (e.g. `onChatStart`)
2259
- * using `chat.initLocal()`. Properties are accessible directly via the Proxy.
2334
+ * Declare at module level, then initialize inside `onBoot` (recommended fires
2335
+ * on every fresh worker including continuation runs). Do NOT initialize in
2336
+ * `onChatStart` alone: `onChatStart` only fires on the chat's very first
2337
+ * message, so `chat.local` would be uninitialized on continuation runs and
2338
+ * `run()` would throw.
2260
2339
  *
2261
2340
  * Multiple locals can coexist — each gets its own isolated run-scoped storage.
2262
2341
  *
@@ -2273,7 +2352,7 @@ export type ChatLocal<T extends Record<string, unknown>> = T & {
2273
2352
  *
2274
2353
  * export const myChat = chat.agent({
2275
2354
  * id: "my-chat",
2276
- * onChatStart: async ({ clientData }) => {
2355
+ * onBoot: async ({ clientData }) => {
2277
2356
  * const prefs = await db.prefs.findUnique({ where: { userId: clientData.userId } });
2278
2357
  * userPrefs.init(prefs ?? { theme: "dark", language: "en" });
2279
2358
  * gameState.init({ score: 0, streak: 0 });
@@ -2314,6 +2393,22 @@ export type { InferChatClientData, InferChatUIMessage } from "./ai-shared.js";
2314
2393
  /**
2315
2394
  * Options for {@link createChatStartSessionAction}.
2316
2395
  */
2396
+ /**
2397
+ * Discriminator for per-endpoint `baseURL` / `fetch` callbacks on
2398
+ * `createChatStartSessionAction`.
2399
+ *
2400
+ * - `"sessions"` — `POST /api/v1/sessions` (session create + first run trigger).
2401
+ * - `"auth"` — `POST /api/v1/auth/jwt/claims` (only fired when
2402
+ * `tokenTTL` is set; otherwise the publicAccessToken from session create
2403
+ * is reused as-is).
2404
+ */
2405
+ export type ChatStartSessionEndpoint = "sessions" | "auth";
2406
+ export type ChatStartSessionEndpointContext = {
2407
+ endpoint: ChatStartSessionEndpoint;
2408
+ chatId: string;
2409
+ };
2410
+ export type ChatStartSessionBaseURLResolver = (ctx: ChatStartSessionEndpointContext) => string;
2411
+ export type ChatStartSessionFetchOverride = (url: string, init: RequestInit, ctx: ChatStartSessionEndpointContext) => Promise<Response>;
2317
2412
  export type CreateChatStartSessionActionOptions = {
2318
2413
  /** TTL for the session-scoped public access token. @default "1h" */
2319
2414
  tokenTTL?: string | number | Date;
@@ -2322,6 +2417,21 @@ export type CreateChatStartSessionActionOptions = {
2322
2417
  * Per-call `params.triggerConfig` shallow-merges on top.
2323
2418
  */
2324
2419
  triggerConfig?: Partial<SessionTriggerConfig>;
2420
+ /**
2421
+ * Override the Trigger.dev API base URL. String applies to both
2422
+ * `/api/v1/sessions` and `/api/v1/auth/jwt/claims`; function picks per
2423
+ * endpoint. When unset, falls back to `apiClientManager.baseURL`
2424
+ * (typically the `TRIGGER_API_URL` env var). Set this to route session
2425
+ * create through a trusted edge proxy that injects server-side signal
2426
+ * into `basePayload.metadata` before forwarding upstream.
2427
+ */
2428
+ baseURL?: string | ChatStartSessionBaseURLResolver;
2429
+ /**
2430
+ * Per-request fetch override. Receives the resolved URL, RequestInit,
2431
+ * and endpoint context. Use for header injection, proxy routing, or
2432
+ * custom retry. Applies to both session-create and JWT-claims POSTs.
2433
+ */
2434
+ fetch?: ChatStartSessionFetchOverride;
2325
2435
  };
2326
2436
  /**
2327
2437
  * Params for the function returned by {@link createChatStartSessionAction}.
@@ -2432,34 +2542,6 @@ export declare const chat: {
2432
2542
  */
2433
2543
  write(part: UIMessageChunk): void;
2434
2544
  };
2435
- /**
2436
- * Typed, bidirectional shared data slot for the chat.
2437
- *
2438
- * Use from `chat.agent` hooks and `run()` to share state with the client.
2439
- * Setting emits a `store-snapshot` chunk; patching emits `store-delta`.
2440
- * The value persists across turns within the same run, and can be
2441
- * restored after continuations via the `hydrateStore` config option.
2442
- *
2443
- * ```ts
2444
- * chat.store.set({ plan: ["research", "draft", "review"] });
2445
- * chat.store.patch([{ op: "replace", path: "/status", value: "done" }]);
2446
- * const current = chat.store.get();
2447
- * const off = chat.store.onChange((value, ops) => { ... });
2448
- * ```
2449
- */
2450
- store: {
2451
- /** Replace the store value. Emits a `store-snapshot` chunk. */
2452
- set: typeof chatStoreSet;
2453
- /**
2454
- * Apply RFC 6902 JSON Patch operations to the current value.
2455
- * Emits a `store-delta` chunk.
2456
- */
2457
- patch: typeof chatStorePatch;
2458
- /** Read the current store value. Returns `undefined` if never set. */
2459
- get: typeof chatStoreGet;
2460
- /** Subscribe to store changes. Returns an unsubscribe function. */
2461
- onChange: typeof chatStoreOnChange;
2462
- };
2463
2545
  /** Pre-built input stream for receiving messages from the transport. */
2464
2546
  messages: RealtimeDefinedInputStream<ChatTaskWirePayload>;
2465
2547
  /** Create a managed stop signal wired to the stop input stream. See {@link createStopSignal}. */