@workflow/world-testing 4.1.0-beta.55 → 4.1.0-beta.56

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.
@@ -1,6 +1,11 @@
1
1
  {
2
2
  "version": "1.0.0",
3
3
  "steps": {
4
+ "workflows/addition.ts": {
5
+ "add": {
6
+ "stepId": "step//./workflows/addition//add"
7
+ }
8
+ },
4
9
  "workflow/dist/internal/builtins.js": {
5
10
  "__builtin_response_array_buffer": {
6
11
  "stepId": "__builtin_response_array_buffer"
@@ -12,12 +17,14 @@
12
17
  "stepId": "__builtin_response_text"
13
18
  }
14
19
  },
15
- "workflows/retriable-and-fatal.ts": {
16
- "stepThatFails": {
17
- "stepId": "step//./workflows/retriable-and-fatal//stepThatFails"
18
- },
19
- "stepThatThrowsRetryableError": {
20
- "stepId": "step//./workflows/retriable-and-fatal//stepThatThrowsRetryableError"
20
+ "workflow/dist/stdlib.js": {
21
+ "fetch": {
22
+ "stepId": "step//workflow@4.1.0-beta.55//fetch"
23
+ }
24
+ },
25
+ "workflows/hooks.ts": {
26
+ "writeEvent": {
27
+ "stepId": "step//./workflows/hooks//writeEvent"
21
28
  }
22
29
  },
23
30
  "workflows/noop.ts": {
@@ -25,49 +32,42 @@
25
32
  "stepId": "step//./workflows/noop//noop"
26
33
  }
27
34
  },
28
- "workflow/dist/stdlib.js": {
29
- "fetch": {
30
- "stepId": "step//workflow@4.1.0-beta.54//fetch"
31
- }
32
- },
33
- "workflows/addition.ts": {
34
- "add": {
35
- "stepId": "step//./workflows/addition//add"
36
- }
37
- },
38
35
  "workflows/null-byte.ts": {
39
36
  "nullByteStep": {
40
37
  "stepId": "step//./workflows/null-byte//nullByteStep"
41
38
  }
42
39
  },
43
- "workflows/hooks.ts": {
44
- "writeEvent": {
45
- "stepId": "step//./workflows/hooks//writeEvent"
40
+ "workflows/retriable-and-fatal.ts": {
41
+ "stepThatFails": {
42
+ "stepId": "step//./workflows/retriable-and-fatal//stepThatFails"
43
+ },
44
+ "stepThatThrowsRetryableError": {
45
+ "stepId": "step//./workflows/retriable-and-fatal//stepThatThrowsRetryableError"
46
46
  }
47
47
  }
48
48
  },
49
49
  "workflows": {
50
- "workflows/retriable-and-fatal.ts": {
51
- "retryableAndFatalErrorWorkflow": {
52
- "workflowId": "workflow//./workflows/retriable-and-fatal//retryableAndFatalErrorWorkflow",
50
+ "workflows/addition.ts": {
51
+ "addition": {
52
+ "workflowId": "workflow//./workflows/addition//addition",
53
53
  "graph": {
54
54
  "nodes": [],
55
55
  "edges": []
56
56
  }
57
57
  }
58
58
  },
59
- "workflows/noop.ts": {
60
- "brokenWf": {
61
- "workflowId": "workflow//./workflows/noop//brokenWf",
59
+ "workflows/hooks.ts": {
60
+ "collectWithHook": {
61
+ "workflowId": "workflow//./workflows/hooks//collectWithHook",
62
62
  "graph": {
63
63
  "nodes": [],
64
64
  "edges": []
65
65
  }
66
66
  }
67
67
  },
68
- "workflows/addition.ts": {
69
- "addition": {
70
- "workflowId": "workflow//./workflows/addition//addition",
68
+ "workflows/noop.ts": {
69
+ "brokenWf": {
70
+ "workflowId": "workflow//./workflows/noop//brokenWf",
71
71
  "graph": {
72
72
  "nodes": [],
73
73
  "edges": []
@@ -83,9 +83,9 @@
83
83
  }
84
84
  }
85
85
  },
86
- "workflows/hooks.ts": {
87
- "collectWithHook": {
88
- "workflowId": "workflow//./workflows/hooks//collectWithHook",
86
+ "workflows/retriable-and-fatal.ts": {
87
+ "retryableAndFatalErrorWorkflow": {
88
+ "workflowId": "workflow//./workflows/retriable-and-fatal//retryableAndFatalErrorWorkflow",
89
89
  "graph": {
90
90
  "nodes": [],
91
91
  "edges": []
@@ -25120,13 +25120,54 @@ var import_node_async_hooks = require("node:async_hooks");
25120
25120
  var contextStorage = /* @__PURE__ */ new import_node_async_hooks.AsyncLocalStorage();
25121
25121
  // ../core/dist/private.js
25122
25122
  var registeredSteps = /* @__PURE__ */ new Map();
25123
+ function getStepIdAliasCandidates(stepId) {
25124
+ const parts = stepId.split("//");
25125
+ if (parts.length !== 3 || parts[0] !== "step") {
25126
+ return [];
25127
+ }
25128
+ const modulePath = parts[1];
25129
+ const fnName = parts[2];
25130
+ const modulePathAliases = /* @__PURE__ */ new Set();
25131
+ const addAlias = /* @__PURE__ */ __name((aliasModulePath) => {
25132
+ if (aliasModulePath !== modulePath) {
25133
+ modulePathAliases.add(aliasModulePath);
25134
+ }
25135
+ }, "addAlias");
25136
+ if (modulePath.startsWith("./workflows/")) {
25137
+ const workflowRelativePath = modulePath.slice("./".length);
25138
+ addAlias(`./example/${workflowRelativePath}`);
25139
+ addAlias(`./src/${workflowRelativePath}`);
25140
+ }
25141
+ else if (modulePath.startsWith("./example/workflows/")) {
25142
+ const workflowRelativePath = modulePath.slice("./example/".length);
25143
+ addAlias(`./${workflowRelativePath}`);
25144
+ addAlias(`./src/${workflowRelativePath}`);
25145
+ }
25146
+ else if (modulePath.startsWith("./src/workflows/")) {
25147
+ const workflowRelativePath = modulePath.slice("./src/".length);
25148
+ addAlias(`./${workflowRelativePath}`);
25149
+ addAlias(`./example/${workflowRelativePath}`);
25150
+ }
25151
+ return Array.from(modulePathAliases, (aliasModulePath) => `step//${aliasModulePath}//${fnName}`);
25152
+ }
25153
+ __name(getStepIdAliasCandidates, "getStepIdAliasCandidates");
25123
25154
  function registerStepFunction(stepId, stepFn) {
25124
25155
  registeredSteps.set(stepId, stepFn);
25125
25156
  stepFn.stepId = stepId;
25126
25157
  }
25127
25158
  __name(registerStepFunction, "registerStepFunction");
25128
25159
  function getStepFunction(stepId) {
25129
- return registeredSteps.get(stepId);
25160
+ const directMatch = registeredSteps.get(stepId);
25161
+ if (directMatch) {
25162
+ return directMatch;
25163
+ }
25164
+ for (const aliasStepId of getStepIdAliasCandidates(stepId)) {
25165
+ const aliasMatch = registeredSteps.get(aliasStepId);
25166
+ if (aliasMatch) {
25167
+ return aliasMatch;
25168
+ }
25169
+ }
25170
+ return void 0;
25130
25171
  }
25131
25172
  __name(getStepFunction, "getStepFunction");
25132
25173
  // ../workflow/dist/internal/builtins.js
@@ -25145,6 +25186,12 @@ __name(__builtin_response_text, "__builtin_response_text");
25145
25186
  registerStepFunction("__builtin_response_array_buffer", __builtin_response_array_buffer);
25146
25187
  registerStepFunction("__builtin_response_json", __builtin_response_json);
25147
25188
  registerStepFunction("__builtin_response_text", __builtin_response_text);
25189
+ // ../workflow/dist/stdlib.js
25190
+ async function fetch2(...args) {
25191
+ return globalThis.fetch(...args);
25192
+ }
25193
+ __name(fetch2, "fetch");
25194
+ registerStepFunction("step//workflow@4.1.0-beta.55//fetch", fetch2);
25148
25195
  // workflows/addition.ts
25149
25196
  async function add(num, num2) {
25150
25197
  return num + num2;
@@ -25248,6 +25295,8 @@ var WorkflowAPIError = class extends WorkflowError {
25248
25295
  status;
25249
25296
  code;
25250
25297
  url;
25298
+ /** Retry-After value in seconds, present on 429 responses */
25299
+ retryAfter;
25251
25300
  constructor(message, options) {
25252
25301
  super(message, {
25253
25302
  cause: options?.cause
@@ -25256,6 +25305,7 @@ var WorkflowAPIError = class extends WorkflowError {
25256
25305
  this.status = options?.status;
25257
25306
  this.code = options?.code;
25258
25307
  this.url = options?.url;
25308
+ this.retryAfter = options?.retryAfter;
25259
25309
  }
25260
25310
  static is(value) {
25261
25311
  return isError(value) && value.name === "WorkflowAPIError";
@@ -39387,7 +39437,9 @@ var TraceCarrierSchema = external_exports.record(external_exports.string(), exte
39387
39437
  var WorkflowInvokePayloadSchema = external_exports.object({
39388
39438
  runId: external_exports.string(),
39389
39439
  traceCarrier: TraceCarrierSchema.optional(),
39390
- requestedAt: external_exports.coerce.date().optional()
39440
+ requestedAt: external_exports.coerce.date().optional(),
39441
+ /** Number of times this message has been re-enqueued due to server errors (5xx) */
39442
+ serverErrorRetryCount: external_exports.number().int().optional()
39391
39443
  });
39392
39444
  var StepInvokePayloadSchema = external_exports.object({
39393
39445
  workflowName: external_exports.string(),
@@ -47169,7 +47221,7 @@ var RpcSystem3 = SemanticConvention3("rpc.system");
47169
47221
  var RpcService3 = SemanticConvention3("rpc.service");
47170
47222
  var RpcMethod3 = SemanticConvention3("rpc.method");
47171
47223
  // ../world-vercel/dist/version.js
47172
- var version2 = "4.1.0-beta.31";
47224
+ var version2 = "4.1.0-beta.32";
47173
47225
  // ../world-vercel/dist/utils.js
47174
47226
  var WORKFLOW_SERVER_URL_OVERRIDE = "";
47175
47227
  var DEFAULT_RESOLVE_DATA_OPTION2 = "all";
@@ -47317,10 +47369,21 @@ async function makeRequest({ endpoint, options = {}, config: config3 = {}, schem
47317
47369
  console.error(`Failed to fetch, reproduce with:
47318
47370
  curl -X ${request.method} ${stringifiedHeaders} "${url2}"`);
47319
47371
  }
47372
+ let retryAfter;
47373
+ if (response.status === 429) {
47374
+ const retryAfterHeader = response.headers.get("Retry-After");
47375
+ if (retryAfterHeader) {
47376
+ const parsed = parseInt(retryAfterHeader, 10);
47377
+ if (!Number.isNaN(parsed)) {
47378
+ retryAfter = parsed;
47379
+ }
47380
+ }
47381
+ }
47320
47382
  const error45 = new WorkflowAPIError(errorData.message || `${request.method} ${endpoint} -> HTTP ${response.status}: ${response.statusText}`, {
47321
47383
  url: url2,
47322
47384
  status: response.status,
47323
- code: errorData.code
47385
+ code: errorData.code,
47386
+ retryAfter
47324
47387
  });
47325
47388
  span?.setAttributes({
47326
47389
  ...ErrorType2(errorData.code || `HTTP ${response.status}`)
@@ -48856,7 +48919,7 @@ async function waitedUntil(fn) {
48856
48919
  }
48857
48920
  __name(waitedUntil, "waitedUntil");
48858
48921
  // ../core/dist/runtime/helpers.js
48859
- var SAFE_WORKFLOW_NAME_PATTERN = /^[a-zA-Z0-9_\-.\/]+$/;
48922
+ var SAFE_WORKFLOW_NAME_PATTERN = /^[a-zA-Z0-9_\-./]+$/;
48860
48923
  function getWorkflowQueueName(workflowName) {
48861
48924
  if (!SAFE_WORKFLOW_NAME_PATTERN.test(workflowName)) {
48862
48925
  throw new Error(`Invalid workflow name "${workflowName}": must only contain alphanumeric characters, underscores, hyphens, dots, or forward slashes`);
@@ -49057,12 +49120,6 @@ function getStepMetadata() {
49057
49120
  return ctx.stepMetadata;
49058
49121
  }
49059
49122
  __name(getStepMetadata, "getStepMetadata");
49060
- // ../workflow/dist/stdlib.js
49061
- async function fetch2(...args) {
49062
- return globalThis.fetch(...args);
49063
- }
49064
- __name(fetch2, "fetch");
49065
- registerStepFunction("step//workflow@4.1.0-beta.54//fetch", fetch2);
49066
49123
  // workflows/hooks.ts
49067
49124
  var Hook = defineHook({
49068
49125
  schema: object({
@@ -49100,6 +49157,17 @@ async function brokenWf() {
49100
49157
  __name(brokenWf, "brokenWf");
49101
49158
  brokenWf.workflowId = "workflow//./workflows/noop//brokenWf";
49102
49159
  registerStepFunction("step//./workflows/noop//noop", noop);
49160
+ // workflows/null-byte.ts
49161
+ async function nullByteStep() {
49162
+ return "null byte \0";
49163
+ }
49164
+ __name(nullByteStep, "nullByteStep");
49165
+ async function nullByteWorkflow() {
49166
+ throw new Error("You attempted to execute workflow nullByteWorkflow function directly. To start a workflow, use start(nullByteWorkflow) from workflow/api");
49167
+ }
49168
+ __name(nullByteWorkflow, "nullByteWorkflow");
49169
+ nullByteWorkflow.workflowId = "workflow//./workflows/null-byte//nullByteWorkflow";
49170
+ registerStepFunction("step//./workflows/null-byte//nullByteStep", nullByteStep);
49103
49171
  // workflows/retriable-and-fatal.ts
49104
49172
  async function retryableAndFatalErrorWorkflow() {
49105
49173
  throw new Error("You attempted to execute workflow retryableAndFatalErrorWorkflow function directly. To start a workflow, use start(retryableAndFatalErrorWorkflow) from workflow/api");
@@ -49127,17 +49195,6 @@ async function stepThatFails() {
49127
49195
  __name(stepThatFails, "stepThatFails");
49128
49196
  registerStepFunction("step//./workflows/retriable-and-fatal//stepThatThrowsRetryableError", stepThatThrowsRetryableError);
49129
49197
  registerStepFunction("step//./workflows/retriable-and-fatal//stepThatFails", stepThatFails);
49130
- // workflows/null-byte.ts
49131
- async function nullByteStep() {
49132
- return "null byte \0";
49133
- }
49134
- __name(nullByteStep, "nullByteStep");
49135
- async function nullByteWorkflow() {
49136
- throw new Error("You attempted to execute workflow nullByteWorkflow function directly. To start a workflow, use start(nullByteWorkflow) from workflow/api");
49137
- }
49138
- __name(nullByteWorkflow, "nullByteWorkflow");
49139
- nullByteWorkflow.workflowId = "workflow//./workflows/null-byte//nullByteWorkflow";
49140
- registerStepFunction("step//./workflows/null-byte//nullByteStep", nullByteStep);
49141
49198
  // ../core/dist/runtime/suspension-handler.js
49142
49199
  var import_functions3 = __toESM(require_functions(), 1);
49143
49200
  // ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
@@ -49168,6 +49225,62 @@ function getErrorStack(v) {
49168
49225
  return "";
49169
49226
  }
49170
49227
  __name(getErrorStack, "getErrorStack");
49228
+ function isThenable(value) {
49229
+ return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
49230
+ }
49231
+ __name(isThenable, "isThenable");
49232
+ function normalizeSyncError(v) {
49233
+ if (import_node_util3.types.isNativeError(v)) {
49234
+ return {
49235
+ name: v.name,
49236
+ message: v.message,
49237
+ stack: v.stack ?? ""
49238
+ };
49239
+ }
49240
+ if (typeof v === "string") {
49241
+ return {
49242
+ name: "Error",
49243
+ message: v,
49244
+ stack: ""
49245
+ };
49246
+ }
49247
+ try {
49248
+ return {
49249
+ name: "Error",
49250
+ message: JSON.stringify(v),
49251
+ stack: ""
49252
+ };
49253
+ }
49254
+ catch {
49255
+ return {
49256
+ name: "Error",
49257
+ message: String(v),
49258
+ stack: ""
49259
+ };
49260
+ }
49261
+ }
49262
+ __name(normalizeSyncError, "normalizeSyncError");
49263
+ async function normalizeUnknownError(value) {
49264
+ if (isThenable(value)) {
49265
+ try {
49266
+ const resolved = await value;
49267
+ const normalized = await normalizeUnknownError(resolved);
49268
+ return {
49269
+ ...normalized,
49270
+ message: `Promise rejection: ${normalized.message}`
49271
+ };
49272
+ }
49273
+ catch (rejection) {
49274
+ const normalized = await normalizeUnknownError(rejection);
49275
+ return {
49276
+ ...normalized,
49277
+ message: `Promise rejection: ${normalized.message}`
49278
+ };
49279
+ }
49280
+ }
49281
+ return normalizeSyncError(value);
49282
+ }
49283
+ __name(normalizeUnknownError, "normalizeUnknownError");
49171
49284
  // ../core/dist/events-consumer.js
49172
49285
  var EventConsumerResult;
49173
49286
  (function (EventConsumerResult2) {
@@ -49243,6 +49356,15 @@ var stepHandler = getWorldHandlers().createQueueHandler("__wkf_step_", async (me
49243
49356
  }
49244
49357
  catch (err) {
49245
49358
  if (WorkflowAPIError.is(err)) {
49359
+ if (WorkflowAPIError.is(err) && err.status === 429) {
49360
+ const retryRetryAfter = Math.max(1, typeof err.retryAfter === "number" ? err.retryAfter : 1);
49361
+ runtimeLogger.warn("Throttled again on retry, deferring to queue", {
49362
+ retryAfterSeconds: retryRetryAfter
49363
+ });
49364
+ return {
49365
+ timeoutSeconds: retryRetryAfter
49366
+ };
49367
+ }
49246
49368
  if (err.status === 410) {
49247
49369
  console.warn(`Workflow run "${workflowRunId}" has already completed, skipping step "${stepId}": ${err.message}`);
49248
49370
  return;
@@ -49418,6 +49540,8 @@ var stepHandler = getWorldHandlers().createQueueHandler("__wkf_step_", async (me
49418
49540
  return;
49419
49541
  }
49420
49542
  catch (err) {
49543
+ const normalizedError = await normalizeUnknownError(err);
49544
+ const normalizedStack = normalizedError.stack || getErrorStack(err) || "";
49421
49545
  if (err instanceof Error) {
49422
49546
  span?.recordException?.(err);
49423
49547
  }
@@ -49426,7 +49550,7 @@ var stepHandler = getWorldHandlers().createQueueHandler("__wkf_step_", async (me
49426
49550
  const errorCategory = isFatal ? "fatal" : isRetryable ? "retryable" : "transient";
49427
49551
  span?.setAttributes({
49428
49552
  ...StepErrorName(getErrorName(err)),
49429
- ...StepErrorMessage(String(err)),
49553
+ ...StepErrorMessage(normalizedError.message),
49430
49554
  ...ErrorType(getErrorName(err)),
49431
49555
  ...ErrorCategory(errorCategory),
49432
49556
  ...ErrorRetryable(!isFatal)
@@ -49442,19 +49566,18 @@ var stepHandler = getWorldHandlers().createQueueHandler("__wkf_step_", async (me
49442
49566
  }
49443
49567
  }
49444
49568
  if (isFatal) {
49445
- const errorStack = getErrorStack(err);
49446
49569
  stepLogger.error("Encountered FatalError while executing step, bubbling up to parent workflow", {
49447
49570
  workflowRunId,
49448
49571
  stepName,
49449
- errorStack
49572
+ errorStack: normalizedStack
49450
49573
  });
49451
49574
  await world.events.create(workflowRunId, {
49452
49575
  eventType: "step_failed",
49453
49576
  specVersion: SPEC_VERSION_CURRENT,
49454
49577
  correlationId: stepId,
49455
49578
  eventData: {
49456
- error: String(err),
49457
- stack: errorStack
49579
+ error: normalizedError.message,
49580
+ stack: normalizedStack
49458
49581
  }
49459
49582
  });
49460
49583
  span?.setAttributes({
@@ -49470,23 +49593,22 @@ var stepHandler = getWorldHandlers().createQueueHandler("__wkf_step_", async (me
49470
49593
  ...StepMaxRetries(maxRetries2)
49471
49594
  });
49472
49595
  if (currentAttempt >= maxRetries2 + 1) {
49473
- const errorStack = getErrorStack(err);
49474
49596
  const retryCount = step.attempt - 1;
49475
49597
  stepLogger.error("Max retries reached, bubbling error to parent workflow", {
49476
49598
  workflowRunId,
49477
49599
  stepName,
49478
49600
  attempt: step.attempt,
49479
49601
  retryCount,
49480
- errorStack
49602
+ errorStack: normalizedStack
49481
49603
  });
49482
- const errorMessage = `Step "${stepName}" failed after ${maxRetries2} ${pluralize("retry", "retries", maxRetries2)}: ${String(err)}`;
49604
+ const errorMessage = `Step "${stepName}" failed after ${maxRetries2} ${pluralize("retry", "retries", maxRetries2)}: ${normalizedError.message}`;
49483
49605
  await world.events.create(workflowRunId, {
49484
49606
  eventType: "step_failed",
49485
49607
  specVersion: SPEC_VERSION_CURRENT,
49486
49608
  correlationId: stepId,
49487
49609
  eventData: {
49488
49610
  error: errorMessage,
49489
- stack: errorStack
49611
+ stack: normalizedStack
49490
49612
  }
49491
49613
  });
49492
49614
  span?.setAttributes({
@@ -49504,22 +49626,20 @@ var stepHandler = getWorldHandlers().createQueueHandler("__wkf_step_", async (me
49504
49626
  });
49505
49627
  }
49506
49628
  else {
49507
- const errorStack2 = getErrorStack(err);
49508
49629
  stepLogger.warn("Encountered Error, step will be retried", {
49509
49630
  workflowRunId,
49510
49631
  stepName,
49511
49632
  attempt: currentAttempt,
49512
- errorStack: errorStack2
49633
+ errorStack: normalizedStack
49513
49634
  });
49514
49635
  }
49515
- const errorStack = getErrorStack(err);
49516
49636
  await world.events.create(workflowRunId, {
49517
49637
  eventType: "step_retrying",
49518
49638
  specVersion: SPEC_VERSION_CURRENT,
49519
49639
  correlationId: stepId,
49520
49640
  eventData: {
49521
- error: String(err),
49522
- stack: errorStack,
49641
+ error: normalizedError.message,
49642
+ stack: normalizedStack,
49523
49643
  ...RetryableError.is(err) && {
49524
49644
  retryAfter: err.retryAfter
49525
49645
  }