Skip to content

Commit e754f8a

Browse files
authored
Merge branch 'main' into docs/735-actor-run-example-task-page
2 parents b76064d + 40f241b commit e754f8a

1,523 files changed

Lines changed: 162136 additions & 14933 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@trigger.dev/sdk": patch
3+
---
4+
5+
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.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@trigger.dev/sdk": minor
3+
"trigger.dev": minor
4+
---
5+
6+
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.
7+
8+
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`).
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
"@trigger.dev/core": minor
3+
"@trigger.dev/sdk": minor
4+
"trigger.dev": minor
5+
---
6+
7+
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()`.
8+
9+
```ts
10+
export const stripe = webhooks.endpoint.define({ id: "stripe", source: webhooks.stripe() });
11+
12+
export const fulfill = webhook({
13+
id: "fulfill",
14+
endpoint: stripe,
15+
filter: "event.type == 'checkout.session.completed'",
16+
onEvent: async ({ event }) => {},
17+
});
18+
19+
const waiter = await webhooks.waiter.create(stripe, {
20+
match: { "event.data.object.metadata.orderId": order.id },
21+
});
22+
const { event } = await webhooks.waiter.wait(waiter).unwrap();
23+
```
24+
25+
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.

‎.changeset/hosted-webhook-slack.md‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
"@trigger.dev/sdk": minor
3+
"@trigger.dev/slack": minor
4+
---
5+
6+
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.
7+
8+
```ts
9+
import { appMentions, slack, webhookSource } from "@trigger.dev/slack";
10+
11+
const slackEvents = webhooks.endpoint.define({ id: "slack", source: webhookSource() });
12+
13+
export const support = chat.agent({
14+
id: "support",
15+
channels: [
16+
slack({
17+
id: "slack",
18+
endpoint: slackEvents,
19+
token: process.env.SLACK_BOT_TOKEN!,
20+
startOn: appMentions(),
21+
}),
22+
],
23+
run: async ({ messages, signal, streamText }) =>
24+
streamText({ model, messages, abortSignal: signal }),
25+
});
26+
```
27+
28+
`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.

‎.changeset/linear-channel.md‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
"@trigger.dev/linear": minor
3+
"@trigger.dev/sdk": minor
4+
---
5+
6+
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.
7+
8+
```ts
9+
import { linear, webhookSource } from "@trigger.dev/linear";
10+
11+
const linearEvents = webhooks.endpoint.define({ id: "linear", source: webhookSource() });
12+
13+
export const triage = chat.agent({
14+
id: "triage",
15+
channels: [
16+
linear({ id: "linear", endpoint: linearEvents, token: process.env.LINEAR_ACCESS_TOKEN! }),
17+
],
18+
run: async ({ messages, signal, streamText }) =>
19+
streamText({ model, messages, abortSignal: signal }),
20+
});
21+
```
22+
23+
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.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@trigger.dev/core": patch
3+
---
4+
5+
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.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@trigger.dev/core": patch
3+
"trigger.dev": patch
4+
---
5+
6+
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.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@trigger.dev/core": patch
3+
"@trigger.dev/sdk": patch
4+
---
5+
6+
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.

‎.claude/REVIEW.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Reserve 🔴 for things that would page someone or block a rollback. In this cod
1111
- A Redis data shape used by both versions changes in place. New shapes need a new key namespace.
1212
- A migration is not backward-compatible with the prior image.
1313
- **Schema / migration safety.** Prisma migrations must be backward-compatible with the prior deploy. Adding NOT NULL without a default, dropping a column an old image still reads, renaming a column — all 🔴.
14-
- **ClickHouse migration ordering + idempotency.** Goose runs in strict mode in the deploy pipeline and refuses to apply a missing version below the current version — slotting a new file in below the latest already-applied version blocks the deploy. New ClickHouse migration files MUST use the next available number (`max(files in internal-packages/clickhouse/schema/) + 1`); if main has added migrations while you've been on a branch, renumber yours. DDL must also be idempotent (`ADD COLUMN IF NOT EXISTS`, `DROP COLUMN IF EXISTS`, `CREATE TABLE IF NOT EXISTS`, `ADD INDEX IF NOT EXISTS`) so a partial / `--allow-missing` apply elsewhere doesn't fail on retry. Either fault is 🔴 — both break test/prod deploys. Rules live in `internal-packages/clickhouse/CLAUDE.md`.
14+
- **ClickHouse migration ordering + idempotency.** Goose runs in strict mode in the deploy pipeline and refuses to apply a missing version below the current version — slotting a new file in below the latest already-applied version blocks the deploy. New ClickHouse migration files MUST use the next available number (`max(files in internal-packages/clickhouse/schema/) + 1`); if main has added migrations while you've been on a branch, renumber yours. DDL must also be idempotent (`ADD COLUMN IF NOT EXISTS`, `DROP COLUMN IF EXISTS`, `CREATE TABLE IF NOT EXISTS`, `ADD INDEX IF NOT EXISTS`) so a partial / `--allow-missing` apply elsewhere doesn't fail on retry. Either fault is 🔴 — both break test/prod deploys. Rules live in `internal-packages/clickhouse/AGENTS.md`.
1515
- **Queue / concurrency correctness.** RunQueue, MarQS (V1, legacy), redis-worker — any change to enqueue / dequeue / locking semantics. Re-derive the invariant on paper before flagging or accepting.
1616
- **Missing index on a hot table.** New Prisma queries against `TaskRun`, `TaskRunExecutionSnapshot`, `JobRun`, `Project`, etc. must use an existing index. Check `internal-packages/database/prisma/schema.prisma` for the relevant `@@index` lines — don't guess and don't propose `EXPLAIN`.
1717
- **Recovery-path queries.** Any `TaskRun.findFirst` / `findMany` added to a schedule, run-recovery, or restart loop. Recovery fan-outs (Redis crash, restart storms) turn "rare indexed query" into a DB incident. 🔴 even if indexed.
@@ -32,7 +32,7 @@ Every PR gets a performance pass — not just the ones that look perf-sensitive.
3232

3333
**Hot paths — extra scrutiny on any added query or work:**
3434

35-
- **Trigger + batch trigger** (`triggerTask.server.ts`, `batchTriggerV3.server.ts`) — see `apps/webapp/CLAUDE.md`; do not add DB queries to these.
35+
- **Trigger + batch trigger** (`triggerTask.server.ts`, `batchTriggerV3.server.ts`) — see `apps/webapp/AGENTS.md`; do not add DB queries to these.
3636
- **Dequeue / RunQueue** (`dequeueSystem.ts`, run-queue read/lock paths) — runs on every execution.
3737
- **Execution-snapshot creation in the run engine** — any engine function that writes a `TaskRunExecutionSnapshot` runs per state transition; a new query there multiplies by run volume.
3838
- **OTEL ingestion** (`otel.v1.traces.ts`, `otel.v1.logs.ts`) — write volume scales with customer span counts.
@@ -75,7 +75,7 @@ Every PR gets a performance pass — not just the ones that look perf-sensitive.
7575

7676
## Things V1/legacy that should NOT block a PR
7777

78-
The `apps/webapp/app/v3/` directory name is misleading — most code there is V2. Only specific files are V1-only legacy: `MarQS` queue, `triggerTaskV1`, `cancelTaskRunV1`, and a handful of others (see `apps/webapp/CLAUDE.md` for the exact list). Don't flag "you should refactor this to use V2" on those — they're frozen.
78+
The `apps/webapp/app/v3/` directory name is misleading — most code there is V2. Only specific files are V1-only legacy: `MarQS` queue, `triggerTaskV1`, `cancelTaskRunV1`, and a handful of others (see `apps/webapp/AGENTS.md` for the exact list). Don't flag "you should refactor this to use V2" on those — they're frozen.
7979

8080
## Confidence calibration for this repo
8181

‎.claude/rules/docs-writing.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,9 @@ paths:
1212
- Always import from `@trigger.dev/sdk`, never `@trigger.dev/sdk/v3`.
1313
- Keep paragraphs short. Use headers to break up content.
1414
- Link to related pages using relative paths (e.g., `[Tasks](/tasks/overview)`).
15+
- Features behind a flag that isn't fully on:
16+
- Dark (nobody outside the team has it): don't write docs yet.
17+
- Private beta or rolling out: put the docs in the feature PR with `<PrivateBeta flag="<key>" />` or `<RollingOut flag="<key>" />` (import from `/snippets/feature-status.jsx`), at the top of the page or the section. Use `flag="env:<NAME>"` for env-var gates. Keep the opening tag on one line with string values. To add page-specific text (how to get access, say), put it inside the tag: `<PrivateBeta flag="<key>">...</PrivateBeta>`; it renders after the fixed line.
18+
- The PR that removes the flag also removes the callout. CI fails while a callout points at a missing flag.
19+
- Avoid two callouts in a row. A `<PrivateBeta>` or `<RollingOut>` callout next to another callout is the one exception, because it's temporary. Leave the existing callout as it is.
20+
- Only for flags that cloud rolls out. Never add it to self-host config docs.

0 commit comments

Comments
 (0)