trigger.dev 0.0.0-v3-prerelease-20250108141813 → 0.0.0-v4-prerelease-20250916125920

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 (292) hide show
  1. package/README.md +28 -1
  2. package/dist/esm/apiClient.d.ts +158 -74
  3. package/dist/esm/apiClient.js +341 -76
  4. package/dist/esm/apiClient.js.map +1 -1
  5. package/dist/esm/build/buildWorker.d.ts +10 -6
  6. package/dist/esm/build/buildWorker.js +22 -38
  7. package/dist/esm/build/buildWorker.js.map +1 -1
  8. package/dist/esm/build/bundle.d.ts +18 -1
  9. package/dist/esm/build/bundle.js +142 -52
  10. package/dist/esm/build/bundle.js.map +1 -1
  11. package/dist/esm/build/entryPoints.d.ts +12 -0
  12. package/dist/esm/build/entryPoints.js +127 -0
  13. package/dist/esm/build/entryPoints.js.map +1 -0
  14. package/dist/esm/build/extensions.js +17 -0
  15. package/dist/esm/build/extensions.js.map +1 -1
  16. package/dist/esm/build/externals.js +184 -2
  17. package/dist/esm/build/externals.js.map +1 -1
  18. package/dist/esm/build/packageModules.d.ts +15 -5
  19. package/dist/esm/build/packageModules.js +154 -36
  20. package/dist/esm/build/packageModules.js.map +1 -1
  21. package/dist/esm/cli/common.d.ts +1 -1
  22. package/dist/esm/cli/common.js +38 -45
  23. package/dist/esm/cli/common.js.map +1 -1
  24. package/dist/esm/cli/index.js +19 -3
  25. package/dist/esm/cli/index.js.map +1 -1
  26. package/dist/esm/commands/analyze.d.ts +23 -0
  27. package/dist/esm/commands/analyze.js +122 -0
  28. package/dist/esm/commands/analyze.js.map +1 -0
  29. package/dist/esm/commands/deploy.d.ts +5 -2
  30. package/dist/esm/commands/deploy.js +271 -160
  31. package/dist/esm/commands/deploy.js.map +1 -1
  32. package/dist/esm/commands/dev.d.ts +36 -6
  33. package/dist/esm/commands/dev.js +71 -2
  34. package/dist/esm/commands/dev.js.map +1 -1
  35. package/dist/esm/commands/env.d.ts +2 -0
  36. package/dist/esm/commands/env.js +298 -0
  37. package/dist/esm/commands/env.js.map +1 -0
  38. package/dist/esm/commands/init.d.ts +9 -1
  39. package/dist/esm/commands/init.js +132 -65
  40. package/dist/esm/commands/init.js.map +1 -1
  41. package/dist/esm/commands/install-mcp.d.ts +50 -0
  42. package/dist/esm/commands/install-mcp.js +497 -0
  43. package/dist/esm/commands/install-mcp.js.map +1 -0
  44. package/dist/esm/commands/install-rules.d.ts +11 -0
  45. package/dist/esm/commands/install-rules.js +381 -0
  46. package/dist/esm/commands/install-rules.js.map +1 -0
  47. package/dist/esm/commands/list-profiles.d.ts +3 -7
  48. package/dist/esm/commands/list-profiles.js +7 -4
  49. package/dist/esm/commands/list-profiles.js.map +1 -1
  50. package/dist/esm/commands/login.d.ts +9 -5
  51. package/dist/esm/commands/login.js +40 -7
  52. package/dist/esm/commands/login.js.map +1 -1
  53. package/dist/esm/commands/logout.d.ts +1 -1
  54. package/dist/esm/commands/mcp.d.ts +38 -0
  55. package/dist/esm/commands/mcp.js +82 -0
  56. package/dist/esm/commands/mcp.js.map +1 -0
  57. package/dist/esm/commands/preview.d.ts +5 -0
  58. package/dist/esm/commands/preview.js +93 -0
  59. package/dist/esm/commands/preview.js.map +1 -0
  60. package/dist/esm/commands/promote.d.ts +3 -0
  61. package/dist/esm/commands/promote.js +86 -0
  62. package/dist/esm/commands/promote.js.map +1 -0
  63. package/dist/esm/commands/switch.d.ts +19 -0
  64. package/dist/esm/commands/switch.js +93 -0
  65. package/dist/esm/commands/switch.js.map +1 -0
  66. package/dist/esm/commands/trigger.d.ts +33 -0
  67. package/dist/esm/commands/trigger.js +88 -0
  68. package/dist/esm/commands/trigger.js.map +1 -0
  69. package/dist/esm/commands/update.d.ts +3 -2
  70. package/dist/esm/commands/update.js +23 -9
  71. package/dist/esm/commands/update.js.map +1 -1
  72. package/dist/esm/commands/whoami.d.ts +12 -1
  73. package/dist/esm/commands/whoami.js +36 -6
  74. package/dist/esm/commands/whoami.js.map +1 -1
  75. package/dist/esm/commands/workers/build.d.ts +4 -0
  76. package/dist/esm/commands/workers/build.js +345 -0
  77. package/dist/esm/commands/workers/build.js.map +1 -0
  78. package/dist/esm/commands/workers/create.d.ts +2 -0
  79. package/dist/esm/commands/workers/create.js +91 -0
  80. package/dist/esm/commands/workers/create.js.map +1 -0
  81. package/dist/esm/commands/workers/index.d.ts +2 -0
  82. package/dist/esm/commands/workers/index.js +13 -0
  83. package/dist/esm/commands/workers/index.js.map +1 -0
  84. package/dist/esm/commands/workers/list.d.ts +2 -0
  85. package/dist/esm/commands/workers/list.js +80 -0
  86. package/dist/esm/commands/workers/list.js.map +1 -0
  87. package/dist/esm/commands/workers/run.d.ts +2 -0
  88. package/dist/esm/commands/workers/run.js +105 -0
  89. package/dist/esm/commands/workers/run.js.map +1 -0
  90. package/dist/esm/config.d.ts +2 -1
  91. package/dist/esm/config.js +35 -8
  92. package/dist/esm/config.js.map +1 -1
  93. package/dist/esm/deploy/buildImage.d.ts +12 -11
  94. package/dist/esm/deploy/buildImage.js +360 -115
  95. package/dist/esm/deploy/buildImage.js.map +1 -1
  96. package/dist/esm/dev/backgroundWorker.d.ts +6 -245
  97. package/dist/esm/dev/backgroundWorker.js +11 -320
  98. package/dist/esm/dev/backgroundWorker.js.map +1 -1
  99. package/dist/esm/dev/devOutput.js +48 -9
  100. package/dist/esm/dev/devOutput.js.map +1 -1
  101. package/dist/esm/dev/devSession.d.ts +2 -1
  102. package/dist/esm/dev/devSession.js +68 -65
  103. package/dist/esm/dev/devSession.js.map +1 -1
  104. package/dist/esm/dev/devSupervisor.d.ts +12 -0
  105. package/dist/esm/dev/devSupervisor.js +568 -0
  106. package/dist/esm/dev/devSupervisor.js.map +1 -0
  107. package/dist/esm/dev/lock.d.ts +1 -0
  108. package/dist/esm/dev/lock.js +80 -0
  109. package/dist/esm/dev/lock.js.map +1 -0
  110. package/dist/esm/dev/mcpServer.d.ts +10 -0
  111. package/dist/esm/dev/mcpServer.js +201 -0
  112. package/dist/esm/dev/mcpServer.js.map +1 -0
  113. package/dist/esm/dev/taskRunProcessPool.d.ts +39 -0
  114. package/dist/esm/dev/taskRunProcessPool.js +220 -0
  115. package/dist/esm/dev/taskRunProcessPool.js.map +1 -0
  116. package/dist/esm/dev/workerRuntime.d.ts +2 -2
  117. package/dist/esm/dev/workerRuntime.js +1 -265
  118. package/dist/esm/dev/workerRuntime.js.map +1 -1
  119. package/dist/esm/entryPoints/dev-index-worker.js +45 -8
  120. package/dist/esm/entryPoints/dev-index-worker.js.map +1 -1
  121. package/dist/esm/entryPoints/dev-run-controller.d.ts +58 -0
  122. package/dist/esm/entryPoints/dev-run-controller.js +652 -0
  123. package/dist/esm/entryPoints/dev-run-controller.js.map +1 -0
  124. package/dist/esm/entryPoints/dev-run-worker.js +394 -199
  125. package/dist/esm/entryPoints/dev-run-worker.js.map +1 -1
  126. package/dist/esm/entryPoints/managed/controller.d.ts +63 -0
  127. package/dist/esm/entryPoints/managed/controller.js +482 -0
  128. package/dist/esm/entryPoints/managed/controller.js.map +1 -0
  129. package/dist/esm/entryPoints/managed/env.d.ts +170 -0
  130. package/dist/esm/entryPoints/managed/env.js +199 -0
  131. package/dist/esm/entryPoints/managed/env.js.map +1 -0
  132. package/dist/esm/entryPoints/managed/execution.d.ts +141 -0
  133. package/dist/esm/entryPoints/managed/execution.js +869 -0
  134. package/dist/esm/entryPoints/managed/execution.js.map +1 -0
  135. package/dist/esm/entryPoints/managed/logger.d.ts +30 -0
  136. package/dist/esm/entryPoints/managed/logger.js +47 -0
  137. package/dist/esm/entryPoints/managed/logger.js.map +1 -0
  138. package/dist/esm/entryPoints/managed/notifier.d.ts +30 -0
  139. package/dist/esm/entryPoints/managed/notifier.js +63 -0
  140. package/dist/esm/entryPoints/managed/notifier.js.map +1 -0
  141. package/dist/esm/entryPoints/managed/overrides.d.ts +18 -0
  142. package/dist/esm/entryPoints/managed/overrides.js +19 -0
  143. package/dist/esm/entryPoints/managed/overrides.js.map +1 -0
  144. package/dist/esm/entryPoints/managed/poller.d.ts +31 -0
  145. package/dist/esm/entryPoints/managed/poller.js +89 -0
  146. package/dist/esm/entryPoints/managed/poller.js.map +1 -0
  147. package/dist/esm/entryPoints/managed/snapshot.d.ts +54 -0
  148. package/dist/esm/entryPoints/managed/snapshot.js +293 -0
  149. package/dist/esm/entryPoints/managed/snapshot.js.map +1 -0
  150. package/dist/esm/entryPoints/managed/taskRunProcessProvider.d.ts +62 -0
  151. package/dist/esm/entryPoints/managed/taskRunProcessProvider.js +252 -0
  152. package/dist/esm/entryPoints/managed/taskRunProcessProvider.js.map +1 -0
  153. package/dist/esm/entryPoints/{deploy-index-controller.js → managed-index-controller.js} +27 -3
  154. package/dist/esm/entryPoints/managed-index-controller.js.map +1 -0
  155. package/dist/esm/entryPoints/{deploy-index-worker.js → managed-index-worker.js} +50 -21
  156. package/dist/esm/entryPoints/managed-index-worker.js.map +1 -0
  157. package/dist/esm/entryPoints/managed-run-controller.js +13 -0
  158. package/dist/esm/entryPoints/managed-run-controller.js.map +1 -0
  159. package/dist/esm/entryPoints/managed-run-worker.js +512 -0
  160. package/dist/esm/entryPoints/managed-run-worker.js.map +1 -0
  161. package/dist/esm/executions/taskRunProcess.d.ts +28 -82
  162. package/dist/esm/executions/taskRunProcess.js +130 -74
  163. package/dist/esm/executions/taskRunProcess.js.map +1 -1
  164. package/dist/esm/indexing/indexWorkerManifest.d.ts +21 -5
  165. package/dist/esm/indexing/indexWorkerManifest.js +4 -4
  166. package/dist/esm/indexing/indexWorkerManifest.js.map +1 -1
  167. package/dist/esm/indexing/registerResources.d.ts +5 -0
  168. package/dist/esm/indexing/registerResources.js +44 -0
  169. package/dist/esm/indexing/registerResources.js.map +1 -0
  170. package/dist/esm/mcp/auth.d.ts +12 -0
  171. package/dist/esm/mcp/auth.js +152 -0
  172. package/dist/esm/mcp/auth.js.map +1 -0
  173. package/dist/esm/mcp/capabilities.d.ts +4 -0
  174. package/dist/esm/mcp/capabilities.js +22 -0
  175. package/dist/esm/mcp/capabilities.js.map +1 -0
  176. package/dist/esm/mcp/config.d.ts +82 -0
  177. package/dist/esm/mcp/config.js +87 -0
  178. package/dist/esm/mcp/config.js.map +1 -0
  179. package/dist/esm/mcp/context.d.ts +45 -0
  180. package/dist/esm/mcp/context.js +129 -0
  181. package/dist/esm/mcp/context.js.map +1 -0
  182. package/dist/esm/mcp/formatters.d.ts +7 -0
  183. package/dist/esm/mcp/formatters.js +330 -0
  184. package/dist/esm/mcp/formatters.js.map +1 -0
  185. package/dist/esm/mcp/logger.d.ts +11 -0
  186. package/dist/esm/mcp/logger.js +34 -0
  187. package/dist/esm/mcp/logger.js.map +1 -0
  188. package/dist/esm/mcp/mintlifyClient.d.ts +1 -0
  189. package/dist/esm/mcp/mintlifyClient.js +65 -0
  190. package/dist/esm/mcp/mintlifyClient.js.map +1 -0
  191. package/dist/esm/mcp/schemas.d.ts +324 -0
  192. package/dist/esm/mcp/schemas.js +144 -0
  193. package/dist/esm/mcp/schemas.js.map +1 -0
  194. package/dist/esm/mcp/tools/deploys.d.ts +174 -0
  195. package/dist/esm/mcp/tools/deploys.js +161 -0
  196. package/dist/esm/mcp/tools/deploys.js.map +1 -0
  197. package/dist/esm/mcp/tools/docs.d.ts +77 -0
  198. package/dist/esm/mcp/tools/docs.js +18 -0
  199. package/dist/esm/mcp/tools/docs.js.map +1 -0
  200. package/dist/esm/mcp/tools/orgs.d.ts +172 -0
  201. package/dist/esm/mcp/tools/orgs.js +172 -0
  202. package/dist/esm/mcp/tools/orgs.js.map +1 -0
  203. package/dist/esm/mcp/tools/previewBranches.d.ts +78 -0
  204. package/dist/esm/mcp/tools/previewBranches.js +28 -0
  205. package/dist/esm/mcp/tools/previewBranches.js.map +1 -0
  206. package/dist/esm/mcp/tools/runs.d.ts +335 -0
  207. package/dist/esm/mcp/tools/runs.js +160 -0
  208. package/dist/esm/mcp/tools/runs.js.map +1 -0
  209. package/dist/esm/mcp/tools/tasks.d.ts +200 -0
  210. package/dist/esm/mcp/tools/tasks.js +117 -0
  211. package/dist/esm/mcp/tools/tasks.js.map +1 -0
  212. package/dist/esm/mcp/tools.d.ts +2 -0
  213. package/dist/esm/mcp/tools.js +40 -0
  214. package/dist/esm/mcp/tools.js.map +1 -0
  215. package/dist/esm/mcp/types.d.ts +6 -0
  216. package/dist/esm/mcp/types.js +2 -0
  217. package/dist/esm/mcp/types.js.map +1 -0
  218. package/dist/esm/mcp/utils.d.ts +89 -0
  219. package/dist/esm/mcp/utils.js +95 -0
  220. package/dist/esm/mcp/utils.js.map +1 -0
  221. package/dist/esm/rules/install.d.ts +1 -0
  222. package/dist/esm/rules/install.js +2 -0
  223. package/dist/esm/rules/install.js.map +1 -0
  224. package/dist/esm/rules/manifest.d.ts +145 -0
  225. package/dist/esm/rules/manifest.js +110 -0
  226. package/dist/esm/rules/manifest.js.map +1 -0
  227. package/dist/esm/rules/types.d.ts +3 -0
  228. package/dist/esm/rules/types.js +3 -0
  229. package/dist/esm/rules/types.js.map +1 -0
  230. package/dist/esm/utilities/accessTokens.d.ts +12 -0
  231. package/dist/esm/utilities/accessTokens.js +30 -0
  232. package/dist/esm/utilities/accessTokens.js.map +1 -0
  233. package/dist/esm/utilities/analyze.d.ts +13 -0
  234. package/dist/esm/utilities/analyze.js +463 -0
  235. package/dist/esm/utilities/analyze.js.map +1 -0
  236. package/dist/esm/utilities/cliOutput.d.ts +6 -1
  237. package/dist/esm/utilities/cliOutput.js +11 -2
  238. package/dist/esm/utilities/cliOutput.js.map +1 -1
  239. package/dist/esm/utilities/configFiles.d.ts +65 -15
  240. package/dist/esm/utilities/configFiles.js +124 -26
  241. package/dist/esm/utilities/configFiles.js.map +1 -1
  242. package/dist/esm/utilities/eventBus.d.ts +7 -3
  243. package/dist/esm/utilities/eventBus.js.map +1 -1
  244. package/dist/esm/utilities/fileSystem.d.ts +7 -1
  245. package/dist/esm/utilities/fileSystem.js +42 -4
  246. package/dist/esm/utilities/fileSystem.js.map +1 -1
  247. package/dist/esm/utilities/gitMeta.d.ts +2 -0
  248. package/dist/esm/utilities/gitMeta.js +220 -0
  249. package/dist/esm/utilities/gitMeta.js.map +1 -0
  250. package/dist/esm/utilities/githubActions.d.ts +4 -0
  251. package/dist/esm/utilities/githubActions.js +18 -0
  252. package/dist/esm/utilities/githubActions.js.map +1 -0
  253. package/dist/esm/utilities/initialBanner.js +18 -6
  254. package/dist/esm/utilities/initialBanner.js.map +1 -1
  255. package/dist/esm/utilities/localEnvVars.d.ts +3 -0
  256. package/dist/esm/utilities/localEnvVars.js +19 -0
  257. package/dist/esm/utilities/localEnvVars.js.map +1 -0
  258. package/dist/esm/utilities/sanitizeEnvVars.d.ts +16 -3
  259. package/dist/esm/utilities/sanitizeEnvVars.js +15 -0
  260. package/dist/esm/utilities/sanitizeEnvVars.js.map +1 -1
  261. package/dist/esm/utilities/session.d.ts +14 -0
  262. package/dist/esm/utilities/session.js +44 -47
  263. package/dist/esm/utilities/session.js.map +1 -1
  264. package/dist/esm/utilities/supportsHyperlinks.d.ts +15 -0
  265. package/dist/esm/utilities/supportsHyperlinks.js +122 -0
  266. package/dist/esm/utilities/supportsHyperlinks.js.map +1 -0
  267. package/dist/esm/utilities/tempDirectories.d.ts +1 -0
  268. package/dist/esm/utilities/tempDirectories.js +19 -2
  269. package/dist/esm/utilities/tempDirectories.js.map +1 -1
  270. package/dist/esm/utilities/terminalLink.d.ts +56 -0
  271. package/dist/esm/utilities/terminalLink.js +76 -0
  272. package/dist/esm/utilities/terminalLink.js.map +1 -0
  273. package/dist/esm/utilities/windows.js +51 -1
  274. package/dist/esm/utilities/windows.js.map +1 -1
  275. package/dist/esm/version.js +1 -1
  276. package/package.json +44 -25
  277. package/dist/esm/entryPoints/deploy-index-controller.js.map +0 -1
  278. package/dist/esm/entryPoints/deploy-index-worker.js.map +0 -1
  279. package/dist/esm/entryPoints/deploy-run-controller.js +0 -1099
  280. package/dist/esm/entryPoints/deploy-run-controller.js.map +0 -1
  281. package/dist/esm/entryPoints/deploy-run-worker.js +0 -366
  282. package/dist/esm/entryPoints/deploy-run-worker.js.map +0 -1
  283. package/dist/esm/indexing/registerTasks.d.ts +0 -2
  284. package/dist/esm/indexing/registerTasks.js +0 -62
  285. package/dist/esm/indexing/registerTasks.js.map +0 -1
  286. package/dist/esm/telemetry/tracing.d.ts +0 -3
  287. package/dist/esm/telemetry/tracing.js +0 -58
  288. package/dist/esm/telemetry/tracing.js.map +0 -1
  289. /package/dist/esm/entryPoints/{deploy-index-controller.d.ts → managed-index-controller.d.ts} +0 -0
  290. /package/dist/esm/entryPoints/{deploy-index-worker.d.ts → managed-index-worker.d.ts} +0 -0
  291. /package/dist/esm/entryPoints/{deploy-run-controller.d.ts → managed-run-controller.d.ts} +0 -0
  292. /package/dist/esm/entryPoints/{deploy-run-worker.d.ts → managed-run-worker.d.ts} +0 -0
