@trigger.dev/sdk 4.7.3 → 4.8.0-webhooks.20261015065339

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 (154) hide show
  1. package/dist/commonjs/v3/ai.d.ts +560 -8
  2. package/dist/commonjs/v3/ai.js +2263 -178
  3. package/dist/commonjs/v3/ai.js.map +1 -1
  4. package/dist/commonjs/v3/chat.d.ts +23 -0
  5. package/dist/commonjs/v3/chat.js.map +1 -1
  6. package/dist/commonjs/v3/concurrencyLimits.d.ts +37 -7
  7. package/dist/commonjs/v3/concurrencyLimits.js +38 -70
  8. package/dist/commonjs/v3/concurrencyLimits.js.map +1 -1
  9. package/dist/commonjs/v3/index.d.ts +3 -1
  10. package/dist/commonjs/v3/index.js +23 -17
  11. package/dist/commonjs/v3/index.js.map +1 -1
  12. package/dist/commonjs/v3/modelFileDownload.d.ts +10 -0
  13. package/dist/commonjs/v3/modelFileDownload.js +164 -0
  14. package/dist/commonjs/v3/modelFileDownload.js.map +1 -0
  15. package/dist/commonjs/v3/runs.d.ts +22 -1
  16. package/dist/commonjs/v3/runs.js +6 -3
  17. package/dist/commonjs/v3/runs.js.map +1 -1
  18. package/dist/commonjs/v3/test/index.d.ts +2 -1
  19. package/dist/commonjs/v3/test/index.js +4 -1
  20. package/dist/commonjs/v3/test/index.js.map +1 -1
  21. package/dist/commonjs/v3/test/mock-channel-connector.d.ts +172 -0
  22. package/dist/commonjs/v3/test/mock-channel-connector.js +173 -0
  23. package/dist/commonjs/v3/test/mock-channel-connector.js.map +1 -0
  24. package/dist/commonjs/v3/test/mock-chat-agent.d.ts +81 -1
  25. package/dist/commonjs/v3/test/mock-chat-agent.js +137 -10
  26. package/dist/commonjs/v3/test/mock-chat-agent.js.map +1 -1
  27. package/dist/commonjs/v3/transcriptStorage.d.ts +44 -1
  28. package/dist/commonjs/v3/transcriptStorage.js +24 -0
  29. package/dist/commonjs/v3/transcriptStorage.js.map +1 -1
  30. package/dist/commonjs/v3/webhookWaiters.d.ts +80 -0
  31. package/dist/commonjs/v3/webhookWaiters.js +156 -0
  32. package/dist/commonjs/v3/webhookWaiters.js.map +1 -0
  33. package/dist/commonjs/v3/webhooks.d.ts +178 -2
  34. package/dist/commonjs/v3/webhooks.js +322 -1
  35. package/dist/commonjs/v3/webhooks.js.map +1 -1
  36. package/dist/commonjs/version.js +1 -1
  37. package/dist/esm/v3/ai.d.ts +560 -8
  38. package/dist/esm/v3/ai.js +2257 -178
  39. package/dist/esm/v3/ai.js.map +1 -1
  40. package/dist/esm/v3/chat.d.ts +23 -0
  41. package/dist/esm/v3/chat.js.map +1 -1
  42. package/dist/esm/v3/concurrencyLimits.d.ts +37 -7
  43. package/dist/esm/v3/concurrencyLimits.js +38 -70
  44. package/dist/esm/v3/concurrencyLimits.js.map +1 -1
  45. package/dist/esm/v3/index.d.ts +3 -1
  46. package/dist/esm/v3/index.js +1 -0
  47. package/dist/esm/v3/index.js.map +1 -1
  48. package/dist/esm/v3/modelFileDownload.d.ts +10 -0
  49. package/dist/esm/v3/modelFileDownload.js +161 -0
  50. package/dist/esm/v3/modelFileDownload.js.map +1 -0
  51. package/dist/esm/v3/runs.d.ts +22 -1
  52. package/dist/esm/v3/runs.js +6 -3
  53. package/dist/esm/v3/runs.js.map +1 -1
  54. package/dist/esm/v3/test/index.d.ts +2 -1
  55. package/dist/esm/v3/test/index.js +2 -1
  56. package/dist/esm/v3/test/index.js.map +1 -1
  57. package/dist/esm/v3/test/mock-channel-connector.d.ts +172 -0
  58. package/dist/esm/v3/test/mock-channel-connector.js +170 -0
  59. package/dist/esm/v3/test/mock-channel-connector.js.map +1 -0
  60. package/dist/esm/v3/test/mock-chat-agent.d.ts +81 -1
  61. package/dist/esm/v3/test/mock-chat-agent.js +137 -11
  62. package/dist/esm/v3/test/mock-chat-agent.js.map +1 -1
  63. package/dist/esm/v3/transcriptStorage.d.ts +44 -1
  64. package/dist/esm/v3/transcriptStorage.js +24 -0
  65. package/dist/esm/v3/transcriptStorage.js.map +1 -1
  66. package/dist/esm/v3/webhookWaiters.d.ts +80 -0
  67. package/dist/esm/v3/webhookWaiters.js +149 -0
  68. package/dist/esm/v3/webhookWaiters.js.map +1 -0
  69. package/dist/esm/v3/webhooks.d.ts +178 -2
  70. package/dist/esm/v3/webhooks.js +318 -1
  71. package/dist/esm/v3/webhooks.js.map +1 -1
  72. package/dist/esm/version.js +1 -1
  73. package/docs/ai-chat/actions.mdx +6 -1
  74. package/docs/ai-chat/backend.mdx +34 -0
  75. package/docs/ai-chat/patterns/sub-agents.mdx +33 -0
  76. package/docs/ai-chat/pending-messages.mdx +2 -0
  77. package/docs/ai-chat/reference.mdx +50 -2
  78. package/docs/apikeys.mdx +3 -3
  79. package/docs/billing-limits.mdx +1 -1
  80. package/docs/cli-env-commands.mdx +5 -4
  81. package/docs/cli-init-commands.mdx +27 -1
  82. package/docs/cli-login-commands.mdx +20 -0
  83. package/docs/cli-projects-commands.mdx +13 -1
  84. package/docs/cli-runs-commands.mdx +3 -2
  85. package/docs/cli-update-commands.mdx +9 -3
  86. package/docs/cli-whoami-commands.mdx +12 -0
  87. package/docs/concurrency.mdx +32 -0
  88. package/docs/config/extensions/audioWaveform.mdx +4 -1
  89. package/docs/config/extensions/overview.mdx +2 -0
  90. package/docs/config/extensions/prismaExtension.mdx +2 -3
  91. package/docs/config/extensions/puppeteer.mdx +3 -5
  92. package/docs/config/extensions/pythonExtension.mdx +9 -1
  93. package/docs/config/extensions/syncEnvVars.mdx +6 -0
  94. package/docs/deploy-environment-variables.mdx +1 -1
  95. package/docs/deployment/atomic-deployment.mdx +2 -0
  96. package/docs/deployment/dev-branches.mdx +5 -5
  97. package/docs/deployment/overview.mdx +8 -7
  98. package/docs/deployment/preview-branches.mdx +6 -3
  99. package/docs/errors-retrying.mdx +4 -4
  100. package/docs/how-it-works.mdx +5 -5
  101. package/docs/introduction.mdx +6 -0
  102. package/docs/limits.mdx +26 -8
  103. package/docs/logging.mdx +1 -1
  104. package/docs/machines.mdx +1 -1
  105. package/docs/mcp-introduction.mdx +8 -7
  106. package/docs/mcp-tools.mdx +91 -1
  107. package/docs/migrating-from-v3.mdx +1 -1
  108. package/docs/observability/dashboards.mdx +2 -0
  109. package/docs/observability/query.mdx +6 -2
  110. package/docs/private-networking/aws-console-setup.mdx +1 -1
  111. package/docs/private-networking/overview.mdx +1 -1
  112. package/docs/quick-start.mdx +3 -40
  113. package/docs/realtime/auth.mdx +1 -1
  114. package/docs/realtime/backend/input-streams.mdx +159 -0
  115. package/docs/realtime/backend/streams.mdx +25 -10
  116. package/docs/realtime/how-it-works.mdx +1 -1
  117. package/docs/realtime/react-hooks/overview.mdx +1 -1
  118. package/docs/realtime/react-hooks/streams.mdx +2 -2
  119. package/docs/realtime/react-hooks/subscribe.mdx +19 -3
  120. package/docs/realtime/react-hooks/triggering.mdx +2 -2
  121. package/docs/realtime/react-hooks/use-wait-token.mdx +1 -1
  122. package/docs/realtime/run-object.mdx +47 -24
  123. package/docs/replaying.mdx +26 -1
  124. package/docs/reports.mdx +4 -2
  125. package/docs/run-tests.mdx +2 -2
  126. package/docs/run-usage.mdx +3 -3
  127. package/docs/runs/heartbeats.mdx +2 -2
  128. package/docs/runs/list-best-practices.mdx +234 -0
  129. package/docs/runs/metadata.mdx +7 -10
  130. package/docs/runs.mdx +18 -8
  131. package/docs/self-hosting/env/supervisor.mdx +2 -0
  132. package/docs/self-hosting/env/webapp.mdx +5 -0
  133. package/docs/self-hosting/overview.mdx +26 -0
  134. package/docs/tags.mdx +6 -0
  135. package/docs/tasks/scheduled.mdx +11 -5
  136. package/docs/triggering.mdx +8 -0
  137. package/docs/troubleshooting-alerts.mdx +102 -3
  138. package/docs/troubleshooting.mdx +1 -1
  139. package/docs/upgrading-packages.mdx +3 -3
  140. package/docs/vercel-integration.mdx +13 -3
  141. package/docs/versioning.mdx +1 -1
  142. package/docs/wait-for-token.mdx +3 -3
  143. package/docs/webhooks/channels.mdx +128 -0
  144. package/docs/webhooks/connect.mdx +80 -0
  145. package/docs/webhooks/deliveries.mdx +92 -0
  146. package/docs/webhooks/filters.mdx +109 -0
  147. package/docs/webhooks/human-in-the-loop.mdx +149 -0
  148. package/docs/webhooks/linear.mdx +185 -0
  149. package/docs/webhooks/overview.mdx +99 -0
  150. package/docs/webhooks/session-routing.mdx +132 -0
  151. package/docs/webhooks/slack.mdx +360 -0
  152. package/docs/webhooks/sources.mdx +217 -0
  153. package/docs/webhooks/waiters.mdx +170 -0
  154. package/package.json +3 -2
