@aikirun/workflow 0.23.1 → 0.24.0

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
@@ -58,64 +58,6 @@ function isNonEmptyArray(value) {
58
58
  return value !== void 0 && value.length > 0;
59
59
  }
60
60
 
61
- // ../../lib/async/delay.ts
62
- function delay(ms, options) {
63
- const abortSignal = options?.abortSignal;
64
- if (abortSignal?.aborted) {
65
- return Promise.reject(abortSignal.reason);
66
- }
67
- return new Promise((resolve, reject) => {
68
- const abort = () => {
69
- clearTimeout(timeout);
70
- reject(abortSignal?.reason);
71
- };
72
- const timeout = setTimeout(() => {
73
- abortSignal?.removeEventListener("abort", abort);
74
- resolve();
75
- }, ms);
76
- abortSignal?.addEventListener("abort", abort, { once: true });
77
- });
78
- }
79
-
80
- // ../../lib/crypto/hash.ts
81
- import { createHash } from "crypto";
82
-
83
- // ../../lib/json/stable-stringify.ts
84
- function stableStringify(value) {
85
- return stringifyValue(value);
86
- }
87
- function stringifyValue(value) {
88
- if (value === null || value === void 0) {
89
- return "null";
90
- }
91
- if (typeof value !== "object") {
92
- return JSON.stringify(value);
93
- }
94
- if (Array.isArray(value)) {
95
- return `[${value.map(stringifyValue).join(",")}]`;
96
- }
97
- const keys = Object.keys(value).sort();
98
- const pairs = [];
99
- for (const key of keys) {
100
- const keyValue = value[key];
101
- if (keyValue !== void 0) {
102
- pairs.push(`${JSON.stringify(key)}:${stringifyValue(keyValue)}`);
103
- }
104
- }
105
- return `{${pairs.join(",")}}`;
106
- }
107
-
108
- // ../../lib/crypto/hash.ts
109
- async function sha256(input) {
110
- const data = new TextEncoder().encode(input);
111
- const hashBuffer = await crypto.subtle.digest("SHA-256", data);
112
- const hashArray = Array.from(new Uint8Array(hashBuffer));
113
- return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
114
- }
115
- async function hashInput(input) {
116
- return sha256(stableStringify({ input }));
117
- }
118
-
119
61
  // ../../lib/duration/convert.ts
120
62
  var MS_PER_SECOND = 1e3;
121
63
  var MS_PER_MINUTE = 60 * MS_PER_SECOND;
@@ -162,19 +104,6 @@ function assertIsPositiveNumber(value, field) {
162
104
  }
163
105
  }
164
106
 
165
- // ../../lib/error/serializable.ts
166
- function createSerializableError(error) {
167
- return error instanceof Error ? {
168
- message: error.message,
169
- name: error.name,
170
- stack: error.stack,
171
- cause: error.cause ? createSerializableError(error.cause) : void 0
172
- } : {
173
- message: String(error),
174
- name: "UnknownError"
175
- };
176
- }
177
-
178
107
  // ../../lib/object/overrider.ts