@@ -0,0 +1,652 @@
1
+ import { IntervalService, SuspendedProcessError, } from "@trigger.dev/core/v3";
2
+ import { setTimeout as sleep } from "timers/promises";
3
+ import { TaskRunProcess } from "../executions/taskRunProcess.js";
4
+ import { assertExhaustive } from "../utilities/assertExhaustive.js";
5
+ import { logger } from "../utilities/logger.js";
6
+ import { sanitizeEnvVars } from "../utilities/sanitizeEnvVars.js";
7
+ import { join } from "node:path";
8
+ import { eventBus } from "../utilities/eventBus.js";
9
+ export class DevRunController {
10
+ opts;
11
+ taskRunProcess;
12
+ worker;
13
+ httpClient;
14
+ snapshotPoller;
15
+ snapshotPollIntervalSeconds;
16
+ cwd;
17
+ isCompletingRun = false;
18
+ isShuttingDown = false;
19
+ state = { phase: "IDLE" };
20
+ enterRunPhase(run, snapshot) {
21
+ this.onExitRunPhase(run);
22
+ this.state = { phase: "RUN", run, snapshot };
23
+ this.snapshotPoller.start();
24
+ }
25
+ constructor(opts) {
26
+ this.opts = opts;
27
+ logger.debug("[DevRunController] Creating controller", {
28
+ run: opts.runFriendlyId,
29
+ });
30
+ this.worker = opts.worker;
31
+ this.snapshotPollIntervalSeconds = 5;
32
+ this.cwd = opts.cwd;
33
+ this.httpClient = opts.httpClient;
34
+ this.snapshotPoller = new IntervalService({
35
+ onInterval: async () => {
36
+ if (!this.runFriendlyId) {
37
+ logger.debug("[DevRunController] Skipping snapshot poll, no run ID");
38
+ return;
39
+ }
40
+ logger.debug("[DevRunController] Polling for latest snapshot");
41
+ this.httpClient.dev.sendDebugLog(this.runFriendlyId, {
42
+ time: new Date(),
43
+ message: `snapshot poll: started`,
44
+ properties: {
45
+ snapshotId: this.snapshotFriendlyId,
46
+ },
47
+ });
48
+ const response = await this.httpClient.dev.getRunExecutionData(this.runFriendlyId);
49
+ if (!response.success) {
50
+ logger.debug("[DevRunController] Snapshot poll failed", { error: response.error });
51
+ this.httpClient.dev.sendDebugLog(this.runFriendlyId, {
52
+ time: new Date(),
53
+ message: `snapshot poll: failed`,
54
+ properties: {
55
+ snapshotId: this.snapshotFriendlyId,
56
+ error: response.error,
57
+ },
58
+ });
59
+ return;
60
+ }
61
+ await this.handleSnapshotChange(response.data.execution);
62
+ },
63
+ intervalMs: this.snapshotPollIntervalSeconds * 1000,
64
+ leadingEdge: false,
65
+ onError: async (error) => {
66
+ logger.debug("[DevRunController] Failed to poll for snapshot", { error });
67
+ },
68
+ });
69
+ process.on("SIGTERM", this.sigterm.bind(this));
70
+ }
71
+ async sigterm() {
72
+ logger.debug("[DevRunController] Received SIGTERM, stopping worker");
73
+ await this.stop();
74
+ }
75
+ // This should only be used when we're already executing a run. Attempt number changes are not allowed.
76
+ updateRunPhase(run, snapshot) {
77
+ if (this.state.phase !== "RUN") {
78
+ this.httpClient.dev.sendDebugLog(run.friendlyId, {
79
+ time: new Date(),
80
+ message: `updateRunPhase: Invalid phase for updating snapshot: ${this.state.phase}`,
81
+ properties: {
82
+ currentPhase: this.state.phase,
83
+ snapshotId: snapshot.friendlyId,
84
+ },
85
+ });
86
+ throw new Error(`Invalid phase for updating snapshot: ${this.state.phase}`);
87
+ }
88
+ if (this.state.run.friendlyId !== run.friendlyId) {
89
+ this.httpClient.dev.sendDebugLog(run.friendlyId, {
90
+ time: new Date(),
91
+ message: `updateRunPhase: Mismatched run IDs`,
92
+ properties: {
93
+ currentRunId: this.state.run.friendlyId,
94
+ newRunId: run.friendlyId,
95
+ currentSnapshotId: this.state.snapshot.friendlyId,
96
+ newSnapshotId: snapshot.friendlyId,
97
+ },
98
+ });
99
+ throw new Error("Mismatched run IDs");
100
+ }
101
+ if (this.state.snapshot.friendlyId === snapshot.friendlyId) {
102
+ logger.debug("updateRunPhase: Snapshot not changed", { run, snapshot });
103
+ this.httpClient.dev.sendDebugLog(run.friendlyId, {
104
+ time: new Date(),
105
+ message: `updateRunPhase: Snapshot not changed`,
106
+ properties: {
107
+ snapshotId: snapshot.friendlyId,
108
+ },
109
+ });
110
+ return;
111
+ }
112
+ if (this.state.run.attemptNumber !== run.attemptNumber) {
113
+ this.httpClient.dev.sendDebugLog(run.friendlyId, {
114
+ time: new Date(),
115
+ message: `updateRunPhase: Attempt number changed`,
116
+ properties: {
117
+ oldAttemptNumber: this.state.run.attemptNumber ?? undefined,
118
+ newAttemptNumber: run.attemptNumber ?? undefined,
119
+ },
120
+ });
121
+ throw new Error("Attempt number changed");
122
+ }
123
+ this.state = {
124
+ phase: "RUN",
125
+ run: {
126
+ friendlyId: run.friendlyId,
127
+ attemptNumber: run.attemptNumber,
128
+ },
129
+ snapshot: {
130
+ friendlyId: snapshot.friendlyId,
131
+ },
132
+ };
133
+ }
134
+ onExitRunPhase(newRun = undefined) {
135
+ // We're not in a run phase, nothing to do
136
+ if (this.state.phase !== "RUN") {
137
+ logger.debug("onExitRunPhase: Not in run phase, skipping", { phase: this.state.phase });
138
+ return;
139
+ }
140
+ // This is still the same run, so we're not exiting the phase
141
+ if (newRun?.friendlyId === this.state.run.friendlyId) {
142
+ logger.debug("onExitRunPhase: Same run, skipping", { newRun });
143
+ return;
144
+ }
145
+ logger.debug("onExitRunPhase: Exiting run phase", { newRun });
146
+ this.snapshotPoller.stop();
147
+ const { run, snapshot } = this.state;
148
+ this.unsubscribeFromRunNotifications({ run, snapshot });
149
+ }
150
+ subscribeToRunNotifications({ run, snapshot }) {
151
+ logger.debug("[DevRunController] Subscribing to run notifications", { run, snapshot });
152
+ this.opts.onSubscribeToRunNotifications(run, snapshot);
153
+ }
154
+ unsubscribeFromRunNotifications({ run, snapshot }) {
155
+ logger.debug("[DevRunController] Unsubscribing from run notifications", { run, snapshot });
156
+ this.opts.onUnsubscribeFromRunNotifications(run, snapshot);
157
+ }
158
+ get runFriendlyId() {
159
+ if (this.state.phase !== "RUN") {
160
+ return undefined;
161
+ }
162
+ return this.state.run.friendlyId;
163
+ }
164
+ get snapshotFriendlyId() {
165
+ if (this.state.phase !== "RUN") {
166
+ return;
167
+ }
168
+ return this.state.snapshot.friendlyId;
169
+ }
170
+ get workerFriendlyId() {
171
+ if (!this.opts.worker.serverWorker) {
172
+ throw new Error("No version for dev worker");
173
+ }
174
+ return this.opts.worker.serverWorker.id;
175
+ }
176
+ handleSnapshotChangeLock = false;
177
+ async handleSnapshotChange({ run, snapshot, completedWaitpoints, }) {
178
+ if (this.handleSnapshotChangeLock) {
179
+ logger.debug("handleSnapshotChange: already in progress");
180
+ return;
181
+ }
182
+ this.handleSnapshotChangeLock = true;
183
+ // Reset the (fallback) snapshot poll interval so we don't do unnecessary work
184
+ this.snapshotPoller.resetCurrentInterval();
185
+ try {
186
+ if (!this.snapshotFriendlyId) {
187
+ logger.debug("handleSnapshotChange: Missing snapshot ID", {
188
+ runId: run.friendlyId,
189
+ snapshotId: this.snapshotFriendlyId,
190
+ });
191
+ this.httpClient.dev.sendDebugLog(run.friendlyId, {
192
+ time: new Date(),
193
+ message: `snapshot change: missing snapshot ID`,
194
+ properties: {
195
+ newSnapshotId: snapshot.friendlyId,
196
+ newSnapshotStatus: snapshot.executionStatus,
197
+ },
198
+ });
199
+ return;
200
+ }
201
+ if (this.snapshotFriendlyId === snapshot.friendlyId) {
202
+ logger.debug("handleSnapshotChange: snapshot not changed, skipping", { snapshot });
203
+ this.httpClient.dev.sendDebugLog(run.friendlyId, {
204
+ time: new Date(),
205
+ message: `snapshot change: skipping, no change`,
206
+ properties: {
207
+ snapshotId: this.snapshotFriendlyId,
208
+ snapshotStatus: snapshot.executionStatus,
209
+ },
210
+ });
211
+ return;
212
+ }
213
+ logger.debug(`handleSnapshotChange: ${snapshot.executionStatus}`, {
214
+ run,
215
+ oldSnapshotId: this.snapshotFriendlyId,
216
+ newSnapshot: snapshot,
217
+ completedWaitpoints: completedWaitpoints.length,
218
+ });
219
+ this.httpClient.dev.sendDebugLog(run.friendlyId, {
220
+ time: new Date(),
221
+ message: `snapshot change: ${snapshot.executionStatus}`,
222
+ properties: {
223
+ oldSnapshotId: this.snapshotFriendlyId,
224
+ newSnapshotId: snapshot.friendlyId,
225
+ completedWaitpoints: completedWaitpoints.length,
226
+ },
227
+ });
228
+ try {
229
+ this.updateRunPhase(run, snapshot);
230
+ }
231
+ catch (error) {
232
+ logger.debug("handleSnapshotChange: failed to update run phase", {
233
+ run,
234
+ snapshot,
235
+ error,
236
+ });
237
+ this.runFinished();
238
+ return;
239
+ }
240
+ switch (snapshot.executionStatus) {
241
+ case "PENDING_CANCEL": {
242
+ try {
243
+ await this.cancelAttempt();
244
+ }
245
+ catch (error) {
246
+ logger.debug("Failed to cancel attempt, killing task run process", {
247
+ error,
248
+ });
249
+ try {
250
+ await this.taskRunProcess?.kill("SIGKILL");
251
+ }
252
+ catch (error) {
253
+ logger.debug("Failed to cancel attempt, failed to kill task run process", { error });
254
+ }
255
+ return;
256
+ }
257
+ return;
258
+ }
259
+ case "FINISHED": {
260
+ if (this.isCompletingRun) {
261
+ logger.debug("Run is finished but we're completing it, skipping");
262
+ return;
263
+ }
264
+ await this.exitTaskRunProcessWithoutFailingRun({
265
+ flush: true,
266
+ reason: "already-finished",
267
+ });
268
+ return;
269
+ }
270
+ case "EXECUTING_WITH_WAITPOINTS": {
271
+ logger.debug("Run is executing with waitpoints", { snapshot });
272
+ try {
273
+ await this.taskRunProcess?.cleanup(false);
274
+ }
275
+ catch (error) {
276
+ logger.debug("Failed to cleanup task run process", { error });
277
+ }
278
+ if (snapshot.friendlyId !== this.snapshotFriendlyId) {
279
+ logger.debug("Snapshot changed after cleanup, abort", {
280
+ oldSnapshotId: snapshot.friendlyId,
281
+ newSnapshotId: this.snapshotFriendlyId,
282
+ });
283
+ return;
284
+ }
285
+ //no snapshots in DEV, so we just return.
286
+ return;
287
+ }
288
+ case "SUSPENDED": {
289
+ logger.debug("Run shouldn't be suspended in DEV", {
290
+ run,
291
+ snapshot,
292
+ });
293
+ return;
294
+ }
295
+ case "PENDING_EXECUTING": {
296
+ logger.debug("Run is pending execution", { run, snapshot });
297
+ if (completedWaitpoints.length === 0) {
298
+ logger.log("No waitpoints to complete, nothing to do");
299
+ return;
300
+ }
301
+ logger.debug("Run shouldn't be PENDING_EXECUTING with completedWaitpoints in DEV", {
302
+ run,
303
+ snapshot,
304
+ });
305
+ return;
306
+ }
307
+ case "EXECUTING": {
308
+ logger.debug("Run is now executing", { run, snapshot });
309
+ if (completedWaitpoints.length === 0) {
310
+ return;
311
+ }
312
+ logger.debug("Processing completed waitpoints", { completedWaitpoints });
313
+ if (!this.taskRunProcess) {
314
+ logger.debug("No task run process, ignoring completed waitpoints", {
315
+ completedWaitpoints,
316
+ });
317
+ return;
318
+ }
319
+ for (const waitpoint of completedWaitpoints) {
320
+ this.taskRunProcess.waitpointCompleted(waitpoint);
321
+ }
322
+ return;
323
+ }
324
+ case "RUN_CREATED":
325
+ case "QUEUED_EXECUTING":
326
+ case "QUEUED": {
327
+ logger.debug("Status change not handled", { status: snapshot.executionStatus });
328
+ return;
329
+ }
330
+ default: {
331
+ assertExhaustive(snapshot.executionStatus);
332
+ }
333
+ }
334
+ }
335
+ catch (error) {
336
+ logger.debug("handleSnapshotChange: unexpected error", { error });
337
+ this.httpClient.dev.sendDebugLog(run.friendlyId, {
338
+ time: new Date(),
339
+ message: `snapshot change: unexpected error`,
340
+ properties: {
341
+ snapshotId: snapshot.friendlyId,
342
+ error: error instanceof Error ? error.message : String(error),
343
+ },
344
+ });
345
+ }
346
+ finally {
347
+ this.handleSnapshotChangeLock = false;
348
+ }
349
+ }
350
+ async startAndExecuteRunAttempt({ runFriendlyId, snapshotFriendlyId, dequeuedAt, isWarmStart = false, }) {
351
+ this.subscribeToRunNotifications({
352
+ run: { friendlyId: runFriendlyId },
353
+ snapshot: { friendlyId: snapshotFriendlyId },
354
+ });
355
+ const attemptStartedAt = Date.now();
356
+ const start = await this.httpClient.dev.startRunAttempt(runFriendlyId, snapshotFriendlyId);
357
+ if (!start.success) {
358
+ logger.debug("[DevRunController] Failed to start run", { error: start.error });
359
+ this.runFinished();
360
+ return;
361
+ }
362
+ const attemptDuration = Date.now() - attemptStartedAt;
363
+ const { run, snapshot, execution, envVars } = start.data;
364
+ eventBus.emit("runStarted", this.opts.worker, execution);
365
+ logger.debug("[DevRunController] Started run", {
366
+ runId: run.friendlyId,
367
+ snapshot: snapshot.friendlyId,
368
+ });
369
+ this.enterRunPhase(run, snapshot);
370
+ const metrics = [
371
+ {
372
+ name: "start",
373
+ event: "create_attempt",
374
+ timestamp: attemptStartedAt,
375
+ duration: attemptDuration,
376
+ },
377
+ ].concat(dequeuedAt
378
+ ? [
379
+ {
380
+ name: "start",
381
+ event: "dequeue",
382
+ timestamp: dequeuedAt.getTime(),
383
+ duration: 0,
384
+ },
385
+ ]
386
+ : []);
387
+ try {
388
+ return await this.executeRun({ run, snapshot, execution, envVars, metrics });
389
+ }
390
+ catch (error) {
391
+ logger.debug("Error while executing attempt", {
392
+ error,
393
+ });
394
+ if (error instanceof SuspendedProcessError) {
395
+ logger.debug("Attempt execution suspended", { error });
396
+ this.runFinished();
397
+ return;
398
+ }
399
+ logger.debug("Submitting attempt completion", {
400
+ runId: run.friendlyId,
401
+ snapshotId: snapshot.friendlyId,
402
+ updatedSnapshotId: this.snapshotFriendlyId,
403
+ });
404
+ const completion = {
405
+ id: execution.run.id,
406
+ ok: false,
407
+ retry: undefined,
408
+ error: TaskRunProcess.parseExecuteError(error),
409
+ };
410
+ const completionResult = await this.httpClient.dev.completeRunAttempt(run.friendlyId, this.snapshotFriendlyId ?? snapshot.friendlyId, { completion });
411
+ if (!completionResult.success) {
412
+ logger.debug("Failed to submit completion after error", {
413
+ error: completionResult.error,
414
+ });
415
+ this.runFinished();
416
+ return;
417
+ }
418
+ logger.debug("Attempt completion submitted after error", completionResult.data.result);
419
+ try {
420
+ await this.handleCompletionResult(completion, completionResult.data.result, execution);
421
+ }
422
+ catch (error) {
423
+ logger.debug("Failed to handle completion result after error", { error });
424
+ this.runFinished();
425
+ return;
426
+ }
427
+ }
428
+ }
429
+ async executeRun({ run, snapshot, execution, envVars, metrics, }) {
430
+ if (!this.opts.worker.serverWorker) {
431
+ throw new Error(`No server worker for Dev ${run.friendlyId}`);
432
+ }
433
+ if (!this.opts.worker.manifest) {
434
+ throw new Error(`No worker manifest for Dev ${run.friendlyId}`);
435
+ }
436
+ this.snapshotPoller.start();
437
+ logger.debug("getProcess", {
438
+ build: this.opts.worker.build,
439
+ });
440
+ this.isCompletingRun = false;
441
+ // Get process from pool instead of creating new one
442
+ const { taskRunProcess, isReused } = await this.opts.taskRunProcessPool.getProcess(this.opts.worker.manifest, {
443
+ id: "unmanaged",
444
+ contentHash: this.opts.worker.build.contentHash,
445
+ version: this.opts.worker.serverWorker?.version,
446
+ engine: "V2",
447
+ }, execution.machine, {
448
+ TRIGGER_WORKER_MANIFEST_PATH: join(this.opts.worker.build.outputPath, "index.json"),
449
+ RUN_WORKER_SHOW_LOGS: this.opts.logLevel === "debug" ? "true" : "false",
450
+ TRIGGER_WORKER_VERSION: this.opts.worker.serverWorker?.version,
451
+ }, this.cwd);
452
+ this.taskRunProcess = taskRunProcess;
453
+ taskRunProcess.unsafeDetachEvtHandlers();
454
+ taskRunProcess.onTaskRunHeartbeat.attach(async (runId) => {
455
+ if (!this.runFriendlyId || !this.snapshotFriendlyId) {
456
+ logger.debug("[DevRunController] Skipping heartbeat, no run ID or snapshot ID");
457
+ return;
458
+ }
459
+ logger.debug("[DevRunController] Sending heartbeat");
460
+ const response = await this.httpClient.dev.heartbeatRun(this.runFriendlyId, this.snapshotFriendlyId, {
461
+ cpu: 0,
462
+ memory: 0,
463
+ });
464
+ if (!response.success) {
465
+ logger.debug("[DevRunController] Heartbeat failed", { error: response.error });
466
+ }
467
+ });
468
+ // Update the process environment for this specific run
469
+ // Note: We may need to enhance TaskRunProcess to support updating env vars
470
+ logger.debug("executing task run process from pool", {
471
+ attemptNumber: execution.attempt.number,
472
+ runId: execution.run.id,
473
+ });
474
+ const completion = await this.taskRunProcess.execute({
475
+ payload: {
476
+ execution,
477
+ traceContext: execution.run.traceContext ?? {},
478
+ metrics,
479
+ },
480
+ messageId: run.friendlyId,
481
+ env: {
482
+ ...sanitizeEnvVars(envVars ?? {}),
483
+ ...sanitizeEnvVars(this.opts.worker.params.env),
484
+ TRIGGER_PROJECT_REF: execution.project.ref,
485
+ },
486
+ }, isReused);
487
+ logger.debug("Completed run", completion);
488
+ this.isCompletingRun = true;
489
+ // Return process to pool instead of killing it
490
+ try {
491
+ const version = this.opts.worker.serverWorker?.version || "unknown";
492
+ await this.opts.taskRunProcessPool.returnProcess(this.taskRunProcess, version);
493
+ this.taskRunProcess = undefined;
494
+ }
495
+ catch (error) {
496
+ logger.debug("Failed to return task run process to pool, submitting completion anyway", {
497
+ error,
498
+ });
499
+ }
500
+ if (!this.runFriendlyId || !this.snapshotFriendlyId) {
501
+ logger.debug("executeRun: Missing run ID or snapshot ID after execution", {
502
+ runId: this.runFriendlyId,
503
+ snapshotId: this.snapshotFriendlyId,
504
+ });
505
+ this.runFinished();
506
+ return;
507
+ }
508
+ const completionResult = await this.httpClient.dev.completeRunAttempt(this.runFriendlyId, this.snapshotFriendlyId, {
509
+ completion,
510
+ });
511
+ if (!completionResult.success) {
512
+ logger.debug("Failed to submit completion", {
513
+ error: completionResult.error,
514
+ });
515
+ this.runFinished();
516
+ return;
517
+ }
518
+ logger.debug("Attempt completion submitted", completionResult.data.result);
519
+ try {
520
+ await this.handleCompletionResult(completion, completionResult.data.result, execution);
521
+ }
522
+ catch (error) {
523
+ logger.debug("Failed to handle completion result", { error });
524
+ this.runFinished();
525
+ return;
526
+ }
527
+ }
528
+ async handleCompletionResult(completion, result, execution) {
529
+ logger.debug("[DevRunController] Handling completion result", { completion, result });
530
+ const { attemptStatus, snapshot: completionSnapshot, run } = result;
531
+ try {
532
+ this.updateRunPhase(run, completionSnapshot);
533
+ }
534
+ catch (error) {
535
+ logger.debug("Failed to update run phase after completion", { error });
536
+ this.runFinished();
537
+ return;
538
+ }
539
+ if (attemptStatus === "RETRY_QUEUED") {
540
+ logger.debug("Retry queued");
541
+ this.runFinished();
542
+ return;
543
+ }
544
+ if (attemptStatus === "RETRY_IMMEDIATELY") {
545
+ if (completion.ok) {
546
+ throw new Error("Should retry but completion OK.");
547
+ }
548
+ if (!completion.retry) {
549
+ throw new Error("Should retry but missing retry params.");
550
+ }
551
+ await sleep(completion.retry.delay);
552
+ if (!this.snapshotFriendlyId) {
553
+ throw new Error("Missing snapshot ID after retry");
554
+ }
555
+ this.startAndExecuteRunAttempt({
556
+ runFriendlyId: run.friendlyId,
557
+ snapshotFriendlyId: this.snapshotFriendlyId,
558
+ }).finally(() => { });
559
+ return;
560
+ }
561
+ if (attemptStatus === "RUN_PENDING_CANCEL") {
562
+ logger.debug("Run pending cancel");
563
+ return;
564
+ }
565
+ eventBus.emit("runCompleted", this.opts.worker, execution, completion, completion.usage?.durationMs ?? 0);
566
+ if (attemptStatus === "RUN_FINISHED") {
567
+ logger.debug("Run finished");
568
+ this.runFinished();
569
+ return;
570
+ }
571
+ assertExhaustive(attemptStatus);
572
+ }
573
+ async exitTaskRunProcessWithoutFailingRun({ flush, reason, }) {
574
+ await this.taskRunProcess?.suspend({ flush });
575
+ // No services should be left running after this line - let's make sure of it
576
+ this.shutdownExecution(`exitTaskRunProcessWithoutFailingRun: ${reason}`);
577
+ }
578
+ shutdownExecution(reason) {
579
+ if (this.isShuttingDown) {
580
+ logger.debug(`[shutdown] ${reason} (already shutting down)`, {
581
+ newReason: reason,
582
+ });
583
+ return;
584
+ }
585
+ logger.debug(`[shutdown] ${reason}`);
586
+ this.isShuttingDown = true;
587
+ this.snapshotPoller.stop();
588
+ this.opts.onFinished();
589
+ this.taskRunProcess?.unsafeDetachEvtHandlers();
590
+ }
591
+ async runFinished() {
592
+ // Return the process to the pool instead of killing it directly
593
+ if (this.taskRunProcess) {
594
+ try {
595
+ const version = this.opts.worker.serverWorker?.version || "unknown";
596
+ await this.opts.taskRunProcessPool.returnProcess(this.taskRunProcess, version);
597
+ this.taskRunProcess = undefined;
598
+ }
599
+ catch (error) {
600
+ logger.debug("Failed to return task run process to pool during runFinished", { error });
601
+ }
602
+ }
603
+ this.snapshotPoller.stop();
604
+ this.opts.onFinished();
605
+ }
606
+ async cancelAttempt() {
607
+ logger.debug("Cancelling attempt", { runId: this.runFriendlyId });
608
+ await this.taskRunProcess?.cancel();
609
+ }
610
+ async start(dequeueMessage) {
611
+ logger.debug("[DevRunController] Starting up");
612
+ await this.startAndExecuteRunAttempt({
613
+ runFriendlyId: dequeueMessage.run.friendlyId,
614
+ snapshotFriendlyId: dequeueMessage.snapshot.friendlyId,
615
+ dequeuedAt: dequeueMessage.dequeuedAt,
616
+ }).finally(async () => { });
617
+ }
618
+ async stop() {
619
+ logger.debug("[DevRunController] Shutting down");
620
+ process.off("SIGTERM", this.sigterm);
621
+ if (this.taskRunProcess && !this.taskRunProcess.isBeingKilled) {
622
+ try {
623
+ const version = this.opts.worker.serverWorker?.version || "unknown";
624
+ await this.opts.taskRunProcessPool.returnProcess(this.taskRunProcess, version);
625
+ this.taskRunProcess = undefined;
626
+ }
627
+ catch (error) {
628
+ logger.debug("Failed to return task run process to pool during stop", { error });
629
+ }
630
+ }
631
+ this.snapshotPoller.stop();
632
+ }
633
+ async getLatestSnapshot() {
634
+ if (!this.runFriendlyId) {
635
+ return;
636
+ }
637
+ logger.debug("[DevRunController] Received notification, manually getting the latest snapshot.");
638
+ const response = await this.httpClient.dev.getRunExecutionData(this.runFriendlyId);
639
+ if (!response.success) {
640
+ logger.debug("Failed to get latest snapshot", { error: response.error });
641
+ return;
642
+ }
643
+ await this.handleSnapshotChange(response.data.execution);
644
+ }
645
+ resubscribeToRunNotifications() {
646
+ if (this.state.phase !== "RUN") {
647
+ return;
648
+ }
649
+ this.subscribeToRunNotifications(this.state);
650
+ }
651
+ }
652
+ //# sourceMappingURL=dev-run-controller.js.map