@@ -1,6 +1,7 @@
1
- import { type AnyTask, type Task, type ApiClientConfiguration, type inferSchemaIn, type inferSchemaOut, type MachinePresetName, type RealtimeDefinedInputStream, type RealtimeDefinedStream, type TaskIdentifier, type TaskOptions, type TaskRunContext, type TaskSchema, type TaskWithSchema, type AnySessionChannel, type SessionChannelName } from "@trigger.dev/core/v3";
1
+ import { type AnyTask, type Task, type ApiClientConfiguration, type inferSchemaIn, type inferSchemaOut, type MachinePresetName, type RealtimeDefinedInputStream, type RealtimeDefinedStream, type TaskIdentifier, type TaskOptions, type TaskRunContext, type TaskSchema, type TaskWithSchema, type AnySessionChannel, type SessionChannelName, type AnyChatEvent, type ChatEventActions, type ValidatedWebhookKey, type ValidateWebhookFilter, type NarrowWebhookEvent, type AnyWebhookEndpoint, type InferWebhookEndpointEvent } from "@trigger.dev/core/v3";
2
2
  import type { streamText as aiStreamTextSignature, FinishReason, LanguageModelUsage, ModelMessage, SystemModelMessage, ProviderMetadata, Tool, ToolSet, UIMessage, UIMessageChunk, UIMessageStreamOptions } from "ai";
3
- import { type TranscriptLoadResult, type TranscriptStorage } from "./transcriptStorage.js";
3
+ import { chatEvent } from "./webhooks.js";
4
+ import { type TranscriptLoadResult, type TranscriptChannelBinding, type TranscriptStorage } from "./transcriptStorage.js";
4
5
  import { type ChatInputChunk, type ChatTaskWirePayload, type InferChatClientData, type InferChatUIMessage, type InferChatUIMessageFromTools, PENDING_MESSAGE_INJECTED_TYPE, upsertIncomingMessage } from "./ai-shared.js";
5
6
  import { locals } from "./locals.js";
6
7
  import type { ResolvedPrompt } from "./prompt.js";
@@ -149,6 +150,31 @@ export declare const ai: {
149
150
  * ```
150
151
  */
151
152
  declare function createChatAccessToken<TTask extends AnyTask>(taskId: TaskIdentifier<TTask>): Promise<string>;
153
+ /**
154
+ * Mint a read-only, session-scoped token for WATCHING a chat session by its `externalId`.
155
+ *
156
+ * A session is addressed by `externalId`, so the same session is reachable from any surface that
157
+ * knows it: a web `useChat` client and a Slack thread converge on one session when they share an
158
+ * `externalId` (for a channel, the connector's `key` template produces it). This token carries
159
+ * `read:sessions:{externalId}` only (no write): the holder can subscribe to the session's `.out`
160
+ * stream (observe the conversation, hydrating history from the snapshot) but cannot append to `.in`.
161
+ *
162
+ * Use it for a dashboard viewer or a cross-surface watcher of a Slack-thread session. Run server-side
163
+ * (needs the secret key). To CONTINUE a session from another surface (drive it, not just watch), mint
164
+ * a read+write token instead ({@link createChatStartSessionAction}).
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * // actions.ts
169
+ * "use server";
170
+ * import { chat } from "@trigger.dev/sdk/ai";
171
+ *
172
+ * export const watchChat = (externalId: string) => chat.createWatchToken(externalId);
173
+ * ```
174
+ */
175
+ declare function createChatWatchToken(externalId: string, options?: {
176
+ tokenTTL?: string;
177
+ }): Promise<string>;
152
178
  /**
153
179
  * Register work that must land before anything from this turn reaches the
154
180
  * frontend.
@@ -308,6 +334,12 @@ export type ChatTaskRunPayload<TClientData = unknown, TTools extends ToolSet = T
308
334
  * `tools` option on `chat.agent`). Empty object when no `tools` were declared.
309
335
  */
310
336
  tools: TTools;
337
+ /**
338
+ * Present for a channel turn whose connector supports reactions or defines a `surface()`. Lets the
339
+ * agent react to the triggering message (e.g. `channel.react("white_check_mark")`) and use the
340
+ * connector's helpers (cast to the connector's exported surface type).
341
+ */
342
+ channel?: ChannelRunSurface;
311
343
  };
