@trigger.dev/sdk 4.5.0-rc.6 → 4.5.0-rc.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/dist/commonjs/v3/ai.d.ts +171 -5
  2. package/dist/commonjs/v3/ai.js +309 -22
  3. package/dist/commonjs/v3/ai.js.map +1 -1
  4. package/dist/commonjs/v3/chat-server.d.ts +8 -0
  5. package/dist/commonjs/v3/chat-server.js +32 -10
  6. package/dist/commonjs/v3/chat-server.js.map +1 -1
  7. package/dist/commonjs/v3/chat-server.test.js +51 -0
  8. package/dist/commonjs/v3/chat-server.test.js.map +1 -1
  9. package/dist/commonjs/v3/createStartSessionAction.test.js +30 -0
  10. package/dist/commonjs/v3/createStartSessionAction.test.js.map +1 -1
  11. package/dist/commonjs/v3/sessions.d.ts +3 -2
  12. package/dist/commonjs/v3/sessions.js +3 -2
  13. package/dist/commonjs/v3/sessions.js.map +1 -1
  14. package/dist/commonjs/version.js +1 -1
  15. package/dist/esm/v3/ai.d.ts +171 -5
  16. package/dist/esm/v3/ai.js +309 -22
  17. package/dist/esm/v3/ai.js.map +1 -1
  18. package/dist/esm/v3/chat-server.d.ts +8 -0
  19. package/dist/esm/v3/chat-server.js +32 -10
  20. package/dist/esm/v3/chat-server.js.map +1 -1
  21. package/dist/esm/v3/chat-server.test.js +51 -0
  22. package/dist/esm/v3/chat-server.test.js.map +1 -1
  23. package/dist/esm/v3/createStartSessionAction.test.js +30 -0
  24. package/dist/esm/v3/createStartSessionAction.test.js.map +1 -1
  25. package/dist/esm/v3/sessions.d.ts +3 -2
  26. package/dist/esm/v3/sessions.js +3 -2
  27. package/dist/esm/v3/sessions.js.map +1 -1
  28. package/dist/esm/version.js +1 -1
  29. package/docs/ai/prompts.mdx +430 -0
  30. package/docs/ai-chat/actions.mdx +115 -0
  31. package/docs/ai-chat/anatomy.mdx +71 -0
  32. package/docs/ai-chat/backend.mdx +817 -0
  33. package/docs/ai-chat/background-injection.mdx +221 -0
  34. package/docs/ai-chat/changelog.mdx +850 -0
  35. package/docs/ai-chat/chat-local.mdx +174 -0
  36. package/docs/ai-chat/client-protocol.mdx +1081 -0
  37. package/docs/ai-chat/compaction.mdx +411 -0
  38. package/docs/ai-chat/custom-agents.mdx +364 -0
  39. package/docs/ai-chat/error-handling.mdx +415 -0
  40. package/docs/ai-chat/fast-starts.mdx +672 -0
  41. package/docs/ai-chat/frontend.mdx +580 -0
  42. package/docs/ai-chat/how-it-works.mdx +230 -0
  43. package/docs/ai-chat/lifecycle-hooks.mdx +530 -0
  44. package/docs/ai-chat/mcp.mdx +101 -0
  45. package/docs/ai-chat/overview.mdx +90 -0
  46. package/docs/ai-chat/patterns/branching-conversations.mdx +284 -0
  47. package/docs/ai-chat/patterns/code-sandbox.mdx +126 -0
  48. package/docs/ai-chat/patterns/database-persistence.mdx +414 -0
  49. package/docs/ai-chat/patterns/human-in-the-loop.mdx +275 -0
  50. package/docs/ai-chat/patterns/large-payloads.mdx +169 -0
  51. package/docs/ai-chat/patterns/oom-resilience.mdx +120 -0
  52. package/docs/ai-chat/patterns/persistence-and-replay.mdx +211 -0
  53. package/docs/ai-chat/patterns/recovery-boot.mdx +230 -0
  54. package/docs/ai-chat/patterns/skills.mdx +221 -0
  55. package/docs/ai-chat/patterns/sub-agents.mdx +383 -0
  56. package/docs/ai-chat/patterns/tool-result-auditing.mdx +148 -0
  57. package/docs/ai-chat/patterns/trusted-edge-signals.mdx +337 -0
  58. package/docs/ai-chat/patterns/version-upgrades.mdx +172 -0
  59. package/docs/ai-chat/pending-messages.mdx +343 -0
  60. package/docs/ai-chat/prompt-caching.mdx +206 -0
  61. package/docs/ai-chat/quick-start.mdx +161 -0
  62. package/docs/ai-chat/reference.mdx +909 -0
  63. package/docs/ai-chat/server-chat.mdx +263 -0
  64. package/docs/ai-chat/sessions.mdx +333 -0
  65. package/docs/ai-chat/testing.mdx +682 -0
  66. package/docs/ai-chat/tools.mdx +191 -0
  67. package/docs/ai-chat/types.mdx +242 -0
  68. package/docs/ai-chat/upgrade-guide.mdx +515 -0
  69. package/docs/apikeys.mdx +54 -0
  70. package/docs/building-with-ai.mdx +261 -0
  71. package/docs/bulk-actions.mdx +49 -0
  72. package/docs/changelog.mdx +6 -0
  73. package/docs/cli-deploy-commands.mdx +9 -0
  74. package/docs/cli-dev-commands.mdx +9 -0
  75. package/docs/cli-dev.mdx +8 -0
  76. package/docs/cli-init-commands.mdx +58 -0
  77. package/docs/cli-introduction.mdx +25 -0
  78. package/docs/cli-list-profiles-commands.mdx +42 -0
  79. package/docs/cli-login-commands.mdx +33 -0
  80. package/docs/cli-logout-commands.mdx +33 -0
  81. package/docs/cli-preview-archive.mdx +59 -0
  82. package/docs/cli-promote-commands.mdx +9 -0
  83. package/docs/cli-switch.mdx +43 -0
  84. package/docs/cli-update-commands.mdx +42 -0
  85. package/docs/cli-whoami-commands.mdx +33 -0
  86. package/docs/community.mdx +6 -0
  87. package/docs/config/config-file.mdx +602 -0
  88. package/docs/config/extensions/additionalFiles.mdx +38 -0
  89. package/docs/config/extensions/additionalPackages.mdx +40 -0
  90. package/docs/config/extensions/aptGet.mdx +34 -0
  91. package/docs/config/extensions/audioWaveform.mdx +20 -0
  92. package/docs/config/extensions/custom.mdx +380 -0
  93. package/docs/config/extensions/emitDecoratorMetadata.mdx +29 -0
  94. package/docs/config/extensions/esbuildPlugin.mdx +31 -0
  95. package/docs/config/extensions/ffmpeg.mdx +45 -0
  96. package/docs/config/extensions/lightpanda.mdx +56 -0
  97. package/docs/config/extensions/overview.mdx +67 -0
  98. package/docs/config/extensions/playwright.mdx +195 -0
  99. package/docs/config/extensions/prismaExtension.mdx +1014 -0
  100. package/docs/config/extensions/puppeteer.mdx +30 -0
  101. package/docs/config/extensions/pythonExtension.mdx +182 -0
  102. package/docs/config/extensions/syncEnvVars.mdx +291 -0
  103. package/docs/context.mdx +235 -0
  104. package/docs/database-connections.mdx +213 -0
  105. package/docs/deploy-environment-variables.mdx +435 -0
  106. package/docs/deployment/atomic-deployment.mdx +172 -0
  107. package/docs/deployment/overview.mdx +257 -0
  108. package/docs/deployment/preview-branches.mdx +224 -0
  109. package/docs/errors-retrying.mdx +379 -0
  110. package/docs/github-actions.mdx +222 -0
  111. package/docs/github-integration.mdx +136 -0
  112. package/docs/github-repo.mdx +8 -0
  113. package/docs/help-email.mdx +6 -0
  114. package/docs/help-slack.mdx +11 -0
  115. package/docs/hidden-tasks.mdx +56 -0
  116. package/docs/how-it-works.mdx +454 -0
  117. package/docs/how-to-reduce-your-spend.mdx +217 -0
  118. package/docs/idempotency.mdx +504 -0
  119. package/docs/introduction.mdx +223 -0
  120. package/docs/limits.mdx +241 -0
  121. package/docs/logging.mdx +195 -0
  122. package/docs/machines.mdx +952 -0
  123. package/docs/manual-setup.mdx +632 -0
  124. package/docs/mcp-agent-rules.mdx +41 -0
  125. package/docs/mcp-introduction.mdx +385 -0
  126. package/docs/mcp-tools.mdx +273 -0
  127. package/docs/migrating-from-v3.mdx +334 -0
  128. package/docs/observability/dashboards.mdx +102 -0
  129. package/docs/observability/query.mdx +585 -0
  130. package/docs/open-source-contributing.mdx +16 -0
  131. package/docs/open-source-self-hosting.mdx +541 -0
  132. package/docs/private-networking/aws-console-setup.mdx +304 -0
  133. package/docs/private-networking/overview.mdx +144 -0
  134. package/docs/private-networking/troubleshooting.mdx +78 -0
  135. package/docs/queue-concurrency.mdx +354 -0
  136. package/docs/quick-start.mdx +97 -0
  137. package/docs/realtime/auth.mdx +208 -0
  138. package/docs/realtime/backend/overview.mdx +45 -0
  139. package/docs/realtime/backend/streams.mdx +418 -0
  140. package/docs/realtime/backend/subscribe.mdx +225 -0
  141. package/docs/realtime/how-it-works.mdx +94 -0
  142. package/docs/realtime/overview.mdx +63 -0
  143. package/docs/realtime/react-hooks/overview.mdx +73 -0
  144. package/docs/realtime/react-hooks/streams.mdx +449 -0
  145. package/docs/realtime/react-hooks/subscribe.mdx +674 -0
  146. package/docs/realtime/react-hooks/swr.mdx +87 -0
  147. package/docs/realtime/react-hooks/triggering.mdx +194 -0
  148. package/docs/realtime/react-hooks/use-wait-token.mdx +34 -0
  149. package/docs/realtime/run-object.mdx +174 -0
  150. package/docs/replaying.mdx +72 -0
  151. package/docs/request-feature.mdx +6 -0
  152. package/docs/roadmap.mdx +6 -0
  153. package/docs/run-tests.mdx +20 -0
  154. package/docs/run-usage.mdx +113 -0
  155. package/docs/runs/heartbeats.mdx +38 -0
  156. package/docs/runs/max-duration.mdx +139 -0
  157. package/docs/runs/metadata.mdx +734 -0
  158. package/docs/runs/priority.mdx +31 -0
  159. package/docs/runs.mdx +396 -0
  160. package/docs/self-hosting/docker.mdx +458 -0
  161. package/docs/self-hosting/env/supervisor.mdx +74 -0
  162. package/docs/self-hosting/env/webapp.mdx +276 -0
  163. package/docs/self-hosting/kubernetes.mdx +601 -0
  164. package/docs/self-hosting/overview.mdx +108 -0
  165. package/docs/skills.mdx +85 -0
  166. package/docs/tags.mdx +120 -0
  167. package/docs/tasks/overview.mdx +697 -0
  168. package/docs/tasks/scheduled.mdx +382 -0
  169. package/docs/tasks/schemaTask.mdx +413 -0
  170. package/docs/tasks/streams.mdx +884 -0
  171. package/docs/triggering.mdx +1320 -0
  172. package/docs/troubleshooting-alerts.mdx +385 -0
  173. package/docs/troubleshooting-debugging-in-vscode.mdx +8 -0
  174. package/docs/troubleshooting-github-issues.mdx +6 -0
  175. package/docs/troubleshooting-uptime-status.mdx +6 -0
  176. package/docs/troubleshooting.mdx +398 -0
  177. package/docs/upgrading-packages.mdx +80 -0
  178. package/docs/vercel-integration.mdx +207 -0
  179. package/docs/versioning.mdx +56 -0
  180. package/docs/video-walkthrough.mdx +23 -0
  181. package/docs/wait-for-token.mdx +540 -0
  182. package/docs/wait-for.mdx +42 -0
  183. package/docs/wait-until.mdx +53 -0
  184. package/docs/wait.mdx +18 -0
  185. package/docs/writing-tasks-introduction.mdx +33 -0
  186. package/package.json +8 -5
  187. package/skills/trigger-authoring-chat-agent/SKILL.md +296 -0
  188. package/skills/trigger-authoring-tasks/SKILL.md +254 -0
  189. package/skills/trigger-chat-agent-advanced/SKILL.md +368 -0
  190. package/skills/trigger-cost-savings/SKILL.md +116 -0
  191. package/skills/trigger-realtime-and-frontend/SKILL.md +276 -0