179
108
  function set(obj, path, value) {
180
109
  const keys = path.split(".");
@@ -205,92 +134,6 @@ var objectOverrider = (defaultObj) => (obj) => {
205
134
  return createBuilder([]);
206
135
  };
207
136
 
208
- // ../../lib/retry/strategy.ts
209
- function withRetry(fn, strategy, options) {
210
- return {
211
- run: async (...args) => {
212
- let attempts = 0;
213
- while (true) {
214
- if (options?.abortSignal?.aborted) {
215
- return {
216
- state: "aborted",
217
- reason: options.abortSignal.reason
218
- };
219
- }
220
- attempts++;
221
- let result;
222
- try {
223
- result = await fn(...args);
224
- if (options?.shouldRetryOnResult === void 0 || !await options.shouldRetryOnResult(result)) {
225
- return {
226
- state: "completed",
227
- result,
228
- attempts
229
- };
230
- }
231
- } catch (err) {
232
- if (options?.shouldNotRetryOnError !== void 0 && await options.shouldNotRetryOnError(err)) {
233
- throw err;
234
- }
235
- }
236
- const retryParams = getRetryParams(attempts, strategy);
237
- if (!retryParams.retriesLeft) {
238
- return {
239
- state: "timeout"
240
- };
241
- }
242
- await delay(retryParams.delayMs, { abortSignal: options?.abortSignal });
243
- }
244
- }
245
- };
246
- }
247
- function getRetryParams(attempts, strategy) {
248
- const strategyType = strategy.type;
249
- switch (strategyType) {
250
- case "never":
251
- return {
252
- retriesLeft: false
253
- };
254
- case "fixed":
255
- if (attempts >= strategy.maxAttempts) {
256
- return {
257
- retriesLeft: false
258
- };
259
- }
260
- return {
261
- retriesLeft: true,
262
- delayMs: strategy.delayMs
263
- };
264
- case "exponential": {
265
- if (attempts >= strategy.maxAttempts) {
266
- return {
267
- retriesLeft: false
268
- };
269
- }
270
- const delayMs = strategy.baseDelayMs * (strategy.factor ?? 2) ** (attempts - 1);
271
- return {
272
- retriesLeft: true,
273
- delayMs: Math.min(delayMs, strategy.maxDelayMs ?? Number.POSITIVE_INFINITY)
274
- };
275
- }
276
- case "jittered": {
277
- if (attempts >= strategy.maxAttempts) {
278
- return {
279
- retriesLeft: false
280
- };
281
- }
282
- const base = strategy.baseDelayMs * (strategy.jitterFactor ?? 2) ** (attempts - 1);
283
- const delayMs = Math.random() * base;
284
- return {
285
- retriesLeft: true,
286
- delayMs: Math.min(delayMs, strategy.maxDelayMs ?? Number.POSITIVE_INFINITY)
287
- };
288
- }
289
- default:
290
- return strategyType;
291
- }
292
- }
293
-
294
137
  // run/event.ts
295
138
  import { INTERNAL } from "@aikirun/types/symbols";
296
139
  import { SchemaValidationError } from "@aikirun/types/validator";
@@ -298,7 +141,7 @@ import {
298
141
  WorkflowRunFailedError,
299
142
  WorkflowRunRevisionConflictError,
300
143
  WorkflowRunSuspendedError
301
- } from "@aikirun/types/workflow-run";
144
+ } from "@aikirun/types/workflow-run-error";
302
145
  function event(params) {
303
146
  return {
304
147
  // biome-ignore lint/style/useNamingConvention: phantom type marker
@@ -388,10 +231,10 @@ function createEventSenders(api, workflowRunId, eventsDefinition, logger) {
388
231
  return senders;
389
232
  }
390
233
  function createEventSender(api, workflowRunId, eventName, schema, logger, options) {
391
- const optsOverrider = objectOverrider(options ?? {});
392
- const createBuilder = (optsBuilder) => ({
393
- opt: (path, value) => createBuilder(optsBuilder.with(path, value)),
394
- send: (...args) => createEventSender(api, workflowRunId, eventName, schema, logger, optsBuilder.build()).send(...args)
234
+ const optionsOverrider = objectOverrider(options ?? {});
235
+ const createBuilder = (optionsBuilder) => ({
236
+ opt: (path, value) => createBuilder(optionsBuilder.with(path, value)),
237
+ send: (...args) => createEventSender(api, workflowRunId, eventName, schema, logger, optionsBuilder.build()).send(...args)
395
238
  });
396
239
  async function send(...args) {
397
240
  let data = args[0];
@@ -415,7 +258,7 @@ function createEventSender(api, workflowRunId, eventName, schema, logger, option
415
258
  });
416
259
  }
417
260
  return {
418
- with: () => createBuilder(optsOverrider()),
261
+ with: () => createBuilder(optionsOverrider()),
419
262
  send
420
263
  };
421
264
  }
@@ -433,19 +276,21 @@ function createEventMulticasters(workflowName, workflowVersionId, eventsDefiniti
433
276
  return senders;
434
277
  }
435
278
  function createEventMulticaster(workflowName, workflowVersionId, eventName, schema, options) {
436
- const optsOverrider = objectOverrider(options ?? {});
437
- const createBuilder = (optsBuilder) => ({
438
- opt: (path, value) => createBuilder(optsBuilder.with(path, value)),
439
- send: (client, runId, ...args) => createEventMulticaster(workflowName, workflowVersionId, eventName, schema, optsBuilder.build()).send(
279
+ const optionsOverrider = objectOverrider(options ?? {});
280
+ const createBuilder = (optionsBuilder) => ({
281
+ opt: (path, value) => createBuilder(optionsBuilder.with(path, value)),
282
+ send: (client, runId, ...args) => createEventMulticaster(workflowName, workflowVersionId, eventName, schema, optionsBuilder.build()).send(
440
283
  client,
441
284
  runId,
442
285
  ...args
443
286
  ),
444
- sendByReferenceId: (client, referenceId, ...args) => createEventMulticaster(workflowName, workflowVersionId, eventName, schema, optsBuilder.build()).sendByReferenceId(
445
- client,
446
- referenceId,
447
- ...args
448
- )
287
+ sendByReferenceId: (client, referenceId, ...args) => createEventMulticaster(
288
+ workflowName,
289
+ workflowVersionId,
290
+ eventName,
291
+ schema,
292
+ optionsBuilder.build()
293
+ ).sendByReferenceId(client, referenceId, ...args)
449
294
  });
450
295
  async function send(client, runId, ...args) {
451
296
  let data = args[0];
@@ -520,18 +365,130 @@ function createEventMulticaster(workflowName, workflowVersionId, eventName, sche
520
365
  });
521
366
  }
522
367
  return {
523
- with: () => createBuilder(optsOverrider()),
368
+ with: () => createBuilder(optionsOverrider()),
524
369
  send,
525
370
  sendByReferenceId
526
371
  };
527
372
  }
528
373
 
374
+ // run/execute.ts
375
+ import { INTERNAL as INTERNAL4 } from "@aikirun/types/symbols";
376
+ import {
377
+ NonDeterminismError,
378
+ WorkflowRunFailedError as WorkflowRunFailedError2,
379
+ WorkflowRunNotExecutableError as WorkflowRunNotExecutableError2,
380
+ WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError4,
381
+ WorkflowRunSuspendedError as WorkflowRunSuspendedError3
382
+ } from "@aikirun/types/workflow-run-error";
383
+
384
+ // ../../lib/async/delay.ts
385
+ function delay(ms, options) {
386
+ const abortSignal = options?.abortSignal;
387
+ if (abortSignal?.aborted) {
388
+ return Promise.reject(abortSignal.reason);
389
+ }
390
+ return new Promise((resolve, reject) => {
391
+ const abort = () => {
392
+ clearTimeout(timeout);
393
+ reject(abortSignal?.reason);
394
+ };
395
+ const timeout = setTimeout(() => {
396
+ abortSignal?.removeEventListener("abort", abort);
397
+ resolve();
398
+ }, ms);
399
+ abortSignal?.addEventListener("abort", abort, { once: true });
400
+ });
401
+ }
402
+
403
+ // ../../lib/retry/strategy.ts
404
+ function withRetry(fn, strategy, options) {
405
+ return {
406
+ run: async (...args) => {
407
+ let attempts = 0;
408
+ while (true) {
409
+ if (options?.abortSignal?.aborted) {
410
+ return {
411
+ state: "aborted",
412
+ reason: options.abortSignal.reason
413
+ };
414
+ }
415
+ attempts++;
416
+ let result;
417
+ try {
418
+ result = await fn(...args);
419
+ if (options?.shouldRetryOnResult === void 0 || !await options.shouldRetryOnResult(result)) {
420
+ return {
421
+ state: "completed",
422
+ result,
423
+ attempts
424
+ };
425
+ }
426
+ } catch (err) {
427
+ if (options?.shouldNotRetryOnError !== void 0 && await options.shouldNotRetryOnError(err)) {
428
+ throw err;
429
+ }
430
+ }
431
+ const retryParams = getRetryParams(attempts, strategy);
432
+ if (!retryParams.retriesLeft) {
433
+ return {
434
+ state: "timeout"
435
+ };
436
+ }
437
+ await delay(retryParams.delayMs, { abortSignal: options?.abortSignal });
438
+ }
439
+ }
440
+ };
441
+ }
442
+ function getRetryParams(attempts, strategy) {
443
+ const strategyType = strategy.type;
444
+ switch (strategyType) {
445
+ case "never":
446
+ return {
447
+ retriesLeft: false
448
+ };
449
+ case "fixed":
450
+ if (attempts >= strategy.maxAttempts) {
451
+ return {
452
+ retriesLeft: false
453
+ };
454
+ }
455
+ return {
456
+ retriesLeft: true,
457
+ delayMs: strategy.delayMs
458
+ };
459
+ case "exponential": {
460
+ if (attempts >= strategy.maxAttempts) {
461
+ return {
462
+ retriesLeft: false
463
+ };
464
+ }
465
+ const delayMs = strategy.baseDelayMs * (strategy.factor ?? 2) ** (attempts - 1);
466
+ return {
467
+ retriesLeft: true,
468
+ delayMs: Math.min(delayMs, strategy.maxDelayMs ?? Number.POSITIVE_INFINITY)
469
+ };
470
+ }
471
+ case "jittered": {
472
+ if (attempts >= strategy.maxAttempts) {
473
+ return {
474
+ retriesLeft: false
475
+ };
476
+ }
477
+ const base = strategy.baseDelayMs * (strategy.jitterFactor ?? 2) ** (attempts - 1);
478
+ const delayMs = Math.random() * base;
479
+ return {
480
+ retriesLeft: true,
481
+ delayMs: Math.min(delayMs, strategy.maxDelayMs ?? Number.POSITIVE_INFINITY)
482
+ };
483
+ }
484
+ default:
485
+ return strategyType;
486
+ }
487
+ }
488
+
529
489
  // run/handle.ts
530
490
  import { INTERNAL as INTERNAL2 } from "@aikirun/types/symbols";
531
- import {
532
- WorkflowRunNotExecutableError,
533
- WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError2
534
- } from "@aikirun/types/workflow-run";
491
+ import { WorkflowRunNotExecutableError, WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError2 } from "@aikirun/types/workflow-run-error";
535
492
  async function workflowRunHandle(client, runOrId, eventsDefinition, logger) {
536
493
  const run = typeof runOrId !== "string" ? runOrId : (await client.api.workflowRun.getByIdV1({ id: runOrId })).run;
537
494
  return new WorkflowRunHandleImpl(
@@ -707,10 +664,10 @@ function createReplayManifest(run) {
707
664
  if (nextIndex >= taskCount) {
708
665
  return void 0;
709
666
  }
710
- const task = taskQueues[address].tasks[nextIndex];
667
+ const task2 = taskQueues[address].tasks[nextIndex];
711
668
  nextTaskIndexByAddress[address] = nextIndex + 1;
712
669
  consumedEntries++;
713
- return task;
670
+ return task2;
714
671
  },
715
672
  consumeNextChildWorkflowRun(address) {
716
673
  const childWorkflowRunCount = childWorkflowRunCountByAddress[address] ?? 0;
@@ -750,10 +707,7 @@ function createReplayManifest(run) {
750
707
 
751
708
  // run/sleeper.ts
752
709
  import { INTERNAL as INTERNAL3 } from "@aikirun/types/symbols";
753
- import {
754
- WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError3,
755
- WorkflowRunSuspendedError as WorkflowRunSuspendedError2
756
- } from "@aikirun/types/workflow-run";
710
+ import { WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError3, WorkflowRunSuspendedError as WorkflowRunSuspendedError2 } from "@aikirun/types/workflow-run-error";
757
711
  var MAX_SLEEP_YEARS = 10;
758
712
  var MAX_SLEEP_MS = MAX_SLEEP_YEARS * 365 * 24 * 60 * 60 * 1e3;
759
713
  function createSleeper(handle, logger) {
@@ -832,9 +786,64 @@ function createSleeper(handle, logger) {
832
786
  };
833
787
  }
834
788
 
789
+ // run/execute.ts
790
+ async function executeWorkflowRun(params) {
791
+ const { client, workflowRun, workflowVersion, logger, options, heartbeat } = params;
792
+ let heartbeatInterval;
793
+ try {
794
+ if (heartbeat) {
795
+ heartbeatInterval = setInterval(async () => {
796
+ try {
797
+ await heartbeat();
798
+ logger.debug("Heartbeat sent");
799
+ } catch (error) {
800
+ logger.warn("Failed to send heartbeat", {
801
+ "aiki.error": error instanceof Error ? error.message : String(error)
802
+ });
803
+ }
804
+ }, options.heartbeatIntervalMs);
805
+ }
806
+ const eventsDefinition = workflowVersion[INTERNAL4].eventsDefinition;
807
+ const handle = await workflowRunHandle(client, workflowRun, eventsDefinition, logger);
808
+ const appContext = client[INTERNAL4].createContext ? client[INTERNAL4].createContext(workflowRun) : null;
809
+ await workflowVersion[INTERNAL4].handler(
810
+ {
811
+ id: workflowRun.id,
812
+ name: workflowRun.name,
813
+ versionId: workflowRun.versionId,
814
+ options: workflowRun.options ?? {},
815
+ logger,
816
+ sleep: createSleeper(handle, logger),
817
+ events: createEventWaiters(handle, eventsDefinition, logger),
818
+ [INTERNAL4]: {
819
+ handle,
820
+ replayManifest: createReplayManifest(workflowRun),
821
+ options: { spinThresholdMs: options.spinThresholdMs }
822
+ }
823
+ },
824
+ workflowRun.input,
825
+ appContext instanceof Promise ? await appContext : appContext
826
+ );
827
+ return true;
828
+ } catch (error) {
829
+ if (error instanceof WorkflowRunNotExecutableError2 || error instanceof WorkflowRunSuspendedError3 || error instanceof WorkflowRunFailedError2 || error instanceof WorkflowRunRevisionConflictError4 || error instanceof NonDeterminismError) {
830
+ return true;
831
+ }
832
+ logger.error("Unexpected error during workflow execution", {
833
+ "aiki.error": error instanceof Error ? error.message : String(error),
834
+ "aiki.stack": error instanceof Error ? error.stack : void 0
835
+ });
836
+ return false;
837
+ } finally {
838
+ if (heartbeatInterval) {
839
+ clearInterval(heartbeatInterval);
840
+ }
841
+ }
842
+ }
843
+
835
844
  // schedule.ts
836
845
  function schedule(params) {
837
- async function activateWithOpts(client, workflow2, options, ...args) {
846
+ async function activateWithOptions(client, workflow2, options, ...args) {
838
847
  const input = args[0];
839
848
  let scheduleSpec;
840
849
  if (params.type === "interval") {
@@ -873,52 +882,338 @@ function schedule(params) {
873
882
  }
874
883
  };
875
884
  }
876
- function createBuilder(optsBuilder) {
885
+ function createBuilder(optionsBuilder) {
877
886
  return {
878
- opt: (path, value) => createBuilder(optsBuilder.with(path, value)),
887
+ opt: (path, value) => createBuilder(optionsBuilder.with(path, value)),
879
888
  async activate(client, workflow2, ...args) {
880
- return activateWithOpts(client, workflow2, optsBuilder.build(), ...args);
889
+ return activateWithOptions(client, workflow2, optionsBuilder.build(), ...args);
881
890
  }
882
891
  };
883
892
  }
884
893
  return {
885
894
  ...params,
886
895
  with() {
887
- const optsOverrider = objectOverrider({});
888
- return createBuilder(optsOverrider());
896
+ const optionsOverrider = objectOverrider({});
897
+ return createBuilder(optionsOverrider());
889
898
  },
890
899
  async activate(client, workflow2, ...args) {
891
- return activateWithOpts(client, workflow2, {}, ...args);
900
+ return activateWithOptions(client, workflow2, {}, ...args);
892
901
  }
893
902
  };
894
903
  }
895
904
 
896
- // workflow.ts
897
- import { INTERNAL as INTERNAL6 } from "@aikirun/types/symbols";
905
+ // system/cancel-child-runs.ts
906
+ import { NON_TERMINAL_WORKFLOW_RUN_STATUSES } from "@aikirun/types/workflow-run";
898
907
 
899
908
  // ../../lib/address/index.ts
909
+ function getTaskAddress(name, inputHash) {
910
+ return `${name}:${inputHash}`;
911
+ }
900
912
  function getWorkflowRunAddress(name, versionId, referenceId) {
901
913
  return `${name}:${versionId}:${referenceId}`;
902
914
  }
903
915
 
904
- // workflow-version.ts
916
+ // ../../lib/crypto/hash.ts
917
+ import { createHash } from "crypto";
918
+
919
+ // ../../lib/json/stable-stringify.ts
920
+ function stableStringify(value) {
921
+ return stringifyValue(value);
922
+ }
923
+ function stringifyValue(value) {
924
+ if (value === null || value === void 0) {
925
+ return "null";
926
+ }
927
+ if (typeof value !== "object") {
928
+ return JSON.stringify(value);
929
+ }
930
+ if (Array.isArray(value)) {
931
+ return `[${value.map(stringifyValue).join(",")}]`;
932
+ }
933
+ const keys = Object.keys(value).sort();
934
+ const pairs = [];
935
+ for (const key of keys) {
936
+ const keyValue = value[key];
937
+ if (keyValue !== void 0) {
938
+ pairs.push(`${JSON.stringify(key)}:${stringifyValue(keyValue)}`);
939
+ }
940
+ }
941
+ return `{${pairs.join(",")}}`;
942
+ }
943
+
944
+ // ../../lib/crypto/hash.ts
945
+ async function sha256(input) {
946
+ const data = new TextEncoder().encode(input);
947
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
948
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
949
+ return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
950
+ }
951
+ async function hashInput(input) {
952
+ return sha256(stableStringify({ input }));
953
+ }
954
+
955
+ // ../../lib/error/serializable.ts
956
+ function createSerializableError(error) {
957
+ return error instanceof Error ? {
958
+ message: error.message,
959
+ name: error.name,
960
+ stack: error.stack,
961
+ cause: error.cause ? createSerializableError(error.cause) : void 0
962
+ } : {
963
+ message: String(error),
964
+ name: "UnknownError"
965
+ };
966
+ }
967
+
968
+ // ../task/task.ts
905
969
  import { INTERNAL as INTERNAL5 } from "@aikirun/types/symbols";
906
- import { TaskFailedError } from "@aikirun/types/task";
907
- import { SchemaValidationError as SchemaValidationError2 } from "@aikirun/types/validator";
970
+ import { TaskFailedError } from "@aikirun/types/task-error";
908
971
  import {
909
- NonDeterminismError,
910
- WorkflowRunFailedError as WorkflowRunFailedError2,
972
+ NonDeterminismError as NonDeterminismError2,
973
+ WorkflowRunFailedError as WorkflowRunFailedError3,
911
974
  WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError5,
912
975
  WorkflowRunSuspendedError as WorkflowRunSuspendedError4
913
- } from "@aikirun/types/workflow-run";
976
+ } from "@aikirun/types/workflow-run-error";
977
+ function task(params) {
978
+ return new TaskImpl(params);
979
+ }
980
+ var TaskImpl = class {
981
+ constructor(params) {
982
+ this.params = params;
983
+ this.name = params.name;
984
+ }
985
+ name;
986
+ with() {
987
+ const startOptions = this.params.options ?? {};
988
+ const startOptionsOverrider = objectOverrider(startOptions);
989
+ return new TaskBuilderImpl(this, startOptionsOverrider());
990
+ }
991
+ async start(run, ...args) {
992
+ return this.startWithOptions(run, this.params.options ?? {}, ...args);
993
+ }
994
+ async startWithOptions(run, startOptions, ...args) {
995
+ const handle = run[INTERNAL5].handle;
996
+ handle[INTERNAL5].assertExecutionAllowed();
997
+ const inputRaw = args[0];
998
+ const input = await this.parse(handle, this.params.schema?.input, inputRaw, run.logger);
999
+ const inputHash = await hashInput(input);
1000
+ const address = getTaskAddress(this.name, inputHash);
1001
+ const replayManifest = run[INTERNAL5].replayManifest;
1002
+ if (replayManifest.hasUnconsumedEntries()) {
1003
+ const existingTaskInfo = replayManifest.consumeNextTask(address);
1004
+ if (existingTaskInfo) {
1005
+ return this.getExistingTaskResult(run, handle, startOptions, input, existingTaskInfo);
1006
+ }
1007
+ await this.throwNonDeterminismError(run, handle, inputHash, replayManifest.getUnconsumedEntries());
1008
+ }
1009
+ const attempts = 1;
1010
+ const retryStrategy = startOptions.retry ?? { type: "never" };
1011
+ const taskInfo = await handle[INTERNAL5].transitionTaskState({
1012
+ type: "create",
1013
+ taskName: this.name,
1014
+ options: startOptions,
1015
+ taskState: { status: "running", attempts, input }
1016
+ });
1017
+ const logger = run.logger.child({
1018
+ "aiki.taskName": this.name,
1019
+ "aiki.taskId": taskInfo.id
1020
+ });
1021
+ logger.info("Task started", { "aiki.attempts": attempts });
1022
+ const { output, lastAttempt } = await this.tryExecuteTask(
1023
+ handle,
1024
+ input,
1025
+ taskInfo.id,
1026
+ retryStrategy,
1027
+ attempts,
1028
+ run[INTERNAL5].options.spinThresholdMs,
1029
+ logger
1030
+ );
1031
+ await handle[INTERNAL5].transitionTaskState({
1032
+ taskId: taskInfo.id,
1033
+ taskState: { status: "completed", attempts: lastAttempt, output }
1034
+ });
1035
+ logger.info("Task complete", { "aiki.attempts": lastAttempt });
1036
+ return output;
1037
+ }
1038
+ async getExistingTaskResult(run, handle, startOptions, input, existingTaskInfo) {
1039
+ const existingTaskState = existingTaskInfo.state;
1040
+ if (existingTaskState.status === "completed") {
1041
+ return this.parse(handle, this.params.schema?.output, existingTaskState.output, run.logger);
1042
+ }
1043
+ if (existingTaskState.status === "failed") {
1044
+ throw new TaskFailedError(
1045
+ existingTaskInfo.id,
1046
+ existingTaskState.attempts,
1047
+ existingTaskState.error.message
1048
+ );
1049
+ }
1050
+ existingTaskState.status;
1051
+ const attempts = existingTaskState.attempts;
1052
+ const retryStrategy = startOptions.retry ?? { type: "never" };
1053
+ this.assertRetryAllowed(existingTaskInfo.id, attempts, retryStrategy, run.logger);
1054
+ run.logger.debug("Retrying task", {
1055
+ "aiki.taskName": this.name,
1056
+ "aiki.taskId": existingTaskInfo.id,
1057
+ "aiki.attempts": attempts,
1058
+ "aiki.taskStatus": existingTaskState.status
1059
+ });
1060
+ return this.retryAndExecute(run, handle, input, existingTaskInfo.id, startOptions, retryStrategy, attempts);
1061
+ }
1062
+ async throwNonDeterminismError(run, handle, inputHash, unconsumedManifestEntries) {
1063
+ run.logger.error("Replay divergence", {
1064
+ "aiki.taskName": this.name,
1065
+ "aiki.inputHash": inputHash,
1066
+ "aiki.unconsumedManifestEntries": unconsumedManifestEntries
1067
+ });
1068
+ const error = new NonDeterminismError2(run.id, handle.run.attempts, unconsumedManifestEntries);
1069
+ await handle[INTERNAL5].transitionState({
1070
+ status: "failed",
1071
+ cause: "self",
1072
+ error: createSerializableError(error)
1073
+ });
1074
+ throw error;
1075
+ }
1076
+ async retryAndExecute(run, handle, input, taskId, startOptions, retryStrategy, previousAttempts) {
1077
+ const attempts = previousAttempts + 1;
1078
+ const taskInfo = await handle[INTERNAL5].transitionTaskState({
1079
+ type: "retry",
1080
+ taskId,
1081
+ options: startOptions,
1082
+ taskState: { status: "running", attempts, input }
1083
+ });
1084
+ const logger = run.logger.child({
1085
+ "aiki.taskName": this.name,
1086
+ "aiki.taskId": taskInfo.id
1087
+ });
1088
+ logger.info("Task started", { "aiki.attempts": attempts });
1089
+ const { output, lastAttempt } = await this.tryExecuteTask(
1090
+ handle,
1091
+ input,
1092
+ taskInfo.id,
1093
+ retryStrategy,
1094
+ attempts,
1095
+ run[INTERNAL5].options.spinThresholdMs,
1096
+ logger
1097
+ );
1098
+ await handle[INTERNAL5].transitionTaskState({
1099
+ taskId: taskInfo.id,
1100
+ taskState: { status: "completed", attempts: lastAttempt, output }
1101
+ });
1102
+ logger.info("Task complete", { "aiki.attempts": lastAttempt });
1103
+ return output;
1104
+ }
1105
+ async tryExecuteTask(handle, input, taskId, retryStrategy, currentAttempt, spinThresholdMs, logger) {
1106
+ let attempts = currentAttempt;
1107
+ while (true) {
1108
+ try {
1109
+ const outputRaw = await this.params.handler(input);
1110
+ const output = await this.parse(handle, this.params.schema?.output, outputRaw, logger);
1111
+ return { output, lastAttempt: attempts };
1112
+ } catch (error) {
1113
+ if (error instanceof WorkflowRunSuspendedError4 || error instanceof WorkflowRunFailedError3 || error instanceof WorkflowRunRevisionConflictError5) {
1114
+ throw error;
1115
+ }
1116
+ const serializableError = createSerializableError(error);
1117
+ const retryParams = getRetryParams(attempts, retryStrategy);
1118
+ if (!retryParams.retriesLeft) {
1119
+ logger.error("Task failed", {
1120
+ "aiki.attempts": attempts,
1121
+ "aiki.reason": serializableError.message
1122
+ });
1123
+ await handle[INTERNAL5].transitionTaskState({
1124
+ taskId,
1125
+ taskState: { status: "failed", attempts, error: serializableError }
1126
+ });
1127
+ throw new TaskFailedError(taskId, attempts, serializableError.message);
1128
+ }
1129
+ logger.debug("Task failed. It will be retried", {
1130
+ "aiki.attempts": attempts,
1131
+ "aiki.nextAttemptInMs": retryParams.delayMs,
1132
+ "aiki.reason": serializableError.message
1133
+ });
1134
+ if (retryParams.delayMs <= spinThresholdMs) {
1135
+ await delay(retryParams.delayMs);
1136
+ attempts++;
1137
+ continue;
1138
+ }
1139
+ await handle[INTERNAL5].transitionTaskState({
1140
+ taskId,
1141
+ taskState: {
1142
+ status: "awaiting_retry",
1143
+ attempts,
1144
+ error: serializableError,
1145
+ nextAttemptInMs: retryParams.delayMs
1146
+ }
1147
+ });
1148
+ throw new WorkflowRunSuspendedError4(handle.run.id);
1149
+ }
1150
+ }
1151
+ }
1152
+ assertRetryAllowed(taskId, attempts, retryStrategy, logger) {
1153
+ const retryParams = getRetryParams(attempts, retryStrategy);
1154
+ if (!retryParams.retriesLeft) {
1155
+ logger.error("Task retry not allowed", {
1156
+ "aiki.taskName": this.name,
1157
+ "aiki.taskId": taskId,
1158
+ "aiki.attempts": attempts
1159
+ });
1160
+ throw new TaskFailedError(taskId, attempts, "Task retry not allowed");
1161
+ }
1162
+ }
1163
+ async parse(handle, schema, data, logger) {
1164
+ if (!schema) {
1165
+ return data;
1166
+ }
1167
+ const schemaValidation = schema["~standard"].validate(data);
1168
+ const schemaValidationResult = schemaValidation instanceof Promise ? await schemaValidation : schemaValidation;
1169
+ if (!schemaValidationResult.issues) {
1170
+ return schemaValidationResult.value;
1171
+ }
1172
+ logger.error("Invalid task data", { "aiki.issues": schemaValidationResult.issues });
1173
+ await handle[INTERNAL5].transitionState({
1174
+ status: "failed",
1175
+ cause: "self",
1176
+ error: {
1177
+ name: "SchemaValidationError",
1178
+ message: JSON.stringify(schemaValidationResult.issues)
1179
+ }
1180
+ });
1181
+ throw new WorkflowRunFailedError3(handle.run.id, handle.run.attempts);
1182
+ }
1183
+ };
1184
+ var TaskBuilderImpl = class _TaskBuilderImpl {
1185
+ constructor(task2, startOptionsBuilder) {
1186
+ this.task = task2;
1187
+ this.startOptionsBuilder = startOptionsBuilder;
1188
+ }
1189
+ opt(path, value) {
1190
+ return new _TaskBuilderImpl(this.task, this.startOptionsBuilder.with(path, value));
1191
+ }
1192
+ start(run, ...args) {
1193
+ return this.task.startWithOptions(run, this.startOptionsBuilder.build(), ...args);
1194
+ }
1195
+ };
1196
+
1197
+ // workflow.ts
1198
+ import { INTERNAL as INTERNAL8 } from "@aikirun/types/symbols";
1199
+
1200
+ // workflow-version.ts
1201
+ import { INTERNAL as INTERNAL7 } from "@aikirun/types/symbols";
1202
+ import { TaskFailedError as TaskFailedError2 } from "@aikirun/types/task-error";
1203
+ import { SchemaValidationError as SchemaValidationError2 } from "@aikirun/types/validator";
1204
+ import {
1205
+ NonDeterminismError as NonDeterminismError3,
1206
+ WorkflowRunFailedError as WorkflowRunFailedError4,
1207
+ WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError7,
1208
+ WorkflowRunSuspendedError as WorkflowRunSuspendedError6
1209
+ } from "@aikirun/types/workflow-run-error";
914
1210
 
915
1211
  // run/handle-child.ts
916
- import { INTERNAL as INTERNAL4 } from "@aikirun/types/symbols";
1212
+ import { INTERNAL as INTERNAL6 } from "@aikirun/types/symbols";
917
1213
  import {
918
- isTerminalWorkflowRunStatus,
919
- WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError4,
920
- WorkflowRunSuspendedError as WorkflowRunSuspendedError3
1214
+ isTerminalWorkflowRunStatus
921
1215
  } from "@aikirun/types/workflow-run";
1216
+ import { WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError6, WorkflowRunSuspendedError as WorkflowRunSuspendedError5 } from "@aikirun/types/workflow-run-error";
922
1217
  async function childWorkflowRunHandle(client, run, parentRun, childWorkflowRunWaitQueues, logger, eventsDefinition) {
923
1218
  const handle = await workflowRunHandle(client, run, eventsDefinition, logger);
924
1219
  return {
@@ -930,7 +1225,7 @@ async function childWorkflowRunHandle(client, run, parentRun, childWorkflowRunWa
930
1225
  pause: handle.pause.bind(handle),
931
1226
  resume: handle.resume.bind(handle),
932
1227
  awake: handle.awake.bind(handle),
933
- [INTERNAL4]: handle[INTERNAL4]
1228
+ [INTERNAL6]: handle[INTERNAL6]
934
1229
  };
935
1230
  }
936
1231
  function createStatusWaiter(handle, parentRun, childWorkflowRunWaitQueues, logger) {
@@ -940,7 +1235,7 @@ function createStatusWaiter(handle, parentRun, childWorkflowRunWaitQueues, logge
940
1235
  failed: 0
941
1236
  };
942
1237
  async function waitForStatus(expectedStatus, options) {
943
- const parentRunHandle = parentRun[INTERNAL4].handle;
1238
+ const parentRunHandle = parentRun[INTERNAL6].handle;
944
1239
  const nextIndex = nextIndexByStatus[expectedStatus];
945
1240
  const { run } = handle;
946
1241
  const childWorkflowRunWaits = childWorkflowRunWaitQueues[expectedStatus].childWorkflowRunWaits;
@@ -976,7 +1271,7 @@ function createStatusWaiter(handle, parentRun, childWorkflowRunWaitQueues, logge
976
1271
  }
977
1272
  const timeoutInMs = options?.timeout && toMilliseconds(options.timeout);
978
1273
  try {
979
- await parentRunHandle[INTERNAL4].transitionState({
1274
+ await parentRunHandle[INTERNAL6].transitionState({
980
1275
  status: "awaiting_child_workflow",
981
1276
  childWorkflowRunId: run.id,
982
1277
  childWorkflowRunStatus: expectedStatus,
@@ -987,12 +1282,12 @@ function createStatusWaiter(handle, parentRun, childWorkflowRunWaitQueues, logge
987
1282
  ...timeoutInMs !== void 0 ? { "aiki.timeoutInMs": timeoutInMs } : {}
988
1283
  });
989
1284
  } catch (error) {
990
- if (error instanceof WorkflowRunRevisionConflictError4) {
991
- throw new WorkflowRunSuspendedError3(parentRun.id);
1285
+ if (error instanceof WorkflowRunRevisionConflictError6) {
1286
+ throw new WorkflowRunSuspendedError5(parentRun.id);
992
1287
  }
993
1288
  throw error;
994
1289
  }
995
- throw new WorkflowRunSuspendedError3(parentRun.id);
1290
+ throw new WorkflowRunSuspendedError5(parentRun.id);
996
1291
  }
997
1292
  return waitForStatus;
998
1293
  }
@@ -1005,22 +1300,22 @@ var WorkflowVersionImpl = class {
1005
1300
  this.params = params;
1006
1301
  const eventsDefinition = this.params.events ?? {};
1007
1302
  this.events = createEventMulticasters(this.name, this.versionId, eventsDefinition);
1008
- this[INTERNAL5] = {
1303
+ this[INTERNAL7] = {
1009
1304
  eventsDefinition,
1010
1305
  handler: this.handler.bind(this)
1011
1306
  };
1012
1307
  }
1013
1308
  events;
1014
- [INTERNAL5];
1309
+ [INTERNAL7];
1015
1310
  with() {
1016
- const startOpts = this.params.opts ?? {};
1017
- const startOptsOverrider = objectOverrider(startOpts);
1018
- return new WorkflowBuilderImpl(this, startOptsOverrider());
1311
+ const startOptions = this.params.options ?? {};
1312
+ const startOptionsOverrider = objectOverrider(startOptions);
1313
+ return new WorkflowBuilderImpl(this, startOptionsOverrider());
1019
1314
  }
1020
1315
  async start(client, ...args) {
1021
- return this.startWithOpts(client, this.params.opts ?? {}, ...args);
1316
+ return this.startWithOptions(client, this.params.options ?? {}, ...args);
1022
1317
  }
1023
- async startWithOpts(client, startOpts, ...args) {
1318
+ async startWithOptions(client, startOptions, ...args) {
1024
1319
  let input = args[0];
1025
1320
  const schema = this.params.schema?.input;
1026
1321
  if (schema) {
@@ -1036,28 +1331,28 @@ var WorkflowVersionImpl = class {
1036
1331
  name: this.name,
1037
1332
  versionId: this.versionId,
1038
1333
  input,
1039
- options: startOpts
1334
+ options: startOptions
1040
1335
  });
1041
1336
  client.logger.info("Created workflow", {
1042
1337
  "aiki.workflowName": this.name,
1043
1338
  "aiki.workflowVersionId": this.versionId,
1044
1339
  "aiki.workflowRunId": id
1045
1340
  });
1046
- return workflowRunHandle(client, id, this[INTERNAL5].eventsDefinition);
1341
+ return workflowRunHandle(client, id, this[INTERNAL7].eventsDefinition);
1047
1342
  }
1048
1343
  async startAsChild(parentRun, ...args) {
1049
- return this.startAsChildWithOpts(parentRun, this.params.opts ?? {}, ...args);
1344
+ return this.startAsChildWithOptions(parentRun, this.params.options ?? {}, ...args);
1050
1345
  }
1051
- async startAsChildWithOpts(parentRun, startOpts, ...args) {
1052
- const parentRunHandle = parentRun[INTERNAL5].handle;
1053
- parentRunHandle[INTERNAL5].assertExecutionAllowed();
1054
- const { client } = parentRunHandle[INTERNAL5];
1346
+ async startAsChildWithOptions(parentRun, startOptions, ...args) {
1347
+ const parentRunHandle = parentRun[INTERNAL7].handle;
1348
+ parentRunHandle[INTERNAL7].assertExecutionAllowed();
1349
+ const { client } = parentRunHandle[INTERNAL7];
1055
1350
  const inputRaw = args[0];
1056
1351
  const input = await this.parse(parentRunHandle, this.params.schema?.input, inputRaw, parentRun.logger);
1057
1352
  const inputHash = await hashInput(input);
1058
- const referenceId = startOpts.reference?.id;
1353
+ const referenceId = startOptions.reference?.id;
1059
1354
  const address = getWorkflowRunAddress(this.name, this.versionId, referenceId ?? inputHash);
1060
- const replayManifest = parentRun[INTERNAL5].replayManifest;
1355
+ const replayManifest = parentRun[INTERNAL7].replayManifest;
1061
1356
  if (replayManifest.hasUnconsumedEntries()) {
1062
1357
  const existingRunInfo = replayManifest.consumeNextChildWorkflowRun(address);
1063
1358
  if (existingRunInfo) {
@@ -1076,7 +1371,7 @@ var WorkflowVersionImpl = class {
1076
1371
  parentRun,
1077
1372
  existingRunInfo.childWorkflowRunWaitQueues,
1078
1373
  logger2,
1079
- this[INTERNAL5].eventsDefinition
1374
+ this[INTERNAL7].eventsDefinition
1080
1375
  );
1081
1376
  }
1082
1377
  await this.throwNonDeterminismError(parentRun, parentRunHandle, inputHash, referenceId, replayManifest);
@@ -1087,7 +1382,7 @@ var WorkflowVersionImpl = class {
1087
1382
  versionId: this.versionId,
1088
1383
  input,
1089
1384
  parentWorkflowRunId: parentRun.id,
1090
- options: shard === void 0 ? startOpts : { ...startOpts, shard }
1385
+ options: shard === void 0 ? startOptions : { ...startOptions, shard }
1091
1386
  });
1092
1387
  const { run: newRun } = await client.api.workflowRun.getByIdV1({ id: newRunId });
1093
1388
  const logger = parentRun.logger.child({
@@ -1106,7 +1401,7 @@ var WorkflowVersionImpl = class {
1106
1401
  failed: { childWorkflowRunWaits: [] }
1107
1402
  },
1108
1403
  logger,
1109
- this[INTERNAL5].eventsDefinition
1404
+ this[INTERNAL7].eventsDefinition
1110
1405
  );
1111
1406
  }
1112
1407
  async throwNonDeterminismError(parentRun, parentRunHandle, inputHash, referenceId, manifest) {
@@ -1120,8 +1415,8 @@ var WorkflowVersionImpl = class {
1120
1415
  logMeta["aiki.referenceId"] = referenceId;
1121
1416
  }
1122
1417
  parentRun.logger.error("Replay divergence", logMeta);
1123
- const error = new NonDeterminismError(parentRun.id, parentRunHandle.run.attempts, unconsumedManifestEntries);
1124
- await parentRunHandle[INTERNAL5].transitionState({
1418
+ const error = new NonDeterminismError3(parentRun.id, parentRunHandle.run.attempts, unconsumedManifestEntries);
1419
+ await parentRunHandle[INTERNAL7].transitionState({
1125
1420
  status: "failed",
1126
1421
  cause: "self",
1127
1422
  error: createSerializableError(error)
@@ -1129,7 +1424,7 @@ var WorkflowVersionImpl = class {
1129
1424
  throw error;
1130
1425
  }
1131
1426
  async getHandleById(client, runId) {
1132
- return workflowRunHandle(client, runId, this[INTERNAL5].eventsDefinition);
1427
+ return workflowRunHandle(client, runId, this[INTERNAL7].eventsDefinition);
1133
1428
  }
1134
1429
  async getHandleByReferenceId(client, referenceId) {
1135
1430
  const { run } = await client.api.workflowRun.getByReferenceIdV1({
@@ -1137,39 +1432,39 @@ var WorkflowVersionImpl = class {
1137
1432
  versionId: this.versionId,
1138
1433
  referenceId
1139
1434
  });
1140
- return workflowRunHandle(client, run, this[INTERNAL5].eventsDefinition);
1435
+ return workflowRunHandle(client, run, this[INTERNAL7].eventsDefinition);
1141
1436
  }
1142
1437
  async handler(run, input, context) {
1143
1438
  const { logger } = run;
1144
- const { handle } = run[INTERNAL5];
1145
- handle[INTERNAL5].assertExecutionAllowed();
1146
- const retryStrategy = this.params.opts?.retry ?? { type: "never" };
1439
+ const { handle } = run[INTERNAL7];
1440
+ handle[INTERNAL7].assertExecutionAllowed();
1441
+ const retryStrategy = this.params.options?.retry ?? { type: "never" };
1147
1442
  const state = handle.run.state;
1148
1443
  if (state.status === "queued" && state.reason === "retry") {
1149
1444
  await this.assertRetryAllowed(handle, retryStrategy, logger);
1150
1445
  }
1151
1446
  logger.info("Starting workflow");
1152
- await handle[INTERNAL5].transitionState({ status: "running" });
1447
+ await handle[INTERNAL7].transitionState({ status: "running" });
1153
1448
  const output = await this.tryExecuteWorkflow(input, run, context, retryStrategy);
1154
- await handle[INTERNAL5].transitionState({ status: "completed", output });
1449
+ await handle[INTERNAL7].transitionState({ status: "completed", output });
1155
1450
  logger.info("Workflow complete");
1156
1451
  }
1157
1452
  async tryExecuteWorkflow(input, run, context, retryStrategy) {
1158
- const { handle } = run[INTERNAL5];
1453
+ const { handle } = run[INTERNAL7];
1159
1454
  while (true) {
1160
1455
  try {
1161
1456
  const outputRaw = await this.params.handler(run, input, context);
1162
1457
  const output = await this.parse(handle, this.params.schema?.output, outputRaw, run.logger);
1163
1458
  return output;
1164
1459
  } catch (error) {
1165
- if (error instanceof WorkflowRunSuspendedError4 || error instanceof WorkflowRunFailedError2 || error instanceof WorkflowRunRevisionConflictError5 || error instanceof NonDeterminismError) {
1460
+ if (error instanceof WorkflowRunSuspendedError6 || error instanceof WorkflowRunFailedError4 || error instanceof WorkflowRunRevisionConflictError7 || error instanceof NonDeterminismError3) {
1166
1461
  throw error;
1167
1462
  }
1168
1463
  const attempts = handle.run.attempts;
1169
1464
  const retryParams = getRetryParams(attempts, retryStrategy);
1170
1465
  if (!retryParams.retriesLeft) {
1171
1466
  const failedState = this.createFailedState(error);
1172
- await handle[INTERNAL5].transitionState(failedState);
1467
+ await handle[INTERNAL7].transitionState(failedState);
1173
1468
  const logMeta2 = {};
1174
1469
  for (const [key, value] of Object.entries(failedState)) {
1175
1470
  logMeta2[`aiki.${key}`] = value;
@@ -1178,10 +1473,10 @@ var WorkflowVersionImpl = class {
1178
1473
  "aiki.attempts": attempts,
1179
1474
  ...logMeta2
1180
1475
  });
1181
- throw new WorkflowRunFailedError2(run.id, attempts);
1476
+ throw new WorkflowRunFailedError4(run.id, attempts);
1182
1477
  }
1183
1478
  const awaitingRetryState = this.createAwaitingRetryState(error, retryParams.delayMs);
1184
- await handle[INTERNAL5].transitionState(awaitingRetryState);
1479
+ await handle[INTERNAL7].transitionState(awaitingRetryState);
1185
1480
  const logMeta = {};
1186
1481
  for (const [key, value] of Object.entries(awaitingRetryState)) {
1187
1482
  logMeta[`aiki.${key}`] = value;
@@ -1190,7 +1485,7 @@ var WorkflowVersionImpl = class {
1190
1485
  "aiki.attempts": attempts,
1191
1486
  ...logMeta
1192
1487
  });
1193
- throw new WorkflowRunSuspendedError4(run.id);
1488
+ throw new WorkflowRunSuspendedError6(run.id);
1194
1489
  }
1195
1490
  }
1196
1491
  }
@@ -1199,8 +1494,8 @@ var WorkflowVersionImpl = class {
1199
1494
  const retryParams = getRetryParams(attempts, retryStrategy);
1200
1495
  if (!retryParams.retriesLeft) {
1201
1496
  logger.error("Workflow retry not allowed", { "aiki.attempts": attempts });
1202
- const error = new WorkflowRunFailedError2(id, attempts);
1203
- await handle[INTERNAL5].transitionState({
1497
+ const error = new WorkflowRunFailedError4(id, attempts);
1498
+ await handle[INTERNAL7].transitionState({
1204
1499
  status: "failed",
1205
1500
  cause: "self",
1206
1501
  error: createSerializableError(error)
@@ -1218,7 +1513,7 @@ var WorkflowVersionImpl = class {
1218
1513
  return schemaValidationResult.value;
1219
1514
  }
1220
1515
  logger.error("Invalid workflow data", { "aiki.issues": schemaValidationResult.issues });
1221
- await handle[INTERNAL5].transitionState({
1516
+ await handle[INTERNAL7].transitionState({
1222
1517
  status: "failed",
1223
1518
  cause: "self",
1224
1519
  error: {
@@ -1226,10 +1521,10 @@ var WorkflowVersionImpl = class {
1226
1521
  message: JSON.stringify(schemaValidationResult.issues)
1227
1522
  }
1228
1523
  });
1229
- throw new WorkflowRunFailedError2(handle.run.id, handle.run.attempts);
1524
+ throw new WorkflowRunFailedError4(handle.run.id, handle.run.attempts);
1230
1525
  }
1231
1526
  createFailedState(error) {
1232
- if (error instanceof TaskFailedError) {
1527
+ if (error instanceof TaskFailedError2) {
1233
1528
  return {
1234
1529
  status: "failed",
1235
1530
  cause: "task",
@@ -1243,7 +1538,7 @@ var WorkflowVersionImpl = class {
1243
1538
  };
1244
1539
  }
1245
1540
  createAwaitingRetryState(error, nextAttemptInMs) {
1246
- if (error instanceof TaskFailedError) {
1541
+ if (error instanceof TaskFailedError2) {
1247
1542
  return {
1248
1543
  status: "awaiting_retry",
1249
1544
  cause: "task",
@@ -1260,18 +1555,18 @@ var WorkflowVersionImpl = class {
1260
1555
  }
1261
1556
  };
1262
1557
  var WorkflowBuilderImpl = class _WorkflowBuilderImpl {
1263
- constructor(workflow2, startOptsBuilder) {
1558
+ constructor(workflow2, startOptionsBuilder) {
1264
1559
  this.workflow = workflow2;
1265
- this.startOptsBuilder = startOptsBuilder;
1560
+ this.startOptionsBuilder = startOptionsBuilder;
1266
1561
  }
1267
1562
  opt(path, value) {
1268
- return new _WorkflowBuilderImpl(this.workflow, this.startOptsBuilder.with(path, value));
1563
+ return new _WorkflowBuilderImpl(this.workflow, this.startOptionsBuilder.with(path, value));
1269
1564
  }
1270
1565
  start(client, ...args) {
1271
- return this.workflow.startWithOpts(client, this.startOptsBuilder.build(), ...args);
1566
+ return this.workflow.startWithOptions(client, this.startOptionsBuilder.build(), ...args);
1272
1567
  }
1273
1568
  startAsChild(parentRun, ...args) {
1274
- return this.workflow.startAsChildWithOpts(parentRun, this.startOptsBuilder.build(), ...args);
1569
+ return this.workflow.startAsChildWithOptions(parentRun, this.startOptionsBuilder.build(), ...args);
1275
1570
  }
1276
1571
  };
1277
1572
 
@@ -1281,11 +1576,11 @@ function workflow(params) {
1281
1576
  }
1282
1577
  var WorkflowImpl = class {
1283
1578
  name;
1284
- [INTERNAL6];
1579
+ [INTERNAL8];
1285
1580
  workflowVersions = /* @__PURE__ */ new Map();
1286
1581
  constructor(params) {
1287
1582
  this.name = params.name;
1288
- this[INTERNAL6] = {
1583
+ this[INTERNAL8] = {
1289
1584
  getAllVersions: this.getAllVersions.bind(this),
1290
1585
  getVersion: this.getVersion.bind(this)
1291
1586
  };
@@ -1295,10 +1590,7 @@ var WorkflowImpl = class {
1295
1590
  throw new Error(`Workflow "${this.name}:${versionId}" already exists`);
1296
1591
  }
1297
1592
  const workflowVersion = new WorkflowVersionImpl(this.name, versionId, params);
1298
- this.workflowVersions.set(
1299
- versionId,
1300
- workflowVersion
1301
- );
1593
+ this.workflowVersions.set(versionId, workflowVersion);
1302
1594
  return workflowVersion;
1303
1595
  }
1304
1596
  getAllVersions() {
@@ -1308,13 +1600,49 @@ var WorkflowImpl = class {
1308
1600
  return this.workflowVersions.get(versionId);
1309
1601
  }
1310
1602
  };
1603
+
1604
+ // system/cancel-child-runs.ts
1605
+ var createCancelChildRunsV1 = (api) => {
1606
+ const listNonTerminalChildRuns = task({
1607
+ name: "aiki:list-non-terminal-child-runs",
1608
+ async handler(parentRunId) {
1609
+ const { runs } = await api.workflowRun.listChildRunsV1({
1610
+ parentRunId,
1611
+ status: NON_TERMINAL_WORKFLOW_RUN_STATUSES
1612
+ });
1613
+ return runs.map((r) => r.id);
1614
+ }
1615
+ });
1616
+ const cancelRuns = task({
1617
+ name: "aiki:cancel-runs",
1618
+ async handler(runIds) {
1619
+ const { cancelledIds } = await api.workflowRun.cancelByIdsV1({ ids: runIds });
1620
+ return cancelledIds;
1621
+ }
1622
+ });
1623
+ return workflow({ name: "aiki:cancel-child-runs" }).v("1.0.0", {
1624
+ async handler(run, parentRunId) {
1625
+ const childRunIds = await listNonTerminalChildRuns.start(run, parentRunId);
1626
+ if (!isNonEmptyArray(childRunIds)) {
1627
+ return;
1628
+ }
1629
+ await cancelRuns.start(run, childRunIds);
1630
+ }
1631
+ });
1632
+ };
1633
+
1634
+ // system/index.ts
1635
+ function getSystemWorkflows(api) {
1636
+ return [createCancelChildRunsV1(api)];
1637
+ }
1311
1638
  export {
1312
- WorkflowVersionImpl,
1313
1639
  createEventSenders,
1314
1640
  createEventWaiters,
1315
1641
  createReplayManifest,
1316
1642
  createSleeper,
1317
1643
  event,
1644
+ executeWorkflowRun,
1645
+ getSystemWorkflows,
1318
1646
  schedule,
1319
1647
  workflow,
1320
1648
  workflowRegistry,