312
344
  /**
313
345
  * One message record delivered through {@link chat.messages}.
@@ -1042,6 +1074,8 @@ declare const actionTurnBrand: unique symbol;
1042
1074
  */
1043
1075
  export type ActionTurn = {
1044
1076
  readonly [actionTurnBrand]: true;
1077
+ /** A user message the turn answers, appended to the history after the action's edit. */
1078
+ readonly message?: string | UIMessage;
1045
1079
  };
1046
1080
  /**
1047
1081
  * Turn the current action into a turn.
@@ -1054,6 +1088,9 @@ export type ActionTurn = {
1054
1088
  * tools, steering, compaction, injected instructions and persistence, with no
1055
1089
  * action-specific handling.
1056
1090
  *
1091
+ * Pass `message` to have the turn answer a new user message, appended after the edit: a click on a
1092
+ * "Explain more" button becomes `chat.turn("Explain that in more detail.")`.
1093
+ *
1057
1094
  * @example
1058
1095
  * ```ts
1059
1096
  * onAction: async ({ action }) => {
@@ -1061,11 +1098,12 @@ export type ActionTurn = {
1061
1098
  * chat.history.slice(0, -1);
1062
1099
  * return chat.turn();
1063
1100
  * }
1101
+ * if (action.type === "ask") return chat.turn(action.question);
1064
1102
  * if (action.type === "undo") chat.history.slice(0, -2); // no turn
1065
1103
  * },
1066
1104
  * ```
1067
1105
  */
1068
- declare function chatTurn(): ActionTurn;
1106
+ declare function chatTurn(message?: string | UIMessage): ActionTurn;
1069
1107
  /**
1070
1108
  * Pipes a chat stream to the realtime stream, making it available to the
1071
1109
  * `TriggerChatTransport` on the frontend.
@@ -1408,6 +1446,18 @@ export type ActionEvent<TAction = unknown, TClientData = unknown, TUIM extends U
1408
1446
  uiMessages: TUIM[];
1409
1447
  /** The accumulated model messages (after hydration, if set). */
1410
1448
  messages: ModelMessage[];
1449
+ /**
1450
+ * The click that sent a channel action (a `slackButton()` in Slack): the verified provider event,
1451
+ * with who clicked and the message the button was on. Absent for client and webhook actions.
1452
+ */
1453
+ channel?: ChannelActionSource;
1454
+ };
1455
+ /** Where a channel action came from: the connector and the verified event of the click. */
1456
+ export type ChannelActionSource = {
1457
+ connectorId: string;
1458
+ provider: string;
1459
+ event: unknown;
1460
+ deliveryId: string;
1411
1461
  };
1412
1462
  /**
1413
1463
  * Event passed to the `onTurnStart` callback.
@@ -1632,7 +1682,464 @@ export type ChatResumeEvent<TClientData = unknown, TUIM extends UIMessage = UIMe
1632
1682
  /** Custom data from the frontend. */
1633
1683
  clientData?: TClientData;
1634
1684
  };
