Repository navigation
Tags: triggerdotdev/trigger.dev
Tags
fix(sdk): keep the persisted chat cursor at the turn start while stre… …aming Fix reloading a chat mid-turn after its access token was refreshed. `TriggerChatTransport` persists a resume cursor (`lastEventId`) so a reloaded page can reconnect to `.out`. Sends persist it before the turn streams, so a reload normally replays the whole turn. A token refresh during a streaming turn (the 401 retry on a steering send or on an `.out` reconnect) persisted the latest record's cursor instead, from the middle of the turn. A reload then resumed past the turn's opening chunks, and `useChat` failed to rebuild the assistant message: "No tool invocation found for tool call ID". The transport now remembers the cursor from before each turn's first record, set when the turn is sent or, after a reconnect, when its first record arrives (so it also holds for apps that don't persist `isStreaming`). It persists that cursor in place of the live one until the turn ends, then persists the latest cursor as before. `getSession()` returns the same value, and the frontend docs describe it. Mono-RevId: 13ad0c6f4d89f44707f9683a6faa7b362268d9f4
chore: release v4.8.2 (#5073) ## Summary 5 new features, 19 improvements, 23 bug fixes. ## Breaking changes - Query dashboard APIs reject run tokens and public access tokens without user delegation. Existing API key access, including restricted keys with the required query scopes, is unchanged. MCP dashboard access remains supported through delegated tokens for current organization members. - The legacy `clickhouse` event store is retired: task events now go to `clickhouse_v2`. If you self-host with `EVENT_REPOSITORY_DEFAULT_STORE=clickhouse`, switch it to `clickhouse_v2` and follow the self-hosting guide to copy older events, which no longer show until you do. ## Improvements - Deployed tasks now keep a valid short-lived run token for their whole run: the token is refreshed during long runs and before a run resumes from a checkpoint. A warm-started task no longer keeps the previous run's token when the next run has none, and run credentials are left out of runner debug logs. ([`aa9de9d94`](aa9de9d)) - Upgrade `socket.io-client` to 4.8.4 so projects using the SDK and CLI install `ws` 8.21 instead of 8.17.1, which has published advisories (GHSA-96hv-2xvq-fx4p, GHSA-58qx-3vcg-4xpx). The old pin blocked upgrading `ws` without a package manager override. ([`2df9860b4`](2df9860)) - Adds the `bun-1.4` runtime. `runtime: "bun-1.4"` deploys on Bun 1.4.4 in a Bun-only image with no Node.js binary, and the run controller itself runs under Bun. `runtime: "bun"` is unchanged (Bun 1.3 with Node.js alongside it); `bun-legacy` is accepted as an explicit spelling of the same runtime. On Bun 1.4 the worker no longer crashes at startup on the `--no-warnings=ExperimentalWarning` flag. ([`a8a87850b`](a8a8785)) - Add an experimental Convex component for triggering tasks transactionally and reading their status and results through reactive queries, without configuring webhooks. ([`3c1cf656c`](3c1cf65)) - Run metadata operations now reject JSON-path keys that use escaped dots to reach `__proto__`, `constructor` or `prototype`. ([`dce5048a8`](dce5048)) - Use short-lived run tokens for supported SDK operations inside deployed tasks when available, retaining environment-key compatibility for unsupported operations and missing or expired tokens. Explicit credentials still take precedence. Public-token helpers use server-side minting with run tokens rather than signing locally. ([`5a1c14239`](5a1c142)) Project and organization queries, and branch overrides targeting another PREVIEW or DEVELOPMENT environment, keep using compatibility credentials. Branch headers do not change credential selection in STAGING or PRODUCTION. Chat subscriptions reread implicit credentials for each connection. - `runs.subscribeToRun` now ends after the run completes. The `for await` loop exits right after the update with the final status, and the subscription stops its connection, so a script that subscribes to a run exits on its own. Pass `stopOnCompletion: false` to keep the subscription open after completion. ([`485ab83aa`](485ab83)) - Add `SupervisorHttpClient.releaseRun`, which gives back a dequeued run the worker never started so the platform requeues it at once instead of after the pending execution timeout. ([`ba51e5573`](ba51e55)) - The supervisor keeps its run notification subscriptions across reconnects to the webapp, and reconnects when the webapp turns its handshake away, so cancellations and resolved waits keep reaching running tasks after a webapp restart or deploy. ([`a9e69ab7d`](a9e69ab)) - Asymmetric webhook sources can now verify ECDSA P-384 signatures (`algorithm: "ecdsa-p384"`, SHA-384) and providers that sign a SHA-256 digest of the signing string (`prehash: "sha256"`). ECDSA signatures are accepted in DER or raw `r||s` form. ([`4ed2e3780`](4ed2e37)) - The bundled `trigger-cost-savings` skill now notes that a webhook delivery starts no run when no subscriber's filter matches, so it costs no compute. ([#5051](#5051)) - Stream a sub-agent's reply through a parent tool call with `chat.forwardSubAgent`. Each chunk is written to the parent chat once and the tool resolves with the sub-agent's final message, so streaming a sub-agent costs bytes in proportion to its reply. Yielding `stream.messages()` snapshots resends the whole message on every chunk, which grows with the square of the reply. ([`bdc994c4d`](bdc994c)) ```ts execute: async ({ topic }, { toolCallId, abortSignal }) => { const stream = await researcher.sendMessage(topic, { abortSignal }); return await chat.forwardSubAgent(stream, { toolCallId }); }, ``` Render it while it runs with `useSubAgentMessages()` from `@trigger.dev/sdk/chat/react` (or `createSubAgentMessages()` outside React). ## Bug fixes - Fix `chat.inject` messages added from a tool mid-turn being saved before the assistant's response. They now stay after the tool result, where the model saw them, so the next turn keeps the same prompt prefix. If you roll `@trigger.dev/sdk` back to an earlier version, chats saved by this version lose these mid-turn `chat.inject` messages from the model's context, though the chat history shown in the UI keeps them. ([`fc33769a5`](fc33769)) - Fix a `chat.agent` turn failing after a head start that ended with two or more parallel tool calls. When those tools finished out of call order, the agent sent their results to the model twice on the next step, and the provider rejected the request (Anthropic: "each tool_use must have a single result"). Each handed-over tool result is now sent once. ([`d06ee5825`](d06ee58)) ## Server changes These changes affect the self-hosted Docker image and Trigger.dev Cloud: - Add "Ignored paths" to the Git settings: pushes and pull request updates that only change files matching these patterns no longer create a deployment. Ignored paths don't apply while the Vercel integration is connected. - The `metrics` query table now includes queue size (`queue.size.*`) and webhook limit metrics (`webhook.waiters.*`, `webhook.processing.*`, `webhook.ingress.*`), so you can chart and alert on queue capacity and webhook rate limits. - New Limits alerts: watch the limits that can interrupt or degrade runtime flow, one at a time or combined into a single alert with "any" or "all" and the signals you choose (limit reached or approaching), in the dashboard, the API and the agent. - Expand short-lived run-token support to task APIs, with permission checks for packets, metadata, streams and waits. Run tokens last one hour independently of root-key rotation and cannot be individually revoked. They can mint public access tokens for up to 30 days; those tokens may outlive the run token that minted them. - Hosted webhook endpoints can verify ECDSA P-384 (SHA-384) signatures, ECDSA signatures in raw `r||s` form, and RSA signatures made over a SHA-256 digest of the signing string (`prehash: "sha256"`). - Older runs now load their trace, span details and run events faster. A span that finishes more than a week after its run shows as still in progress. - The run page now loads large traces progressively and updates live runs incrementally, so big traces open faster and open run pages no longer reload the whole trace while a run is executing. The run trace API can also page large traces. - Query alerts now accept queries whose columns are computed from other aggregate columns, such as a percentage of two aggregates. When a query can't be watched, the Watch button stays visible but disabled and explains why. - Archiving unused queues from the Concurrency page is now available on all instances, including self-hosted. - Runs whose container or pod could not be created, or whose pod failed before the run started, can now be requeued straight away instead of waiting for the pending execution timeout. Both are off by default: set `RELEASE_UNSTARTED_RUNS_ENABLED=true` on a supervisor for creates that fail, and `RELEASE_FAILED_POD_RUNS_ENABLED=true` for pods that fail. - Session external ids can no longer contain a `/channels` path segment (for example `chat-1/channels/support`) or end in `:channels`, since both forms name a session's channels. Creating a session with one now returns a 422 validation error. - Selecting a span that started a session now shows a link to that session in the span panel, so you can jump from an orchestrator's run to its sub-agents. - Fix the batch results API returning an empty list of items for completed batches. It now returns every run's result in trigger order. - Fix the batch results API returning "Batch not found" for some batches that the batch retrieve API could see. - Fix the run page continuing to live-update forever for some cancelled runs. These runs now show as finished, and loading their trace is faster. - Fix fetching the trace of a child run through the API sometimes being very slow or failing. These requests now return quickly. - Run metadata changes sent with an attempt's completion, such as increments and appends, are no longer applied a second time when a completion that already went through is retried. - Changing your email address now requires clicking a confirmation button after opening the emailed link. - Fix intermittent read and subscription errors when multiple clients first open the same realtime stream. - Fix intermittent subscription failures and missed records when reading newly created realtime streams. - Fix the dashboard's task list and task filters occasionally going stale when several `trigger dev` sessions register at the same time. - Deleting an organization now cancels its billing subscription. - Fix the dashboard agent's suggested threshold and window being dropped when it prefills a query alert. - Queries now reject an alias that reuses a table's alias in the same SELECT, unless the aliased expression contains an aggregate or window function (`count() AS runs FROM runs` still works). - Queries using `WITH <expression> AS <name>` now run instead of failing with a syntax error, and the name can be used in the rest of the query. The name can't reuse a table alias used anywhere in the query. - Fix a rare case where clock skew between run engine instances could leave a run executing after its task finished, or stop a wait from ever resuming. A run's state changes are now always ordered in the order they happened, regardless of clock skew. - A run whose attempt start was interrupted no longer gets stuck executing without its task ever running, then failing as stalled. - Fixed dropdowns sometimes picking an option by themselves when typing with some on-screen keyboards or autofill. - New runs a session starts are now always linked to their session, so their Agent tab no longer fails to load because the link was missing. - Runs no longer lose their worker's token when the cluster answers the worker's create with a 408, so the worker starts instead of waiting for a requeue. - Runs no longer lose their worker's token when a concurrent delivery or a lost answer leaves a failed worker create's token behind: the worker that took the name keeps it, and a token nothing will use is cleaned up instead of being kept. - Deleting an organization now uninstalls its Vercel integration. A Vercel installation disabled on Vercel's side is reported as such instead of as an expired connection, and removing it no longer reports success. - Promoting or rolling back a deployment now updates your webhook endpoints to match the deployment that's now current. <details> <summary>Raw changeset output</summary> # Releases ## @trigger.dev/build@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.2` ## trigger.dev@4.8.2 ### Patch Changes - Deployed tasks now keep a valid short-lived run token for their whole run: the token is refreshed during long runs and before a run resumes from a checkpoint. A warm-started task no longer keeps the previous run's token when the next run has none, and run credentials are left out of runner debug logs. ([`aa9de9d94`](aa9de9d)) - Upgrade `socket.io-client` to 4.8.4 so projects using the SDK and CLI install `ws` 8.21 instead of 8.17.1, which has published advisories (GHSA-96hv-2xvq-fx4p, GHSA-58qx-3vcg-4xpx). The old pin blocked upgrading `ws` without a package manager override. ([`2df9860b4`](2df9860)) - Adds the `bun-1.4` runtime. `runtime: "bun-1.4"` deploys on Bun 1.4.4 in a Bun-only image with no Node.js binary, and the run controller itself runs under Bun. `runtime: "bun"` is unchanged (Bun 1.3 with Node.js alongside it); `bun-legacy` is accepted as an explicit spelling of the same runtime. On Bun 1.4 the worker no longer crashes at startup on the `--no-warnings=ExperimentalWarning` flag. ([`a8a87850b`](a8a8785)) - Updated dependencies: - `@trigger.dev/core@4.8.2` - `@trigger.dev/build@4.8.2` - `@trigger.dev/schema-to-json@4.8.2` ## @trigger.dev/convex@4.8.2 ### Patch Changes - Add an experimental Convex component for triggering tasks transactionally and reading their status and results through reactive queries, without configuring webhooks. ([`3c1cf656c`](3c1cf65)) ## @trigger.dev/core@4.8.2 ### Patch Changes - Run metadata operations now reject JSON-path keys that use escaped dots to reach `__proto__`, `constructor` or `prototype`. ([`dce5048a8`](dce5048)) - Deployed tasks now keep a valid short-lived run token for their whole run: the token is refreshed during long runs and before a run resumes from a checkpoint. A warm-started task no longer keeps the previous run's token when the next run has none, and run credentials are left out of runner debug logs. ([`aa9de9d94`](aa9de9d)) - Use short-lived run tokens for supported SDK operations inside deployed tasks when available, retaining environment-key compatibility for unsupported operations and missing or expired tokens. Explicit credentials still take precedence. Public-token helpers use server-side minting with run tokens rather than signing locally. ([`5a1c14239`](5a1c142)) Project and organization queries, and branch overrides targeting another PREVIEW or DEVELOPMENT environment, keep using compatibility credentials. Branch headers do not change credential selection in STAGING or PRODUCTION. Chat subscriptions reread implicit credentials for each connection. - Upgrade `socket.io-client` to 4.8.4 so projects using the SDK and CLI install `ws` 8.21 instead of 8.17.1, which has published advisories (GHSA-96hv-2xvq-fx4p, GHSA-58qx-3vcg-4xpx). The old pin blocked upgrading `ws` without a package manager override. ([`2df9860b4`](2df9860)) - `runs.subscribeToRun` now ends after the run completes. The `for await` loop exits right after the update with the final status, and the subscription stops its connection, so a script that subscribes to a run exits on its own. Pass `stopOnCompletion: false` to keep the subscription open after completion. ([`485ab83aa`](485ab83)) - Add `SupervisorHttpClient.releaseRun`, which gives back a dequeued run the worker never started so the platform requeues it at once instead of after the pending execution timeout. ([`ba51e5573`](ba51e55)) - The supervisor keeps its run notification subscriptions across reconnects to the webapp, and reconnects when the webapp turns its handshake away, so cancellations and resolved waits keep reaching running tasks after a webapp restart or deploy. ([`a9e69ab7d`](a9e69ab)) - Adds the `bun-1.4` runtime. `runtime: "bun-1.4"` deploys on Bun 1.4.4 in a Bun-only image with no Node.js binary, and the run controller itself runs under Bun. `runtime: "bun"` is unchanged (Bun 1.3 with Node.js alongside it); `bun-legacy` is accepted as an explicit spelling of the same runtime. On Bun 1.4 the worker no longer crashes at startup on the `--no-warnings=ExperimentalWarning` flag. ([`a8a87850b`](a8a8785)) - Asymmetric webhook sources can now verify ECDSA P-384 signatures (`algorithm: "ecdsa-p384"`, SHA-384) and providers that sign a SHA-256 digest of the signing string (`prehash: "sha256"`). ECDSA signatures are accepted in DER or raw `r||s` form. ([`4ed2e3780`](4ed2e37)) ## @trigger.dev/linear@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/sdk@4.8.2` - `@trigger.dev/core@4.8.2` ## @trigger.dev/python@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/sdk@4.8.2` - `@trigger.dev/core@4.8.2` - `@trigger.dev/build@4.8.2` ## @trigger.dev/react-hooks@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.2` ## @trigger.dev/redis-worker@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.2` ## @trigger.dev/rsc@4.8.2 ### Patch Changes - Adds the `bun-1.4` runtime. `runtime: "bun-1.4"` deploys on Bun 1.4.4 in a Bun-only image with no Node.js binary, and the run controller itself runs under Bun. `runtime: "bun"` is unchanged (Bun 1.3 with Node.js alongside it); `bun-legacy` is accepted as an explicit spelling of the same runtime. On Bun 1.4 the worker no longer crashes at startup on the `--no-warnings=ExperimentalWarning` flag. ([`a8a87850b`](a8a8785)) - Updated dependencies: - `@trigger.dev/core@4.8.2` ## @trigger.dev/schema-to-json@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.2` ## @trigger.dev/slack@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/sdk@4.8.2` - `@trigger.dev/core@4.8.2` ## @trigger.dev/sdk@4.8.2 ### Patch Changes - Fix `chat.inject` messages added from a tool mid-turn being saved before the assistant's response. They now stay after the tool result, where the model saw them, so the next turn keeps the same prompt prefix. If you roll `@trigger.dev/sdk` back to an earlier version, chats saved by this version lose these mid-turn `chat.inject` messages from the model's context, though the chat history shown in the UI keeps them. ([`fc33769a5`](fc33769)) - The bundled `trigger-cost-savings` skill now notes that a webhook delivery starts no run when no subscriber's filter matches, so it costs no compute. ([#5051](#5051)) - Stream a sub-agent's reply through a parent tool call with `chat.forwardSubAgent`. Each chunk is written to the parent chat once and the tool resolves with the sub-agent's final message, so streaming a sub-agent costs bytes in proportion to its reply. Yielding `stream.messages()` snapshots resends the whole message on every chunk, which grows with the square of the reply. ([`bdc994c4d`](bdc994c)) ```ts execute: async ({ topic }, { toolCallId, abortSignal }) => { const stream = await researcher.sendMessage(topic, { abortSignal }); return await chat.forwardSubAgent(stream, { toolCallId }); }, ``` Render it while it runs with `useSubAgentMessages()` from `@trigger.dev/sdk/chat/react` (or `createSubAgentMessages()` outside React). - Fix a `chat.agent` turn failing after a head start that ended with two or more parallel tool calls. When those tools finished out of call order, the agent sent their results to the model twice on the next step, and the provider rejected the request (Anthropic: "each tool_use must have a single result"). Each handed-over tool result is now sent once. ([`d06ee5825`](d06ee58)) - Use short-lived run tokens for supported SDK operations inside deployed tasks when available, retaining environment-key compatibility for unsupported operations and missing or expired tokens. Explicit credentials still take precedence. Public-token helpers use server-side minting with run tokens rather than signing locally. ([`5a1c14239`](5a1c142)) Project and organization queries, and branch overrides targeting another PREVIEW or DEVELOPMENT environment, keep using compatibility credentials. Branch headers do not change credential selection in STAGING or PRODUCTION. Chat subscriptions reread implicit credentials for each connection. - Updated dependencies: - `@trigger.dev/core@4.8.2` </details> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
chore: release v4.8.2 (#5073) ## Summary 5 new features, 19 improvements, 23 bug fixes. ## Breaking changes - Query dashboard APIs reject run tokens and public access tokens without user delegation. Existing API key access, including restricted keys with the required query scopes, is unchanged. MCP dashboard access remains supported through delegated tokens for current organization members. - The legacy `clickhouse` event store is retired: task events now go to `clickhouse_v2`. If you self-host with `EVENT_REPOSITORY_DEFAULT_STORE=clickhouse`, switch it to `clickhouse_v2` and follow the self-hosting guide to copy older events, which no longer show until you do. ## Improvements - Deployed tasks now keep a valid short-lived run token for their whole run: the token is refreshed during long runs and before a run resumes from a checkpoint. A warm-started task no longer keeps the previous run's token when the next run has none, and run credentials are left out of runner debug logs. ([`aa9de9d94`](aa9de9d)) - Upgrade `socket.io-client` to 4.8.4 so projects using the SDK and CLI install `ws` 8.21 instead of 8.17.1, which has published advisories (GHSA-96hv-2xvq-fx4p, GHSA-58qx-3vcg-4xpx). The old pin blocked upgrading `ws` without a package manager override. ([`2df9860b4`](2df9860)) - Adds the `bun-1.4` runtime. `runtime: "bun-1.4"` deploys on Bun 1.4.4 in a Bun-only image with no Node.js binary, and the run controller itself runs under Bun. `runtime: "bun"` is unchanged (Bun 1.3 with Node.js alongside it); `bun-legacy` is accepted as an explicit spelling of the same runtime. On Bun 1.4 the worker no longer crashes at startup on the `--no-warnings=ExperimentalWarning` flag. ([`a8a87850b`](a8a8785)) - Add an experimental Convex component for triggering tasks transactionally and reading their status and results through reactive queries, without configuring webhooks. ([`3c1cf656c`](3c1cf65)) - Run metadata operations now reject JSON-path keys that use escaped dots to reach `__proto__`, `constructor` or `prototype`. ([`dce5048a8`](dce5048)) - Use short-lived run tokens for supported SDK operations inside deployed tasks when available, retaining environment-key compatibility for unsupported operations and missing or expired tokens. Explicit credentials still take precedence. Public-token helpers use server-side minting with run tokens rather than signing locally. ([`5a1c14239`](5a1c142)) Project and organization queries, and branch overrides targeting another PREVIEW or DEVELOPMENT environment, keep using compatibility credentials. Branch headers do not change credential selection in STAGING or PRODUCTION. Chat subscriptions reread implicit credentials for each connection. - `runs.subscribeToRun` now ends after the run completes. The `for await` loop exits right after the update with the final status, and the subscription stops its connection, so a script that subscribes to a run exits on its own. Pass `stopOnCompletion: false` to keep the subscription open after completion. ([`485ab83aa`](485ab83)) - Add `SupervisorHttpClient.releaseRun`, which gives back a dequeued run the worker never started so the platform requeues it at once instead of after the pending execution timeout. ([`ba51e5573`](ba51e55)) - The supervisor keeps its run notification subscriptions across reconnects to the webapp, and reconnects when the webapp turns its handshake away, so cancellations and resolved waits keep reaching running tasks after a webapp restart or deploy. ([`a9e69ab7d`](a9e69ab)) - Asymmetric webhook sources can now verify ECDSA P-384 signatures (`algorithm: "ecdsa-p384"`, SHA-384) and providers that sign a SHA-256 digest of the signing string (`prehash: "sha256"`). ECDSA signatures are accepted in DER or raw `r||s` form. ([`4ed2e3780`](4ed2e37)) - The bundled `trigger-cost-savings` skill now notes that a webhook delivery starts no run when no subscriber's filter matches, so it costs no compute. ([#5051](#5051)) - Stream a sub-agent's reply through a parent tool call with `chat.forwardSubAgent`. Each chunk is written to the parent chat once and the tool resolves with the sub-agent's final message, so streaming a sub-agent costs bytes in proportion to its reply. Yielding `stream.messages()` snapshots resends the whole message on every chunk, which grows with the square of the reply. ([`bdc994c4d`](bdc994c)) ```ts execute: async ({ topic }, { toolCallId, abortSignal }) => { const stream = await researcher.sendMessage(topic, { abortSignal }); return await chat.forwardSubAgent(stream, { toolCallId }); }, ``` Render it while it runs with `useSubAgentMessages()` from `@trigger.dev/sdk/chat/react` (or `createSubAgentMessages()` outside React). ## Bug fixes - Fix `chat.inject` messages added from a tool mid-turn being saved before the assistant's response. They now stay after the tool result, where the model saw them, so the next turn keeps the same prompt prefix. If you roll `@trigger.dev/sdk` back to an earlier version, chats saved by this version lose these mid-turn `chat.inject` messages from the model's context, though the chat history shown in the UI keeps them. ([`fc33769a5`](fc33769)) - Fix a `chat.agent` turn failing after a head start that ended with two or more parallel tool calls. When those tools finished out of call order, the agent sent their results to the model twice on the next step, and the provider rejected the request (Anthropic: "each tool_use must have a single result"). Each handed-over tool result is now sent once. ([`d06ee5825`](d06ee58)) ## Server changes These changes affect the self-hosted Docker image and Trigger.dev Cloud: - Add "Ignored paths" to the Git settings: pushes and pull request updates that only change files matching these patterns no longer create a deployment. Ignored paths don't apply while the Vercel integration is connected. - The `metrics` query table now includes queue size (`queue.size.*`) and webhook limit metrics (`webhook.waiters.*`, `webhook.processing.*`, `webhook.ingress.*`), so you can chart and alert on queue capacity and webhook rate limits. - New Limits alerts: watch the limits that can interrupt or degrade runtime flow, one at a time or combined into a single alert with "any" or "all" and the signals you choose (limit reached or approaching), in the dashboard, the API and the agent. - Expand short-lived run-token support to task APIs, with permission checks for packets, metadata, streams and waits. Run tokens last one hour independently of root-key rotation and cannot be individually revoked. They can mint public access tokens for up to 30 days; those tokens may outlive the run token that minted them. - Hosted webhook endpoints can verify ECDSA P-384 (SHA-384) signatures, ECDSA signatures in raw `r||s` form, and RSA signatures made over a SHA-256 digest of the signing string (`prehash: "sha256"`). - Older runs now load their trace, span details and run events faster. A span that finishes more than a week after its run shows as still in progress. - The run page now loads large traces progressively and updates live runs incrementally, so big traces open faster and open run pages no longer reload the whole trace while a run is executing. The run trace API can also page large traces. - Query alerts now accept queries whose columns are computed from other aggregate columns, such as a percentage of two aggregates. When a query can't be watched, the Watch button stays visible but disabled and explains why. - Archiving unused queues from the Concurrency page is now available on all instances, including self-hosted. - Runs whose container or pod could not be created, or whose pod failed before the run started, can now be requeued straight away instead of waiting for the pending execution timeout. Both are off by default: set `RELEASE_UNSTARTED_RUNS_ENABLED=true` on a supervisor for creates that fail, and `RELEASE_FAILED_POD_RUNS_ENABLED=true` for pods that fail. - Session external ids can no longer contain a `/channels` path segment (for example `chat-1/channels/support`) or end in `:channels`, since both forms name a session's channels. Creating a session with one now returns a 422 validation error. - Selecting a span that started a session now shows a link to that session in the span panel, so you can jump from an orchestrator's run to its sub-agents. - Fix the batch results API returning an empty list of items for completed batches. It now returns every run's result in trigger order. - Fix the batch results API returning "Batch not found" for some batches that the batch retrieve API could see. - Fix the run page continuing to live-update forever for some cancelled runs. These runs now show as finished, and loading their trace is faster. - Fix fetching the trace of a child run through the API sometimes being very slow or failing. These requests now return quickly. - Run metadata changes sent with an attempt's completion, such as increments and appends, are no longer applied a second time when a completion that already went through is retried. - Changing your email address now requires clicking a confirmation button after opening the emailed link. - Fix intermittent read and subscription errors when multiple clients first open the same realtime stream. - Fix intermittent subscription failures and missed records when reading newly created realtime streams. - Fix the dashboard's task list and task filters occasionally going stale when several `trigger dev` sessions register at the same time. - Deleting an organization now cancels its billing subscription. - Fix the dashboard agent's suggested threshold and window being dropped when it prefills a query alert. - Queries now reject an alias that reuses a table's alias in the same SELECT, unless the aliased expression contains an aggregate or window function (`count() AS runs FROM runs` still works). - Queries using `WITH <expression> AS <name>` now run instead of failing with a syntax error, and the name can be used in the rest of the query. The name can't reuse a table alias used anywhere in the query. - Fix a rare case where clock skew between run engine instances could leave a run executing after its task finished, or stop a wait from ever resuming. A run's state changes are now always ordered in the order they happened, regardless of clock skew. - A run whose attempt start was interrupted no longer gets stuck executing without its task ever running, then failing as stalled. - Fixed dropdowns sometimes picking an option by themselves when typing with some on-screen keyboards or autofill. - New runs a session starts are now always linked to their session, so their Agent tab no longer fails to load because the link was missing. - Runs no longer lose their worker's token when the cluster answers the worker's create with a 408, so the worker starts instead of waiting for a requeue. - Runs no longer lose their worker's token when a concurrent delivery or a lost answer leaves a failed worker create's token behind: the worker that took the name keeps it, and a token nothing will use is cleaned up instead of being kept. - Deleting an organization now uninstalls its Vercel integration. A Vercel installation disabled on Vercel's side is reported as such instead of as an expired connection, and removing it no longer reports success. - Promoting or rolling back a deployment now updates your webhook endpoints to match the deployment that's now current. <details> <summary>Raw changeset output</summary> # Releases ## @trigger.dev/build@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.2` ## trigger.dev@4.8.2 ### Patch Changes - Deployed tasks now keep a valid short-lived run token for their whole run: the token is refreshed during long runs and before a run resumes from a checkpoint. A warm-started task no longer keeps the previous run's token when the next run has none, and run credentials are left out of runner debug logs. ([`aa9de9d94`](aa9de9d)) - Upgrade `socket.io-client` to 4.8.4 so projects using the SDK and CLI install `ws` 8.21 instead of 8.17.1, which has published advisories (GHSA-96hv-2xvq-fx4p, GHSA-58qx-3vcg-4xpx). The old pin blocked upgrading `ws` without a package manager override. ([`2df9860b4`](2df9860)) - Adds the `bun-1.4` runtime. `runtime: "bun-1.4"` deploys on Bun 1.4.4 in a Bun-only image with no Node.js binary, and the run controller itself runs under Bun. `runtime: "bun"` is unchanged (Bun 1.3 with Node.js alongside it); `bun-legacy` is accepted as an explicit spelling of the same runtime. On Bun 1.4 the worker no longer crashes at startup on the `--no-warnings=ExperimentalWarning` flag. ([`a8a87850b`](a8a8785)) - Updated dependencies: - `@trigger.dev/core@4.8.2` - `@trigger.dev/build@4.8.2` - `@trigger.dev/schema-to-json@4.8.2` ## @trigger.dev/convex@4.8.2 ### Patch Changes - Add an experimental Convex component for triggering tasks transactionally and reading their status and results through reactive queries, without configuring webhooks. ([`3c1cf656c`](3c1cf65)) ## @trigger.dev/core@4.8.2 ### Patch Changes - Run metadata operations now reject JSON-path keys that use escaped dots to reach `__proto__`, `constructor` or `prototype`. ([`dce5048a8`](dce5048)) - Deployed tasks now keep a valid short-lived run token for their whole run: the token is refreshed during long runs and before a run resumes from a checkpoint. A warm-started task no longer keeps the previous run's token when the next run has none, and run credentials are left out of runner debug logs. ([`aa9de9d94`](aa9de9d)) - Use short-lived run tokens for supported SDK operations inside deployed tasks when available, retaining environment-key compatibility for unsupported operations and missing or expired tokens. Explicit credentials still take precedence. Public-token helpers use server-side minting with run tokens rather than signing locally. ([`5a1c14239`](5a1c142)) Project and organization queries, and branch overrides targeting another PREVIEW or DEVELOPMENT environment, keep using compatibility credentials. Branch headers do not change credential selection in STAGING or PRODUCTION. Chat subscriptions reread implicit credentials for each connection. - Upgrade `socket.io-client` to 4.8.4 so projects using the SDK and CLI install `ws` 8.21 instead of 8.17.1, which has published advisories (GHSA-96hv-2xvq-fx4p, GHSA-58qx-3vcg-4xpx). The old pin blocked upgrading `ws` without a package manager override. ([`2df9860b4`](2df9860)) - `runs.subscribeToRun` now ends after the run completes. The `for await` loop exits right after the update with the final status, and the subscription stops its connection, so a script that subscribes to a run exits on its own. Pass `stopOnCompletion: false` to keep the subscription open after completion. ([`485ab83aa`](485ab83)) - Add `SupervisorHttpClient.releaseRun`, which gives back a dequeued run the worker never started so the platform requeues it at once instead of after the pending execution timeout. ([`ba51e5573`](ba51e55)) - The supervisor keeps its run notification subscriptions across reconnects to the webapp, and reconnects when the webapp turns its handshake away, so cancellations and resolved waits keep reaching running tasks after a webapp restart or deploy. ([`a9e69ab7d`](a9e69ab)) - Adds the `bun-1.4` runtime. `runtime: "bun-1.4"` deploys on Bun 1.4.4 in a Bun-only image with no Node.js binary, and the run controller itself runs under Bun. `runtime: "bun"` is unchanged (Bun 1.3 with Node.js alongside it); `bun-legacy` is accepted as an explicit spelling of the same runtime. On Bun 1.4 the worker no longer crashes at startup on the `--no-warnings=ExperimentalWarning` flag. ([`a8a87850b`](a8a8785)) - Asymmetric webhook sources can now verify ECDSA P-384 signatures (`algorithm: "ecdsa-p384"`, SHA-384) and providers that sign a SHA-256 digest of the signing string (`prehash: "sha256"`). ECDSA signatures are accepted in DER or raw `r||s` form. ([`4ed2e3780`](4ed2e37)) ## @trigger.dev/linear@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/sdk@4.8.2` - `@trigger.dev/core@4.8.2` ## @trigger.dev/python@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/sdk@4.8.2` - `@trigger.dev/core@4.8.2` - `@trigger.dev/build@4.8.2` ## @trigger.dev/react-hooks@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.2` ## @trigger.dev/redis-worker@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.2` ## @trigger.dev/rsc@4.8.2 ### Patch Changes - Adds the `bun-1.4` runtime. `runtime: "bun-1.4"` deploys on Bun 1.4.4 in a Bun-only image with no Node.js binary, and the run controller itself runs under Bun. `runtime: "bun"` is unchanged (Bun 1.3 with Node.js alongside it); `bun-legacy` is accepted as an explicit spelling of the same runtime. On Bun 1.4 the worker no longer crashes at startup on the `--no-warnings=ExperimentalWarning` flag. ([`a8a87850b`](a8a8785)) - Updated dependencies: - `@trigger.dev/core@4.8.2` ## @trigger.dev/schema-to-json@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.2` ## @trigger.dev/slack@4.8.2 ### Patch Changes - Updated dependencies: - `@trigger.dev/sdk@4.8.2` - `@trigger.dev/core@4.8.2` ## @trigger.dev/sdk@4.8.2 ### Patch Changes - Fix `chat.inject` messages added from a tool mid-turn being saved before the assistant's response. They now stay after the tool result, where the model saw them, so the next turn keeps the same prompt prefix. If you roll `@trigger.dev/sdk` back to an earlier version, chats saved by this version lose these mid-turn `chat.inject` messages from the model's context, though the chat history shown in the UI keeps them. ([`fc33769a5`](fc33769)) - The bundled `trigger-cost-savings` skill now notes that a webhook delivery starts no run when no subscriber's filter matches, so it costs no compute. ([#5051](#5051)) - Stream a sub-agent's reply through a parent tool call with `chat.forwardSubAgent`. Each chunk is written to the parent chat once and the tool resolves with the sub-agent's final message, so streaming a sub-agent costs bytes in proportion to its reply. Yielding `stream.messages()` snapshots resends the whole message on every chunk, which grows with the square of the reply. ([`bdc994c4d`](bdc994c)) ```ts execute: async ({ topic }, { toolCallId, abortSignal }) => { const stream = await researcher.sendMessage(topic, { abortSignal }); return await chat.forwardSubAgent(stream, { toolCallId }); }, ``` Render it while it runs with `useSubAgentMessages()` from `@trigger.dev/sdk/chat/react` (or `createSubAgentMessages()` outside React). - Fix a `chat.agent` turn failing after a head start that ended with two or more parallel tool calls. When those tools finished out of call order, the agent sent their results to the model twice on the next step, and the provider rejected the request (Anthropic: "each tool_use must have a single result"). Each handed-over tool result is now sent once. ([`d06ee5825`](d06ee58)) - Use short-lived run tokens for supported SDK operations inside deployed tasks when available, retaining environment-key compatibility for unsupported operations and missing or expired tokens. Explicit credentials still take precedence. Public-token helpers use server-side minting with run tokens rather than signing locally. ([`5a1c14239`](5a1c142)) Project and organization queries, and branch overrides targeting another PREVIEW or DEVELOPMENT environment, keep using compatibility credentials. Branch headers do not change credential selection in STAGING or PRODUCTION. Chat subscriptions reread implicit credentials for each connection. - Updated dependencies: - `@trigger.dev/core@4.8.2` </details> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Publish docs: alerts, webhooks, self-hosting, Bun runtime and chat up… …dates
Publish docs: webhook pricing/limits, bun-1.4 runtime, trace paging, … …chat.forwardSubAgent, chat.inject history, deployment index storage
chore: release v4.8.1 (#5057) ## Summary 1 new feature, 1 bug fix. ## Bug fixes - Fix `trigger deploy` failing on self-hosted instances with custom base images. Stages built on a custom image now keep the trust store that image ships with. ([`b5ed66b74`](b5ed66b)) ## Server changes These changes affect the self-hosted Docker image and Trigger.dev Cloud: - Alerts can now watch the result of any supported query: raise when a value crosses a threshold, when matching rows stop appearing, or when new matching rows appear. Create them from the Query page, the Dashboard Agent or the API, and see the alert's values charted on its page. <details> <summary>Raw changeset output</summary> # Releases ## @trigger.dev/build@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## trigger.dev@4.8.1 ### Patch Changes - Fix `trigger deploy` failing on self-hosted instances with custom base images. Stages built on a custom image now keep the trust store that image ships with. ([`b5ed66b74`](b5ed66b)) - Updated dependencies: - `@trigger.dev/build@4.8.1` - `@trigger.dev/core@4.8.1` - `@trigger.dev/schema-to-json@4.8.1` ## @trigger.dev/linear@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` - `@trigger.dev/sdk@4.8.1` ## @trigger.dev/python@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/build@4.8.1` - `@trigger.dev/core@4.8.1` - `@trigger.dev/sdk@4.8.1` ## @trigger.dev/react-hooks@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/redis-worker@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/rsc@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/schema-to-json@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/slack@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` - `@trigger.dev/sdk@4.8.1` ## @trigger.dev/sdk@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/core@4.8.1 </details> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
chore: release v4.8.0 (#5044) ## Summary 3 new features, 14 improvements, 4 bug fixes. ## Improvements - Route verified webhooks into agent sessions with `chat.event({ endpoint, key })`, and connect external chat surfaces with `chat.channels.custom({ endpoint })`. Both subscribe to a shared webhook endpoint, so an agent and your other webhook tasks can use the same provider URL. Channels support reply delivery, session binding, conversation seeding, and lifecycle reactions, and a failed turn posts a short line instead of the error (`errorMessage` sets it, as a string or a function of the failure). Use `chat.createWatchToken()` to watch a session from another surface. ([`d6955ee9f`](d6955ee)) A connector can also stream replies natively (`stream()`), mirror the session's state into the surface (`lifecycle()`), show tool calls as they run (`progress()`), stop a running turn from the surface (`onControl()`), post approvals and tool controls and resume the run from a verified click, download files only the surface can read (`download()`), and acknowledge or fold in messages that arrive mid-turn (`received()`, `pendingMessages`). - Add hosted webhooks: declare an endpoint once with `webhooks.endpoint.define({ id, source })` and Trigger.dev hosts its URL, verifies every request, and routes each event to the endpoint's subscribers. Subscribe tasks with `webhook({ endpoint, filter, onEvent })`, each with its own type-safe filter, and pause a run until a matching webhook arrives with `webhooks.waiter.create()` and `webhooks.waiter.wait()`. ([`d6955ee9f`](d6955ee)) ```ts export const stripe = webhooks.endpoint.define({ id: "stripe", source: webhooks.stripe(), }); export const fulfill = webhook({ id: "fulfill", endpoint: stripe, filter: "event.type == 'checkout.session.completed'", onEvent: async ({ event }) => {}, }); const waiter = await webhooks.waiter.create(stripe, { match: { "event.data.object.metadata.orderId": order.id }, }); const { event } = await webhooks.waiter.wait(waiter).unwrap(); ``` Sources cover presets (`webhooks.stripe()`, `webhooks.github()`, `webhooks.svix()`, `webhooks.discord()`, and others), named providers (`webhooks.clerk()`, `webhooks.shopify()`, and more) and `webhooks.custom<T>(config)`, and most carry a setup prompt an AI coding agent can follow to register the endpoint. Retries are deduplicated on the provider's own event or delivery id where it sends one. Filters, keys and waiter `match` paths share the `event.`, `header.` and `webhook.` namespaces, and filters accept `== null` / `!= null` presence checks and `event any (...)` over a payload that is an array of events. `webhook()` takes `task()` options such as `queue`, `machine` and `retry`. The HTTP API lists endpoints and deliveries, replays deliveries, and creates and cancels waiters, and both it and the MCP server can read an endpoint's setup prompt and generate or store its signing secret. - The `generate_webhook_secret` and `set_webhook_secret` MCP tools take an optional `previousSecretTtlSeconds` to keep accepting a webhook endpoint's old signing secret while the provider switches to the new one (up to 7 days), and report when the old secret stops working. ([`98adb6662`](98adb66)) - Realtime streams now reconnect and resume when the stream backend reports a failed read mid-stream, instead of ending early as if the stream had finished. This affects `runs.subscribeToRun` with streams, `useRealtimeRunWithStreams`, and chat streams. ([`23730b034`](23730b0)) - HMAC webhook verifier configs accept `additionalSignatureHeaders`: more headers that can carry a signature, matched as alternatives to `signatureHeader`. Providers that send a second signature during a secret rotation (Hookdeck's `x-hookdeck-signature-2`) keep verifying through the rotation. ([`08d1ddbd3`](08d1ddb)) - Add `webhooks.hookdeck()`, a source for deliveries relayed through a Hookdeck connection. It verifies the `x-hookdeck-signature` header with the project's signing secret, keeps verifying while the secret is being rolled (Hookdeck sends the previous secret's signature in `x-hookdeck-signature-2`), and deduplicates retries on `x-hookdeck-eventid`. The event is the original provider's payload, so pass its type: `webhooks.hookdeck<Stripe.Event>()`. If the Hookdeck project's header prefix was changed, pass it as `webhooks.hookdeck({ headerPrefix })` so retries keep deduplicating. ([`51b39fbc6`](51b39fb)) - Add `@trigger.dev/linear`: turn a `chat.agent` into a Linear agent. Assign it an issue or @mention it, and Linear's agent session becomes a durable Trigger.dev session: the reply posts back to Linear, tool calls show as activities, `linearPlanTool()` keeps the plan Linear shows as a checklist, and approvals are Approve and Deny options that resume the run. ([`1586c4a3f`](1586c4a)) ```ts import { linear, webhookSource } from "@trigger.dev/linear"; const linearEvents = webhooks.endpoint.define({ id: "linear", source: webhookSource(), }); export const triage = chat.agent({ id: "triage", channels: [ linear({ id: "linear", endpoint: linearEvents, token: process.env.LINEAR_ACCESS_TOKEN!, }), ], run: async ({ messages, signal, streamText }) => streamText({ model, messages, abortSignal: signal }), }); ``` The first turn gets the issue's context and earlier comments, images and PDFs in the issue reach the model, a Stop in Linear winds the turn down, and `errorMessage` sets the text a failed turn shows. - Add `@trigger.dev/slack`: turn a `chat.agent` into a native Slack agent. Each DM or channel thread is a durable session, the reply streams into the thread with the turn's tool calls shown as a plan, approvals are Approve and Deny buttons, and Slack's stop button stops the turn. ([`6e715da77`](6e715da)) ```ts import { appMentions, slack, webhookSource } from "@trigger.dev/slack"; const slackEvents = webhooks.endpoint.define({ id: "slack", source: webhookSource(), }); export const support = chat.agent({ id: "support", channels: [ slack({ id: "slack", endpoint: slackEvents, token: process.env.SLACK_BOT_TOKEN!, startOn: appMentions(), }), ], run: async ({ messages, signal, streamText }) => streamText({ model, messages, abortSignal: signal }), }); ``` `startOn` decides which channel messages start a session (`appMentions()` answers when the agent is @mentioned). Images and PDFs people share reach the model, messages sent while the agent is answering can be folded into the reply, tools can post their own buttons, and `ownWorkspaceOnly` ignores Slack Connect guests. - The `streamText` passed to a `chat.agent`'s `run()` now turns AI SDK telemetry on by default, so each model step and tool call shows up as a span in the run trace even when the agent doesn't store a prompt with `chat.prompt.set()`. An agent with `telemetry: { recordUserMessage: false }` gets these spans without prompt and response content, including when it stores a prompt (whose variables are left out of the span metadata). Pass `experimental_telemetry: { isEnabled: false }` at the call site to turn them off, or `recordInputs: false` / `recordOutputs: false` to keep them without content. ([`bd7cc3525`](bd7cc35)) ## Server changes These changes affect the self-hosted Docker image and Trigger.dev Cloud: - When regenerating an environment's API key you can now revoke the previous key immediately instead of keeping it working for 24 hours. Use this when a key may have leaked. - Set `KUBERNETES_POD_RESERVED_SOURCE_PORTS` on the supervisor (for example `50080,50081`) to stop runs using those ports for outbound connections, which is useful to avoid port clashes. - Rotating a webhook endpoint's signing secret can keep the old one valid for a while, so you can rotate without failing deliveries that are still signed with it. The rotate and regenerate dialogs let you choose how long the old secret stays valid (up to 7 days, 24 hours by default). The `rotate-secret` and `secret` endpoints accept an optional `previousSecretTtlSeconds` and return `previousSecretExpiresAt`. With no value, the old secret stops working immediately, as before. - Alerts are now checked every minute instead of every 5–10 minutes, so they raise and recover sooner. - Run traces and trace APIs load faster for older runs. - The API keys page now always lists your root API key, masked to its last 4 characters when it's hidden, so you can regenerate it and revoke the previous key. When the root key is hidden, the page points you to creating an API key for your backend. - Runs whose deployment has no compute template now go to containers when they are triggered, instead of first passing through the compute worker queue. - Runs now get a `TRIGGER_DASHBOARD_URL` environment variable with the dashboard's address, so a task can link to its run (`${TRIGGER_DASHBOARD_URL}/runs/${ctx.run.id}`) on any Trigger.dev instance. A `TRIGGER_DASHBOARD_URL` you set on the project still wins. - Creating an alert works without the dashboard agent. - Small fixes to creating and editing alerts. - Alerts sent to Slack channels connected through a removed Slack installation deliver again. - The supervisor no longer trusts certificates issued under the compromised emSign (eMudhra) certificate authorities. <details> <summary>Raw changeset output</summary> # Releases ## trigger.dev@4.8.0 ### Minor Changes - Route verified webhooks into agent sessions with `chat.event({ endpoint, key })`, and connect external chat surfaces with `chat.channels.custom({ endpoint })`. Both subscribe to a shared webhook endpoint, so an agent and your other webhook tasks can use the same provider URL. Channels support reply delivery, session binding, conversation seeding, and lifecycle reactions, and a failed turn posts a short line instead of the error (`errorMessage` sets it, as a string or a function of the failure). Use `chat.createWatchToken()` to watch a session from another surface. ([`d6955ee9f`](d6955ee)) A connector can also stream replies natively (`stream()`), mirror the session's state into the surface (`lifecycle()`), show tool calls as they run (`progress()`), stop a running turn from the surface (`onControl()`), post approvals and tool controls and resume the run from a verified click, download files only the surface can read (`download()`), and acknowledge or fold in messages that arrive mid-turn (`received()`, `pendingMessages`). - Add hosted webhooks: declare an endpoint once with `webhooks.endpoint.define({ id, source })` and Trigger.dev hosts its URL, verifies every request, and routes each event to the endpoint's subscribers. Subscribe tasks with `webhook({ endpoint, filter, onEvent })`, each with its own type-safe filter, and pause a run until a matching webhook arrives with `webhooks.waiter.create()` and `webhooks.waiter.wait()`. ([`d6955ee9f`](d6955ee)) ```ts export const stripe = webhooks.endpoint.define({ id: "stripe", source: webhooks.stripe(), }); export const fulfill = webhook({ id: "fulfill", endpoint: stripe, filter: "event.type == 'checkout.session.completed'", onEvent: async ({ event }) => {}, }); const waiter = await webhooks.waiter.create(stripe, { match: { "event.data.object.metadata.orderId": order.id }, }); const { event } = await webhooks.waiter.wait(waiter).unwrap(); ``` Sources cover presets (`webhooks.stripe()`, `webhooks.github()`, `webhooks.svix()`, `webhooks.discord()`, and others), named providers (`webhooks.clerk()`, `webhooks.shopify()`, and more) and `webhooks.custom<T>(config)`, and most carry a setup prompt an AI coding agent can follow to register the endpoint. Retries are deduplicated on the provider's own event or delivery id where it sends one. Filters, keys and waiter `match` paths share the `event.`, `header.` and `webhook.` namespaces, and filters accept `== null` / `!= null` presence checks and `event any (...)` over a payload that is an array of events. `webhook()` takes `task()` options such as `queue`, `machine` and `retry`. The HTTP API lists endpoints and deliveries, replays deliveries, and creates and cancels waiters, and both it and the MCP server can read an endpoint's setup prompt and generate or store its signing secret. ### Patch Changes - The `generate_webhook_secret` and `set_webhook_secret` MCP tools take an optional `previousSecretTtlSeconds` to keep accepting a webhook endpoint's old signing secret while the provider switches to the new one (up to 7 days), and report when the old secret stops working. ([`98adb6662`](98adb66)) - Updated dependencies: - `@trigger.dev/core@4.8.0` - `@trigger.dev/build@4.8.0` - `@trigger.dev/schema-to-json@4.8.0` ## @trigger.dev/core@4.8.0 ### Minor Changes - Add hosted webhooks: declare an endpoint once with `webhooks.endpoint.define({ id, source })` and Trigger.dev hosts its URL, verifies every request, and routes each event to the endpoint's subscribers. Subscribe tasks with `webhook({ endpoint, filter, onEvent })`, each with its own type-safe filter, and pause a run until a matching webhook arrives with `webhooks.waiter.create()` and `webhooks.waiter.wait()`. ([`d6955ee9f`](d6955ee)) ```ts export const stripe = webhooks.endpoint.define({ id: "stripe", source: webhooks.stripe(), }); export const fulfill = webhook({ id: "fulfill", endpoint: stripe, filter: "event.type == 'checkout.session.completed'", onEvent: async ({ event }) => {}, }); const waiter = await webhooks.waiter.create(stripe, { match: { "event.data.object.metadata.orderId": order.id }, }); const { event } = await webhooks.waiter.wait(waiter).unwrap(); ``` Sources cover presets (`webhooks.stripe()`, `webhooks.github()`, `webhooks.svix()`, `webhooks.discord()`, and others), named providers (`webhooks.clerk()`, `webhooks.shopify()`, and more) and `webhooks.custom<T>(config)`, and most carry a setup prompt an AI coding agent can follow to register the endpoint. Retries are deduplicated on the provider's own event or delivery id where it sends one. Filters, keys and waiter `match` paths share the `event.`, `header.` and `webhook.` namespaces, and filters accept `== null` / `!= null` presence checks and `event any (...)` over a payload that is an array of events. `webhook()` takes `task()` options such as `queue`, `machine` and `retry`. The HTTP API lists endpoints and deliveries, replays deliveries, and creates and cancels waiters, and both it and the MCP server can read an endpoint's setup prompt and generate or store its signing secret. ### Patch Changes - Realtime streams now reconnect and resume when the stream backend reports a failed read mid-stream, instead of ending early as if the stream had finished. This affects `runs.subscribeToRun` with streams, `useRealtimeRunWithStreams`, and chat streams. ([`23730b034`](23730b0)) - HMAC webhook verifier configs accept `additionalSignatureHeaders`: more headers that can carry a signature, matched as alternatives to `signatureHeader`. Providers that send a second signature during a secret rotation (Hookdeck's `x-hookdeck-signature-2`) keep verifying through the rotation. ([`08d1ddbd3`](08d1ddb)) - The `generate_webhook_secret` and `set_webhook_secret` MCP tools take an optional `previousSecretTtlSeconds` to keep accepting a webhook endpoint's old signing secret while the provider switches to the new one (up to 7 days), and report when the old secret stops working. ([`98adb6662`](98adb66)) - Add `webhooks.hookdeck()`, a source for deliveries relayed through a Hookdeck connection. It verifies the `x-hookdeck-signature` header with the project's signing secret, keeps verifying while the secret is being rolled (Hookdeck sends the previous secret's signature in `x-hookdeck-signature-2`), and deduplicates retries on `x-hookdeck-eventid`. The event is the original provider's payload, so pass its type: `webhooks.hookdeck<Stripe.Event>()`. If the Hookdeck project's header prefix was changed, pass it as `webhooks.hookdeck({ headerPrefix })` so retries keep deduplicating. ([`51b39fbc6`](51b39fb)) ## @trigger.dev/linear@4.8.0 ### Minor Changes - Add `@trigger.dev/linear`: turn a `chat.agent` into a Linear agent. Assign it an issue or @mention it, and Linear's agent session becomes a durable Trigger.dev session: the reply posts back to Linear, tool calls show as activities, `linearPlanTool()` keeps the plan Linear shows as a checklist, and approvals are Approve and Deny options that resume the run. ([`1586c4a3f`](1586c4a)) ```ts import { linear, webhookSource } from "@trigger.dev/linear"; const linearEvents = webhooks.endpoint.define({ id: "linear", source: webhookSource(), }); export const triage = chat.agent({ id: "triage", channels: [ linear({ id: "linear", endpoint: linearEvents, token: process.env.LINEAR_ACCESS_TOKEN!, }), ], run: async ({ messages, signal, streamText }) => streamText({ model, messages, abortSignal: signal }), }); ``` The first turn gets the issue's context and earlier comments, images and PDFs in the issue reach the model, a Stop in Linear winds the turn down, and `errorMessage` sets the text a failed turn shows. ### Patch Changes - Updated dependencies: - `@trigger.dev/sdk@4.8.0` - `@trigger.dev/core@4.8.0` ## @trigger.dev/slack@4.8.0 ### Minor Changes - Add `@trigger.dev/slack`: turn a `chat.agent` into a native Slack agent. Each DM or channel thread is a durable session, the reply streams into the thread with the turn's tool calls shown as a plan, approvals are Approve and Deny buttons, and Slack's stop button stops the turn. ([`6e715da77`](6e715da)) ```ts import { appMentions, slack, webhookSource } from "@trigger.dev/slack"; const slackEvents = webhooks.endpoint.define({ id: "slack", source: webhookSource(), }); export const support = chat.agent({ id: "support", channels: [ slack({ id: "slack", endpoint: slackEvents, token: process.env.SLACK_BOT_TOKEN!, startOn: appMentions(), }), ], run: async ({ messages, signal, streamText }) => streamText({ model, messages, abortSignal: signal }), }); ``` `startOn` decides which channel messages start a session (`appMentions()` answers when the agent is @mentioned). Images and PDFs people share reach the model, messages sent while the agent is answering can be folded into the reply, tools can post their own buttons, and `ownWorkspaceOnly` ignores Slack Connect guests. ### Patch Changes - Updated dependencies: - `@trigger.dev/sdk@4.8.0` - `@trigger.dev/core@4.8.0` ## @trigger.dev/sdk@4.8.0 ### Minor Changes - Route verified webhooks into agent sessions with `chat.event({ endpoint, key })`, and connect external chat surfaces with `chat.channels.custom({ endpoint })`. Both subscribe to a shared webhook endpoint, so an agent and your other webhook tasks can use the same provider URL. Channels support reply delivery, session binding, conversation seeding, and lifecycle reactions, and a failed turn posts a short line instead of the error (`errorMessage` sets it, as a string or a function of the failure). Use `chat.createWatchToken()` to watch a session from another surface. ([`d6955ee9f`](d6955ee)) A connector can also stream replies natively (`stream()`), mirror the session's state into the surface (`lifecycle()`), show tool calls as they run (`progress()`), stop a running turn from the surface (`onControl()`), post approvals and tool controls and resume the run from a verified click, download files only the surface can read (`download()`), and acknowledge or fold in messages that arrive mid-turn (`received()`, `pendingMessages`). - Add hosted webhooks: declare an endpoint once with `webhooks.endpoint.define({ id, source })` and Trigger.dev hosts its URL, verifies every request, and routes each event to the endpoint's subscribers. Subscribe tasks with `webhook({ endpoint, filter, onEvent })`, each with its own type-safe filter, and pause a run until a matching webhook arrives with `webhooks.waiter.create()` and `webhooks.waiter.wait()`. ([`d6955ee9f`](d6955ee)) ```ts export const stripe = webhooks.endpoint.define({ id: "stripe", source: webhooks.stripe(), }); export const fulfill = webhook({ id: "fulfill", endpoint: stripe, filter: "event.type == 'checkout.session.completed'", onEvent: async ({ event }) => {}, }); const waiter = await webhooks.waiter.create(stripe, { match: { "event.data.object.metadata.orderId": order.id }, }); const { event } = await webhooks.waiter.wait(waiter).unwrap(); ``` Sources cover presets (`webhooks.stripe()`, `webhooks.github()`, `webhooks.svix()`, `webhooks.discord()`, and others), named providers (`webhooks.clerk()`, `webhooks.shopify()`, and more) and `webhooks.custom<T>(config)`, and most carry a setup prompt an AI coding agent can follow to register the endpoint. Retries are deduplicated on the provider's own event or delivery id where it sends one. Filters, keys and waiter `match` paths share the `event.`, `header.` and `webhook.` namespaces, and filters accept `== null` / `!= null` presence checks and `event any (...)` over a payload that is an array of events. `webhook()` takes `task()` options such as `queue`, `machine` and `retry`. The HTTP API lists endpoints and deliveries, replays deliveries, and creates and cancels waiters, and both it and the MCP server can read an endpoint's setup prompt and generate or store its signing secret. - Add `@trigger.dev/slack`: turn a `chat.agent` into a native Slack agent. Each DM or channel thread is a durable session, the reply streams into the thread with the turn's tool calls shown as a plan, approvals are Approve and Deny buttons, and Slack's stop button stops the turn. ([`6e715da77`](6e715da)) ```ts import { appMentions, slack, webhookSource } from "@trigger.dev/slack"; const slackEvents = webhooks.endpoint.define({ id: "slack", source: webhookSource(), }); export const support = chat.agent({ id: "support", channels: [ slack({ id: "slack", endpoint: slackEvents, token: process.env.SLACK_BOT_TOKEN!, startOn: appMentions(), }), ], run: async ({ messages, signal, streamText }) => streamText({ model, messages, abortSignal: signal }), }); ``` `startOn` decides which channel messages start a session (`appMentions()` answers when the agent is @mentioned). Images and PDFs people share reach the model, messages sent while the agent is answering can be folded into the reply, tools can post their own buttons, and `ownWorkspaceOnly` ignores Slack Connect guests. - Add `@trigger.dev/linear`: turn a `chat.agent` into a Linear agent. Assign it an issue or @mention it, and Linear's agent session becomes a durable Trigger.dev session: the reply posts back to Linear, tool calls show as activities, `linearPlanTool()` keeps the plan Linear shows as a checklist, and approvals are Approve and Deny options that resume the run. ([`1586c4a3f`](1586c4a)) ```ts import { linear, webhookSource } from "@trigger.dev/linear"; const linearEvents = webhooks.endpoint.define({ id: "linear", source: webhookSource(), }); export const triage = chat.agent({ id: "triage", channels: [ linear({ id: "linear", endpoint: linearEvents, token: process.env.LINEAR_ACCESS_TOKEN!, }), ], run: async ({ messages, signal, streamText }) => streamText({ model, messages, abortSignal: signal }), }); ``` The first turn gets the issue's context and earlier comments, images and PDFs in the issue reach the model, a Stop in Linear winds the turn down, and `errorMessage` sets the text a failed turn shows. ### Patch Changes - The `streamText` passed to a `chat.agent`'s `run()` now turns AI SDK telemetry on by default, so each model step and tool call shows up as a span in the run trace even when the agent doesn't store a prompt with `chat.prompt.set()`. An agent with `telemetry: { recordUserMessage: false }` gets these spans without prompt and response content, including when it stores a prompt (whose variables are left out of the span metadata). Pass `experimental_telemetry: { isEnabled: false }` at the call site to turn them off, or `recordInputs: false` / `recordOutputs: false` to keep them without content. ([`bd7cc3525`](bd7cc35)) - Add `webhooks.hookdeck()`, a source for deliveries relayed through a Hookdeck connection. It verifies the `x-hookdeck-signature` header with the project's signing secret, keeps verifying while the secret is being rolled (Hookdeck sends the previous secret's signature in `x-hookdeck-signature-2`), and deduplicates retries on `x-hookdeck-eventid`. The event is the original provider's payload, so pass its type: `webhooks.hookdeck<Stripe.Event>()`. If the Hookdeck project's header prefix was changed, pass it as `webhooks.hookdeck({ headerPrefix })` so retries keep deduplicating. ([`51b39fbc6`](51b39fb)) - Updated dependencies: - `@trigger.dev/core@4.8.0` ## @trigger.dev/build@4.8.0 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.0` ## @trigger.dev/python@4.8.0 ### Patch Changes - Updated dependencies: - `@trigger.dev/sdk@4.8.0` - `@trigger.dev/core@4.8.0` - `@trigger.dev/build@4.8.0` ## @trigger.dev/react-hooks@4.8.0 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.0` ## @trigger.dev/redis-worker@4.8.0 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.0` ## @trigger.dev/rsc@4.8.0 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.0` ## @trigger.dev/schema-to-json@4.8.0 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.0` </details> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
chore: release v4.8.1 (#5057) ## Summary 1 new feature, 1 bug fix. ## Bug fixes - Fix `trigger deploy` failing on self-hosted instances with custom base images. Stages built on a custom image now keep the trust store that image ships with. ([`b5ed66b74`](b5ed66b)) ## Server changes These changes affect the self-hosted Docker image and Trigger.dev Cloud: - Alerts can now watch the result of any supported query: raise when a value crosses a threshold, when matching rows stop appearing, or when new matching rows appear. Create them from the Query page, the Dashboard Agent or the API, and see the alert's values charted on its page. <details> <summary>Raw changeset output</summary> # Releases ## @trigger.dev/build@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## trigger.dev@4.8.1 ### Patch Changes - Fix `trigger deploy` failing on self-hosted instances with custom base images. Stages built on a custom image now keep the trust store that image ships with. ([`b5ed66b74`](b5ed66b)) - Updated dependencies: - `@trigger.dev/build@4.8.1` - `@trigger.dev/core@4.8.1` - `@trigger.dev/schema-to-json@4.8.1` ## @trigger.dev/linear@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` - `@trigger.dev/sdk@4.8.1` ## @trigger.dev/python@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/build@4.8.1` - `@trigger.dev/core@4.8.1` - `@trigger.dev/sdk@4.8.1` ## @trigger.dev/react-hooks@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/redis-worker@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/rsc@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/schema-to-json@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/slack@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` - `@trigger.dev/sdk@4.8.1` ## @trigger.dev/sdk@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/core@4.8.1 </details> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
chore: release v4.8.0 (#5044) ## Summary 3 new features, 14 improvements, 4 bug fixes. ## Improvements - Route verified webhooks into agent sessions with `chat.event({ endpoint, key })`, and connect external chat surfaces with `chat.channels.custom({ endpoint })`. Both subscribe to a shared webhook endpoint, so an agent and your other webhook tasks can use the same provider URL. Channels support reply delivery, session binding, conversation seeding, and lifecycle reactions, and a failed turn posts a short line instead of the error (`errorMessage` sets it, as a string or a function of the failure). Use `chat.createWatchToken()` to watch a session from another surface. ([`d6955ee9f`](d6955ee)) A connector can also stream replies natively (`stream()`), mirror the session's state into the surface (`lifecycle()`), show tool calls as they run (`progress()`), stop a running turn from the surface (`onControl()`), post approvals and tool controls and resume the run from a verified click, download files only the surface can read (`download()`), and acknowledge or fold in messages that arrive mid-turn (`received()`, `pendingMessages`). - Add hosted webhooks: declare an endpoint once with `webhooks.endpoint.define({ id, source })` and Trigger.dev hosts its URL, verifies every request, and routes each event to the endpoint's subscribers. Subscribe tasks with `webhook({ endpoint, filter, onEvent })`, each with its own type-safe filter, and pause a run until a matching webhook arrives with `webhooks.waiter.create()` and `webhooks.waiter.wait()`. ([`d6955ee9f`](d6955ee)) ```ts export const stripe = webhooks.endpoint.define({ id: "stripe", source: webhooks.stripe(), }); export const fulfill = webhook({ id: "fulfill", endpoint: stripe, filter: "event.type == 'checkout.session.completed'", onEvent: async ({ event }) => {}, }); const waiter = await webhooks.waiter.create(stripe, { match: { "event.data.object.metadata.orderId": order.id }, }); const { event } = await webhooks.waiter.wait(waiter).unwrap(); ``` Sources cover presets (`webhooks.stripe()`, `webhooks.github()`, `webhooks.svix()`, `webhooks.discord()`, and others), named providers (`webhooks.clerk()`, `webhooks.shopify()`, and more) and `webhooks.custom<T>(config)`, and most carry a setup prompt an AI coding agent can follow to register the endpoint. Retries are deduplicated on the provider's own event or delivery id where it sends one. Filters, keys and waiter `match` paths share the `event.`, `header.` and `webhook.` namespaces, and filters accept `== null` / `!= null` presence checks and `event any (...)` over a payload that is an array of events. `webhook()` takes `task()` options such as `queue`, `machine` and `retry`. The HTTP API lists endpoints and deliveries, replays deliveries, and creates and cancels waiters, and both it and the MCP server can read an endpoint's setup prompt and generate or store its signing secret. - The `generate_webhook_secret` and `set_webhook_secret` MCP tools take an optional `previousSecretTtlSeconds` to keep accepting a webhook endpoint's old signing secret while the provider switches to the new one (up to 7 days), and report when the old secret stops working. ([`98adb6662`](98adb66)) - Realtime streams now reconnect and resume when the stream backend reports a failed read mid-stream, instead of ending early as if the stream had finished. This affects `runs.subscribeToRun` with streams, `useRealtimeRunWithStreams`, and chat streams. ([`23730b034`](23730b0)) - HMAC webhook verifier configs accept `additionalSignatureHeaders`: more headers that can carry a signature, matched as alternatives to `signatureHeader`. Providers that send a second signature during a secret rotation (Hookdeck's `x-hookdeck-signature-2`) keep verifying through the rotation. ([`08d1ddbd3`](08d1ddb)) - Add `webhooks.hookdeck()`, a source for deliveries relayed through a Hookdeck connection. It verifies the `x-hookdeck-signature` header with the project's signing secret, keeps verifying while the secret is being rolled (Hookdeck sends the previous secret's signature in `x-hookdeck-signature-2`), and deduplicates retries on `x-hookdeck-eventid`. The event is the original provider's payload, so pass its type: `webhooks.hookdeck<Stripe.Event>()`. If the Hookdeck project's header prefix was changed, pass it as `webhooks.hookdeck({ headerPrefix })` so retries keep deduplicating. ([`51b39fbc6`](51b39fb)) - Add `@trigger.dev/linear`: turn a `chat.agent` into a Linear agent. Assign it an issue or @mention it, and Linear's agent session becomes a durable Trigger.dev session: the reply posts back to Linear, tool calls show as activities, `linearPlanTool()` keeps the plan Linear shows as a checklist, and approvals are Approve and Deny options that resume the run. ([`1586c4a3f`](1586c4a)) ```ts import { linear, webhookSource } from "@trigger.dev/linear"; const linearEvents = webhooks.endpoint.define({ id: "linear", source: webhookSource(), }); export const triage = chat.agent({ id: "triage", channels: [ linear({ id: "linear", endpoint: linearEvents, token: process.env.LINEAR_ACCESS_TOKEN!, }), ], run: async ({ messages, signal, streamText }) => streamText({ model, messages, abortSignal: signal }), }); ``` The first turn gets the issue's context and earlier comments, images and PDFs in the issue reach the model, a Stop in Linear winds the turn down, and `errorMessage` sets the text a failed turn shows. - Add `@trigger.dev/slack`: turn a `chat.agent` into a native Slack agent. Each DM or channel thread is a durable session, the reply streams into the thread with the turn's tool calls shown as a plan, approvals are Approve and Deny buttons, and Slack's stop button stops the turn. ([`6e715da77`](6e715da)) ```ts import { appMentions, slack, webhookSource } from "@trigger.dev/slack"; const slackEvents = webhooks.endpoint.define({ id: "slack", source: webhookSource(), }); export const support = chat.agent({ id: "support", channels: [ slack({ id: "slack", endpoint: slackEvents, token: process.env.SLACK_BOT_TOKEN!, startOn: appMentions(), }), ], run: async ({ messages, signal, streamText }) => streamText({ model, messages, abortSignal: signal }), }); ``` `startOn` decides which channel messages start a session (`appMentions()` answers when the agent is @mentioned). Images and PDFs people share reach the model, messages sent while the agent is answering can be folded into the reply, tools can post their own buttons, and `ownWorkspaceOnly` ignores Slack Connect guests. - The `streamText` passed to a `chat.agent`'s `run()` now turns AI SDK telemetry on by default, so each model step and tool call shows up as a span in the run trace even when the agent doesn't store a prompt with `chat.prompt.set()`. An agent with `telemetry: { recordUserMessage: false }` gets these spans without prompt and response content, including when it stores a prompt (whose variables are left out of the span metadata). Pass `experimental_telemetry: { isEnabled: false }` at the call site to turn them off, or `recordInputs: false` / `recordOutputs: false` to keep them without content. ([`bd7cc3525`](bd7cc35)) ## Server changes These changes affect the self-hosted Docker image and Trigger.dev Cloud: - When regenerating an environment's API key you can now revoke the previous key immediately instead of keeping it working for 24 hours. Use this when a key may have leaked. - Set `KUBERNETES_POD_RESERVED_SOURCE_PORTS` on the supervisor (for example `50080,50081`) to stop runs using those ports for outbound connections, which is useful to avoid port clashes. - Rotating a webhook endpoint's signing secret can keep the old one valid for a while, so you can rotate without failing deliveries that are still signed with it. The rotate and regenerate dialogs let you choose how long the old secret stays valid (up to 7 days, 24 hours by default). The `rotate-secret` and `secret` endpoints accept an optional `previousSecretTtlSeconds` and return `previousSecretExpiresAt`. With no value, the old secret stops working immediately, as before. - Alerts are now checked every minute instead of every 5–10 minutes, so they raise and recover sooner. - Run traces and trace APIs load faster for older runs. - The API keys page now always lists your root API key, masked to its last 4 characters when it's hidden, so you can regenerate it and revoke the previous key. When the root key is hidden, the page points you to creating an API key for your backend. - Runs whose deployment has no compute template now go to containers when they are triggered, instead of first passing through the compute worker queue. - Runs now get a `TRIGGER_DASHBOARD_URL` environment variable with the dashboard's address, so a task can link to its run (`${TRIGGER_DASHBOARD_URL}/runs/${ctx.run.id}`) on any Trigger.dev instance. A `TRIGGER_DASHBOARD_URL` you set on the project still wins. - Creating an alert works without the dashboard agent. - Small fixes to creating and editing alerts. - Alerts sent to Slack channels connected through a removed Slack installation deliver again. - The supervisor no longer trusts certificates issued under the compromised emSign (eMudhra) certificate authorities. <details> <summary>Raw changeset output</summary> # Releases ## trigger.dev@4.8.0 ### Minor Changes - Route verified webhooks into agent sessions with `chat.event({ endpoint, key })`, and connect external chat surfaces with `chat.channels.custom({ endpoint })`. Both subscribe to a shared webhook endpoint, so an agent and your other webhook tasks can use the same provider URL. Channels support reply delivery, session binding, conversation seeding, and lifecycle reactions, and a failed turn posts a short line instead of the error (`errorMessage` sets it, as a string or a function of the failure). Use `chat.createWatchToken()` to watch a session from another surface. ([`d6955ee9f`](d6955ee)) A connector can also stream replies natively (`stream()`), mirror the session's state into the surface (`lifecycle()`), show tool calls as they run (`progress()`), stop a running turn from the surface (`onControl()`), post approvals and tool controls and resume the run from a verified click, download files only the surface can read (`download()`), and acknowledge or fold in messages that arrive mid-turn (`received()`, `pendingMessages`). - Add hosted webhooks: declare an endpoint once with `webhooks.endpoint.define({ id, source })` and Trigger.dev hosts its URL, verifies every request, and routes each event to the endpoint's subscribers. Subscribe tasks with `webhook({ endpoint, filter, onEvent })`, each with its own type-safe filter, and pause a run until a matching webhook arrives with `webhooks.waiter.create()` and `webhooks.waiter.wait()`. ([`d6955ee9f`](d6955ee)) ```ts export const stripe = webhooks.endpoint.define({ id: "stripe", source: webhooks.stripe(), }); export const fulfill = webhook({ id: "fulfill", endpoint: stripe, filter: "event.type == 'checkout.session.completed'", onEvent: async ({ event }) => {}, }); const waiter = await webhooks.waiter.create(stripe, { match: { "event.data.object.metadata.orderId": order.id }, }); const { event } = await webhooks.waiter.wait(waiter).unwrap(); ``` Sources cover presets (`webhooks.stripe()`, `webhooks.github()`, `webhooks.svix()`, `webhooks.discord()`, and others), named providers (`webhooks.clerk()`, `webhooks.shopify()`, and more) and `webhooks.custom<T>(config)`, and most carry a setup prompt an AI coding agent can follow to register the endpoint. Retries are deduplicated on the provider's own event or delivery id where it sends one. Filters, keys and waiter `match` paths share the `event.`, `header.` and `webhook.` namespaces, and filters accept `== null` / `!= null` presence checks and `event any (...)` over a payload that is an array of events. `webhook()` takes `task()` options such as `queue`, `machine` and `retry`. The HTTP API lists endpoints and deliveries, replays deliveries, and creates and cancels waiters, and both it and the MCP server can read an endpoint's setup prompt and generate or store its signing secret. ### Patch Changes - The `generate_webhook_secret` and `set_webhook_secret` MCP tools take an optional `previousSecretTtlSeconds` to keep accepting a webhook endpoint's old signing secret while the provider switches to the new one (up to 7 days), and report when the old secret stops working. ([`98adb6662`](98adb66)) - Updated dependencies: - `@trigger.dev/core@4.8.0` - `@trigger.dev/build@4.8.0` - `@trigger.dev/schema-to-json@4.8.0` ## @trigger.dev/core@4.8.0 ### Minor Changes - Add hosted webhooks: declare an endpoint once with `webhooks.endpoint.define({ id, source })` and Trigger.dev hosts its URL, verifies every request, and routes each event to the endpoint's subscribers. Subscribe tasks with `webhook({ endpoint, filter, onEvent })`, each with its own type-safe filter, and pause a run until a matching webhook arrives with `webhooks.waiter.create()` and `webhooks.waiter.wait()`. ([`d6955ee9f`](d6955ee)) ```ts export const stripe = webhooks.endpoint.define({ id: "stripe", source: webhooks.stripe(), }); export const fulfill = webhook({ id: "fulfill", endpoint: stripe, filter: "event.type == 'checkout.session.completed'", onEvent: async ({ event }) => {}, }); const waiter = await webhooks.waiter.create(stripe, { match: { "event.data.object.metadata.orderId": order.id }, }); const { event } = await webhooks.waiter.wait(waiter).unwrap(); ``` Sources cover presets (`webhooks.stripe()`, `webhooks.github()`, `webhooks.svix()`, `webhooks.discord()`, and others), named providers (`webhooks.clerk()`, `webhooks.shopify()`, and more) and `webhooks.custom<T>(config)`, and most carry a setup prompt an AI coding agent can follow to register the endpoint. Retries are deduplicated on the provider's own event or delivery id where it sends one. Filters, keys and waiter `match` paths share the `event.`, `header.` and `webhook.` namespaces, and filters accept `== null` / `!= null` presence checks and `event any (...)` over a payload that is an array of events. `webhook()` takes `task()` options such as `queue`, `machine` and `retry`. The HTTP API lists endpoints and deliveries, replays deliveries, and creates and cancels waiters, and both it and the MCP server can read an endpoint's setup prompt and generate or store its signing secret. ### Patch Changes - Realtime streams now reconnect and resume when the stream backend reports a failed read mid-stream, instead of ending early as if the stream had finished. This affects `runs.subscribeToRun` with streams, `useRealtimeRunWithStreams`, and chat streams. ([`23730b034`](23730b0)) - HMAC webhook verifier configs accept `additionalSignatureHeaders`: more headers that can carry a signature, matched as alternatives to `signatureHeader`. Providers that send a second signature during a secret rotation (Hookdeck's `x-hookdeck-signature-2`) keep verifying through the rotation. ([`08d1ddbd3`](08d1ddb)) - The `generate_webhook_secret` and `set_webhook_secret` MCP tools take an optional `previousSecretTtlSeconds` to keep accepting a webhook endpoint's old signing secret while the provider switches to the new one (up to 7 days), and report when the old secret stops working. ([`98adb6662`](98adb66)) - Add `webhooks.hookdeck()`, a source for deliveries relayed through a Hookdeck connection. It verifies the `x-hookdeck-signature` header with the project's signing secret, keeps verifying while the secret is being rolled (Hookdeck sends the previous secret's signature in `x-hookdeck-signature-2`), and deduplicates retries on `x-hookdeck-eventid`. The event is the original provider's payload, so pass its type: `webhooks.hookdeck<Stripe.Event>()`. If the Hookdeck project's header prefix was changed, pass it as `webhooks.hookdeck({ headerPrefix })` so retries keep deduplicating. ([`51b39fbc6`](51b39fb)) ## @trigger.dev/linear@4.8.0 ### Minor Changes - Add `@trigger.dev/linear`: turn a `chat.agent` into a Linear agent. Assign it an issue or @mention it, and Linear's agent session becomes a durable Trigger.dev session: the reply posts back to Linear, tool calls show as activities, `linearPlanTool()` keeps the plan Linear shows as a checklist, and approvals are Approve and Deny options that resume the run. ([`1586c4a3f`](1586c4a)) ```ts import { linear, webhookSource } from "@trigger.dev/linear"; const linearEvents = webhooks.endpoint.define({ id: "linear", source: webhookSource(), }); export const triage = chat.agent({ id: "triage", channels: [ linear({ id: "linear", endpoint: linearEvents, token: process.env.LINEAR_ACCESS_TOKEN!, }), ], run: async ({ messages, signal, streamText }) => streamText({ model, messages, abortSignal: signal }), }); ``` The first turn gets the issue's context and earlier comments, images and PDFs in the issue reach the model, a Stop in Linear winds the turn down, and `errorMessage` sets the text a failed turn shows. ### Patch Changes - Updated dependencies: - `@trigger.dev/sdk@4.8.0` - `@trigger.dev/core@4.8.0` ## @trigger.dev/slack@4.8.0 ### Minor Changes - Add `@trigger.dev/slack`: turn a `chat.agent` into a native Slack agent. Each DM or channel thread is a durable session, the reply streams into the thread with the turn's tool calls shown as a plan, approvals are Approve and Deny buttons, and Slack's stop button stops the turn. ([`6e715da77`](6e715da)) ```ts import { appMentions, slack, webhookSource } from "@trigger.dev/slack"; const slackEvents = webhooks.endpoint.define({ id: "slack", source: webhookSource(), }); export const support = chat.agent({ id: "support", channels: [ slack({ id: "slack", endpoint: slackEvents, token: process.env.SLACK_BOT_TOKEN!, startOn: appMentions(), }), ], run: async ({ messages, signal, streamText }) => streamText({ model, messages, abortSignal: signal }), }); ``` `startOn` decides which channel messages start a session (`appMentions()` answers when the agent is @mentioned). Images and PDFs people share reach the model, messages sent while the agent is answering can be folded into the reply, tools can post their own buttons, and `ownWorkspaceOnly` ignores Slack Connect guests. ### Patch Changes - Updated dependencies: - `@trigger.dev/sdk@4.8.0` - `@trigger.dev/core@4.8.0` ## @trigger.dev/sdk@4.8.0 ### Minor Changes - Route verified webhooks into agent sessions with `chat.event({ endpoint, key })`, and connect external chat surfaces with `chat.channels.custom({ endpoint })`. Both subscribe to a shared webhook endpoint, so an agent and your other webhook tasks can use the same provider URL. Channels support reply delivery, session binding, conversation seeding, and lifecycle reactions, and a failed turn posts a short line instead of the error (`errorMessage` sets it, as a string or a function of the failure). Use `chat.createWatchToken()` to watch a session from another surface. ([`d6955ee9f`](d6955ee)) A connector can also stream replies natively (`stream()`), mirror the session's state into the surface (`lifecycle()`), show tool calls as they run (`progress()`), stop a running turn from the surface (`onControl()`), post approvals and tool controls and resume the run from a verified click, download files only the surface can read (`download()`), and acknowledge or fold in messages that arrive mid-turn (`received()`, `pendingMessages`). - Add hosted webhooks: declare an endpoint once with `webhooks.endpoint.define({ id, source })` and Trigger.dev hosts its URL, verifies every request, and routes each event to the endpoint's subscribers. Subscribe tasks with `webhook({ endpoint, filter, onEvent })`, each with its own type-safe filter, and pause a run until a matching webhook arrives with `webhooks.waiter.create()` and `webhooks.waiter.wait()`. ([`d6955ee9f`](d6955ee)) ```ts export const stripe = webhooks.endpoint.define({ id: "stripe", source: webhooks.stripe(), }); export const fulfill = webhook({ id: "fulfill", endpoint: stripe, filter: "event.type == 'checkout.session.completed'", onEvent: async ({ event }) => {}, }); const waiter = await webhooks.waiter.create(stripe, { match: { "event.data.object.metadata.orderId": order.id }, }); const { event } = await webhooks.waiter.wait(waiter).unwrap(); ``` Sources cover presets (`webhooks.stripe()`, `webhooks.github()`, `webhooks.svix()`, `webhooks.discord()`, and others), named providers (`webhooks.clerk()`, `webhooks.shopify()`, and more) and `webhooks.custom<T>(config)`, and most carry a setup prompt an AI coding agent can follow to register the endpoint. Retries are deduplicated on the provider's own event or delivery id where it sends one. Filters, keys and waiter `match` paths share the `event.`, `header.` and `webhook.` namespaces, and filters accept `== null` / `!= null` presence checks and `event any (...)` over a payload that is an array of events. `webhook()` takes `task()` options such as `queue`, `machine` and `retry`. The HTTP API lists endpoints and deliveries, replays deliveries, and creates and cancels waiters, and both it and the MCP server can read an endpoint's setup prompt and generate or store its signing secret. - Add `@trigger.dev/slack`: turn a `chat.agent` into a native Slack agent. Each DM or channel thread is a durable session, the reply streams into the thread with the turn's tool calls shown as a plan, approvals are Approve and Deny buttons, and Slack's stop button stops the turn. ([`6e715da77`](6e715da)) ```ts import { appMentions, slack, webhookSource } from "@trigger.dev/slack"; const slackEvents = webhooks.endpoint.define({ id: "slack", source: webhookSource(), }); export const support = chat.agent({ id: "support", channels: [ slack({ id: "slack", endpoint: slackEvents, token: process.env.SLACK_BOT_TOKEN!, startOn: appMentions(), }), ], run: async ({ messages, signal, streamText }) => streamText({ model, messages, abortSignal: signal }), }); ``` `startOn` decides which channel messages start a session (`appMentions()` answers when the agent is @mentioned). Images and PDFs people share reach the model, messages sent while the agent is answering can be folded into the reply, tools can post their own buttons, and `ownWorkspaceOnly` ignores Slack Connect guests. - Add `@trigger.dev/linear`: turn a `chat.agent` into a Linear agent. Assign it an issue or @mention it, and Linear's agent session becomes a durable Trigger.dev session: the reply posts back to Linear, tool calls show as activities, `linearPlanTool()` keeps the plan Linear shows as a checklist, and approvals are Approve and Deny options that resume the run. ([`1586c4a3f`](1586c4a)) ```ts import { linear, webhookSource } from "@trigger.dev/linear"; const linearEvents = webhooks.endpoint.define({ id: "linear", source: webhookSource(), }); export const triage = chat.agent({ id: "triage", channels: [ linear({ id: "linear", endpoint: linearEvents, token: process.env.LINEAR_ACCESS_TOKEN!, }), ], run: async ({ messages, signal, streamText }) => streamText({ model, messages, abortSignal: signal }), }); ``` The first turn gets the issue's context and earlier comments, images and PDFs in the issue reach the model, a Stop in Linear winds the turn down, and `errorMessage` sets the text a failed turn shows. ### Patch Changes - The `streamText` passed to a `chat.agent`'s `run()` now turns AI SDK telemetry on by default, so each model step and tool call shows up as a span in the run trace even when the agent doesn't store a prompt with `chat.prompt.set()`. An agent with `telemetry: { recordUserMessage: false }` gets these spans without prompt and response content, including when it stores a prompt (whose variables are left out of the span metadata). Pass `experimental_telemetry: { isEnabled: false }` at the call site to turn them off, or `recordInputs: false` / `recordOutputs: false` to keep them without content. ([`bd7cc3525`](bd7cc35)) - Add `webhooks.hookdeck()`, a source for deliveries relayed through a Hookdeck connection. It verifies the `x-hookdeck-signature` header with the project's signing secret, keeps verifying while the secret is being rolled (Hookdeck sends the previous secret's signature in `x-hookdeck-signature-2`), and deduplicates retries on `x-hookdeck-eventid`. The event is the original provider's payload, so pass its type: `webhooks.hookdeck<Stripe.Event>()`. If the Hookdeck project's header prefix was changed, pass it as `webhooks.hookdeck({ headerPrefix })` so retries keep deduplicating. ([`51b39fbc6`](51b39fb)) - Updated dependencies: - `@trigger.dev/core@4.8.0` ## @trigger.dev/build@4.8.0 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.0` ## @trigger.dev/python@4.8.0 ### Patch Changes - Updated dependencies: - `@trigger.dev/sdk@4.8.0` - `@trigger.dev/core@4.8.0` - `@trigger.dev/build@4.8.0` ## @trigger.dev/react-hooks@4.8.0 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.0` ## @trigger.dev/redis-worker@4.8.0 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.0` ## @trigger.dev/rsc@4.8.0 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.0` ## @trigger.dev/schema-to-json@4.8.0 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.0` </details> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
chore: release v4.8.1 (#5057) ## Summary 1 new feature, 1 bug fix. ## Bug fixes - Fix `trigger deploy` failing on self-hosted instances with custom base images. Stages built on a custom image now keep the trust store that image ships with. ([`b5ed66b74`](b5ed66b)) ## Server changes These changes affect the self-hosted Docker image and Trigger.dev Cloud: - Alerts can now watch the result of any supported query: raise when a value crosses a threshold, when matching rows stop appearing, or when new matching rows appear. Create them from the Query page, the Dashboard Agent or the API, and see the alert's values charted on its page. <details> <summary>Raw changeset output</summary> # Releases ## @trigger.dev/build@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## trigger.dev@4.8.1 ### Patch Changes - Fix `trigger deploy` failing on self-hosted instances with custom base images. Stages built on a custom image now keep the trust store that image ships with. ([`b5ed66b74`](b5ed66b)) - Updated dependencies: - `@trigger.dev/build@4.8.1` - `@trigger.dev/core@4.8.1` - `@trigger.dev/schema-to-json@4.8.1` ## @trigger.dev/linear@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` - `@trigger.dev/sdk@4.8.1` ## @trigger.dev/python@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/build@4.8.1` - `@trigger.dev/core@4.8.1` - `@trigger.dev/sdk@4.8.1` ## @trigger.dev/react-hooks@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/redis-worker@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/rsc@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/schema-to-json@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/slack@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` - `@trigger.dev/sdk@4.8.1` ## @trigger.dev/sdk@4.8.1 ### Patch Changes - Updated dependencies: - `@trigger.dev/core@4.8.1` ## @trigger.dev/core@4.8.1 </details> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
PreviousNext