trigger.dev 3.0.0-beta.33 → 3.0.0-beta.35

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.
package/dist/index.js CHANGED
@@ -799,7 +799,7 @@ import invariant from "tiny-invariant";
799
799
  import { z as z4 } from "zod";
800
800
 
801
801
  // package.json
802
- var version = "3.0.0-beta.33";
802
+ var version = "3.0.0-beta.35";
803
803
  var dependencies = {
804
804
  "@anatine/esbuild-decorators": "^0.2.19",
805
805
  "@clack/prompts": "^0.7.0",
@@ -816,7 +816,7 @@ var dependencies = {
816
816
  "@opentelemetry/sdk-trace-base": "^1.22.0",
817
817
  "@opentelemetry/sdk-trace-node": "^1.22.0",
818
818
  "@opentelemetry/semantic-conventions": "^1.22.0",
819
- "@trigger.dev/core": "workspace:3.0.0-beta.33",
819
+ "@trigger.dev/core": "workspace:3.0.0-beta.35",
820
820
  "@types/degit": "^2.8.3",
821
821
  chalk: "^5.2.0",
822
822
  chokidar: "^3.5.3",
@@ -948,8 +948,12 @@ import {
948
948
  InitializeDeploymentResponseBody,
949
949
  GetDeploymentResponseBody,
950
950
  GetProjectsResponseBody,
951
- GetProjectResponseBody
951
+ GetProjectResponseBody,
952
+ EnvironmentVariableResponseBody,
953
+ TaskRunExecution,
954
+ APIError
952
955
  } from "@trigger.dev/core/v3";
956
+ import { zodfetch } from "@trigger.dev/core/v3/zodfetch";
953
957
  var CliApiClient = class {
954
958
  constructor(apiURL, accessToken) {
955
959
  this.accessToken = accessToken;
@@ -957,7 +961,7 @@ var CliApiClient = class {
957
961
  }
958
962
  apiURL;
959
963
  async createAuthorizationCode() {
960
- return zodfetch(
964
+ return wrapZodFetch(
961
965
  CreateAuthorizationCodeResponseSchema,
962
966
  `${this.apiURL}/api/v1/authorization-code`,
963
967
  {
@@ -966,7 +970,7 @@ var CliApiClient = class {
966
970
  );
967
971
  }
968
972
  async getPersonalAccessToken(authorizationCode) {
969
- return zodfetch(GetPersonalAccessTokenResponseSchema, `${this.apiURL}/api/v1/token`, {
973
+ return wrapZodFetch(GetPersonalAccessTokenResponseSchema, `${this.apiURL}/api/v1/token`, {
970
974
  method: "POST",
971
975
  body: JSON.stringify({
972
976
  authorizationCode
@@ -977,7 +981,7 @@ var CliApiClient = class {
977
981
  if (!this.accessToken) {
978
982
  throw new Error("whoAmI: No access token");
979
983
  }
980
- return zodfetch(WhoAmIResponseSchema, `${this.apiURL}/api/v2/whoami`, {
984
+ return wrapZodFetch(WhoAmIResponseSchema, `${this.apiURL}/api/v2/whoami`, {
981
985
  headers: {
982
986
  Authorization: `Bearer ${this.accessToken}`,
983
987
  "Content-Type": "application/json"
@@ -988,7 +992,7 @@ var CliApiClient = class {
988
992
  if (!this.accessToken) {
989
993
  throw new Error("getProject: No access token");
990
994
  }
991
- return zodfetch(GetProjectResponseBody, `${this.apiURL}/api/v1/projects/${projectRef}`, {
995
+ return wrapZodFetch(GetProjectResponseBody, `${this.apiURL}/api/v1/projects/${projectRef}`, {
992
996
  headers: {
993
997
  Authorization: `Bearer ${this.accessToken}`,
994
998
  "Content-Type": "application/json"
@@ -999,7 +1003,7 @@ var CliApiClient = class {
999
1003
  if (!this.accessToken) {
1000
1004
  throw new Error("getProjects: No access token");
1001
1005
  }
1002
- return zodfetch(GetProjectsResponseBody, `${this.apiURL}/api/v1/projects`, {
1006
+ return wrapZodFetch(GetProjectsResponseBody, `${this.apiURL}/api/v1/projects`, {
1003
1007
  headers: {
1004
1008
  Authorization: `Bearer ${this.accessToken}`,
1005
1009
  "Content-Type": "application/json"
@@ -1010,7 +1014,7 @@ var CliApiClient = class {
1010
1014
  if (!this.accessToken) {
1011
1015
  throw new Error("createBackgroundWorker: No access token");
1012
1016
  }
1013
- return zodfetch(
1017
+ return wrapZodFetch(
1014
1018
  CreateBackgroundWorkerResponse,
1015
1019
  `${this.apiURL}/api/v1/projects/${projectRef}/background-workers`,
1016
1020
  {
@@ -1023,6 +1027,18 @@ var CliApiClient = class {
1023
1027
  }
1024
1028
  );
1025
1029
  }
1030
+ async createTaskRunAttempt(runFriendlyId) {
1031
+ if (!this.accessToken) {
1032
+ throw new Error("creatTaskRunAttempt: No access token");
1033
+ }
1034
+ return wrapZodFetch(TaskRunExecution, `${this.apiURL}/api/v1/runs/${runFriendlyId}/attempts`, {
1035
+ method: "POST",
1036
+ headers: {
1037
+ Authorization: `Bearer ${this.accessToken}`,
1038
+ "Content-Type": "application/json"
1039
+ }
1040
+ });
1041
+ }
1026
1042
  async getProjectEnv({
1027
1043
  projectRef,
1028
1044
  env
@@ -1030,18 +1046,22 @@ var CliApiClient = class {
1030
1046
  if (!this.accessToken) {
1031
1047
  throw new Error("getProjectDevEnv: No access token");
1032
1048
  }
1033
- return zodfetch(GetProjectEnvResponse, `${this.apiURL}/api/v1/projects/${projectRef}/${env}`, {
1034
- headers: {
1035
- Authorization: `Bearer ${this.accessToken}`,
1036
- "Content-Type": "application/json"
1049
+ return wrapZodFetch(
1050
+ GetProjectEnvResponse,
1051
+ `${this.apiURL}/api/v1/projects/${projectRef}/${env}`,
1052
+ {
1053
+ headers: {
1054
+ Authorization: `Bearer ${this.accessToken}`,
1055
+ "Content-Type": "application/json"
1056
+ }
1037
1057
  }
1038
- });
1058
+ );
1039
1059
  }
1040
1060
  async getEnvironmentVariables(projectRef) {
1041
1061
  if (!this.accessToken) {
1042
1062
  throw new Error("getEnvironmentVariables: No access token");
1043
1063
  }
1044
- return zodfetch(
1064
+ return wrapZodFetch(
1045
1065
  GetEnvironmentVariablesResponseBody,
1046
1066
  `${this.apiURL}/api/v1/projects/${projectRef}/envvars`,
1047
1067
  {
@@ -1052,11 +1072,28 @@ var CliApiClient = class {
1052
1072
  }
1053
1073
  );
1054
1074
  }
1075
+ async importEnvVars(projectRef, slug, params) {
1076
+ if (!this.accessToken) {
1077
+ throw new Error("importEnvVars: No access token");
1078
+ }
1079
+ return wrapZodFetch(
1080
+ EnvironmentVariableResponseBody,
1081
+ `${this.apiURL}/api/v1/projects/${projectRef}/envvars/${slug}/import`,
1082
+ {
1083
+ method: "POST",
1084
+ headers: {
1085
+ Authorization: `Bearer ${this.accessToken}`,
1086
+ "Content-Type": "application/json"
1087
+ },
1088
+ body: JSON.stringify(params)
1089
+ }
1090
+ );
1091
+ }
1055
1092
  async initializeDeployment(body) {
1056
1093
  if (!this.accessToken) {
1057
1094
  throw new Error("initializeDeployment: No access token");
1058
1095
  }
1059
- return zodfetch(InitializeDeploymentResponseBody, `${this.apiURL}/api/v1/deployments`, {
1096
+ return wrapZodFetch(InitializeDeploymentResponseBody, `${this.apiURL}/api/v1/deployments`, {
1060
1097
  method: "POST",
1061
1098
  headers: {
1062
1099
  Authorization: `Bearer ${this.accessToken}`,
@@ -1069,7 +1106,7 @@ var CliApiClient = class {
1069
1106
  if (!this.accessToken) {
1070
1107
  throw new Error("startDeploymentIndexing: No access token");
1071
1108
  }
1072
- return zodfetch(
1109
+ return wrapZodFetch(
1073
1110
  StartDeploymentIndexingResponseBody,
1074
1111
  `${this.apiURL}/api/v1/deployments/${deploymentId}/start-indexing`,
1075
1112
  {
@@ -1086,7 +1123,7 @@ var CliApiClient = class {
1086
1123
  if (!this.accessToken) {
1087
1124
  throw new Error("getDeployment: No access token");
1088
1125
  }
1089
- return zodfetch(
1126
+ return wrapZodFetch(
1090
1127
  GetDeploymentResponseBody,
1091
1128
  `${this.apiURL}/api/v1/deployments/${deploymentId}`,
1092
1129
  {
@@ -1098,45 +1135,38 @@ var CliApiClient = class {
1098
1135
  );
1099
1136
  }
1100
1137
  };
1101
- async function zodfetch(schema, url, requestInit) {
1138
+ async function wrapZodFetch(schema, url, requestInit) {
1102
1139
  try {
1103
- const response = await fetch(url, requestInit);
1104
- if ((!requestInit || requestInit.method === "GET") && response.status === 404) {
1140
+ const response = await zodfetch(schema, url, requestInit, {
1141
+ retry: {
1142
+ minTimeoutInMs: 500,
1143
+ maxTimeoutInMs: 5e3,
1144
+ maxAttempts: 3,
1145
+ factor: 2,
1146
+ randomize: false
1147
+ }
1148
+ });
1149
+ return {
1150
+ success: true,
1151
+ data: response
1152
+ };
1153
+ } catch (error) {
1154
+ if (error instanceof APIError) {
1105
1155
  return {
1106
1156
  success: false,
1107
- error: `404: ${response.statusText}`
1157
+ error: error.message
1108
1158
  };
1109
- }
1110
- if (response.status >= 400 && response.status < 500) {
1111
- const body = await response.json();
1112
- if (!body.error) {
1113
- return { success: false, error: "Something went wrong" };
1114
- }
1115
- return { success: false, error: body.error };
1116
- }
1117
- if (response.status !== 200) {
1159
+ } else if (error instanceof Error) {
1118
1160
  return {
1119
1161
  success: false,
1120
- error: `Failed to fetch ${url}, got status code ${response.status}`
1162
+ error: error.message
1121
1163
  };
1122
- }
1123
- const jsonBody = await response.json();
1124
- const parsedResult = schema.safeParse(jsonBody);
1125
- if (parsedResult.success) {
1126
- return { success: true, data: parsedResult.data };
1127
- }
1128
- if ("error" in jsonBody) {
1164
+ } else {
1129
1165
  return {
1130
1166
  success: false,
1131
- error: typeof jsonBody.error === "string" ? jsonBody.error : JSON.stringify(jsonBody.error)
1167
+ error: String(error)
1132
1168
  };
1133
1169
  }
1134
- return { success: false, error: parsedResult.error.message };
1135
- } catch (error) {
1136
- return {
1137
- success: false,
1138
- error: error instanceof Error ? error.message : JSON.stringify(error)
1139
- };
1140
1170
  }
1141
1171
  }
1142
1172
 
@@ -1710,7 +1740,15 @@ async function readConfig(dir, options) {
1710
1740
  cwd: absoluteDir,
1711
1741
  tsx: false,
1712
1742
  force: false
1713
- })
1743
+ }),
1744
+ {
1745
+ name: "native-node-modules",
1746
+ setup(build3) {
1747
+ const opts = build3.initialOptions;
1748
+ opts.loader = opts.loader || {};
1749
+ opts.loader[".node"] = "copy";
1750
+ }
1751
+ }
1714
1752
  ]
1715
1753
  });
1716
1754
  try {
@@ -1723,7 +1761,8 @@ async function readConfig(dir, options) {
1723
1761
  return {
1724
1762
  status: "file",
1725
1763
  config: await resolveConfig(absoluteDir, config),
1726
- path: configPath
1764
+ path: configPath,
1765
+ module: userConfigModule
1727
1766
  };
1728
1767
  } catch (error) {
1729
1768
  return {
@@ -2302,14 +2341,14 @@ var baseOpen = async (options) => {
2302
2341
  }
2303
2342
  const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
2304
2343
  if (options.wait) {
2305
- return new Promise((resolve5, reject) => {
2344
+ return new Promise((resolve6, reject) => {
2306
2345
  subprocess.once("error", reject);
2307
2346
  subprocess.once("close", (exitCode) => {
2308
2347
  if (!options.allowNonzeroExitCode && exitCode > 0) {
2309
2348
  reject(new Error(`Exited with code ${exitCode}`));
2310
2349
  return;
2311
2350
  }
2312
- resolve5(subprocess);
2351
+ resolve6(subprocess);
2313
2352
  });
2314
2353
  });
2315
2354
  }
@@ -2426,7 +2465,7 @@ var decorateErrorWithCounts = (error, attemptNumber, options) => {
2426
2465
  return error;
2427
2466
  };
2428
2467
  async function pRetry(input, options) {
2429
- return new Promise((resolve5, reject) => {
2468
+ return new Promise((resolve6, reject) => {
2430
2469
  options = {
2431
2470
  onFailedAttempt() {
2432
2471
  },
@@ -2449,7 +2488,7 @@ async function pRetry(input, options) {
2449
2488
  try {
2450
2489
  const result = await input(attemptNumber);
2451
2490
  cleanUp();
2452
- resolve5(result);
2491
+ resolve6(result);
2453
2492
  } catch (error) {
2454
2493
  try {
2455
2494
  if (!(error instanceof Error)) {
@@ -2572,7 +2611,7 @@ async function whoAmI(options, embedded = false) {
2572
2611
  loadingSpinner.stop(
2573
2612
  `You must login first. Use \`trigger.dev login --profile ${options?.profile ?? "default"}\` to login.`
2574
2613
  );
2575
- outro2("Whoami failed");
2614
+ outro2(`Whoami failed: ${authentication.error}`);
2576
2615
  }
2577
2616
  }
2578
2617
  return {
@@ -3832,6 +3871,46 @@ async function getPackageJson(absoluteProjectPath) {
3832
3871
  return { packageJson, readonlyPackageJson, packageJsonPath };
3833
3872
  }
3834
3873
 
3874
+ // src/utilities/resolveEnvVars.ts
3875
+ async function callResolveEnvVars(configModule, env, environment, projectRef) {
3876
+ if (configModule && configModule.resolveEnvVars && typeof configModule.resolveEnvVars === "function") {
3877
+ let resolvedEnvVars2 = {};
3878
+ try {
3879
+ let result = await configModule.resolveEnvVars({
3880
+ projectRef,
3881
+ environment,
3882
+ env
3883
+ });
3884
+ if (!result) {
3885
+ return;
3886
+ }
3887
+ result = await result;
3888
+ if (typeof result === "object" && result !== null && "variables" in result) {
3889
+ const variables = result.variables;
3890
+ if (Array.isArray(variables)) {
3891
+ for (const item of variables) {
3892
+ if (typeof item === "object" && item !== null && "name" in item && "value" in item && typeof item.name === "string" && typeof item.value === "string") {
3893
+ resolvedEnvVars2[item.name] = item.value;
3894
+ }
3895
+ }
3896
+ } else if (typeof variables === "object") {
3897
+ for (const [key, value] of Object.entries(variables)) {
3898
+ if (typeof key === "string" && typeof value === "string") {
3899
+ resolvedEnvVars2[key] = value;
3900
+ }
3901
+ }
3902
+ }
3903
+ }
3904
+ return {
3905
+ variables: resolvedEnvVars2,
3906
+ override: result.override
3907
+ };
3908
+ } catch (error) {
3909
+ logger.error(error);
3910
+ }
3911
+ }
3912
+ }
3913
+
3835
3914
  // src/commands/deploy.ts
3836
3915
  var DeployCommandOptions = CommonCommandOptions.extend({
3837
3916
  skipTypecheck: z4.boolean().default(false),
@@ -3936,7 +4015,11 @@ async function _deployCommand(dir, options) {
3936
4015
  `Failed to connect to ${authorization.auth?.apiUrl}. Are you sure it's the correct URL?`
3937
4016
  );
3938
4017
  } else {
3939
- throw new Error("You must login first. Use `trigger.dev login` to login.");
4018
+ throw new Error(
4019
+ `You must login first. Use the \`login\` CLI command.
4020
+
4021
+ ${authorization.error}`
4022
+ );
3940
4023
  }
3941
4024
  }
3942
4025
  span?.setAttributes({
@@ -3981,6 +4064,7 @@ async function _deployCommand(dir, options) {
3981
4064
  resolvedConfig.status === "file" ? resolvedConfig.path : void 0
3982
4065
  );
3983
4066
  logger.debug("Compilation result", { compilation });
4067
+ await resolveEnvironmentVariables(resolvedConfig, environmentClient, options);
3984
4068
  const deploymentResponse = await environmentClient.initializeDeployment({
3985
4069
  contentHash: compilation.contentHash,
3986
4070
  userId: authorization.userId
@@ -4295,7 +4379,7 @@ async function failDeploy(shortCode, errorSummary, logs, deploymentSpinner, warn
4295
4379
  outro5(`${chalkError("Error:")} ${errorSummary}.`);
4296
4380
  }
4297
4381
  }
4298
- async function waitForDeploymentToFinish(deploymentId, client, timeoutInSeconds = 60) {
4382
+ async function waitForDeploymentToFinish(deploymentId, client, timeoutInSeconds = 180) {
4299
4383
  return tracer.startActiveSpan("waitForDeploymentToFinish", async (span) => {
4300
4384
  try {
4301
4385
  const start = Date.now();
@@ -4579,7 +4663,9 @@ async function compileProject(config, options, configPath) {
4579
4663
  const workerSetupPath = join6(cliRootPath(), "workers", "prod", "worker-setup.js");
4580
4664
  let workerContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace(
4581
4665
  "__WORKER_SETUP__",
4582
- `import { tracingSDK } from "${escapeImportPath(workerSetupPath)}";`
4666
+ `import { tracingSDK, otelTracer, otelLogger } from "${escapeImportPath(
4667
+ workerSetupPath
4668
+ )}";`
4583
4669
  );
4584
4670
  if (configPath) {
4585
4671
  logger.debug("Importing project config from", { configPath });
@@ -4794,6 +4880,68 @@ If this is unexpected you should check your ${terminalLink2(
4794
4880
  }
4795
4881
  });
4796
4882
  }
4883
+ async function resolveEnvironmentVariables(config, apiClient2, options) {
4884
+ if (config.status !== "file") {
4885
+ return;
4886
+ }
4887
+ if (!config.module || typeof config.module.resolveEnvVars !== "function") {
4888
+ return;
4889
+ }
4890
+ const projectConfig = config.config;
4891
+ return await tracer.startActiveSpan("resolveEnvironmentVariables", async (span) => {
4892
+ try {
4893
+ const $spinner = spinner();
4894
+ $spinner.start("Resolving environment variables");
4895
+ let processEnv = {
4896
+ ...process.env
4897
+ };
4898
+ const environmentVariables = await apiClient2.getEnvironmentVariables(projectConfig.project);
4899
+ if (environmentVariables.success) {
4900
+ processEnv = {
4901
+ ...processEnv,
4902
+ ...environmentVariables.data.variables
4903
+ };
4904
+ }
4905
+ logger.debug("Existing environment variables", {
4906
+ keys: Object.keys(processEnv)
4907
+ });
4908
+ const resolvedEnvVars2 = await callResolveEnvVars(
4909
+ config.module,
4910
+ processEnv,
4911
+ options.env,
4912
+ projectConfig.project
4913
+ );
4914
+ if (resolvedEnvVars2) {
4915
+ const total = Object.keys(resolvedEnvVars2.variables).length;
4916
+ logger.debug("Resolved env vars", {
4917
+ keys: Object.keys(resolvedEnvVars2.variables)
4918
+ });
4919
+ if (total > 0) {
4920
+ $spinner.message(
4921
+ `Syncing ${total} environment variable${total > 1 ? "s" : ""} with the server`
4922
+ );
4923
+ const uploadResult = await apiClient2.importEnvVars(projectConfig.project, options.env, {
4924
+ variables: resolvedEnvVars2.variables,
4925
+ override: typeof resolvedEnvVars2.override === "boolean" ? resolvedEnvVars2.override : true
4926
+ });
4927
+ if (uploadResult.success) {
4928
+ $spinner.stop(`${total} environment variable${total > 1 ? "s" : ""} synced`);
4929
+ } else {
4930
+ $spinner.stop("Failed to sync environment variables");
4931
+ throw new Error(uploadResult.error);
4932
+ }
4933
+ } else {
4934
+ $spinner.stop("No environment variables to sync");
4935
+ }
4936
+ }
4937
+ } catch (e) {
4938
+ recordSpanException5(span, e);
4939
+ throw e;
4940
+ } finally {
4941
+ span.end();
4942
+ }
4943
+ });
4944
+ }
4797
4945
  async function resolveDependencies(projectDir, packageJsonContents, config, options) {
4798
4946
  return await tracer.startActiveSpan("resolveDependencies", async (span) => {
4799
4947
  const resolvingDepsSpinner = spinner();
@@ -4830,10 +4978,29 @@ async function resolveDependencies(projectDir, packageJsonContents, config, opti
4830
4978
  });
4831
4979
  logger.debug(`No cached package-lock.json found for ${digest}`);
4832
4980
  try {
4833
- await execa2("npm", ["install", "--package-lock-only", "--ignore-scripts", "--no-audit"], {
4834
- cwd: projectDir,
4835
- stdio: logger.loggerLevel === "debug" ? "inherit" : "pipe"
4836
- });
4981
+ if (logger.loggerLevel === "debug") {
4982
+ const childProcess2 = await execa2("npm", ["config", "list"], {
4983
+ cwd: projectDir,
4984
+ stdio: "inherit"
4985
+ });
4986
+ logger.debug("npm config list");
4987
+ console.log(childProcess2.stdout);
4988
+ }
4989
+ await execa2(
4990
+ "npm",
4991
+ [
4992
+ "install",
4993
+ "--package-lock-only",
4994
+ "--ignore-scripts",
4995
+ "--no-audit",
4996
+ "--legacy-peer-deps=false",
4997
+ "--strict-peer-deps=false"
4998
+ ],
4999
+ {
5000
+ cwd: projectDir,
5001
+ stdio: logger.loggerLevel === "debug" ? "inherit" : "pipe"
5002
+ }
5003
+ );
4837
5004
  const packageLockContents = await readFile2(join6(projectDir, "package-lock.json"), "utf-8");
4838
5005
  logger.debug(`Writing package-lock.json to cache for ${digest}`);
4839
5006
  await mkdir(cacheDir, { recursive: true });
@@ -4890,8 +5057,8 @@ async function typecheckProject(config, options) {
4890
5057
  tscTypecheck.stdout?.on("data", (chunk) => stdouts.push(chunk.toString()));
4891
5058
  tscTypecheck.stderr?.on("data", (chunk) => stderrs.push(chunk.toString()));
4892
5059
  try {
4893
- await new Promise((resolve5, reject) => {
4894
- tscTypecheck.addListener("exit", (code) => code === 0 ? resolve5(code) : reject(code));
5060
+ await new Promise((resolve6, reject) => {
5061
+ tscTypecheck.addListener("exit", (code) => code === 0 ? resolve6(code) : reject(code));
4895
5062
  });
4896
5063
  } catch (error) {
4897
5064
  typecheckSpinner.stop(
@@ -5123,6 +5290,31 @@ var TaskMetadataParseError = class extends Error {
5123
5290
  this.name = "TaskMetadataParseError";
5124
5291
  }
5125
5292
  };
5293
+ var UnexpectedExitError = class extends Error {
5294
+ constructor(code) {
5295
+ super(`Unexpected exit with code ${code}`);
5296
+ this.code = code;
5297
+ this.name = "UnexpectedExitError";
5298
+ }
5299
+ };
5300
+ var CleanupProcessError = class extends Error {
5301
+ constructor() {
5302
+ super("Cancelled");
5303
+ this.name = "CleanupProcessError";
5304
+ }
5305
+ };
5306
+ var CancelledProcessError = class extends Error {
5307
+ constructor() {
5308
+ super("Cancelled");
5309
+ this.name = "CancelledProcessError";
5310
+ }
5311
+ };
5312
+ var SigKillTimeoutProcessError = class extends Error {
5313
+ constructor() {
5314
+ super("Process kill timeout");
5315
+ this.name = "SigKillTimeoutProcessError";
5316
+ }
5317
+ };
5126
5318
 
5127
5319
  // src/workers/dev/backgroundWorker.ts
5128
5320
  import {
@@ -5137,28 +5329,36 @@ import { ZodMessageHandler, ZodMessageSender } from "@trigger.dev/core/v3/zodMes
5137
5329
  import dotenv from "dotenv";
5138
5330
  import { Evt } from "evt";
5139
5331
  import { fork } from "node:child_process";
5140
- import { dirname as dirname2, resolve as resolve3 } from "node:path";
5332
+ import { dirname as dirname2, resolve as resolve4 } from "node:path";
5141
5333
  import terminalLink3 from "terminal-link";
5142
5334
  var BackgroundWorkerCoordinator = class {
5143
5335
  constructor(baseURL) {
5144
5336
  this.baseURL = baseURL;
5145
- this.onTaskCompleted.attach(async ({ completion, execution }) => {
5337
+ this.onTaskCompleted.attach(async ({ completion }) => {
5146
5338
  if (!completion.ok && typeof completion.retry !== "undefined") {
5147
5339
  return;
5148
5340
  }
5149
- await this.#notifyWorkersOfTaskCompletion(completion, execution);
5341
+ await this.#notifyWorkersOfTaskCompletion(completion);
5342
+ });
5343
+ this.onTaskFailedToRun.attach(async ({ completion }) => {
5344
+ await this.#notifyWorkersOfTaskCompletion(completion);
5150
5345
  });
5151
5346
  }
5152
5347
  onTaskCompleted = new Evt();
5348
+ onTaskFailedToRun = new Evt();
5153
5349
  onWorkerRegistered = new Evt();
5350
+ /**
5351
+ * @deprecated use onWorkerTaskRunHeartbeat instead
5352
+ */
5154
5353
  onWorkerTaskHeartbeat = new Evt();
5354
+ onWorkerTaskRunHeartbeat = new Evt();
5155
5355
  onWorkerDeprecated = new Evt();
5156
5356
  _backgroundWorkers = /* @__PURE__ */ new Map();
5157
5357
  _records = /* @__PURE__ */ new Map();
5158
5358
  _deprecatedWorkers = /* @__PURE__ */ new Set();
5159
- async #notifyWorkersOfTaskCompletion(completion, execution) {
5359
+ async #notifyWorkersOfTaskCompletion(completion) {
5160
5360
  for (const worker of this._backgroundWorkers.values()) {
5161
- await worker.taskRunCompletedNotification(completion, execution);
5361
+ await worker.taskRunCompletedNotification(completion);
5162
5362
  }
5163
5363
  }
5164
5364
  get currentWorkers() {
@@ -5183,6 +5383,9 @@ var BackgroundWorkerCoordinator = class {
5183
5383
  worker.onTaskHeartbeat.attach((id) => {
5184
5384
  this.onWorkerTaskHeartbeat.post({ id, backgroundWorkerId: record.id, worker });
5185
5385
  });
5386
+ worker.onTaskRunHeartbeat.attach((id) => {
5387
+ this.onWorkerTaskRunHeartbeat.post({ id, backgroundWorkerId: record.id, worker });
5388
+ });
5186
5389
  }
5187
5390
  close() {
5188
5391
  for (const worker of this._backgroundWorkers.values()) {
@@ -5205,10 +5408,14 @@ var BackgroundWorkerCoordinator = class {
5205
5408
  return;
5206
5409
  }
5207
5410
  await worker.cancelRun(message.taskRunId);
5411
+ break;
5412
+ }
5413
+ case "EXECUTE_RUN_LAZY_ATTEMPT": {
5414
+ await this.#executeTaskRunLazyAttempt(id, message.payload);
5208
5415
  }
5209
5416
  }
5210
5417
  }
5211
- async #executeTaskRun(id, payload) {
5418
+ async #executeTaskRunLazyAttempt(id, payload) {
5212
5419
  const worker = this._backgroundWorkers.get(id);
5213
5420
  if (!worker) {
5214
5421
  logger.error(`Could not find worker ${id}`);
@@ -5219,103 +5426,89 @@ var BackgroundWorkerCoordinator = class {
5219
5426
  logger.error(`Could not find worker record ${id}`);
5220
5427
  return;
5221
5428
  }
5222
- const { execution } = payload;
5223
- const logsUrl = `${this.baseURL}/runs/${execution.run.id}`;
5224
- const pipe = chalkGrey("|");
5225
- const bullet = chalkGrey("\u25CB");
5226
- const link = chalkLink(terminalLink3("View logs", logsUrl));
5227
- let timestampPrefix = chalkGrey(prettyPrintDate(payload.execution.attempt.startedAt));
5228
- const workerPrefix = chalkWorker(record.version);
5229
- const taskPrefix = chalkTask(execution.task.id);
5230
- const runId = chalkRun(`${execution.run.id}.${execution.attempt.number}`);
5231
- logger.log(
5232
- `${bullet} ${timestampPrefix} ${chalkGrey(
5233
- "->"
5234
- )} ${link} ${pipe} ${workerPrefix} ${pipe} ${taskPrefix} ${pipe} ${runId}`
5235
- );
5236
- const now = performance.now();
5237
- const completion = await worker.executeTaskRun(payload);
5238
- const elapsed = performance.now() - now;
5239
- const retryingText = chalkGrey(
5240
- !completion.ok && completion.skippedRetrying ? " (retrying skipped)" : !completion.ok && completion.retry !== void 0 ? ` (retrying in ${completion.retry.delay}ms)` : ""
5241
- );
5242
- const resultText = !completion.ok ? completion.error.type === "INTERNAL_ERROR" && (completion.error.code === TaskRunErrorCodes.TASK_EXECUTION_ABORTED || completion.error.code === TaskRunErrorCodes.TASK_RUN_CANCELLED) ? chalkWarning("Cancelled") : `${chalkError("Error")}${retryingText}` : chalkSuccess("Success");
5243
- const errorText = !completion.ok ? this.#formatErrorLog(completion.error) : "retry" in completion ? `retry in ${completion.retry}ms` : "";
5244
- const elapsedText = chalkGrey(`(${formatDurationMilliseconds(elapsed, { style: "short" })})`);
5245
- timestampPrefix = chalkGrey(prettyPrintDate());
5246
- logger.log(
5247
- `${bullet} ${timestampPrefix} ${chalkGrey(
5248
- "->"
5249
- )} ${link} ${pipe} ${workerPrefix} ${pipe} ${taskPrefix} ${pipe} ${runId} ${pipe} ${resultText} ${elapsedText}${errorText}`
5250
- );
5251
- this.onTaskCompleted.post({ completion, execution, worker, backgroundWorkerId: id });
5252
- }
5253
- #formatErrorLog(error) {
5254
- switch (error.type) {
5255
- case "INTERNAL_ERROR": {
5256
- return "";
5257
- }
5258
- case "STRING_ERROR": {
5259
- return `
5260
-
5261
- ${chalkError("X Error:")} ${error.raw}
5262
- `;
5263
- }
5264
- case "CUSTOM_ERROR": {
5265
- return `
5266
-
5267
- ${chalkError("X Error:")} ${error.raw}
5268
- `;
5269
- }
5270
- case "BUILT_IN_ERROR": {
5271
- return `
5272
-
5273
- ${error.stackTrace.replace(/^Error: /, chalkError("X Error: "))}
5274
- `;
5275
- }
5429
+ try {
5430
+ const { completion, execution } = await worker.executeTaskRunLazyAttempt(
5431
+ payload,
5432
+ this.baseURL
5433
+ );
5434
+ this.onTaskCompleted.post({
5435
+ completion,
5436
+ execution,
5437
+ worker,
5438
+ backgroundWorkerId: id
5439
+ });
5440
+ } catch (error) {
5441
+ this.onTaskFailedToRun.post({
5442
+ backgroundWorkerId: id,
5443
+ worker,
5444
+ completion: {
5445
+ ok: false,
5446
+ id: payload.runId,
5447
+ retry: void 0,
5448
+ error: error instanceof Error ? {
5449
+ type: "BUILT_IN_ERROR",
5450
+ name: error.name,
5451
+ message: error.message,
5452
+ stackTrace: error.stack ?? ""
5453
+ } : {
5454
+ type: "BUILT_IN_ERROR",
5455
+ name: "UnknownError",
5456
+ message: String(error),
5457
+ stackTrace: ""
5458
+ }
5459
+ }
5460
+ });
5276
5461
  }
5277
5462
  }
5278
- };
5279
- var UnexpectedExitError = class extends Error {
5280
- constructor(code) {
5281
- super(`Unexpected exit with code ${code}`);
5282
- this.code = code;
5283
- this.name = "UnexpectedExitError";
5284
- }
5285
- };
5286
- var CleanupProcessError = class extends Error {
5287
- constructor() {
5288
- super("Cancelled");
5289
- this.name = "CleanupProcessError";
5290
- }
5291
- };
5292
- var CancelledProcessError = class extends Error {
5293
- constructor() {
5294
- super("Cancelled");
5295
- this.name = "CancelledProcessError";
5463
+ async #executeTaskRun(id, payload) {
5464
+ const worker = this._backgroundWorkers.get(id);
5465
+ if (!worker) {
5466
+ logger.error(`Could not find worker ${id}`);
5467
+ return;
5468
+ }
5469
+ const record = this._records.get(id);
5470
+ if (!record) {
5471
+ logger.error(`Could not find worker record ${id}`);
5472
+ return;
5473
+ }
5474
+ const completion = await worker.executeTaskRun(payload, this.baseURL);
5475
+ this.onTaskCompleted.post({
5476
+ completion,
5477
+ execution: payload.execution,
5478
+ worker,
5479
+ backgroundWorkerId: id
5480
+ });
5296
5481
  }
5297
5482
  };
5298
5483
  var BackgroundWorker = class {
5299
- constructor(path7, params) {
5484
+ constructor(path7, params, apiClient2) {
5300
5485
  this.path = path7;
5301
5486
  this.params = params;
5487
+ this.apiClient = apiClient2;
5302
5488
  }
5303
5489
  _initialized = false;
5304
5490
  _handler = new ZodMessageHandler({
5305
5491
  schema: childToWorkerMessages
5306
5492
  });
5493
+ /**
5494
+ * @deprecated use onTaskRunHeartbeat instead
5495
+ */
5307
5496
  onTaskHeartbeat = new Evt();
5497
+ onTaskRunHeartbeat = new Evt();
5308
5498
  _onClose = new Evt();
5309
5499
  tasks = [];
5310
5500
  metadata;
5311
5501
  _taskRunProcesses = /* @__PURE__ */ new Map();
5502
+ _taskRunProcessesBeingKilled = /* @__PURE__ */ new Set();
5312
5503
  _closed = false;
5504
+ _fullEnv = {};
5313
5505
  close() {
5314
5506
  if (this._closed) {
5315
5507
  return;
5316
5508
  }
5317
5509
  this._closed = true;
5318
5510
  this.onTaskHeartbeat.detach();
5511
+ this.onTaskRunHeartbeat.detach();
5319
5512
  for (const taskRunProcess of this._taskRunProcesses.values()) {
5320
5513
  taskRunProcess.cleanup(true);
5321
5514
  }
@@ -5323,6 +5516,9 @@ var BackgroundWorker = class {
5323
5516
  safeDeleteFileSync(this.path);
5324
5517
  safeDeleteFileSync(`${this.path}.map`);
5325
5518
  }
5519
+ get inProgressRuns() {
5520
+ return Array.from(this._taskRunProcesses.keys());
5521
+ }
5326
5522
  async initialize() {
5327
5523
  if (this._initialized) {
5328
5524
  throw new Error("Worker already initialized");
@@ -5332,12 +5528,24 @@ var BackgroundWorker = class {
5332
5528
  }
5333
5529
  let resolved = false;
5334
5530
  const cwd = dirname2(this.path);
5335
- const fullEnv = {
5531
+ this._fullEnv = {
5336
5532
  ...this.params.env,
5337
- ...this.#readEnvVars()
5533
+ ...this.#readEnvVars(),
5534
+ ...this.params.debugOtel ? { OTEL_LOG_LEVEL: "debug" } : {}
5338
5535
  };
5339
- logger.debug("Initializing worker", { path: this.path, cwd, fullEnv });
5340
- this.tasks = await new Promise((resolve5, reject) => {
5536
+ let resolvedEnvVars2 = {};
5537
+ if (this.params.resolveEnvVariables) {
5538
+ const resolvedEnv = await this.params.resolveEnvVariables(this._fullEnv, this);
5539
+ if (resolvedEnv) {
5540
+ resolvedEnvVars2 = resolvedEnv;
5541
+ }
5542
+ }
5543
+ this._fullEnv = {
5544
+ ...this._fullEnv,
5545
+ ...resolvedEnvVars2
5546
+ };
5547
+ logger.debug("Initializing worker", { path: this.path, cwd, fullEnv: this._fullEnv });
5548
+ this.tasks = await new Promise((resolve6, reject) => {
5341
5549
  const child = fork(this.path, {
5342
5550
  stdio: [
5343
5551
  /*stdin*/
@@ -5349,7 +5557,7 @@ var BackgroundWorker = class {
5349
5557
  "ipc"
5350
5558
  ],
5351
5559
  cwd,
5352
- env: fullEnv
5560
+ env: this._fullEnv
5353
5561
  });
5354
5562
  const timeout = setTimeout(() => {
5355
5563
  if (resolved) {
@@ -5364,7 +5572,7 @@ var BackgroundWorker = class {
5364
5572
  if (message.type === "TASKS_READY" && !resolved) {
5365
5573
  clearTimeout(timeout);
5366
5574
  resolved = true;
5367
- resolve5(message.payload.tasks);
5575
+ resolve6(message.payload.tasks);
5368
5576
  child.kill();
5369
5577
  } else if (message.type === "UNCAUGHT_EXCEPTION") {
5370
5578
  clearTimeout(timeout);
@@ -5393,37 +5601,105 @@ var BackgroundWorker = class {
5393
5601
  }
5394
5602
  // We need to notify all the task run processes that a task run has completed,
5395
5603
  // in case they are waiting for it through triggerAndWait
5396
- async taskRunCompletedNotification(completion, execution) {
5604
+ async taskRunCompletedNotification(completion) {
5397
5605
  for (const taskRunProcess of this._taskRunProcesses.values()) {
5398
- taskRunProcess.taskRunCompletedNotification(completion, execution);
5606
+ taskRunProcess.taskRunCompletedNotification(completion);
5399
5607
  }
5400
5608
  }
5401
- async #initializeTaskRunProcess(payload) {
5609
+ #prefixedMessage(payload, message = "") {
5610
+ return `[${payload.execution.run.id}.${payload.execution.attempt.number}] ${message}`;
5611
+ }
5612
+ async #getFreshTaskRunProcess(payload, messageId) {
5613
+ logger.debug(this.#prefixedMessage(payload, "getFreshTaskRunProcess()"));
5402
5614
  if (!this.metadata) {
5403
5615
  throw new Error("Worker not registered");
5404
5616
  }
5405
- if (!this._taskRunProcesses.has(payload.execution.run.id)) {
5406
- const taskRunProcess = new TaskRunProcess(
5407
- payload.execution,
5408
- this.path,
5409
- {
5410
- ...this.params.env,
5411
- ...payload.environment ?? {},
5412
- ...this.#readEnvVars()
5413
- },
5414
- this.metadata,
5415
- this.params
5416
- );
5417
- taskRunProcess.onExit.attach(() => {
5617
+ this._closed = false;
5618
+ logger.debug(this.#prefixedMessage(payload, "killing current task run process before attempt"));
5619
+ await this.#killCurrentTaskRunProcessBeforeAttempt(payload.execution.run.id);
5620
+ logger.debug(this.#prefixedMessage(payload, "creating new task run process"));
5621
+ const taskRunProcess = new TaskRunProcess(
5622
+ payload.execution.run.id,
5623
+ payload.execution.run.isTest,
5624
+ this.path,
5625
+ {
5626
+ ...this._fullEnv,
5627
+ ...payload.environment ?? {},
5628
+ ...this.#readEnvVars()
5629
+ },
5630
+ this.metadata,
5631
+ this.params,
5632
+ messageId
5633
+ );
5634
+ taskRunProcess.onExit.attach(({ pid }) => {
5635
+ logger.debug(this.#prefixedMessage(payload, "onExit()"), { pid });
5636
+ const taskRunProcess2 = this._taskRunProcesses.get(payload.execution.run.id);
5637
+ if (taskRunProcess2?.pid === pid) {
5418
5638
  this._taskRunProcesses.delete(payload.execution.run.id);
5419
- });
5420
- taskRunProcess.onTaskHeartbeat.attach((id) => {
5421
- this.onTaskHeartbeat.post(id);
5422
- });
5423
- await taskRunProcess.initialize();
5424
- this._taskRunProcesses.set(payload.execution.run.id, taskRunProcess);
5639
+ }
5640
+ if (pid) {
5641
+ this._taskRunProcessesBeingKilled.delete(pid);
5642
+ }
5643
+ });
5644
+ taskRunProcess.onIsBeingKilled.attach((pid) => {
5645
+ if (pid) {
5646
+ this._taskRunProcessesBeingKilled.add(pid);
5647
+ }
5648
+ });
5649
+ taskRunProcess.onTaskHeartbeat.attach((id) => {
5650
+ this.onTaskHeartbeat.post(id);
5651
+ });
5652
+ taskRunProcess.onTaskRunHeartbeat.attach((id) => {
5653
+ this.onTaskRunHeartbeat.post(id);
5654
+ });
5655
+ await taskRunProcess.initialize();
5656
+ this._taskRunProcesses.set(payload.execution.run.id, taskRunProcess);
5657
+ return taskRunProcess;
5658
+ }
5659
+ async #killCurrentTaskRunProcessBeforeAttempt(runId) {
5660
+ const taskRunProcess = this._taskRunProcesses.get(runId);
5661
+ if (!taskRunProcess) {
5662
+ logger.debug(`[${runId}] no current task process to kill`);
5663
+ return;
5664
+ }
5665
+ logger.debug(`[${runId}] killing current task process`, {
5666
+ pid: taskRunProcess.pid
5667
+ });
5668
+ if (taskRunProcess.isBeingKilled) {
5669
+ if (this._taskRunProcessesBeingKilled.size > 1) {
5670
+ await this.#tryGracefulExit(taskRunProcess);
5671
+ } else {
5672
+ }
5673
+ } else {
5674
+ if (this._taskRunProcessesBeingKilled.size > 0) {
5675
+ await this.#tryGracefulExit(taskRunProcess);
5676
+ } else {
5677
+ taskRunProcess.kill("SIGTERM", 5e3).catch(() => {
5678
+ });
5679
+ }
5680
+ }
5681
+ }
5682
+ async #tryGracefulExit(taskRunProcess, kill = false, initialSignal = "SIGTERM") {
5683
+ try {
5684
+ const initialExit = taskRunProcess.onExit.waitFor(5e3);
5685
+ if (kill) {
5686
+ taskRunProcess.kill(initialSignal);
5687
+ }
5688
+ await initialExit;
5689
+ } catch (error) {
5690
+ logger.error("TaskRunProcess graceful kill timeout exceeded", error);
5691
+ this.#tryForcefulExit(taskRunProcess);
5692
+ }
5693
+ }
5694
+ async #tryForcefulExit(taskRunProcess) {
5695
+ try {
5696
+ const forcedKill = taskRunProcess.onExit.waitFor(5e3);
5697
+ taskRunProcess.kill("SIGKILL");
5698
+ await forcedKill;
5699
+ } catch (error) {
5700
+ logger.error("TaskRunProcess forced kill timeout exceeded", error);
5701
+ throw new SigKillTimeoutProcessError();
5425
5702
  }
5426
- return this._taskRunProcesses.get(payload.execution.run.id);
5427
5703
  }
5428
5704
  async cancelRun(taskRunId) {
5429
5705
  const taskRunProcess = this._taskRunProcesses.get(taskRunId);
@@ -5432,12 +5708,66 @@ var BackgroundWorker = class {
5432
5708
  }
5433
5709
  await taskRunProcess.cancel();
5434
5710
  }
5711
+ async executeTaskRunLazyAttempt(payload, baseURL) {
5712
+ const attemptResponse = await this.apiClient.createTaskRunAttempt(payload.runId);
5713
+ if (!attemptResponse.success) {
5714
+ throw new Error(`Failed to create task run attempt: ${attemptResponse.error}`);
5715
+ }
5716
+ const execution = attemptResponse.data;
5717
+ const completion = await this.executeTaskRun(
5718
+ { execution, traceContext: payload.traceContext, environment: payload.environment },
5719
+ baseURL,
5720
+ payload.messageId
5721
+ );
5722
+ return { execution, completion };
5723
+ }
5435
5724
  // We need to fork the process before we can execute any tasks
5436
- async executeTaskRun(payload) {
5725
+ async executeTaskRun(payload, baseURL, messageId) {
5726
+ if (this._closed) {
5727
+ throw new Error("Worker is closed");
5728
+ }
5729
+ if (!this.metadata) {
5730
+ throw new Error("Worker not registered");
5731
+ }
5732
+ const { execution } = payload;
5733
+ const logsUrl = `${baseURL}/runs/${execution.run.id}`;
5734
+ const pipe = chalkGrey("|");
5735
+ const bullet = chalkGrey("\u25CB");
5736
+ const link = chalkLink(terminalLink3("View logs", logsUrl));
5737
+ let timestampPrefix = chalkGrey(prettyPrintDate(payload.execution.attempt.startedAt));
5738
+ const workerPrefix = chalkWorker(this.metadata.version);
5739
+ const taskPrefix = chalkTask(execution.task.id);
5740
+ const runId = chalkRun(`${execution.run.id}.${execution.attempt.number}`);
5741
+ logger.log(
5742
+ `${bullet} ${timestampPrefix} ${chalkGrey(
5743
+ "->"
5744
+ )} ${link} ${pipe} ${workerPrefix} ${pipe} ${taskPrefix} ${pipe} ${runId}`
5745
+ );
5746
+ const now = performance.now();
5747
+ const completion = await this.#doExecuteTaskRun(payload, messageId);
5748
+ const elapsed = performance.now() - now;
5749
+ const retryingText = chalkGrey(
5750
+ !completion.ok && completion.skippedRetrying ? " (retrying skipped)" : !completion.ok && completion.retry !== void 0 ? ` (retrying in ${completion.retry.delay}ms)` : ""
5751
+ );
5752
+ const resultText = !completion.ok ? completion.error.type === "INTERNAL_ERROR" && (completion.error.code === TaskRunErrorCodes.TASK_EXECUTION_ABORTED || completion.error.code === TaskRunErrorCodes.TASK_RUN_CANCELLED) ? chalkWarning("Cancelled") : `${chalkError("Error")}${retryingText}` : chalkSuccess("Success");
5753
+ const errorText = !completion.ok ? formatErrorLog(completion.error) : "retry" in completion ? `retry in ${completion.retry}ms` : "";
5754
+ const elapsedText = chalkGrey(`(${formatDurationMilliseconds(elapsed, { style: "short" })})`);
5755
+ timestampPrefix = chalkGrey(prettyPrintDate());
5756
+ logger.log(
5757
+ `${bullet} ${timestampPrefix} ${chalkGrey(
5758
+ "->"
5759
+ )} ${link} ${pipe} ${workerPrefix} ${pipe} ${taskPrefix} ${pipe} ${runId} ${pipe} ${resultText} ${elapsedText}${errorText}`
5760
+ );
5761
+ return completion;
5762
+ }
5763
+ async #doExecuteTaskRun(payload, messageId) {
5437
5764
  try {
5438
- const taskRunProcess = await this.#initializeTaskRunProcess(payload);
5765
+ const taskRunProcess = await this.#getFreshTaskRunProcess(payload, messageId);
5766
+ logger.debug(this.#prefixedMessage(payload, "executing task run"), {
5767
+ pid: taskRunProcess.pid
5768
+ });
5439
5769
  const result = await taskRunProcess.executeTaskRun(payload);
5440
- await taskRunProcess.cleanup(result.ok || result.retry === void 0);
5770
+ await taskRunProcess.cleanup(true);
5441
5771
  if (result.ok) {
5442
5772
  return result;
5443
5773
  }
@@ -5499,7 +5829,7 @@ var BackgroundWorker = class {
5499
5829
  const result = {};
5500
5830
  dotenv.config({
5501
5831
  processEnv: result,
5502
- path: [".env", ".env.local", ".env.development.local"].map((p) => resolve3(process.cwd(), p))
5832
+ path: [".env", ".env.local", ".env.development.local"].map((p) => resolve4(process.cwd(), p))
5503
5833
  });
5504
5834
  process.env.TRIGGER_API_URL && (result.TRIGGER_API_URL = process.env.TRIGGER_API_URL);
5505
5835
  delete result.TRIGGER_API_URL;
@@ -5514,12 +5844,14 @@ var BackgroundWorker = class {
5514
5844
  }
5515
5845
  };
5516
5846
  var TaskRunProcess = class {
5517
- constructor(execution, path7, env, metadata, worker) {
5518
- this.execution = execution;
5847
+ constructor(runId, isTest, path7, env, metadata, worker, messageId) {
5848
+ this.runId = runId;
5849
+ this.isTest = isTest;
5519
5850
  this.path = path7;
5520
5851
  this.env = env;
5521
5852
  this.metadata = metadata;
5522
5853
  this.worker = worker;
5854
+ this.messageId = messageId;
5523
5855
  this._sender = new ZodMessageSender({
5524
5856
  schema: workerToChildMessages,
5525
5857
  sender: async (message) => {
@@ -5534,20 +5866,26 @@ var TaskRunProcess = class {
5534
5866
  });
5535
5867
  _sender;
5536
5868
  _child;
5869
+ _childPid;
5537
5870
  _attemptPromises = /* @__PURE__ */ new Map();
5538
5871
  _attemptStatuses = /* @__PURE__ */ new Map();
5539
5872
  _currentExecution;
5540
5873
  _isBeingKilled = false;
5541
5874
  _isBeingCancelled = false;
5875
+ /**
5876
+ * @deprecated use onTaskRunHeartbeat instead
5877
+ */
5542
5878
  onTaskHeartbeat = new Evt();
5879
+ onTaskRunHeartbeat = new Evt();
5543
5880
  onExit = new Evt();
5881
+ onIsBeingKilled = new Evt();
5544
5882
  async cancel() {
5545
5883
  this._isBeingCancelled = true;
5546
5884
  await this.cleanup(true);
5547
5885
  }
5548
5886
  async initialize() {
5549
5887
  const fullEnv = {
5550
- ...this.execution.run.isTest ? { TRIGGER_LOG_LEVEL: "debug" } : {},
5888
+ ...this.isTest ? { TRIGGER_LOG_LEVEL: "debug" } : {},
5551
5889
  ...this.env,
5552
5890
  OTEL_RESOURCE_ATTRIBUTES: JSON.stringify({
5553
5891
  [SemanticInternalAttributes.PROJECT_DIR]: this.worker.projectConfig.projectDir
@@ -5556,7 +5894,7 @@ var TaskRunProcess = class {
5556
5894
  ...this.worker.debugOtel ? { OTEL_LOG_LEVEL: "debug" } : {}
5557
5895
  };
5558
5896
  const cwd = dirname2(this.path);
5559
- logger.debug(`[${this.execution.run.id}] initializing task run process`, {
5897
+ logger.debug(`[${this.runId}] initializing task run process`, {
5560
5898
  env: fullEnv,
5561
5899
  path: this.path,
5562
5900
  cwd
@@ -5575,6 +5913,7 @@ var TaskRunProcess = class {
5575
5913
  env: fullEnv,
5576
5914
  execArgv: this.worker.debuggerOn ? ["--inspect-brk", "--trace-uncaught", "--no-warnings=ExperimentalWarning"] : ["--trace-uncaught", "--no-warnings=ExperimentalWarning"]
5577
5915
  });
5916
+ this._childPid = this._child?.pid;
5578
5917
  this._child.on("message", this.#handleMessage.bind(this));
5579
5918
  this._child.on("exit", this.#handleExit.bind(this));
5580
5919
  this._child.stdout?.on("data", this.#handleLog.bind(this));
@@ -5584,15 +5923,21 @@ var TaskRunProcess = class {
5584
5923
  if (kill && this._isBeingKilled) {
5585
5924
  return;
5586
5925
  }
5587
- logger.debug(`[${this.execution.run.id}] cleaning up task run process`, { kill });
5926
+ if (kill) {
5927
+ this._isBeingKilled = true;
5928
+ this.onIsBeingKilled.post(this._child?.pid);
5929
+ }
5930
+ logger.debug(`[${this.runId}] cleaning up task run process`, { kill, pid: this.pid });
5588
5931
  await this._sender.send("CLEANUP", {
5589
5932
  flush: true,
5590
5933
  kill
5591
5934
  });
5592
- this._isBeingKilled = kill;
5935
+ if (!kill) {
5936
+ return;
5937
+ }
5593
5938
  setTimeout(() => {
5594
5939
  if (this._child && !this._child.killed) {
5595
- logger.debug(`[${this.execution.run.id}] killing task run process after timeout`);
5940
+ logger.debug(`[${this.runId}] killing task run process after timeout`, { pid: this.pid });
5596
5941
  this._child.kill();
5597
5942
  }
5598
5943
  }, 5e3);
@@ -5600,8 +5945,8 @@ var TaskRunProcess = class {
5600
5945
  async executeTaskRun(payload) {
5601
5946
  let resolver;
5602
5947
  let rejecter;
5603
- const promise = new Promise((resolve5, reject) => {
5604
- resolver = resolve5;
5948
+ const promise = new Promise((resolve6, reject) => {
5949
+ resolver = resolve6;
5605
5950
  rejecter = reject;
5606
5951
  });
5607
5952
  this._attemptStatuses.set(payload.execution.attempt.id, "PENDING");
@@ -5617,20 +5962,19 @@ var TaskRunProcess = class {
5617
5962
  this._currentExecution = void 0;
5618
5963
  return result;
5619
5964
  }
5620
- taskRunCompletedNotification(completion, execution) {
5965
+ taskRunCompletedNotification(completion) {
5621
5966
  if (!completion.ok && typeof completion.retry !== "undefined") {
5622
5967
  return;
5623
5968
  }
5624
- if (execution.run.id === this.execution.run.id) {
5969
+ if (completion.id === this.runId) {
5625
5970
  return;
5626
5971
  }
5627
- logger.debug(`[${this.execution.run.id}] task run completed notification`, {
5628
- completion,
5629
- execution
5972
+ logger.debug(`[${this.runId}] task run completed notification`, {
5973
+ completion
5630
5974
  });
5631
5975
  this._sender.send("TASK_RUN_COMPLETED_NOTIFICATION", {
5632
- completion,
5633
- execution
5976
+ version: "v2",
5977
+ completion
5634
5978
  });
5635
5979
  }
5636
5980
  async #handleMessage(msg) {
@@ -5652,12 +5996,16 @@ var TaskRunProcess = class {
5652
5996
  break;
5653
5997
  }
5654
5998
  case "READY_TO_DISPOSE": {
5655
- logger.debug(`[${this.execution.run.id}] task run process is ready to dispose`);
5999
+ logger.debug(`[${this.runId}] task run process is ready to dispose`);
5656
6000
  this.#kill();
5657
6001
  break;
5658
6002
  }
5659
6003
  case "TASK_HEARTBEAT": {
5660
- this.onTaskHeartbeat.post(message.payload.id);
6004
+ if (this.messageId) {
6005
+ this.onTaskRunHeartbeat.post(this.messageId);
6006
+ } else {
6007
+ this.onTaskHeartbeat.post(message.payload.id);
6008
+ }
5661
6009
  break;
5662
6010
  }
5663
6011
  case "TASKS_READY": {
@@ -5665,8 +6013,8 @@ var TaskRunProcess = class {
5665
6013
  }
5666
6014
  }
5667
6015
  }
5668
- async #handleExit(code) {
5669
- logger.debug(`[${this.execution.run.id}] task run process exiting`, { code });
6016
+ async #handleExit(code, signal) {
6017
+ logger.debug(`[${this.runId}] handle task run process exit`, { code, signal, pid: this.pid });
5670
6018
  for (const [id, status] of this._attemptStatuses.entries()) {
5671
6019
  if (status === "PENDING") {
5672
6020
  this._attemptStatuses.set(id, "REJECTED");
@@ -5680,11 +6028,11 @@ var TaskRunProcess = class {
5680
6028
  } else if (this._isBeingKilled) {
5681
6029
  rejecter(new CleanupProcessError());
5682
6030
  } else {
5683
- rejecter(new UnexpectedExitError(code));
6031
+ rejecter(new UnexpectedExitError(code ?? -1));
5684
6032
  }
5685
6033
  }
5686
6034
  }
5687
- this.onExit.post(code);
6035
+ this.onExit.post({ code, signal, pid: this.pid });
5688
6036
  }
5689
6037
  #handleLog(data) {
5690
6038
  if (!this._currentExecution) {
@@ -5714,12 +6062,57 @@ var TaskRunProcess = class {
5714
6062
  );
5715
6063
  }
5716
6064
  #kill() {
6065
+ logger.debug(`[${this.runId}] #kill()`, { pid: this.pid });
5717
6066
  if (this._child && !this._child.killed) {
5718
- logger.debug(`[${this.execution.run.id}] killing task run process`);
5719
6067
  this._child?.kill();
5720
6068
  }
5721
6069
  }
6070
+ async kill(signal, timeoutInMs) {
6071
+ logger.debug(`[${this.runId}] killing task run process`, {
6072
+ signal,
6073
+ timeoutInMs,
6074
+ pid: this.pid
6075
+ });
6076
+ this._isBeingKilled = true;
6077
+ const killTimeout = this.onExit.waitFor(timeoutInMs);
6078
+ this.onIsBeingKilled.post(this._child?.pid);
6079
+ this._child?.kill(signal);
6080
+ if (timeoutInMs) {
6081
+ await killTimeout;
6082
+ }
6083
+ }
6084
+ get isBeingKilled() {
6085
+ return this._isBeingKilled || this._child?.killed;
6086
+ }
6087
+ get pid() {
6088
+ return this._childPid;
6089
+ }
5722
6090
  };
6091
+ function formatErrorLog(error) {
6092
+ switch (error.type) {
6093
+ case "INTERNAL_ERROR": {
6094
+ return "";
6095
+ }
6096
+ case "STRING_ERROR": {
6097
+ return `
6098
+
6099
+ ${chalkError("X Error:")} ${error.raw}
6100
+ `;
6101
+ }
6102
+ case "CUSTOM_ERROR": {
6103
+ return `
6104
+
6105
+ ${chalkError("X Error:")} ${error.raw}
6106
+ `;
6107
+ }
6108
+ case "BUILT_IN_ERROR": {
6109
+ return `
6110
+
6111
+ ${error.stackTrace.replace(/^Error: /, chalkError("X Error: "))}
6112
+ `;
6113
+ }
6114
+ }
6115
+ }
5723
6116
 
5724
6117
  // src/utilities/runtimeCheck.ts
5725
6118
  function runtimeCheck(minimumMajor, minimumMinor) {
@@ -5782,7 +6175,11 @@ async function devCommand(dir, options) {
5782
6175
  )} Connecting to the server failed. Please check your internet connection or contact eric@trigger.dev for help.`
5783
6176
  );
5784
6177
  } else {
5785
- logger.log(`${chalkError("X Error:")} You must login first. Use the \`login\` CLI command.`);
6178
+ logger.log(
6179
+ `${chalkError("X Error:")} You must login first. Use the \`login\` CLI command.
6180
+
6181
+ ${authorization.error}`
6182
+ );
5786
6183
  }
5787
6184
  process.exitCode = 1;
5788
6185
  return;
@@ -5813,7 +6210,7 @@ async function startDev(dir, options, authorization, dashboardUrl) {
5813
6210
  logger.error("Failed to read config", config.error);
5814
6211
  process.exit(1);
5815
6212
  }
5816
- async function getDevReactElement(configParam, authorization2, configPath) {
6213
+ async function getDevReactElement(configParam, authorization2, configPath, configModule) {
5817
6214
  const accessToken = authorization2.accessToken;
5818
6215
  const apiUrl = authorization2.apiUrl;
5819
6216
  apiClient = new CliApiClient(apiUrl, accessToken);
@@ -5845,7 +6242,8 @@ async function startDev(dir, options, authorization, dashboardUrl) {
5845
6242
  projectName: devEnv.data.name,
5846
6243
  debuggerOn: options.debugger,
5847
6244
  debugOtel: options.debugOtel,
5848
- configPath
6245
+ configPath,
6246
+ configModule
5849
6247
  }
5850
6248
  );
5851
6249
  }
@@ -5853,7 +6251,8 @@ async function startDev(dir, options, authorization, dashboardUrl) {
5853
6251
  await getDevReactElement(
5854
6252
  config.config,
5855
6253
  authorization,
5856
- config.status === "file" ? config.path : void 0
6254
+ config.status === "file" ? config.path : void 0,
6255
+ config.status === "file" ? config.module : void 0
5857
6256
  )
5858
6257
  );
5859
6258
  rerender = devReactElement.rerender;
@@ -5876,7 +6275,8 @@ function useDev({
5876
6275
  projectName,
5877
6276
  debuggerOn,
5878
6277
  debugOtel,
5879
- configPath
6278
+ configPath,
6279
+ configModule
5880
6280
  }) {
5881
6281
  useEffect(() => {
5882
6282
  const websocketUrl = new URL(apiUrl);
@@ -5918,6 +6318,17 @@ function useDev({
5918
6318
  });
5919
6319
  }
5920
6320
  );
6321
+ backgroundWorkerCoordinator.onWorkerTaskRunHeartbeat.attach(
6322
+ async ({ worker, backgroundWorkerId, id }) => {
6323
+ await sender.send("BACKGROUND_WORKER_MESSAGE", {
6324
+ backgroundWorkerId,
6325
+ data: {
6326
+ type: "TASK_RUN_HEARTBEAT",
6327
+ id
6328
+ }
6329
+ });
6330
+ }
6331
+ );
5921
6332
  backgroundWorkerCoordinator.onTaskCompleted.attach(
5922
6333
  async ({ backgroundWorkerId, completion, execution }) => {
5923
6334
  await sender.send("BACKGROUND_WORKER_MESSAGE", {
@@ -5930,6 +6341,17 @@ function useDev({
5930
6341
  });
5931
6342
  }
5932
6343
  );
6344
+ backgroundWorkerCoordinator.onTaskFailedToRun.attach(
6345
+ async ({ backgroundWorkerId, completion }) => {
6346
+ await sender.send("BACKGROUND_WORKER_MESSAGE", {
6347
+ backgroundWorkerId,
6348
+ data: {
6349
+ type: "TASK_RUN_FAILED_TO_RUN",
6350
+ completion
6351
+ }
6352
+ });
6353
+ }
6354
+ );
5933
6355
  backgroundWorkerCoordinator.onWorkerRegistered.attach(async ({ id, worker, record }) => {
5934
6356
  await sender.send("READY_FOR_TASKS", {
5935
6357
  backgroundWorkerId: id
@@ -5950,7 +6372,8 @@ function useDev({
5950
6372
  SERVER_READY: async (payload) => {
5951
6373
  for (const worker of backgroundWorkerCoordinator.currentWorkers) {
5952
6374
  await sender.send("READY_FOR_TASKS", {
5953
- backgroundWorkerId: worker.id
6375
+ backgroundWorkerId: worker.id,
6376
+ inProgressRuns: worker.worker.inProgressRuns
5954
6377
  });
5955
6378
  }
5956
6379
  },
@@ -5965,6 +6388,7 @@ function useDev({
5965
6388
  await messageHandler.handleMessage(data);
5966
6389
  });
5967
6390
  let ctx;
6391
+ let firstBuild = true;
5968
6392
  async function runBuild() {
5969
6393
  if (ctx) {
5970
6394
  await ctx.dispose();
@@ -5976,7 +6400,9 @@ function useDev({
5976
6400
  const workerSetupPath = join7(cliRootPath(), "workers", "dev", "worker-setup.js");
5977
6401
  let entryPointContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace(
5978
6402
  "__WORKER_SETUP__",
5979
- `import { tracingSDK, sender } from "${escapeImportPath(workerSetupPath)}";`
6403
+ `import { tracingSDK, otelTracer, otelLogger, sender } from "${escapeImportPath(
6404
+ workerSetupPath
6405
+ )}";`
5980
6406
  );
5981
6407
  if (configPath) {
5982
6408
  configPath = normalize(configPath);
@@ -5993,7 +6419,6 @@ function useDev({
5993
6419
  `const importedConfig = undefined; const handleError = undefined;`
5994
6420
  );
5995
6421
  }
5996
- let firstBuild = true;
5997
6422
  logger.log(chalkGrey("\u25CB Building background worker\u2026"));
5998
6423
  ctx = await context2({
5999
6424
  stdin: {
@@ -6084,18 +6509,23 @@ function useDev({
6084
6509
  }
6085
6510
  const environmentVariablesResponse = await environmentClient.getEnvironmentVariables(config.project);
6086
6511
  const processEnv = await gatherProcessEnv();
6087
- const backgroundWorker = new BackgroundWorker(fullPath, {
6088
- projectConfig: config,
6089
- dependencies: dependencies2,
6090
- env: {
6091
- ...processEnv,
6092
- TRIGGER_API_URL: apiUrl,
6093
- TRIGGER_SECRET_KEY: apiKey,
6094
- ...environmentVariablesResponse.success ? environmentVariablesResponse.data.variables : {}
6512
+ const backgroundWorker = new BackgroundWorker(
6513
+ fullPath,
6514
+ {
6515
+ projectConfig: config,
6516
+ dependencies: dependencies2,
6517
+ env: {
6518
+ ...processEnv,
6519
+ TRIGGER_API_URL: apiUrl,
6520
+ TRIGGER_SECRET_KEY: apiKey,
6521
+ ...environmentVariablesResponse.success ? environmentVariablesResponse.data.variables : {}
6522
+ },
6523
+ debuggerOn,
6524
+ debugOtel,
6525
+ resolveEnvVariables: createResolveEnvironmentVariablesFunction(configModule)
6095
6526
  },
6096
- debuggerOn,
6097
- debugOtel
6098
- });
6527
+ environmentClient
6528
+ );
6099
6529
  try {
6100
6530
  await backgroundWorker.initialize();
6101
6531
  latestWorkerContentHash = contentHash;
@@ -6138,7 +6568,8 @@ function useDev({
6138
6568
  cliPackageVersion: version,
6139
6569
  tasks: taskResources,
6140
6570
  contentHash
6141
- }
6571
+ },
6572
+ supportsLazyAttempts: true
6142
6573
  };
6143
6574
  const backgroundWorkerRecord = await environmentClient.createBackgroundWorker(
6144
6575
  config.project,
@@ -6326,18 +6757,9 @@ ${task.filePath} -> ${task.exportName}`).join("")}`;
6326
6757
  }
6327
6758
  async function gatherProcessEnv() {
6328
6759
  const env = {
6760
+ ...process.env,
6329
6761
  NODE_ENV: process.env.NODE_ENV ?? "development",
6330
- PATH: process.env.PATH,
6331
- USER: process.env.USER,
6332
- SHELL: process.env.SHELL,
6333
- NVM_INC: process.env.NVM_INC,
6334
- NVM_DIR: process.env.NVM_DIR,
6335
- NVM_BIN: process.env.NVM_BIN,
6336
- LANG: process.env.LANG,
6337
- TERM: process.env.TERM,
6338
- NODE_PATH: await amendNodePathWithPnpmNodeModules(process.env.NODE_PATH),
6339
- HOME: process.env.HOME,
6340
- BUN_INSTALL: process.env.BUN_INSTALL
6762
+ NODE_PATH: await amendNodePathWithPnpmNodeModules(process.env.NODE_PATH)
6341
6763
  };
6342
6764
  return Object.fromEntries(Object.entries(env).filter(([key, value]) => value !== void 0));
6343
6765
  }
@@ -6366,6 +6788,26 @@ async function findPnpmNodeModulesPath() {
6366
6788
  { type: "directory" }
6367
6789
  );
6368
6790
  }
6791
+ var hasResolvedEnvVars = false;
6792
+ var resolvedEnvVars = {};
6793
+ function createResolveEnvironmentVariablesFunction(configModule) {
6794
+ return async (env, worker) => {
6795
+ if (hasResolvedEnvVars) {
6796
+ return resolvedEnvVars;
6797
+ }
6798
+ const $resolvedEnvVars = await callResolveEnvVars(
6799
+ configModule,
6800
+ env,
6801
+ "dev",
6802
+ worker.params.projectConfig.project
6803
+ );
6804
+ if ($resolvedEnvVars) {
6805
+ resolvedEnvVars = $resolvedEnvVars.variables;
6806
+ hasResolvedEnvVars = true;
6807
+ }
6808
+ return resolvedEnvVars;
6809
+ };
6810
+ }
6369
6811
 
6370
6812
  // src/commands/init.ts
6371
6813
  import { intro as intro5, isCancel as isCancel2, log as log6, outro as outro6, select as select2, text } from "@clack/prompts";
@@ -6374,9 +6816,9 @@ import { flattenAttributes as flattenAttributes4 } from "@trigger.dev/core/v3";
6374
6816
  import { recordSpanException as recordSpanException6 } from "@trigger.dev/core/v3/workers";
6375
6817
  import chalk5 from "chalk";
6376
6818
  import { execa as execa3 } from "execa";
6377
- import { applyEdits, modify } from "jsonc-parser";
6819
+ import { applyEdits, modify, findNodeAtLocation, parseTree, getNodeValue } from "jsonc-parser";
6378
6820
  import { writeFile as writeFile3 } from "node:fs/promises";
6379
- import { join as join8, relative as relative4, resolve as resolve4 } from "node:path";
6821
+ import { join as join8, relative as relative4, resolve as resolve5 } from "node:path";
6380
6822
  import terminalLink4 from "terminal-link";
6381
6823
  import { z as z6 } from "zod";
6382
6824
 
@@ -6541,7 +6983,7 @@ async function createTriggerDir(dir, options) {
6541
6983
  if (isCancel2(location)) {
6542
6984
  throw new OutroCommandError();
6543
6985
  }
6544
- const triggerDir = resolve4(process.cwd(), location);
6986
+ const triggerDir = resolve5(process.cwd(), location);
6545
6987
  logger.debug({ triggerDir });
6546
6988
  span.setAttributes({
6547
6989
  "cli.triggerDir": triggerDir
@@ -6596,7 +7038,7 @@ async function createTriggerDir(dir, options) {
6596
7038
  async function gitIgnoreDotTriggerDir(dir, options) {
6597
7039
  return await tracer.startActiveSpan("gitIgnoreDotTriggerDir", async (span) => {
6598
7040
  try {
6599
- const projectDir = resolve4(process.cwd(), dir);
7041
+ const projectDir = resolve5(process.cwd(), dir);
6600
7042
  const gitIgnorePath = join8(projectDir, ".gitignore");
6601
7043
  span.setAttributes({
6602
7044
  "cli.projectDir": projectDir,
@@ -6630,14 +7072,30 @@ async function gitIgnoreDotTriggerDir(dir, options) {
6630
7072
  async function addConfigFileToTsConfig(dir, options) {
6631
7073
  return await tracer.startActiveSpan("createTriggerDir", async (span) => {
6632
7074
  try {
6633
- const projectDir = resolve4(process.cwd(), dir);
7075
+ const projectDir = resolve5(process.cwd(), dir);
6634
7076
  const tsconfigPath = join8(projectDir, "tsconfig.json");
6635
7077
  span.setAttributes({
6636
7078
  "cli.projectDir": projectDir,
6637
7079
  "cli.tsconfigPath": tsconfigPath
6638
7080
  });
6639
7081
  const tsconfigContent = await readFile(tsconfigPath);
6640
- const edits = modify(tsconfigContent, ["include", -1], "trigger.config.ts", {
7082
+ const tsconfigContentTree = parseTree(tsconfigContent, void 0);
7083
+ if (!tsconfigContentTree) {
7084
+ span.end();
7085
+ return;
7086
+ }
7087
+ const tsconfigIncludeOption = findNodeAtLocation(tsconfigContentTree, ["include"]);
7088
+ if (!tsconfigIncludeOption) {
7089
+ span.end();
7090
+ return;
7091
+ }
7092
+ const tsConfigFileName = "trigger.config.ts";
7093
+ const tsconfigIncludeOptionValue = getNodeValue(tsconfigIncludeOption);
7094
+ if (tsconfigIncludeOptionValue.includes(tsConfigFileName)) {
7095
+ span.end();
7096
+ return;
7097
+ }
7098
+ const edits = modify(tsconfigContent, ["include", -1], tsConfigFileName, {
6641
7099
  isArrayInsertion: true,
6642
7100
  formattingOptions: {
6643
7101
  tabSize: 2,
@@ -6664,7 +7122,7 @@ async function installPackages2(dir, options) {
6664
7122
  return await tracer.startActiveSpan("installPackages", async (span) => {
6665
7123
  const installSpinner = spinner();
6666
7124
  try {
6667
- const projectDir = resolve4(process.cwd(), dir);
7125
+ const projectDir = resolve5(process.cwd(), dir);
6668
7126
  const pkgManager = await getUserPackageManager(projectDir);
6669
7127
  span.setAttributes({
6670
7128
  "cli.projectDir": projectDir,
@@ -6716,7 +7174,7 @@ async function writeConfigFile(dir, project, options, triggerDir) {
6716
7174
  try {
6717
7175
  const spnnr = spinner();
6718
7176
  spnnr.start("Creating config file");
6719
- const projectDir = resolve4(process.cwd(), dir);
7177
+ const projectDir = resolve5(process.cwd(), dir);
6720
7178
  const templatePath = join8(cliRootPath(), "templates", "trigger.config.ts.template");
6721
7179
  const outputPath = join8(projectDir, "trigger.config.ts");
6722
7180
  span.setAttributes({