1635
- export type ChatAgentOptions<TIdentifier extends string, TClientDataSchema extends TaskSchema | undefined = undefined, TUIMessage extends UIMessage = UIMessage, TActionSchema extends TaskSchema | undefined = undefined, TTools extends ToolSet = ToolSet> = Omit<TaskOptions<TIdentifier, ChatTaskWirePayload<TUIMessage, inferSchemaIn<TClientDataSchema>>, unknown>, "run" | "retry"> & {
1685
+ export type ChannelMessageInput = string | UIMessage;
1686
+ /**
1687
+ * What a connector's `inbound()` returns: the turn's message, optionally with who sent it on
1688
+ * the provider and the provider's own message id. Both land on the user message's `metadata`
1689
+ * (with `source: "channel"`, the connector id, the provider and the delivery id), so a
1690
+ * transcript storage can attribute and reconcile channel messages.
1691
+ */
1692
+ export type ChannelInbound = ChannelMessageInput | {
1693
+ message: ChannelMessageInput;
1694
+ externalUserId?: string;
1695
+ externalMessageId?: string;
1696
+ };
1697
+ /** The `metadata` the runtime stamps on a channel-delivered user message. */
1698
+ export type ChannelMessageMetadata = {
1699
+ source: "channel";
1700
+ connectorId: string;
1701
+ provider: string;
1702
+ /** The delivery that carried the message (`whd_...`). */
1703
+ deliveryId: string;
1704
+ /** The provider's id for that delivery, the same across replays. */
1705
+ externalDeliveryId?: string;
1706
+ externalUserId?: string;
1707
+ externalMessageId?: string;
1708
+ /** True on a message the connector supplied from the surface's existing conversation via `seed()`. */
1709
+ seeded?: boolean;
1710
+ };
1711
+ /**
1712
+ * A prior message from the surface, returned by a connector's `seed()` when a session starts on a
1713
+ * conversation that already has history (a Slack thread the bot was summoned into). Becomes a
1714
+ * transcript message ahead of the triggering one, so the agent can answer with the context a human
1715
+ * reading the thread would have.
1716
+ */
1717
+ export type ChannelSeedMessage = {
1718
+ role: "user" | "assistant";
1719
+ text: string;
1720
+ /** The provider's id for the message; used as the transcript message id suffix and kept in metadata. */
1721
+ externalMessageId?: string;
1722
+ externalUserId?: string;
1723
+ };
1724
+ export type ChannelSeedCtx<TEvent = unknown> = {
1725
+ event: TEvent;
1726
+ deliveryId: string;
1727
+ };
1728
+ /** A file a connector fetched for the model: its bytes, and the media type when the surface reports one. */
1729
+ export type ChannelDownloadedFile = {
1730
+ data: Uint8Array;
1731
+ mediaType?: string;
1732
+ };
1733
+ /**
1734
+ * The channel a session answers into, once a channel turn has bound it. The connector's
1735
+ * `bind()` derives the handle from a verified event; later turns that did not start from a
1736
+ * channel delivery (a `chat.event` action that returns `chat.turn()`, a browser message on the
1737
+ * same session) egress through it.
1738
+ */
1739
+ export type ChannelBinding<THandle = unknown> = TranscriptChannelBinding<THandle>;
1740
+ export type ChannelMessage = {
1741
+ text: string;
1742
+ [key: string]: unknown;
1743
+ };
1744
+ export type ChannelReply = {
1745
+ text: string;
1746
+ message: UIMessage;
1747
+ final: boolean;
1748
+ stopped: boolean;
1749
+ error?: unknown;
1750
+ /**
1751
+ * True when the turn paused on a human decision: this text is what the agent wrote before calling
1752
+ * the tool, and the controls follow as their own message. A surface with a notion of "done" (Linear
1753
+ * sessions) should post it as progress rather than as the answer.
1754
+ */
1755
+ pending?: boolean;
1756
+ };
1757
+ export type ChannelSendCtx<TEvent = unknown, THandle = unknown> = {
1758
+ /** The verified event that started this turn. Absent on a bound turn that no channel delivery started. */
1759
+ event?: TEvent;
1760
+ /** The connector's posting handle from `bind()`, when the connector defines one. */
1761
+ handle?: THandle;
1762
+ /** The delivery that started this turn. Absent on a bound turn. */
1763
+ deliveryId?: string;
1764
+ previousRef?: string;
1765
+ mode: "final" | "stream";
1766
+ final: boolean;
1767
+ /** True when this turn was not started by a channel delivery and egresses through the session's binding. */
1768
+ bound: boolean;
1769
+ };
1770
+ export type ChannelAckCtx = {
1771
+ /**
1772
+ * True when this ack is being re-posted because the run is recovering an
1773
+ * interrupted turn after a crash/continuation. The prior run's message ref
1774
+ * is gone, so egress re-emits into the thread as a fresh message; a
1775
+ * connector can vary the placeholder text to read as a deliberate resume
1776
+ * ("picking this back up...") rather than a silent duplicate.
1777
+ */
1778
+ recovered: boolean;
1779
+ };
1780
+ /**
1781
+ * A tool call the turn paused on, awaiting a human decision (HITL). `renderInteraction` maps these to
1782
+ * the controls posted in the thread; the callback resolves one by `toolCallId`.
1783
+ */
1784
+ export type ChannelPendingToolCall = {
1785
+ toolCallId: string;
1786
+ toolName: string;
1787
+ input?: unknown;
1788
+ };
1789
+ /**
1790
+ * A verified interaction callback resolved to a tool output. `onInteraction` returns this to resume the
1791
+ * paused run: the framework stitches `output` onto the pending tool part and continues. Name the call
1792
+ * by `toolCallId` when the surface can carry it (a Slack button value), or by `toolName` when it cannot
1793
+ * (a Linear option whose value the user sees); the most recent pending call of that tool is resolved.
1794
+ */
1795
+ export type ChannelInteractionResolution = {
1796
+ toolCallId: string;
1797
+ toolName?: string;
1798
+ output: unknown;
1799
+ } | {
1800
+ toolName: string;
1801
+ toolCallId?: string;
1802
+ output: unknown;
1803
+ };
1804
+ /**
1805
+ * Context for `renderInteraction`: the event and delivery that started the turn, both absent on a
1806
+ * bound turn (a `chat.turn()` action or a browser message answering into the bound thread).
1807
+ */
1808
+ export type ChannelInteractionCtx<TEvent = unknown> = {
1809
+ event?: TEvent;
1810
+ deliveryId?: string;
1811
+ };
1812
+ export type ChannelReaction = {
1813
+ name: string;
1814
+ remove?: boolean;
1815
+ };
1816
+ export type ChannelReactCtx<TEvent = unknown> = {
1817
+ event: TEvent;
1818
+ deliveryId: string;
1819
+ };
1820
+ export type ChannelReactionChoice<TEvent = unknown> = string | string[] | ((event: TEvent) => string | string[] | null | undefined | Promise<string | string[] | null | undefined>);
1821
+ export type ChannelReactions<TEvent = unknown> = {
1822
+ working?: ChannelReactionChoice<TEvent>;
1823
+ done?: ChannelReactionChoice<TEvent>;
1824
+ error?: ChannelReactionChoice<TEvent>;
1825
+ };
1826
+ export type ChannelRunSurface<TExtra extends Record<string, unknown> = Record<string, unknown>> = {
1827
+ react: (name: string) => Promise<void>;
1828
+ unreact: (name: string) => Promise<void>;
1829
+ } & TExtra;
1830
+ /**
1831
+ * The turn a connector hook is running in: the verified event and delivery that started it (absent on
1832
+ * a bound turn), and the session's posting handle from `bind()` when the connector defines one.
1833
+ */
1834
+ export type ChannelTurnCtx<TEvent = unknown, THandle = unknown> = {
1835
+ event?: TEvent;
1836
+ handle?: THandle;
1837
+ deliveryId?: string;
1838
+ /** True when no channel delivery started this turn and it egresses through the session's binding. */
1839
+ bound: boolean;
1840
+ };
1841
+ /**
1842
+ * What a connector's `onControl()` maps a verified event to. `stop` aborts the turn in flight through
1843
+ * the same per-turn stop signal the browser's stop button uses: the run's `stopSignal` fires,
1844
+ * `streamText` aborts, the partial reply posts with `stopped: true`, and the event itself is consumed
1845
+ * (it does not run as a turn).
1846
+ *
1847
+ * `whenIdle` decides what a stop does when no turn is in flight. `"message"` (the default) handles
1848
+ * the event as a normal inbound message, so the connector's `inbound()` should give it a sensible
1849
+ * reading. `"drop"` consumes it without a turn; if the session is paused on a human decision, the
1850
+ * pending tool calls are resolved as stopped (a later approval click finds nothing to resume) and
1851
+ * the connector's `cancelInteraction()` updates the controls.
1852
+ *
1853
+ * `at` is when the user asked to stop (epoch milliseconds). A stop older than the running turn's
1854
+ * start belongs to an earlier turn: it is consumed without aborting this one.
1855
+ */
1856
+ export type ChannelControl = {
1857
+ kind: "stop";
1858
+ message?: string;
1859
+ whenIdle?: "message" | "drop";
1860
+ at?: number;
1861
+ };
1862
+ /**
1863
+ * What a connector's `progress()` hook observes while a turn streams: each tool call as its input is
1864
+ * complete, and each result or error as it lands. Text deltas are not reported (use `delivery: "stream"`).
1865
+ */
1866
+ export type ChannelProgressEvent = {
1867
+ type: "tool-call";
1868
+ toolCallId: string;
1869
+ toolName: string;
1870
+ input: unknown;
1871
+ } | {
1872
+ type: "tool-result";
1873
+ toolCallId: string;
1874
+ toolName: string;
1875
+ output: unknown;
1876
+ } | {
1877
+ type: "tool-error";
1878
+ toolCallId: string;
1879
+ toolName: string;
1880
+ errorText: string;
1881
+ };
1882
+ /**
1883
+ * Where a channel session stands, reported to a connector's `lifecycle()` hook: `working` when a turn
1884
+ * starts (and again every 50 minutes while it runs), `waiting` when it pauses on a human decision,
1885
+ * `idle` when it ends for any reason (answered, empty, stopped or failed), and `closed` when the
1886
+ * conversation is closed with `chat.close()`. A worker suspending between messages reports nothing.
1887
+ */
1888
+ export type ChannelLifecycleState = "working" | "waiting" | "idle" | "closed";
1889
+ export type ChannelLifecycleCtx<TEvent = unknown, THandle = unknown> = ChannelTurnCtx<TEvent, THandle> & {
1890
+ /** True on the session's first turn, when the surface creates its conversation. */
1891
+ firstTurn: boolean;
1892
+ /** The turn's user message text, when it has one (a title for the conversation). */
1893
+ prompt?: string;
1894
+ /** True on the periodic `working` re-send during a long turn. */
1895
+ refresh?: boolean;
1896
+ };
1897
+ /** How a turn's reply stream ended, handed to {@link ChannelReplyStream.end}. */
1898
+ export type ChannelReplyStreamEnd = {
1899
+ /** The turn was stopped (the partial reply is all there is). */
1900
+ stopped: boolean;
1901
+ /** The turn paused on a human decision; the controls follow as their own message. */
1902
+ pending: boolean;
1903
+ /** The sanitized error text when the turn ended on a model or stream error. */
1904
+ errorText?: string;
1905
+ };
1906
+ /**
1907
+ * A connector's native streaming transport for one turn, from its `stream()` hook, used when the
1908
+ * connector's `delivery` is `"stream"`. The runtime feeds it the reply's text deltas as the model
1909
+ * writes them (in the model's markdown) and the turn's tool progress, then ends it exactly once.
1910
+ * `end()` resolves `delivered: true` when the reply reached the surface through the stream, so the
1911
+ * runtime does not post it again; `false` (nothing was streamed) falls back to `send()`.
1912
+ */
1913
+ export type ChannelReplyStream = {
1914
+ text(delta: string): void;
1915
+ progress?(event: ChannelProgressEvent): void;
1916
+ end(outcome: ChannelReplyStreamEnd): Promise<{
1917
+ delivered: boolean;
1918
+ }>;
1919
+ };
1920
+ /**
1921
+ * What a connector's `stream()` hook receives: the turn, and `opened(ref)` to call once the surface
1922
+ * has created the stream message. The ref is saved with the session while the turn runs, so if the
1923
+ * worker dies mid-stream the next worker can end that stream with `endInterruptedStream()`.
1924
+ */
1925
+ export type ChannelStreamCtx<TEvent = unknown, THandle = unknown> = ChannelTurnCtx<TEvent, THandle> & {
1926
+ opened(ref: string): void;
1927
+ };
1928
+ /** A pending tool call a stop cancelled, with the `ref` of the controls message that showed it. */
1929
+ export type ChannelCancelledToolCall = ChannelPendingToolCall & {
1930
+ ref?: string;
1931
+ };
1932
+ export type ResolveChannelToken<TEvent = unknown> = (event: TEvent) => Promise<string>;
1933
+ declare const channelEventPhantom: unique symbol;
1934
+ export interface ChannelConnector<TEvent = unknown, THandle = unknown> {
1935
+ id: string;
1936
+ /** The endpoint this connector subscribes to (`webhooks.endpoint.define` id). */
1937
+ endpointId: string;
1938
+ source: string;
1939
+ key: string;
1940
+ filter?: string;
1941
+ startOn?: string;
1942
+ inbound: (event: TEvent) => ChannelInbound;
1943
+ /**
1944
+ * Derive the durable posting handle from a verified event (for Slack: team, channel, thread). When
1945
+ * set, a channel turn binds the session to this connector, and later turns on the session that no
1946
+ * channel delivery started (an action turn, a browser message) post their answer through `send`
1947
+ * with `ctx.handle` and no `ctx.event`. Return null to leave the binding unchanged.
1948
+ */
1949
+ bind?: (event: TEvent) => THandle | null;
1950
+ /**
1951
+ * Supply the surface's existing conversation when a session starts on it (the bot was summoned
1952
+ * into a thread that already has messages). Called once, on the first channel turn of a session
1953
+ * with no history, before the triggering message is added. Return the prior messages in order,
1954
+ * excluding the triggering one. Best effort: a throw is logged and the session starts empty.
1955
+ */
1956
+ seed?: (event: TEvent, ctx: ChannelSeedCtx<TEvent>) => Promise<ChannelSeedMessage[]> | ChannelSeedMessage[];
1957
+ outbound?: (reply: ChannelReply) => ChannelMessage | null;
1958
+ ack?: (event: TEvent, ctx: ChannelAckCtx) => ChannelMessage | null;
1959
+ send?: (message: ChannelMessage, ctx: ChannelSendCtx<TEvent, THandle>) => Promise<{
1960
+ ref?: string;
1961
+ }>;
1962
+ /** HITL: controls posted when a turn pauses on a human-decision tool (a tool with no `execute`). */
1963
+ renderInteraction?: (pending: ChannelPendingToolCall[], ctx: ChannelInteractionCtx<TEvent>) => ChannelMessage | null;
1964
+ /**
1965
+ * HITL: map a verified callback event to a tool resolution. Non-null resumes the paused run; null
1966
+ * means treat the event as a normal inbound message (a new turn).
1967
+ */
1968
+ onInteraction?: (event: TEvent) => ChannelInteractionResolution | null;
1969
+ /**
1970
+ * HITL: finalize the posted controls once a decision is made (edit them away, show the outcome), so
1971
+ * the buttons can't be clicked again. Called with the same verified callback event when
1972
+ * `onInteraction` resolves, before the run resumes. Best-effort: a throw is logged and the run continues.
1973
+ */
1974
+ finalizeInteraction?: (event: TEvent, resolution: ChannelInteractionResolution) => Promise<void> | void;
1975
+ /**
1976
+ * "final": the ack, then one post (or edit of the ack) when the turn ends. "stream": the connector's
1977
+ * `stream()` transport when it has one, otherwise debounced edits of the ack.
1978
+ */
1979
+ delivery: "final" | "stream";
1980
+ /**
1981
+ * Native streaming for `delivery: "stream"`: open a {@link ChannelReplyStream} for this turn. Called
1982
+ * once per turn that runs the model; return null to fall back to `send()` for this turn.
1983
+ */
1984
+ stream?: (ctx: ChannelStreamCtx<TEvent, THandle>) => ChannelReplyStream | null;
1985
+ /**
1986
+ * A worker booted on a session whose previous worker died with a reply stream open (the `ref` it
1987
+ * passed to `opened()`). End that stream so it does not look like the agent is still writing; the
1988
+ * recovered turn answers in a new one. Best effort: a throw is logged.
1989
+ */
1990
+ endInterruptedStream?: (ref: string, ctx: ChannelTurnCtx<TEvent, THandle>) => Promise<void> | void;
1991
+ /**
1992
+ * Fetch a file URL from the surface for the model, for files only the surface's credentials can
1993
+ * read (a Slack `url_private`). The `streamText` given to `run()` calls it for every file URL in
1994
+ * the prompt; return null for a URL this connector does not own. Throw when an owned file cannot
1995
+ * be read: the turn replaces it with a short note and still runs. `handle` is the session's
1996
+ * binding to this connector, when it has one.
1997
+ */
1998
+ download?: (url: URL, ctx: {
1999
+ handle?: THandle;
2000
+ }) => Promise<ChannelDownloadedFile | null>;
2001
+ /**
2002
+ * Acknowledge a message that arrives while a turn is running, as soon as it arrives: it is either
2003
+ * folded into the running turn (`pendingMessages`) or answered right after it, so the wording
2004
+ * should be true either way (`slack()` reacts with 👀, `linear()` posts a thought). Not called for
2005
+ * stops, interaction clicks or empty messages. Called without waiting; a throw is ignored.
2006
+ * `ctx.event` is the message's event.
2007
+ */
2008
+ received?: (ctx: ChannelTurnCtx<TEvent, THandle>) => Promise<void> | void;
2009
+ /**
2010
+ * Map a click on a control the agent posted (not a pending tool's control) to an action for the
2011
+ * agent's `onAction`, validated against `actionSchema` like a client action. Return null for
2012
+ * anything else. Returning `chat.turn()` from `onAction` answers into the session's thread.
2013
+ */
2014
+ toAction?: (event: TEvent) => unknown | null;
2015
+ /**
2016
+ * Mirror the session's state into the surface (a Slack agent session's status). See
2017
+ * {@link ChannelLifecycleState}. Calls are serialized in order; a throw is logged and never
2018
+ * affects the turn.
2019
+ */
2020
+ lifecycle?: (state: ChannelLifecycleState, ctx: ChannelLifecycleCtx<TEvent, THandle>) => Promise<void> | void;
2021
+ /**
2022
+ * HITL: a stop (`whenIdle: "drop"`) arrived while the session was paused on these tool calls. They
2023
+ * are already resolved as stopped; update the controls so they no longer offer a decision.
2024
+ * Best effort: a throw is logged.
2025
+ */
2026
+ cancelInteraction?: (cancelled: ChannelCancelledToolCall[], ctx: ChannelTurnCtx<TEvent, THandle>) => Promise<void> | void;
2027
+ react?: (reaction: ChannelReaction, ctx: ChannelReactCtx<TEvent>) => Promise<void>;
2028
+ reactions?: ChannelReactions<TEvent>;
2029
+ /**
2030
+ * Observe tool calls and results as the turn streams, to post progress into the surface (a Linear
2031
+ * `action` activity, a Slack status). Called in order, awaited one at a time, independent of
2032
+ * `delivery`. Best effort: a throw is logged and the turn continues.
2033
+ */
2034
+ progress?: (event: ChannelProgressEvent, ctx: ChannelTurnCtx<TEvent, THandle>) => Promise<void> | void;
2035
+ /**
2036
+ * Provider helpers merged into the `channel` object handed to `run()` (alongside `react`/`unreact`),
2037
+ * such as a plan or a status setter. Built once per turn.
2038
+ */
2039
+ surface?: (ctx: ChannelTurnCtx<TEvent, THandle>) => Record<string, unknown>;
2040
+ /**
2041
+ * Map a verified event to a control instruction while a turn is running (a Stop in Linear, a
2042
+ * "stop" slash command in Slack). See {@link ChannelControl}. Return null for an ordinary message.
2043
+ */
2044
+ onControl?: (event: TEvent) => ChannelControl | null;
2045
+ readonly [channelEventPhantom]?: TEvent;
2046
+ }
2047
+ export type AnyChannelConnector = ChannelConnector<any, any>;
2048
+ /**
2049
+ * A generic chat-frontend channel over any verified source. Unlike `slack()`, you supply the egress
2050
+ * `send` yourself (post/edit the reply back to your surface), so the whole round-trip is under your
2051
+ * control. Use for providers without a preset, or to test the channel round-trip end to end.
2052
+ */
2053
+ export declare function chatChannelCustom<TEndpoint extends AnyWebhookEndpoint, const TKey extends string = string, const TFilter extends string = string, const TStartOn extends string = string, THandle = unknown>(options: {
2054
+ id: string;
2055
+ /** The endpoint this connector subscribes to. */
2056
+ endpoint: TEndpoint;
2057
+ /**
2058
+ * The session each delivery goes to, as a template: `{event.x}` reads the event, `{header.x}` a
2059
+ * header and `{webhook.x}` the endpoint, and `{a || b}` falls back to `b` when `a` is empty. e.g.
2060
+ * `"{webhook.externalRef}:{event.data.object.customer}"`.
2061
+ */
2062
+ key: ValidatedWebhookKey<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>, TKey>;
2063
+ inbound: (event: NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>) => ChannelInbound;
2064
+ bind?: (event: NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>) => THandle | null;
2065
+ seed?: (event: NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>, ctx: ChannelSeedCtx<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>>) => Promise<ChannelSeedMessage[]> | ChannelSeedMessage[];
2066
+ outbound?: (reply: ChannelReply) => ChannelMessage | null;
2067
+ ack?: (event: NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>, ctx: ChannelAckCtx) => ChannelMessage | null;
2068
+ send?: (message: ChannelMessage, ctx: ChannelSendCtx<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>, THandle>) => Promise<{
2069
+ ref?: string;
2070
+ }>;
2071
+ renderInteraction?: (pending: ChannelPendingToolCall[], ctx: ChannelInteractionCtx<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>>) => ChannelMessage | null;
2072
+ onInteraction?: (event: NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>) => ChannelInteractionResolution | null;
2073
+ finalizeInteraction?: (event: NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>, resolution: ChannelInteractionResolution) => Promise<void> | void;
2074
+ react?: (reaction: ChannelReaction, ctx: ChannelReactCtx<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>>) => Promise<void>;
2075
+ reactions?: ChannelReactions<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>>;
2076
+ progress?: (event: ChannelProgressEvent, ctx: ChannelTurnCtx<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>, THandle>) => Promise<void> | void;
2077
+ surface?: (ctx: ChannelTurnCtx<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>, THandle>) => Record<string, unknown>;
2078
+ onControl?: (event: NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>) => ChannelControl | null;
2079
+ stream?: (ctx: ChannelStreamCtx<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>, THandle>) => ChannelReplyStream | null;
2080
+ endInterruptedStream?: (ref: string, ctx: ChannelTurnCtx<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>, THandle>) => Promise<void> | void;
2081
+ download?: (url: URL, ctx: {
2082
+ handle?: THandle;
2083
+ }) => Promise<ChannelDownloadedFile | null>;
2084
+ received?: (ctx: ChannelTurnCtx<InferWebhookEndpointEvent<TEndpoint>, THandle>) => Promise<void> | void;
2085
+ toAction?: (event: InferWebhookEndpointEvent<TEndpoint>) => unknown | null;
2086
+ lifecycle?: (state: ChannelLifecycleState, ctx: ChannelLifecycleCtx<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>, THandle>) => Promise<void> | void;
2087
+ cancelInteraction?: (cancelled: ChannelCancelledToolCall[], ctx: ChannelTurnCtx<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>, THandle>) => Promise<void> | void;
2088
+ filter?: ValidateWebhookFilter<InferWebhookEndpointEvent<TEndpoint>, TFilter>;
2089
+ startOn?: ValidateWebhookFilter<InferWebhookEndpointEvent<TEndpoint>, TStartOn>;
2090
+ delivery?: "final" | "stream";
2091
+ }): ChannelConnector<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>, THandle>;
2092
+ export declare function resolveReactionChoice(choice: ChannelReactionChoice | undefined, event: unknown): Promise<string | undefined>;
2093
+ /**
2094
+ * Feed a connector's `progress()` from the UI message stream: a tool call once its input is available,
2095
+ * then its result or error. Calls are serialized so the surface sees them in order; a throw is logged.
2096
+ * `stop()` refuses further chunks and drains what is already queued, so a slow first post does not
2097
+ * lose the results behind it, and nothing new lands after the turn ended.
2098
+ */
2099
+ declare function makeChannelProgressObserver(connector: AnyChannelConnector, wireEvent: {
2100
+ event: unknown;
2101
+ deliveryId: string;
2102
+ } | undefined, handle: unknown): ChannelStreamEditor;
2103
+ /**
2104
+ * Report a session's lifecycle to its connector in order, one call at a time, and re-send `working`
2105
+ * while a long turn runs. Every report bumps a sequence number and a refresh only fires while its
2106
+ * `working` is still the latest report, so a refresh can never land after the turn went idle.
2107
+ */
2108
+ declare function makeChannelLifecycleReporter(): {
2109
+ report(connector: AnyChannelConnector | undefined, state: ChannelLifecycleState, ctx: ChannelLifecycleCtx): Promise<void>;
2110
+ dispose: () => void;
2111
+ };
2112
+ declare function makeChannelStreamEditor<TEvent>(connector: ChannelConnector<TEvent>, channelEvent: {
2113
+ event: unknown;
2114
+ deliveryId: string;
2115
+ }, ackRef: string, handle?: unknown): {
2116
+ observe(chunk: unknown): void;
2117
+ stop(): Promise<void>;
2118
+ };
2119
+ type ChannelStreamEditor = {
2120
+ observe(chunk: unknown): void;
2121
+ stop(): void | Promise<void>;
2122
+ };
2123
+ /**
2124
+ * Wrap the reply stream so it debounce-edits the channel message as it streams.
2125
+ * Both `flush` (the stream completed) and `cancel` (the stream was aborted or
2126
+ * cancelled downstream) stop the editor, so a pending debounce timer can never
2127
+ * fire an edit after the turn ended, onto a message the next turn already owns.
2128
+ */
2129
+ /**
2130
+ * Feed every chunk of a stream to `editor`. By default the editor is stopped when the stream ends or
2131
+ * is cancelled (one stream per turn, the automatic pipe). With `stopOnEnd: false` the editor outlives
2132
+ * the stream, for a turn whose run() pipes several streams through `chat.pipe()`; the turn boundary
2133
+ * stops it.
2134
+ */
2135
+ declare function makeChannelStreamTap(editor: ChannelStreamEditor, options?: {
2136
+ stopOnEnd?: boolean;
2137
+ }): TransformStream<unknown, unknown>;
2138
+ export { makeChannelStreamEditor as __makeChannelStreamEditorForTests, makeChannelStreamTap as __makeChannelStreamTapForTests, makeChannelProgressObserver as __makeChannelProgressObserverForTests, makeChannelLifecycleReporter as __makeChannelLifecycleReporterForTests, };
2139
+ /** Resolves once the post-turn channel egress for `chatId` has finished (immediately when none is running). */
2140
+ export declare function __waitForChannelEgressForTests(chatId: string): Promise<void>;
2141
+ type ChatActionType<TActionSchema extends TaskSchema | undefined, TW extends readonly AnyChatEvent[]> = [TActionSchema] extends [TaskSchema] ? inferSchemaOut<TActionSchema> | ChatEventActions<TW> : [TW] extends [readonly []] ? unknown : ChatEventActions<TW>;
2142
+ export type ChatAgentOptions<TIdentifier extends string, TClientDataSchema extends TaskSchema | undefined = undefined, TUIMessage extends UIMessage = UIMessage, TActionSchema extends TaskSchema | undefined = undefined, TTools extends ToolSet = ToolSet, TW extends readonly AnyChatEvent[] = [], TChannels extends readonly AnyChannelConnector[] = []> = Omit<TaskOptions<TIdentifier, ChatTaskWirePayload<TUIMessage, inferSchemaIn<TClientDataSchema>>, unknown>, "run" | "retry"> & {
1636
2143
  /**
1637
2144
  * Fallback machine preset to use when an attempt fails with an
1638
2145
  * out-of-memory (OOM) error. Setting this enables a single OOM retry:
@@ -1736,9 +2243,22 @@ export type ChatAgentOptions<TIdentifier extends string, TClientDataSchema exten
1736
2243
  * action that returns nothing is a state edit only. Returning anything else
1737
2244
  * is an error; a response can no longer be returned directly.
1738
2245
  */
1739
- onAction?: (event: ActionEvent<[
1740
- TActionSchema
1741
- ] extends [TaskSchema] ? inferSchemaOut<TActionSchema> : unknown, inferSchemaOut<TClientDataSchema>, TUIMessage>) => Promise<void | ActionTurn> | void | ActionTurn;
2246
+ /**
2247
+ * Inbound `chat.event(...)` descriptors this agent handles. Listing one subscribes this agent to the
2248
+ * descriptor's endpoint: each verified delivery goes to the session its `key` names and arrives at
2249
+ * `onAction` as a `{ type, event, source, headers, deliveryId, externalDeliveryId, endpoint }` envelope whose `type` is
2250
+ * the descriptor's `type`. The same descriptor listed on another agent is a second subscriber on the
2251
+ * same endpoint.
2252
+ */
2253
+ events?: TW;
2254
+ /**
2255
+ * Inbound chat frontends (Slack, etc.) via `chat.channels.*`. Listing one subscribes this agent to
2256
+ * the connector's endpoint, routing verified events to a durable per-key session as turns: the
2257
+ * connector's `inbound()` maps the raw event to the turn's message, `run()` fires as normal, and the
2258
+ * reply streams back to the channel. Use the connector's `filter` to ignore events.
2259
+ */
2260
+ channels?: TChannels;
2261
+ onAction?: (event: ActionEvent<ChatActionType<TActionSchema, TW>, inferSchemaOut<TClientDataSchema>, TUIMessage>) => Promise<void | ActionTurn> | void | ActionTurn;
1742
2262
  /**
1743
2263
  * The tools available to this agent.
1744
2264
  *
@@ -1954,6 +2474,13 @@ export type ChatAgentOptions<TIdentifier extends string, TClientDataSchema exten
1954
2474
  * },
1955
2475
  * });
1956
2476
  * ```
2477
+ *
2478
+ * Note: on a channel HITL resume turn (a button click that lands on a fresh
2479
+ * run whose accumulator doesn't yet hold the pending tool call), this hook is
2480
+ * called twice for the one delivery: once with `incomingMessages: []` to load
2481
+ * the chain and locate the pending tool call, then again with the synthesized
2482
+ * resolution message so it can be persisted. Keep the hook's read path
2483
+ * idempotent.
1957
2484
  */
1958
2485
  hydrateMessages?: (event: HydrateMessagesEvent<inferSchemaOut<TClientDataSchema>, TUIMessage>) => TUIMessage[] | Promise<TUIMessage[]>;
1959
2486
  /**
@@ -2341,7 +2868,7 @@ type ChatCustomAgentOptions<TIdentifier extends string, TClientDataSchema extend
2341
2868
  run: TaskOptions<TIdentifier, ChatTaskWirePayload<TUIMessage, inferSchemaOut<TClientDataSchema>>, unknown>["run"];
2342
2869
  };
2343
2870
  declare function chatCustomAgent<TIdentifier extends string, TClientDataSchema extends TaskSchema | undefined = undefined, TUIMessage extends UIMessage = UIMessage>(options: ChatCustomAgentOptions<TIdentifier, TClientDataSchema, TUIMessage>): Task<TIdentifier, ChatTaskWirePayload<TUIMessage, inferSchemaIn<TClientDataSchema>>, unknown>;
2344
- declare function chatAgent<TIdentifier extends string, TClientDataSchema extends TaskSchema | undefined = undefined, TUIMessage extends UIMessage = UIMessage, TActionSchema extends TaskSchema | undefined = undefined, TTools extends ToolSet = ToolSet>(options: ChatAgentOptions<TIdentifier, TClientDataSchema, TUIMessage, TActionSchema, TTools>): Task<TIdentifier, ChatTaskWirePayload<TUIMessage, inferSchemaIn<TClientDataSchema>>, unknown>;
2871
+ declare function chatAgent<TIdentifier extends string, TClientDataSchema extends TaskSchema | undefined = undefined, TUIMessage extends UIMessage = UIMessage, TActionSchema extends TaskSchema | undefined = undefined, TTools extends ToolSet = ToolSet, const TW extends readonly AnyChatEvent[] = [], const TChannels extends readonly AnyChannelConnector[] = []>(options: ChatAgentOptions<TIdentifier, TClientDataSchema, TUIMessage, TActionSchema, TTools, TW, TChannels>): Task<TIdentifier, ChatTaskWirePayload<TUIMessage, inferSchemaIn<TClientDataSchema>>, unknown>;
2345
2872
  /**
2346
2873
  * Optional config for {@link chat.withUIMessage}. `streamOptions` become default
2347
2874
  * static `toUIMessageStream()` settings; inner `chat.agent({ uiMessageStreamOptions })`
@@ -2552,6 +3079,20 @@ declare function setIdleTimeoutInSeconds(seconds: number): void;
2552
3079
  * ```
2553
3080
  */
2554
3081
  declare function setUIMessageStreamOptions(options: ChatUIMessageStreamOptions<UIMessage>): void;
3082
+ /**
3083
+ * The channel surface of the current turn, from anywhere inside a `chat.agent` run, including a
3084
+ * tool's `execute`. Undefined on a browser turn or when the connector defines no reactions and no
3085
+ * `surface()`. Pass the connector's surface type to get its helpers typed:
3086
+ *
3087
+ * @example
3088
+ * ```ts
3089
+ * execute: async ({ steps }) => {
3090
+ * const linear = chat.surface<LinearRunSurface>();
3091
+ * if (linear) await linear.plan(steps);
3092
+ * }
3093
+ * ```
3094
+ */
3095
+ declare function getChannelSurface<T extends ChannelRunSurface = ChannelRunSurface>(): T | undefined;
2555
3096
  /**
2556
3097
  * Check whether the user stopped generation during the current turn.
2557
3098
  *
@@ -3407,6 +3948,13 @@ declare function createChatLoadTranscriptAction<TClientData = unknown>(storage:
3407
3948
  export declare const chat: {
3408
3949
  /** Create a chat agent. See {@link chatAgent}. */
3409
3950
  agent: typeof chatAgent;
3951
+ /** Declare an inbound webhook event an agent claims via `chat.agent({ events })`. See {@link chatEvent}. */
3952
+ event: typeof chatEvent;
3953
+ /** Chat frontend connectors (Slack, etc.) an agent claims via `chat.agent({ channels })`. */
3954
+ channels: {
3955
+ /** A generic chat-frontend channel over any source, with your own egress. See {@link chatChannelCustom}. */
3956
+ custom: typeof chatChannelCustom;
3957
+ };
3410
3958
  /** Create a custom agent with manual lifecycle control. See {@link chatCustomAgent}. */
3411
3959
  customAgent: typeof chatCustomAgent;
3412
3960
  /** Create a chat task with a fixed {@link UIMessage} subtype and optional default stream options. See {@link withUIMessage}. */
@@ -3425,6 +3973,8 @@ export declare const chat: {
3425
3973
  local: typeof chatLocal;
3426
3974
  /** Create a public access token for a chat task. See {@link createChatAccessToken}. */
3427
3975
  createAccessToken: typeof createChatAccessToken;
3976
+ /** Mint a read-only token to WATCH a session by externalId (cross-surface). See {@link createChatWatchToken}. */
3977
+ createWatchToken: typeof createChatWatchToken;
3428
3978
  /** Override the turn timeout at runtime (duration string). See {@link setTurnTimeout}. */
3429
3979
  setTurnTimeout: typeof setTurnTimeout;
3430
3980
  /** Override the turn timeout at runtime (seconds). See {@link setTurnTimeoutInSeconds}. */
@@ -3435,6 +3985,8 @@ export declare const chat: {
3435
3985
  setUIMessageStreamOptions: typeof setUIMessageStreamOptions;
3436
3986
  /** Check if the current turn was stopped by the user. See {@link isStopped}. */
3437
3987
  isStopped: typeof isStopped;
3988
+ /** The current turn's channel surface (reactions plus connector helpers), also from inside a tool. See {@link getChannelSurface}. */
3989
+ surface: typeof getChannelSurface;
3438
3990
  /** Request that the run exits after the current turn so the next message starts on the latest version. See {@link requestUpgrade}. */
3439
3991
  requestUpgrade: typeof requestUpgrade;
3440
3992
  /** Hand off a custom agent Session to a fresh run. See {@link endAndContinue}. */