chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
---
|
||||
name: trigger-authoring-chat-agent
|
||||
description: >
|
||||
Author and run a durable AI chat agent with chat.agent from @trigger.dev/sdk/ai: the per-turn
|
||||
run loop, why you MUST spread ...chat.toStreamTextOptions() first, returning a StreamTextResult
|
||||
vs calling chat.pipe(), the two server actions (chat.createStartSessionAction +
|
||||
auth.createPublicToken), and wiring useChat to useTriggerChatTransport. Load this when building,
|
||||
modifying, or debugging a chat backend (the agent task or its lifecycle hooks) or its React
|
||||
transport, when declaring typed tools or custom data parts, or when migrating a plain AI SDK
|
||||
streamText route to chat.agent.
|
||||
type: core
|
||||
library: trigger.dev
|
||||
---
|
||||
|
||||
# Authoring a chat.agent
|
||||
|
||||
The full, version-pinned reference ships **inside your installed `@trigger.dev/sdk`**. Read it before writing code — it always matches the SDK version in this project, so it never drifts:
|
||||
|
||||
- **Skill:** `node_modules/@trigger.dev/sdk/skills/trigger-authoring-chat-agent/SKILL.md` — the per-turn run loop, `chat.toStreamTextOptions()`, the two server actions, typed tools/data parts, and the React transport.
|
||||
- **Docs:** the full, version-pinned docs ship bundled at `node_modules/@trigger.dev/sdk/docs/ai-chat/`; the skill above lists the exact pages it draws from in its `sources:` frontmatter. Grep for an API, e.g. `grep -rl "toStreamTextOptions" node_modules/@trigger.dev/sdk/docs/`.
|
||||
|
||||
If those paths don't exist, `@trigger.dev/sdk` isn't installed yet — install it first. In a non-hoisted layout, resolve the package with `node -p "require.resolve('@trigger.dev/sdk/package.json')"` and read `skills/` + `docs/` beside it.
|
||||
|
||||
## Common mistakes
|
||||
|
||||
- **CRITICAL: forgetting `...chat.toStreamTextOptions()`.**
|
||||
```ts
|
||||
// Wrong - compaction / steering / background injection silently no-op
|
||||
return streamText({ model, messages, abortSignal: signal });
|
||||
// Correct - spread FIRST so explicit overrides win
|
||||
return streamText({ ...chat.toStreamTextOptions(), model, messages, abortSignal: signal });
|
||||
```
|
||||
It wires the `prepareStep` callback behind compaction, mid-turn steering, and background
|
||||
injection, injects the system prompt from `chat.prompt()`, resolves the registry model, and adds
|
||||
telemetry. Omitting it makes all of those silently no-op with no error.
|
||||
|
||||
- **Declaring tools only on `streamText`.** Also declare them on `chat.agent({ tools })`, read them
|
||||
back from `run`, and pass `chat.toStreamTextOptions({ tools })`. Otherwise each tool's
|
||||
`toModelOutput` runs on turn 1 but is dropped when history is re-converted on later turns.
|
||||
|
||||
- **Not forwarding `signal` for stop.** Without `abortSignal: signal`, Stop updates the UI but the
|
||||
model keeps generating server-side.
|
||||
|
||||
- **Initializing `chat.local` in `onChatStart`.** Initialize it in `onBoot`. `onChatStart` fires
|
||||
once per chat, so continuation runs skip it and crash with
|
||||
`chat.local can only be modified after initialization`. `onBoot` fires on every fresh worker.
|
||||
|
||||
- **Minting tokens in the browser.** Never expose the environment secret key client-side. Mint via
|
||||
the two server actions; the transport calls them.
|
||||
|
||||
- **Clearing `lastEventId` on `chat.endRun()`.** Keep the cursor for the Session lifetime; clear it
|
||||
only when the Session itself closes. It is sessionId-keyed, so clearing forces a resubscribe from
|
||||
`seq_num=0` that can hit the prior turn's stale `turn-complete` and close the stream empty.
|
||||
|
||||
- **Returning the raw error from `uiMessageStreamOptions.onError`.** It leaks internals (keys,
|
||||
stack traces). Return a sanitized string instead.
|
||||
|
||||
## References
|
||||
|
||||
Sibling skills: **trigger-chat-agent-advanced** (Sessions primitive, custom transports, sub-agents, HITL, fast starts, resilience, testing, upgrades), **trigger-authoring-tasks** and **trigger-realtime-and-frontend** (the task + frontend foundations chat builds on).
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
name: trigger-authoring-tasks
|
||||
description: >
|
||||
Covers writing backend Trigger.dev tasks with @trigger.dev/sdk: defining task() and
|
||||
schemaTask(), the run function and its ctx, retries, waits, queues and concurrency,
|
||||
idempotency keys, run metadata, logging, triggering other tasks (and the Result shape),
|
||||
scheduled/cron tasks, and the essentials of trigger.config.ts. Load this whenever you are
|
||||
authoring or editing code inside a /trigger directory, defining a task, or writing backend
|
||||
code that triggers tasks. Realtime/React hooks and AI chat are covered by separate skills.
|
||||
type: core
|
||||
library: trigger.dev
|
||||
---
|
||||
|
||||
# Authoring Trigger.dev Tasks
|
||||
|
||||
The full, version-pinned reference for authoring tasks ships **inside your installed `@trigger.dev/sdk`**. Read it before writing code — it always matches the SDK version in this project, so it never drifts:
|
||||
|
||||
- **Skill:** `node_modules/@trigger.dev/sdk/skills/trigger-authoring-tasks/SKILL.md` — the complete guide (setup, `schemaTask`, retries, triggering + the Result shape, idempotency, waits, metadata, scheduled tasks, queues/concurrency, `trigger.config.ts`).
|
||||
- **Docs:** the full, version-pinned docs ship bundled at `node_modules/@trigger.dev/sdk/docs/`; the skill above lists the exact pages it draws from in its `sources:` frontmatter. Grep for an API, e.g. `grep -rl "schemaTask" node_modules/@trigger.dev/sdk/docs/`.
|
||||
|
||||
If those paths don't exist, `@trigger.dev/sdk` isn't installed yet — install it first. In a non-hoisted layout, resolve the package with `node -p "require.resolve('@trigger.dev/sdk/package.json')"` and read `skills/` + `docs/` beside it.
|
||||
|
||||
Always import from `@trigger.dev/sdk` — never `@trigger.dev/sdk/v3` (deprecated alias) or `@trigger.dev/core`.
|
||||
|
||||
## Common mistakes
|
||||
|
||||
1. **CRITICAL: Treating the wait result as the output.** `triggerAndWait` and `wait.forToken` return a Result object, not the raw output.
|
||||
- Wrong: `const out = await childTask.triggerAndWait(p); use(out.foo);`
|
||||
- Correct: `const r = await childTask.triggerAndWait(p); if (r.ok) use(r.output.foo);` (or `.unwrap()`).
|
||||
|
||||
2. **Wrapping `triggerAndWait` / `batchTriggerAndWait` / `wait` in `Promise.all`.**
|
||||
- Wrong: `await Promise.all([childTask.triggerAndWait(a), childTask.triggerAndWait(b)]);`
|
||||
- Correct: `await childTask.batchTriggerAndWait([{ payload: a }, { payload: b }]);` (or a sequential for-loop).
|
||||
|
||||
3. **Importing the task instance into backend code.**
|
||||
- Wrong: `import { emailSequence } from "~/trigger/emails";` in a route handler.
|
||||
- Correct: `import type { emailSequence }` plus `tasks.trigger<typeof emailSequence>("email-sequence", payload)`.
|
||||
|
||||
4. **Calling `metadata.set/get` outside `run()`.**
|
||||
- Wrong: setting metadata at module scope or in unrelated backend code (a no-op; `get` returns `undefined`).
|
||||
- Correct: call inside `run()` or a task lifecycle hook.
|
||||
|
||||
5. **Assuming child tasks inherit the parent's queue or metadata.**
|
||||
- Wrong: expecting a subtask to share the parent's `concurrencyLimit` or see its metadata.
|
||||
- Correct: subtasks run on their own queue; pass metadata explicitly via `{ metadata: metadata.current() }`, or push up with `metadata.parent.*`.
|
||||
|
||||
6. **Bundling native/WASM packages.**
|
||||
- Wrong: leaving `sharp`, `re2`, `sqlite3`, or WASM packages in the default bundle.
|
||||
- Correct: add them to `build.external` in `trigger.config.ts`.
|
||||
|
||||
7. **Relying on a raw string idempotency key being global.**
|
||||
- Wrong: `trigger(p, { idempotencyKey: "welcome-email" })` expecting once-ever (true only in v4.3.0 and earlier).
|
||||
- Correct: `await idempotencyKeys.create("welcome-email", { scope: "global" })`.
|
||||
|
||||
## References
|
||||
|
||||
Sibling skills: **trigger-realtime-and-frontend** (subscribe to runs, trigger from the frontend), **trigger-authoring-chat-agent** and **trigger-chat-agent-advanced** (AI chat agents).
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
name: trigger-chat-agent-advanced
|
||||
description: >
|
||||
Advanced and operational chat.agent capabilities for Trigger.dev, loaded on demand. Load this when
|
||||
working on the raw Sessions primitive (sessions / SessionHandle), a custom chat transport or the
|
||||
realtime wire protocol, durable sub-agents (AgentChat, chat.stream.writer), human-in-the-loop,
|
||||
steering, actions, background injection (chat.defer / chat.inject), fast starts (preload, Head
|
||||
Start via @trigger.dev/sdk/chat-server), context resilience (compaction, recovery boot, OOM, large
|
||||
payloads), chat.local run-scoped state, offline testing with mockChatAgent, or prerelease/version
|
||||
upgrades. For the everyday chat.agent({...}) definition and the useTriggerChatTransport happy path,
|
||||
use the trigger-authoring-chat-agent skill instead.
|
||||
type: core
|
||||
library: trigger.dev
|
||||
---
|
||||
|
||||
# chat.agent — advanced & operational
|
||||
|
||||
The full, version-pinned reference ships **inside your installed `@trigger.dev/sdk`**. Read it before writing code — it always matches the SDK version in this project, so it never drifts:
|
||||
|
||||
- **Skill:** `node_modules/@trigger.dev/sdk/skills/trigger-chat-agent-advanced/SKILL.md` — Sessions primitive, custom transports/wire protocol, sub-agents, HITL, steering, actions, background injection, fast starts, resilience (compaction/recovery/OOM/large payloads), `chat.local`, testing, upgrades.
|
||||
- **Docs:** the full, version-pinned docs ship bundled at `node_modules/@trigger.dev/sdk/docs/ai-chat/` (including `patterns/` for HITL, sub-agents, sessions); the skill above lists the exact pages it draws from in its `sources:` frontmatter. Grep for an API, e.g. `grep -rl "mockChatAgent" node_modules/@trigger.dev/sdk/docs/`.
|
||||
|
||||
If those paths don't exist, `@trigger.dev/sdk` isn't installed yet — install it first. In a non-hoisted layout, resolve the package with `node -p "require.resolve('@trigger.dev/sdk/package.json')"` and read `skills/` + `docs/` beside it.
|
||||
|
||||
## Common mistakes
|
||||
|
||||
- **CRITICAL: sending a follow-up by re-POSTing `POST /api/v1/sessions`.**
|
||||
```ts
|
||||
// Wrong - a cached re-POST silently drops basePayload.message; basePayload is trigger config, not a channel
|
||||
await fetch("/api/v1/sessions", { method: "POST", body: JSON.stringify({ ...createBody }) });
|
||||
// Correct - append to the session's input channel
|
||||
await fetch(`/realtime/v1/sessions/${id}/in/append`, { method: "POST", body: JSON.stringify({ kind: "message", payload }) });
|
||||
```
|
||||
|
||||
- **Using the wrong token for `.in` / `.out`.** Use `publicAccessToken` from the create response
|
||||
body (session-scoped). The `x-trigger-jwt` response header is run-scoped and cannot subscribe.
|
||||
|
||||
- **Initializing `chat.local` in `onChatStart`.** It is skipped on continuation runs, so `run()`
|
||||
crashes with `chat.local can only be modified after initialization`. Init in `onBoot`.
|
||||
|
||||
- **`chat.defer` for the message-history write.** A mid-stream refresh would read `[]`. `await` that
|
||||
write inline before the model streams; reserve `chat.defer` for analytics, audit, cache warming.
|
||||
|
||||
- **Giving the HITL tool an `execute`.** `streamText` calls it immediately. Leave it execute-less;
|
||||
the frontend supplies the answer via `addToolOutput` + `sendAutomaticallyWhen`.
|
||||
|
||||
- **Declaring sub-agent / heavy tools only on `streamText`.** Also declare them on
|
||||
`chat.agent({ tools })` (or pass to `convertToModelMessages(uiMessages, { tools })` in a custom
|
||||
agent) so `toModelOutput` re-applies on every turn.
|
||||
|
||||
- **Importing heavy-execute tools into the Head Start route module.** This is a build-time import
|
||||
chain problem; runtime strip helpers do not fix it. Keep schemas in an `ai` + `zod`-only module.
|
||||
|
||||
- **Returning a megabyte tool output on the stream.** One `tool-output-available` record over ~1 MiB
|
||||
throws `ChatChunkTooLargeError`. Persist to your store, write the row first, then emit only an id.
|
||||
|
||||
- **Setting `X-Peek-Settled: 1` on the active-send path.** It races the new turn's first chunk and
|
||||
closes the stream early. Use it only on reconnect-on-reload paths.
|
||||
|
||||
> Note on docs vocabulary: agent-side examples in some docs still use the legacy
|
||||
> `trigger:turn-complete` chunk type. That is the agent-emit vocabulary. A custom **reader** must
|
||||
> filter on the `trigger-control` header, not on `chunk.type`.
|
||||
>
|
||||
> MCP-driven agent chats (`list_agents`, `start_agent_chat`, `send_agent_message`,
|
||||
> `close_agent_chat`) are MCP server tools used from Claude Code / Cursor, not importable SDK
|
||||
> functions. See `/mcp-tools#agent-chat-tools`.
|
||||
|
||||
## References
|
||||
|
||||
Sibling skills: **trigger-authoring-chat-agent** (the everyday `chat.agent({...})` happy path), **trigger-authoring-tasks** and **trigger-realtime-and-frontend** (task + frontend foundations).
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
name: trigger-cost-savings
|
||||
description: >
|
||||
Analyze Trigger.dev tasks, schedules, and runs for cost optimization opportunities. Use when
|
||||
asked to reduce spend, optimize costs, audit usage, right-size machines, or review task
|
||||
efficiency. Combines static source analysis with live run analysis via the Trigger.dev MCP
|
||||
tools (list_runs, get_run_details, get_current_worker).
|
||||
type: core
|
||||
library: trigger.dev
|
||||
---
|
||||
|
||||
# Trigger.dev Cost Savings Analysis
|
||||
|
||||
The full, version-pinned cost-audit workflow ships **inside your installed `@trigger.dev/sdk`**. Read it before giving recommendations so they match the SDK version in this project:
|
||||
|
||||
- **Skill:** `node_modules/@trigger.dev/sdk/skills/trigger-cost-savings/SKILL.md` — the static-analysis checklist, the MCP run-analysis steps (`list_runs`, `get_run_details`, `get_current_worker`), the report format, and the machine-preset cost table.
|
||||
- **Docs:** the canonical guidance is bundled at `node_modules/@trigger.dev/sdk/docs/how-to-reduce-your-spend.mdx`, with supporting pages under `node_modules/@trigger.dev/sdk/docs/` (`machines.mdx`, `runs/max-duration.mdx`, `queue-concurrency.mdx`, `idempotency.mdx`, `triggering.mdx`, `errors-retrying.mdx`).
|
||||
|
||||
If those paths don't exist, `@trigger.dev/sdk` isn't installed yet — install it first. In a non-hoisted layout, resolve the package with `node -p "require.resolve('@trigger.dev/sdk/package.json')"` and read `skills/` + `docs/` beside it.
|
||||
|
||||
Live run analysis needs the Trigger.dev MCP server (`npx trigger.dev@latest install-mcp`). Without it, do the static source analysis only — never fabricate run data.
|
||||
|
||||
## Key principles
|
||||
|
||||
- **Waits > 5 seconds are free** — checkpointed, no compute charge.
|
||||
- **Start small, scale up** — the default `small-1x` is right for most tasks; right-size down tasks stuck on `large-*` with short durations.
|
||||
- **I/O-bound tasks don't need big machines** — API calls and DB queries wait on the network.
|
||||
- **Add `maxDuration`** — cap runaway compute.
|
||||
- **Debounce high-frequency triggers** — consolidate bursts into single runs.
|
||||
- **Idempotency keys prevent duplicate billed work.**
|
||||
- **`AbortTaskRunError` stops wasteful retries** — don't pay to retry permanent failures.
|
||||
|
||||
## References
|
||||
|
||||
Sibling skills: **trigger-authoring-tasks** (the task options these levers tune: `machine`, `maxDuration`, `retry`, `queue`, idempotency), **trigger-realtime-and-frontend**, **trigger-authoring-chat-agent** and **trigger-chat-agent-advanced** (AI agents).
|
||||
@@ -0,0 +1,214 @@
|
||||
---
|
||||
name: trigger-getting-started
|
||||
description: >
|
||||
Bootstrap Trigger.dev into an existing project from scratch: authenticate the
|
||||
CLI, install @trigger.dev/sdk and @trigger.dev/build, write trigger.config.ts
|
||||
with the project ref and task dirs, scaffold a /trigger directory with a first
|
||||
task, wire tsconfig and .gitignore, set TRIGGER_SECRET_KEY, and run the dev
|
||||
server. Load this when a project has no trigger.config.ts yet and the user
|
||||
asks to "add Trigger.dev", "set up Trigger.dev", "initialize Trigger.dev", or
|
||||
get a first task running, including in a monorepo. Once the project is set up
|
||||
and you are writing task code, switch to the trigger-authoring-tasks skill.
|
||||
type: core
|
||||
library: trigger.dev
|
||||
library_version: "{{TRIGGER_SDK_VERSION}}"
|
||||
sources:
|
||||
- docs/quick-start.mdx
|
||||
- docs/manual-setup.mdx
|
||||
- docs/config/config-file.mdx
|
||||
- docs/triggering.mdx
|
||||
---
|
||||
|
||||
# Getting started with Trigger.dev
|
||||
|
||||
Set up Trigger.dev in an existing project. The end state is: the SDK installed, a
|
||||
`trigger.config.ts` pointing at a project ref, a `/trigger` directory with at least
|
||||
one exported task, and `trigger dev` running so the task shows up in the dashboard.
|
||||
|
||||
The fastest path is the CLI's own wizard, which performs every mechanical step below
|
||||
and also offers to install the MCP server and these agent skills:
|
||||
|
||||
```bash
|
||||
npx trigger.dev@latest init
|
||||
```
|
||||
|
||||
Prefer `init` when you can. Do the manual steps further down when `init` does not fit
|
||||
(monorepos, an existing config to extend, or a non-interactive environment).
|
||||
|
||||
## Two steps need the human
|
||||
|
||||
Most of setup is automatable, but two steps require a person and cannot be done
|
||||
headlessly. When you reach them, stop and ask the user to do them, then continue:
|
||||
|
||||
1. **Authenticating the CLI.** `npx trigger.dev@latest login` opens a browser for the
|
||||
user to sign in. If they have no account, point them to https://cloud.trigger.dev
|
||||
(or a self-hosted instance) first. You cannot complete this for them.
|
||||
2. **The secret key and project ref.** `TRIGGER_SECRET_KEY` and the project ref
|
||||
(`proj_...`) come from the dashboard. Ask the user to copy the **DEV** secret key
|
||||
from the project's API Keys page, and to pick or create the project so you have its
|
||||
ref. `trigger init` can select the project interactively once the user is logged in.
|
||||
|
||||
Treat these as handoffs: state exactly what you need, wait for the user, then resume.
|
||||
|
||||
## Manual setup
|
||||
|
||||
### 1. Authenticate (human step)
|
||||
|
||||
```bash
|
||||
npx trigger.dev@latest login
|
||||
# self-hosted:
|
||||
npx trigger.dev@latest login --api-url https://your-trigger-instance.com
|
||||
```
|
||||
|
||||
### 2. Install the packages
|
||||
|
||||
`@trigger.dev/sdk` is a runtime dependency; `@trigger.dev/build` is a dev dependency.
|
||||
Pin both to the same version as the `trigger.dev` CLI you run; the CLI warns on a
|
||||
mismatch during `dev`/`deploy`.
|
||||
|
||||
```bash
|
||||
npm add @trigger.dev/sdk@latest
|
||||
npm add --save-dev @trigger.dev/build@latest
|
||||
```
|
||||
|
||||
### 3. Write `trigger.config.ts`
|
||||
|
||||
Create it in the project root (or `trigger.config.mjs` for JavaScript). The `project`
|
||||
ref and `dirs` are the only required fields.
|
||||
|
||||
```ts
|
||||
import { defineConfig } from "@trigger.dev/sdk";
|
||||
|
||||
export default defineConfig({
|
||||
project: "<project ref>", // e.g. "proj_abc123", from the dashboard
|
||||
dirs: ["./src/trigger"], // where your tasks live
|
||||
maxDuration: 3600,
|
||||
retries: {
|
||||
enabledInDev: false,
|
||||
default: { maxAttempts: 3, factor: 2, minTimeoutInMs: 1000, maxTimeoutInMs: 10000, randomize: true },
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Use the Bun runtime by adding `runtime: "bun"`. Build extensions (`prismaExtension`,
|
||||
`puppeteer`, `additionalFiles`, etc.) come from `@trigger.dev/build` and go in
|
||||
`build.extensions`.
|
||||
|
||||
### 4. Add a first task
|
||||
|
||||
Create the directory that matches `dirs` and export a task from it. Every task must be
|
||||
a named export with a project-unique `id`.
|
||||
|
||||
```ts
|
||||
// src/trigger/example.ts
|
||||
import { task } from "@trigger.dev/sdk";
|
||||
|
||||
export const helloWorld = task({
|
||||
id: "hello-world",
|
||||
run: async (payload: { name: string }) => {
|
||||
return { message: `Hello ${payload.name}!` };
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### 5. Wire tsconfig and gitignore
|
||||
|
||||
Add `trigger.config.ts` to the `include` array in `tsconfig.json`, and add `.trigger`
|
||||
to `.gitignore` (the CLI writes local dev state there).
|
||||
|
||||
```jsonc
|
||||
// tsconfig.json
|
||||
{ "include": ["trigger.config.ts" /* ...existing */] }
|
||||
```
|
||||
|
||||
```bash
|
||||
# .gitignore
|
||||
.trigger
|
||||
```
|
||||
|
||||
### 6. Set the secret key (human step)
|
||||
|
||||
For triggering from your own code, set `TRIGGER_SECRET_KEY` to the DEV key from the
|
||||
dashboard's API Keys page. Self-hosted users also set `TRIGGER_API_URL`.
|
||||
|
||||
```bash
|
||||
# .env (or .env.local for Next.js)
|
||||
TRIGGER_SECRET_KEY=tr_dev_xxxxxxxx
|
||||
```
|
||||
|
||||
### 7. Run the dev server
|
||||
|
||||
```bash
|
||||
npx trigger.dev@latest dev
|
||||
```
|
||||
|
||||
Leave it running. Tasks register with the dashboard, where the user can fire a test run
|
||||
from the task's test page. On first run the CLI offers to install the MCP server and
|
||||
agent skills; recommend both.
|
||||
|
||||
## Triggering from your app
|
||||
|
||||
Once a task exists, trigger it from backend code with a **type-only** import so the
|
||||
task code is never bundled into your app. Trigger by id, not by calling the task object.
|
||||
|
||||
```ts
|
||||
import { tasks } from "@trigger.dev/sdk";
|
||||
import type { helloWorld } from "@/trigger/example"; // type-only
|
||||
|
||||
const handle = await tasks.trigger<typeof helloWorld>("hello-world", { name: "Ada" });
|
||||
```
|
||||
|
||||
`TRIGGER_SECRET_KEY` must be set wherever this runs. Framework specifics live in the
|
||||
Next.js / Remix / Node.js guides.
|
||||
|
||||
## Monorepos
|
||||
|
||||
Two layouts, both supported: put tasks in a shared package (`@repo/tasks` with its own
|
||||
`trigger.config.ts`, consumed via `workspace:*`), or install Trigger.dev directly in the
|
||||
app that needs it. Run `trigger dev` from the directory that holds `trigger.config.ts`.
|
||||
See the manual setup docs for full Turborepo examples before scaffolding either.
|
||||
|
||||
## Common mistakes
|
||||
|
||||
1. **Trying to do the human-only steps headlessly.** You cannot complete `trigger login`
|
||||
or read the dashboard secret key for the user.
|
||||
- Wrong: spawning `trigger login` and waiting on it to finish in an agent session.
|
||||
- Correct: ask the user to log in and to paste the DEV key, then continue.
|
||||
|
||||
2. **Mismatched CLI and SDK versions.** A `trigger.dev` CLI on a different major than
|
||||
`@trigger.dev/sdk` breaks dev/deploy.
|
||||
- Wrong: `npx trigger.dev@latest dev` against an old pinned SDK.
|
||||
- Correct: keep `trigger.dev`, `@trigger.dev/sdk`, and `@trigger.dev/build` on the same version.
|
||||
|
||||
3. **Importing from `@trigger.dev/sdk/v3` or using `client.defineJob()`.** Both are old.
|
||||
- Correct: always import from `@trigger.dev/sdk`; define work with `task()`.
|
||||
|
||||
4. **Tasks not exported, or outside `dirs`.** A task that is not a named export inside a
|
||||
configured directory will not be picked up.
|
||||
- Correct: `export const ... = task({ ... })` in a file under a `dirs` path.
|
||||
|
||||
5. **Importing the task instance into backend code.** This bundles the task.
|
||||
- Wrong: `import { helloWorld } from "@/trigger/example"` in a route handler.
|
||||
- Correct: `import type { helloWorld }` plus `tasks.trigger<typeof helloWorld>("hello-world", payload)`.
|
||||
|
||||
6. **Forgetting `TRIGGER_SECRET_KEY`.** Triggering from your app fails without it; the
|
||||
`dev` server itself works once the CLI is logged in.
|
||||
|
||||
## References
|
||||
|
||||
Sibling skills:
|
||||
|
||||
- **trigger-authoring-tasks** for writing the tasks themselves once setup is done: retries, waits,
|
||||
queues, scheduled tasks, triggering, and the full `trigger.config.ts`.
|
||||
- **trigger-realtime-and-frontend** for showing live run status in a frontend.
|
||||
- **trigger-authoring-chat-agent** and **trigger-chat-agent-advanced** for building AI chat agents.
|
||||
|
||||
Docs:
|
||||
|
||||
- [Quick start](https://trigger.dev/docs/quick-start)
|
||||
- [Manual setup](https://trigger.dev/docs/manual-setup)
|
||||
- [Configuration file](https://trigger.dev/docs/config/config-file)
|
||||
|
||||
## Version
|
||||
|
||||
Generated for @trigger.dev/sdk {{TRIGGER_SDK_VERSION}}. Re-run the trigger.dev skills installer after upgrading.
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
name: trigger-realtime-and-frontend
|
||||
description: >
|
||||
Trigger.dev client/frontend surface: subscribe to runs in realtime
|
||||
(runs.subscribeToRun and the @trigger.dev/react-hooks hook useRealtimeRun),
|
||||
consume metadata and AI/text streams in React (useRealtimeStream), trigger
|
||||
tasks from the browser (useTaskTrigger, useRealtimeTaskTrigger), and mint
|
||||
scoped frontend credentials with auth.createPublicToken /
|
||||
auth.createTriggerPublicToken.
|
||||
Load when wiring a frontend (React/Next.js/Remix) or backend-for-frontend to
|
||||
show live run progress, status badges, token streams, trigger buttons, or
|
||||
wait-token approval UIs. NOT for writing the backend task itself (streams.define
|
||||
/ metadata.set is trigger-authoring-tasks territory); this is the consumer side.
|
||||
type: core
|
||||
library: trigger.dev
|
||||
---
|
||||
|
||||
# Realtime and Frontend
|
||||
|
||||
The full, version-pinned reference ships **inside your installed `@trigger.dev/sdk`**. Read it before writing code — it always matches the SDK version in this project, so it never drifts:
|
||||
|
||||
- **Skill:** `node_modules/@trigger.dev/sdk/skills/trigger-realtime-and-frontend/SKILL.md` — run subscriptions, `@trigger.dev/react-hooks`, streams, frontend triggering, and scoped tokens.
|
||||
- **Docs:** the full, version-pinned docs ship bundled at `node_modules/@trigger.dev/sdk/docs/realtime/`; the skill above lists the exact pages it draws from in its `sources:` frontmatter. Grep for a hook, e.g. `grep -rl "useRealtimeRun" node_modules/@trigger.dev/sdk/docs/`.
|
||||
|
||||
If those paths don't exist, `@trigger.dev/sdk` isn't installed yet — install it first. In a non-hoisted layout, resolve the package with `node -p "require.resolve('@trigger.dev/sdk/package.json')"` and read `skills/` + `docs/` beside it.
|
||||
|
||||
## Common mistakes
|
||||
|
||||
1. **CRITICAL: Triggering from the browser with a Public Access Token.** The
|
||||
read token from `createPublicToken` cannot trigger tasks.
|
||||
- Wrong: `useTaskTrigger("my-task", { accessToken: publicAccessTokenFromCreatePublicToken })`
|
||||
- Correct: mint a single-use Trigger Token with `auth.createTriggerPublicToken("my-task")` and pass that.
|
||||
|
||||
2. **Token with no scopes.** A scopeless token authorizes nothing, so every subscribe 403s.
|
||||
- Wrong: `await auth.createPublicToken()`
|
||||
- Correct: `await auth.createPublicToken({ scopes: { read: { runs: ["run_1234"] } } })`
|
||||
|
||||
3. **Polling with `useRun`/SWR for live updates.** `useRun` is the SWR-based
|
||||
management-API hook (not recommended for live state); set `refreshInterval: 0`
|
||||
to stop polling if you do use it.
|
||||
- Wrong: `useRun(runId, { refreshInterval: 1000 })` to track progress
|
||||
- Correct: `useRealtimeRun(runId, { accessToken })` (no polling, no WebSocket setup)
|
||||
|
||||
4. **Forgetting `"use client"`.** Realtime/trigger hooks cannot run in a server component.
|
||||
- Wrong: a Next.js App Router server component using `useRealtimeRun`
|
||||
- Correct: put `"use client";` at the top of any component using these hooks.
|
||||
|
||||
5. **Shipping `payload`/`output` you do not render.**
|
||||
- Wrong: `useRealtimeRun(runId, { accessToken })` for a status badge (large payloads over the wire)
|
||||
- Correct: `useRealtimeRun(runId, { accessToken, skipColumns: ["payload", "output"] })`
|
||||
|
||||
6. **Subscribing before the handle exists.**
|
||||
- Wrong: `useRealtimeRun(handle, { accessToken: handle?.publicAccessToken })` with no guard
|
||||
- Correct: add `enabled: !!handle` so it subscribes only once the trigger returns a handle.
|
||||
|
||||
## References
|
||||
|
||||
Sibling skills: **trigger-authoring-tasks** (the task side: `streams.define()`, `metadata.set()`, `wait.createToken`), **trigger-authoring-chat-agent** and **trigger-chat-agent-advanced** (chat agents build on these realtime streams).
|
||||
Reference in New Issue
Block a user