@@ -0,0 +1,136 @@
1
+ ---
2
+ title: "GitHub integration"
3
+ description: "Automatically deploy your tasks on every push to your GitHub repository."
4
+ ---
5
+
6
+ ## How it works
7
+
8
+ Once you connect a GitHub repository to your project, you can configure tracking branches for the production and staging environments.
9
+ Every push to a tracked branch creates a deployment in the corresponding environment. Preview branch deployments are also supported for pull requests.
10
+
11
+ This eliminates the need to manually run the `trigger.dev deploy` command or set up custom CI/CD workflows.
12
+
13
+ ## Setup
14
+
15
+ <Steps>
16
+
17
+ <Step title="Install our GitHub app">
18
+ Go to your project's settings page and click `Install GitHub app`.
19
+ This will take you to GitHub to authorize the Trigger.dev app for your organization or personal account.
20
+ </Step>
21
+
22
+ <Step title="Connect your repository">
23
+ Select a repository to connect to your project.
24
+ </Step>
25
+
26
+ <Step title="Configure branch tracking">
27
+ Choose which branches should trigger automatic deployments:
28
+
29
+ - **Production**: The branch that deploys to your production environment, e.g., `main`.
30
+ - **Staging**: The branch that deploys to your staging environment.
31
+ - **Preview**: Toggle to enable preview deployments for pull requests
32
+ </Step>
33
+
34
+ <Step title="Customize build settings (optional)">
35
+ Configure how your project is built:
36
+
37
+ - **Trigger config file**: Path to your `trigger.config.ts` file. By default, we look for it in the root of your repository. The path should be relative to the root of your repository and contain the config file name, e.g., `apps/tasks/trigger.config.ts`.
38
+ - **Install command**: Auto-detected by default, but you can override it if necessary. The command will be run from the root of your repository.
39
+ - **Pre-build command**: Run any commands before building and deploying your project, e.g., `pnpm run prisma:generate`. The command will be run from the root of your repository.
40
+ </Step>
41
+
42
+ </Steps>
43
+
44
+ ## Branch tracking
45
+
46
+ Our GitHub integration uses branch tracking to determine when and where to deploy your code.
47
+
48
+ ![Trigger.dev project git settings](/deployment/git-settings.png)
49
+
50
+ ### Production and staging branches
51
+
52
+ When you connect a repository, the default branch of your repository will be used as the production tracking branch, by default.
53
+
54
+ When you configure a production or staging branch, every push to that branch will trigger a deployment.
55
+ Our build server will install the project dependencies, build your project, and deploy it to the corresponding environment.
56
+
57
+ If there are multiple consecutive pushes to a tracked branch, the later deployments will be queued until the previous deployment completes.
58
+
59
+ <Note>
60
+ When you connect a repository, the default branch of your repository will be used as the production tracking branch by default.
61
+ You can change this in the git settings of your project.
62
+ </Note>
63
+
64
+ ### Pull requests
65
+
66
+ By default, pull requests will be deployed to preview branch environments, enabling you to test changes before merging.
67
+ When the pull request is merged or closed, the preview branch is automatically archived.
68
+
69
+ The name of the preview branch matches the branch name of the pull request.
70
+
71
+ <Note>
72
+ Preview branch deployments require the preview environment to be enabled on your project. Learn more about [preview branches](/deployment/preview-branches).
73
+ </Note>
74
+
75
+ ## Disconnecting a repository
76
+
77
+ You can disconnect a repository at any time from your project git settings. This will stop automatic deployments triggered from GitHub.
78
+
79
+ ## Managing repository access
80
+
81
+ To add or remove repository access for the Trigger.dev GitHub app, follow the link in the `Connect GitHub repository` modal:
82
+
83
+ ![Trigger.dev prompt to connect a GitHub repository](/deployment/connect-repo.png)
84
+
85
+ Alternatively, you can follow these steps on GitHub:
86
+
87
+ 1. Go to your GitHub account settings
88
+ 2. Navigate to **Settings** → **Applications** → **Installed GitHub Apps**
89
+ 3. Click **Configure** next to `Trigger.dev App`
90
+ 4. Update repository access under `Repository access`
91
+
92
+ Changes to repository access will be reflected immediately in your Trigger.dev project settings.
93
+
94
+ ## Environment variables at build time
95
+
96
+ You can expose environment variables during the build and deployment process by prefixing them with `TRIGGER_BUILD_`.
97
+ In the build server, the `TRIGGER_BUILD_` prefix is stripped from the variable name, i.e., `TRIGGER_BUILD_MY_TOKEN` is exposed as `MY_TOKEN`.
98
+
99
+ Build extensions will also have access to these variables.
100
+
101
+ <Note>
102
+ Build environment variables only apply to deployments in the environment you set them in.
103
+ </Note>
104
+
105
+ Learn more about managing [environment variables](/deploy-environment-variables).
106
+
107
+ ## Using a private npm registry
108
+
109
+ If your project uses packages from a private npm registry, you can provide authentication by setting a `TRIGGER_BUILD_NPM_RC` environment variable.
110
+
111
+ The value should be the contents of your `.npmrc` file including any token credentials, encoded to base64.
112
+
113
+ ### Example
114
+
115
+ Example `.npmrc` file containing credentials for a private npm registry and a GitHub package registry:
116
+
117
+ ```
118
+ //registry.npmjs.org/:_authToken=<YOUR_NPM_TOKEN>
119
+ @<YOUR_NAMESPACE>:registry=https://npm.pkg.github.com
120
+ //npm.pkg.github.com/:always-auth=true
121
+ //npm.pkg.github.com/:_authToken=<YOUR_GITHUB_TOKEN>
122
+ ```
123
+
124
+ Encode it to base64:
125
+
126
+ ```bash
127
+ # Encode your .npmrc file
128
+ cat .npmrc | base64
129
+ ```
130
+
131
+ Then, set the `TRIGGER_BUILD_NPM_RC` environment variable in your project settings with the encoded value.
132
+
133
+ <Note>
134
+ The build server will automatically create a `.npmrc` file in the installation directory based on the content of the `TRIGGER_BUILD_NPM_RC` environment variable.
135
+ This enables the build server to authenticate to your private npm registry.
136
+ </Note>
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: "GitHub repo"
3
+ url: "https://github.com/triggerdotdev/trigger.dev"
4
+ ---
5
+
6
+ Trigger.dev is [Open Source on GitHub](https://github.com/triggerdotdev/trigger.dev). You can contribute to the project by submitting issues, pull requests, or simply by using it and providing feedback.
7
+
8
+ You can also [self-host](/open-source-self-hosting) the project if you want to run it on your own infrastructure.
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: "Email us"
3
+ url: "https://trigger.dev/contact"
4
+ ---
5
+
6
+ You can [email us](https://trigger.dev/contact) by filling out this form.
@@ -0,0 +1,11 @@
1
+ ---
2
+ title: "Slack support"
3
+ ---
4
+
5
+ If you're on the Trigger.dev Pro plan, you can request a private Slack Connect channel.
6
+
7
+ To do this:
8
+
9
+ 1. Login to the [Trigger.dev web app](https://cloud.trigger.dev).
10
+ 2. Subscribe to a paid plan if you haven't already.
11
+ 3. In the bottom-left corner click "Join our Slack".
@@ -0,0 +1,56 @@
1
+ ---
2
+ title: "Hidden tasks"
3
+ description: "Create tasks that are not exported from your trigger files but can still be executed."
4
+ ---
5
+
6
+ Hidden tasks are tasks that are not exported from your trigger files but can still be executed. These tasks are only accessible to other tasks within the same file or module where they're defined.
7
+
8
+ ```ts trigger/my-task.ts
9
+ import { task } from "@trigger.dev/sdk";
10
+
11
+ // This is a hidden task - not exported
12
+ const internalTask = task({
13
+ id: "internal-processing",
14
+ run: async (payload: any, { ctx }) => {
15
+ // Internal processing logic
16
+ },
17
+ });
18
+ ```
19
+
20
+ Hidden tasks are useful for creating internal workflows that should only be triggered by other tasks in the same file:
21
+
22
+ ```ts trigger/my-workflow.ts
23
+ import { task } from "@trigger.dev/sdk";
24
+
25
+ // Hidden task for internal use
26
+ const processData = task({
27
+ id: "process-data",
28
+ run: async (payload: { data: string }, { ctx }) => {
29
+ // Process the data
30
+ return { processed: payload.data.toUpperCase() };
31
+ },
32
+ });
33
+
34
+ // Public task that uses the hidden task
35
+ export const mainWorkflow = task({
36
+ id: "main-workflow",
37
+ run: async (payload: any, { ctx }) => {
38
+ const result = await processData.trigger({ data: payload.input });
39
+ return result;
40
+ },
41
+ });
42
+ ```
43
+
44
+ You can also create packages of reusable tasks that can be imported and used without needing to re-export them:
45
+
46
+ ```ts trigger/my-task.ts
47
+ import { task } from "@trigger.dev/sdk";
48
+ import { sendToSlack } from "@repo/tasks"; // Hidden task from another package
49
+
50
+ export const notificationTask = task({
51
+ id: "send-notification",
52
+ run: async (payload: any, { ctx }) => {
53
+ await sendToSlack.trigger(payload);
54
+ },
55
+ });
56
+ ```
@@ -0,0 +1,454 @@
1
+ ---
2
+ title: "How it works"
3
+ sidebarTitle: "How it works"
4
+ description: "Understand how Trigger.dev works and how it can help you."
5
+ ---
6
+
7
+ ## Introduction
8
+
9
+ Trigger.dev v3 allows you to integrate long-running async tasks into your application and run them in the background. This allows you to offload tasks that take a long time to complete, such as sending multi-day email campaigns, processing videos, or running long chains of AI tasks.
10
+
11
+ For example, the below task processes a video with `ffmpeg` and sends the results to an s3 bucket, then updates a database with the results and sends an email to the user.
12
+
13
+ ```ts /trigger/video.ts
14
+ import { logger, task } from "@trigger.dev/sdk";
15
+ import { updateVideoUrl } from "../db.js";
16
+ import ffmpeg from "fluent-ffmpeg";
17
+ import { Readable } from "node:stream";
18
+ import type { ReadableStream } from "node:stream/web";
19
+ import * as fs from "node:fs/promises";
20
+ import * as path from "node:path";
21
+ import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
22
+ import { sendEmail } from "../email.js";
23
+ import { getVideo } from "../db.js";
24
+
25
+ // Initialize S3 client
26
+ const s3Client = new S3Client({
27
+ region: process.env.AWS_REGION,
28
+ });
29
+
30
+ export const convertVideo = task({
31
+ id: "convert-video",
32
+ retry: {
33
+ maxAttempts: 5,
34
+ minTimeoutInMs: 1000,
35
+ maxTimeoutInMs: 10000,
36
+ factor: 2,
37
+ },
38
+ run: async ({ videoId }: { videoId: string }) => {
39
+ const { url, userId } = await getVideo(videoId);
40
+
41
+ const outputPath = path.join("/tmp", `output_${videoId}.mp4`);
42
+
43
+ const response = await fetch(url);
44
+
45
+ await new Promise((resolve, reject) => {
46
+ ffmpeg(Readable.fromWeb(response.body as ReadableStream))
47
+ .videoFilters("scale=iw/2:ih/2")
48
+ .output(outputPath)
49
+ .on("end", resolve)
50
+ .on("error", reject)
51
+ .run();
52
+ });
53
+
54
+ const processedContent = await fs.readFile(outputPath);
55
+
56
+ // Upload to S3
57
+ const s3Key = `processed-videos/output_${videoId}.mp4`;
58
+
59
+ const uploadParams = {
60
+ Bucket: process.env.S3_BUCKET,
61
+ Key: s3Key,
62
+ Body: processedContent,
63
+ };
64
+
65
+ await s3Client.send(new PutObjectCommand(uploadParams));
66
+ const s3Url = `https://${process.env.S3_BUCKET}.s3.amazonaws.com/${s3Key}`;
67
+
68
+ logger.info("Video converted", { videoId, s3Url });
69
+
70
+ // Update database
71
+ await updateVideoUrl(videoId, s3Url);
72
+
73
+ await sendEmail(
74
+ userId,
75
+ "Video Processing Complete",
76
+ `Your video has been processed and is available at: ${s3Url}`
77
+ );
78
+
79
+ return { success: true, s3Url };
80
+ },
81
+ });
82
+ ```
83
+
84
+ Now in your application, you can trigger this task by calling:
85
+
86
+ ```ts
87
+ import { NextResponse } from "next/server";
88
+ import { tasks } from "@trigger.dev/sdk";
89
+ import type { convertVideo } from "./trigger/video";
90
+ // 👆 **type-only** import
91
+
92
+ export async function POST(request: Request) {
93
+ const body = await request.json();
94
+
95
+ // Trigger the task, this will return before the task is completed
96
+ const handle = await tasks.trigger<typeof convertVideo>("convert-video", body);
97
+
98
+ return NextResponse.json(handle);
99
+ }
100
+ ```
101
+
102
+ This will schedule the task to run in the background and return a handle that you can use to check the status of the task. This allows your backend application to respond quickly to the user and offload the long-running task to Trigger.dev.
103
+
104
+ ## The CLI
105
+
106
+ Trigger.dev comes with a CLI that allows you to initialize Trigger.dev into your project, deploy your tasks, and run your tasks locally. You can run it via `npx` like so:
107
+
108
+ ```sh
109
+ npx trigger.dev@latest login # Log in to your Trigger.dev account
110
+ npx trigger.dev@latest init # Initialize Trigger.dev in your project
111
+ npx trigger.dev@latest dev # Run your tasks locally
112
+ npx trigger.dev@latest deploy # Deploy your tasks to the Trigger.dev instance
113
+ ```
114
+
115
+ All these commands work with the Trigger.dev cloud and/or your self-hosted instance. It supports multiple profiles so you can easily switch between different accounts or instances.
116
+
117
+ ```sh
118
+ npx trigger.dev@latest login --profile <profile> -a https://trigger.example.com # Log in to a specific profile into a self-hosted instance
119
+ npx trigger.dev@latest dev --profile <profile> # Initialize Trigger.dev in your project
120
+ npx trigger.dev@latest deploy --profile <profile> # Deploy your tasks to the Trigger.dev instance
121
+ ```
122
+
123
+ ## Trigger.dev architecture
124
+
125
+ Trigger.dev implements a serverless architecture (without timeouts!) that allows you to run your tasks in a scalable and reliable way. When you run `npx trigger.dev@latest deploy`, we build and deploy your task code to your Trigger.dev instance. Then, when you trigger a task from your application, it's run in a secure, isolated environment with the resources you need to complete the task. A simplified diagram for a task execution looks like this:
126
+
127
+ ```mermaid
128
+ sequenceDiagram
129
+ participant App
130
+ participant Trigger.dev
131
+ participant Task Worker
132
+
133
+ App->>Trigger.dev: Trigger task
134
+ Trigger.dev-->>App: Task handle
135
+ Trigger.dev->>Task Worker: Run task
136
+ Task Worker-->>Trigger.dev: Task completed
137
+ ```
138
+
139
+ In reality there are many more components involved, such as the task queue, the task scheduler, and the task worker pool, logging (etc.), but this diagram gives you a high-level overview of how Trigger.dev works.
140
+
141
+ ## The Checkpoint-Resume System
142
+
143
+ Trigger.dev implements a powerful Checkpoint-Resume System that enables efficient execution of long-running background tasks in a serverless-like environment. This system allows tasks to pause, checkpoint their state, and resume seamlessly, optimizing resource usage and enabling complex workflows.
144
+
145
+ Here's how the Checkpoint-Resume System works:
146
+
147
+ 1. **Task Execution**: When a task is triggered, it runs in an isolated environment with all necessary resources.
148
+
149
+ 2. **Subtask Handling**: If a task needs to trigger a subtask, it can do so and wait for its completion using `triggerAndWait`
150
+
151
+ 3. **State Checkpointing**: While waiting for a subtask or during a programmed pause (e.g., `wait.for({ seconds: 30 })`), the system uses CRIU (Checkpoint/Restore In Userspace) to create a checkpoint of the task's entire state, including memory, CPU registers, and open file descriptors.
152
+
153
+ 4. **Resource Release**: After checkpointing, the parent task's resources are released, freeing up the execution environment.
154
+
155
+ 5. **Efficient Storage**: The checkpoint is efficiently compressed and stored on disk, ready to be restored when needed.
156
+
157
+ 6. **Event-Driven Resumption**: When a subtask completes or a wait period ends, Trigger.dev's event system triggers the restoration process.
158
+
159
+ 7. **State Restoration**: The checkpoint is loaded back into a new execution environment, restoring the task to its exact state before suspension.
160
+
161
+ 8. **Seamless Continuation**: The task resumes execution from where it left off, with any subtask results or updated state seamlessly integrated.
162
+
163
+ This approach allows Trigger.dev to manage resources efficiently, handle complex task dependencies, and provide a virtually limitless execution time for your tasks, all while maintaining the simplicity and scalability of a serverless architecture.
164
+
165
+ Example of a parent and child task using the Checkpoint-Resume System:
166
+
167
+ ```ts
168
+ import { task, wait } from "@trigger.dev/sdk";
169
+
170
+ export const parentTask = task({
171
+ id: "parent-task",
172
+ run: async () => {
173
+ console.log("Starting parent task");
174
+
175
+ // This will cause the parent task to be checkpointed and suspended
176
+ const result = await childTask.triggerAndWait({ data: "some data" });
177
+
178
+ console.log("Child task result:", result);
179
+
180
+ // This will also cause the task to be checkpointed and suspended
181
+ await wait.for({ seconds: 30 });
182
+
183
+ console.log("Resumed after 30 seconds");
184
+
185
+ return "Parent task completed";
186
+ },
187
+ });
188
+
189
+ export const childTask = task({
190
+ id: "child-task",
191
+ run: async (payload: { data: string }) => {
192
+ console.log("Starting child task with data:", payload.data);
193
+
194
+ // Simulate some work
195
+ await sleep(5);
196
+
197
+ return "Child task result";
198
+ },
199
+ });
200
+ ```
201
+
202
+ The diagram below illustrates the flow of the parent and child tasks using the Checkpoint-Resume System:
203
+
204
+ ```mermaid
205
+ sequenceDiagram
206
+ participant App
207
+ participant Trigger.dev
208
+ participant Parent Task
209
+ participant Child Task
210
+ participant CR System
211
+ participant Storage
212
+
213
+ App->>Trigger.dev: Trigger parent task
214
+ Trigger.dev->>Parent Task: Start execution
215
+ Parent Task->>Child Task: Trigger child task
216
+ Parent Task->>CR System: Request snapshot
217
+ CR System->>Storage: Store snapshot
218
+ CR System-->>Parent Task: Confirm snapshot stored
219
+ Parent Task->>Trigger.dev: Release resources
220
+
221
+ Child Task->>Trigger.dev: Complete execution
222
+ Trigger.dev->>CR System: Request parent task restoration
223
+ CR System->>Storage: Retrieve snapshot
224
+ CR System->>Parent Task: Restore state
225
+ Parent Task->>Trigger.dev: Resume execution
226
+ Parent Task->>Trigger.dev: Complete execution
227
+ ```
228
+
229
+ <Note>
230
+ This is why, in the Trigger.dev Cloud, we don't charge for the time waiting for subtasks or the
231
+ time spent in a paused state.
232
+ </Note>
233
+
234
+ ## Durable execution
235
+
236
+ Trigger.dev's Checkpoint-Resume System, combined with idempotency keys, enables durable execution of complex workflows. This approach allows for efficient retries and caching of results, ensuring that work is not unnecessarily repeated in case of failures.
237
+
238
+ ### How it works
239
+
240
+ 1. **Task breakdown**: Complex workflows are broken down into smaller, independent subtasks.
241
+ 2. **Idempotency keys**: Each subtask is assigned a unique idempotency key.
242
+ 3. **Result caching**: The output of each subtask is cached based on its idempotency key.
243
+ 4. **Intelligent retries**: If a failure occurs, only the failed subtask and subsequent tasks are retried.
244
+
245
+ ### Example: Video processing workflow
246
+
247
+ Let's rewrite the `convert-video` task above to be more durable:
248
+
249
+ <CodeGroup>
250
+
251
+ ```ts /trigger/video.ts
252
+ import { idempotencyKeys, logger, task } from "@trigger.dev/sdk";
253
+ import { processVideo, sendUserEmail, uploadToS3 } from "./tasks.js";
254
+ import { updateVideoUrl } from "../db.js";
255
+
256
+ export const convertVideo = task({
257
+ id: "convert-video",
258
+ retry: {
259
+ maxAttempts: 5,
260
+ minTimeoutInMs: 1000,
261
+ maxTimeoutInMs: 10000,
262
+ factor: 2,
263
+ },
264
+ run: async ({ videoId }: { videoId: string }) => {
265
+ // Automatically scope the idempotency key to this run, across retries
266
+ const idempotencyKey = await idempotencyKeys.create(videoId);
267
+
268
+ // Process video
269
+ const { processedContent } = await processVideo
270
+ .triggerAndWait({ videoId }, { idempotencyKey })
271
+ .unwrap(); // Calling unwrap will return the output of the subtask, or throw an error if the subtask failed
272
+
273
+ // Upload to S3
274
+ const { s3Url } = await uploadToS3
275
+ .triggerAndWait({ processedContent, videoId }, { idempotencyKey })
276
+ .unwrap();
277
+
278
+ // Update database
279
+ await updateVideoUrl(videoId, s3Url);
280
+
281
+ // Send email, we don't need to wait for this to finish
282
+ await sendUserEmail.trigger({ videoId, s3Url }, { idempotencyKey });
283
+
284
+ return { success: true, s3Url };
285
+ },
286
+ });
287
+ ```
288
+
289
+ ```ts /trigger/tasks.ts
290
+ import { task, logger } from "@trigger.dev/sdk";
291
+ import ffmpeg from "fluent-ffmpeg";
292
+ import { Readable } from "node:stream";
293
+ import type { ReadableStream } from "node:stream/web";
294
+ import * as fs from "node:fs/promises";
295
+ import * as path from "node:path";
296
+ import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
297
+ import { sendEmail } from "../email.js";
298
+ import { getVideo } from "../db.js";
299
+
300
+ // Initialize S3 client
301
+ const s3Client = new S3Client({
302
+ region: process.env.AWS_REGION,
303
+ });
304
+
305
+ export const processVideo = task({
306
+ id: "process-video",
307
+ run: async ({ videoId }: { videoId: string }) => {
308
+ const { url } = await getVideo(videoId);
309
+
310
+ const outputPath = path.join("/tmp", `output_${videoId}.mp4`);
311
+ const response = await fetch(url);
312
+
313
+ await logger.trace("ffmpeg", async (span) => {
314
+ await new Promise((resolve, reject) => {
315
+ ffmpeg(Readable.fromWeb(response.body as ReadableStream))
316
+ .videoFilters("scale=iw/2:ih/2")
317
+ .output(outputPath)
318
+ .on("end", resolve)
319
+ .on("error", reject)
320
+ .run();
321
+ });
322
+ });
323
+
324
+ const processedContent = await fs.readFile(outputPath);
325
+
326
+ await fs.unlink(outputPath);
327
+
328
+ return { processedContent: processedContent.toString("base64") };
329
+ },
330
+ });
331
+
332
+ export const uploadToS3 = task({
333
+ id: "upload-to-s3",
334
+ run: async (payload: { processedContent: string; videoId: string }) => {
335
+ const { processedContent, videoId } = payload;
336
+
337
+ const s3Key = `processed-videos/output_${videoId}.mp4`;
338
+
339
+ const uploadParams = {
340
+ Bucket: process.env.S3_BUCKET,
341
+ Key: s3Key,
342
+ Body: Buffer.from(processedContent, "base64"),
343
+ };
344
+
345
+ await s3Client.send(new PutObjectCommand(uploadParams));
346
+ const s3Url = `https://${process.env.S3_BUCKET}.s3.amazonaws.com/${s3Key}`;
347
+
348
+ return { s3Url };
349
+ },
350
+ });
351
+
352
+ export const sendUserEmail = task({
353
+ id: "send-user-email",
354
+ run: async ({ videoId, s3Url }: { videoId: string; s3Url: string }) => {
355
+ const { userId } = await getVideo(videoId);
356
+
357
+ return await sendEmail(
358
+ userId,
359
+ "Video Processing Complete",
360
+ `Your video has been processed and is available at: ${s3Url}`
361
+ );
362
+ },
363
+ });
364
+ ```
365
+
366
+ </CodeGroup>
367
+
368
+ ### How retries work
369
+
370
+ Let's say the email sending fails in our video processing workflow. Here's how the retry process works:
371
+
372
+ 1. The main task throws an error and is scheduled for retry.
373
+ 2. When retried, it starts from the beginning, but leverages cached results for completed subtasks.
374
+
375
+ Here's a sequence diagram illustrating this process:
376
+
377
+ ```mermaid
378
+ sequenceDiagram
379
+ participant Main as Main Task
380
+ participant Process as Process Video
381
+ participant Upload as Upload to S3
382
+ participant DB as Update Database
383
+ participant Email as Send Email
384
+
385
+ Main->>Process: triggerAndWait (1st attempt)
386
+ Process-->>Main: Return result
387
+ Main->>Upload: triggerAndWait (1st attempt)
388
+ Upload-->>Main: Return result
389
+ Main->>DB: Update
390
+ Main->>Email: triggerAndWait (1st attempt)
391
+ Email--xMain: Fail
392
+ Main-->>Main: Schedule retry
393
+
394
+ Main->>Process: triggerAndWait (2nd attempt)
395
+ Process-->>Main: Return cached result
396
+ Main->>Upload: triggerAndWait (2nd attempt)
397
+ Upload-->>Main: Return cached result
398
+ Main->>DB: Update (idempotent)
399
+ Main->>Email: triggerAndWait (2nd attempt)
400
+ Email-->>Main: Success
401
+ ```
402
+
403
+ ## The build system
404
+
405
+ When you run `npx trigger.dev@latest deploy` or `npx trigger.dev@latest dev`, we build your task code using our build system, which is powered by [esbuild](https://esbuild.github.io/). When deploying, the code is packaged up into a Docker image and deployed to your Trigger.dev instance. When running in dev mode, the code is built and run locally on your machine. Some features of our build system include:
406
+
407
+ - **Bundled by default**: Code + dependencies are bundled and tree-shaked by default.
408
+ - **Build extensions**: Use and write custom build extensions to transform your code or the resulting docker image.
409
+ - **ESM ouput**: We output to ESM, which allows tree-shaking and better performance.
410
+
411
+ You can review the build output by running deploy with the `--dry-run` flag, which will output the Containerfile and the build output.
412
+
413
+ Learn more about working with our build system in the [configuration docs](/config/config-file).
414
+
415
+ ## Dev mode
416
+
417
+ When you run `npx trigger.dev@latest dev`, we run your task code locally on your machine. All scheduling is still done in the Trigger.dev server instance, but the task code is run locally. This allows you to develop and test your tasks locally before deploying them to the cloud, and is especially useful for debugging and testing.
418
+
419
+ - The same build system is used in dev mode, so you can be sure that your code will run the same locally as it does in the cloud.
420
+ - Changes are automatically detected and a new version is spun up when you save your code.
421
+ - Add debuggers and breakpoints to your code and debug it locally.
422
+ - Each task is run in a separate process, so you can run multiple tasks in parallel.
423
+ - Auto-cancels tasks when you stop the dev server.
424
+
425
+ <Note>
426
+ Trigger.dev currently does not support "offline" dev mode, where you can run tasks without an
427
+ internet connection. [Please let us know](https://feedback.trigger.dev/) if this is a feature you
428
+ want/need.
429
+ </Note>
430
+
431
+ ## Staging and production environments
432
+
433
+ Trigger.dev supports deploying to `prod` and `staging` environments. This allows you to test your tasks in a staging environment before deploying them to production. You can deploy to a different environment by running `npx trigger.dev@latest deploy --env <env>`, where `<env>` is either `prod` or `staging`. Each environment has its own API Key, which you can use to trigger tasks in that environment.
434
+
435
+ For additional isolated environments, you can use [preview branches](/deployment/preview-branches), which allow you to create separate environments for each branch of your code.
436
+
437
+ ## OpenTelemetry
438
+
439
+ The Trigger.dev logging and task dashboard is powered by OpenTelemetry traces and logs, which allows you to trace your tasks and auto-instrument your code. We also auto-correlate logs from subtasks and parent tasks, making it easy view the entire trace of a task execution. A single run of the video processing task above looks like this in the dashboard:
440
+
441
+ ![OpenTelemetry trace](/images/opentelemetry-trace.png)
442
+
443
+ Because we use standard OpenTelemetry, you can instrument your code and OpenTelemetry compatible libraries to get detailed traces and logs of your tasks. The above trace instruments both Prisma and the AWS SDK:
444
+
445
+ ```ts trigger.config.ts
446
+ import { defineConfig } from "@trigger.dev/sdk";
447
+ import { PrismaInstrumentation } from "@prisma/instrumentation";
448
+ import { AwsInstrumentation } from "@opentelemetry/instrumentation-aws-sdk";
449
+
450
+ export default defineConfig({
451
+ project: "<your-project-ref>",
452
+ instrumentations: [new PrismaInstrumentation(), new AwsInstrumentation()],
453
+ });
454
+ ```