@aikirun/workflow 0.23.0 → 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(
@@ -581,12 +538,13 @@ var WorkflowRunHandleImpl = class {
581
538
  const delayMs = options?.interval ? toMilliseconds(options.interval) : 1e3;
582
539
  const maxAttempts = options?.timeout ? Math.ceil(toMilliseconds(options.timeout) / delayMs) : Number.POSITIVE_INFINITY;
583
540
  const retryStrategy = { type: "fixed", maxAttempts, delayMs };
584
- const afterStateTransitionId = this._run.stateTransitionId;
541
+ let afterStateTransitionId = this._run.stateTransitionId;
585
542
  const hasTerminated = async () => {
586
- const { terminated } = await this.api.workflowRun.hasTerminatedV1({
543
+ const { terminated, latestStateTransitionId } = await this.api.workflowRun.hasTerminatedV1({
587
544
  id: this._run.id,
588
545
  afterStateTransitionId
589
546
  });
547
+ afterStateTransitionId = latestStateTransitionId;
590
548
  return terminated;
591
549
  };
592
550
  const shouldRetryOnResult = async (terminated) => !terminated;
@@ -706,10 +664,10 @@ function createReplayManifest(run) {
706
664
  if (nextIndex >= taskCount) {
707
665
  return void 0;
708
666
  }
709
- const task = taskQueues[address].tasks[nextIndex];
667
+ const task2 = taskQueues[address].tasks[nextIndex];
710
668
  nextTaskIndexByAddress[address] = nextIndex + 1;
711
669
  consumedEntries++;
712
- return task;
670
+ return task2;
713
671
  },
714
672
  consumeNextChildWorkflowRun(address) {
715
673
  const childWorkflowRunCount = childWorkflowRunCountByAddress[address] ?? 0;
@@ -749,10 +707,7 @@ function createReplayManifest(run) {
749
707
 
750
708
  // run/sleeper.ts
751
709
  import { INTERNAL as INTERNAL3 } from "@aikirun/types/symbols";
752
- import {
753
- WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError3,
754
- WorkflowRunSuspendedError as WorkflowRunSuspendedError2
755
- } from "@aikirun/types/workflow-run";
710
+ import { WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError3, WorkflowRunSuspendedError as WorkflowRunSuspendedError2 } from "@aikirun/types/workflow-run-error";
756
711
  var MAX_SLEEP_YEARS = 10;
757
712
  var MAX_SLEEP_MS = MAX_SLEEP_YEARS * 365 * 24 * 60 * 60 * 1e3;
758
713
  function createSleeper(handle, logger) {
@@ -831,9 +786,64 @@ function createSleeper(handle, logger) {
831
786
  };
832
787
  }
833
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
+
834
844
  // schedule.ts
835
845
  function schedule(params) {
836
- async function activateWithOpts(client, workflow2, options, ...args) {
846
+ async function activateWithOptions(client, workflow2, options, ...args) {
837
847
  const input = args[0];
838
848
  let scheduleSpec;
839
849
  if (params.type === "interval") {
@@ -872,52 +882,338 @@ function schedule(params) {
872
882
  }
873
883
  };
874
884
  }
875
- function createBuilder(optsBuilder) {
885
+ function createBuilder(optionsBuilder) {
876
886
  return {
877
- opt: (path, value) => createBuilder(optsBuilder.with(path, value)),
887
+ opt: (path, value) => createBuilder(optionsBuilder.with(path, value)),
878
888
  async activate(client, workflow2, ...args) {
879
- return activateWithOpts(client, workflow2, optsBuilder.build(), ...args);
889
+ return activateWithOptions(client, workflow2, optionsBuilder.build(), ...args);
880
890
  }
881
891
  };
882
892
  }
883
893
  return {
884
894
  ...params,
885
895
  with() {
886
- const optsOverrider = objectOverrider({});
887
- return createBuilder(optsOverrider());
896
+ const optionsOverrider = objectOverrider({});
897
+ return createBuilder(optionsOverrider());
888
898
  },
889
899
  async activate(client, workflow2, ...args) {
890
- return activateWithOpts(client, workflow2, {}, ...args);
900
+ return activateWithOptions(client, workflow2, {}, ...args);
891
901
  }
892
902
  };
893
903
  }
894
904
 
895
- // workflow.ts
896
- 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";
897
907
 
898
908
  // ../../lib/address/index.ts
909
+ function getTaskAddress(name, inputHash) {
910
+ return `${name}:${inputHash}`;
911
+ }
899
912
  function getWorkflowRunAddress(name, versionId, referenceId) {
900
913
  return `${name}:${versionId}:${referenceId}`;
901
914
  }
902
915
 
903
- // 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
904
969
  import { INTERNAL as INTERNAL5 } from "@aikirun/types/symbols";
905
- import { TaskFailedError } from "@aikirun/types/task";
906
- import { SchemaValidationError as SchemaValidationError2 } from "@aikirun/types/validator";
970
+ import { TaskFailedError } from "@aikirun/types/task-error";
907
971
  import {
908
- NonDeterminismError,
909
- WorkflowRunFailedError as WorkflowRunFailedError2,
972
+ NonDeterminismError as NonDeterminismError2,
973
+ WorkflowRunFailedError as WorkflowRunFailedError3,
910
974
  WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError5,
911
975
  WorkflowRunSuspendedError as WorkflowRunSuspendedError4
912
- } 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";
913
1210
 
914
1211
  // run/handle-child.ts
915
- import { INTERNAL as INTERNAL4 } from "@aikirun/types/symbols";
1212
+ import { INTERNAL as INTERNAL6 } from "@aikirun/types/symbols";
916
1213
  import {
917
- isTerminalWorkflowRunStatus,
918
- WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError4,
919
- WorkflowRunSuspendedError as WorkflowRunSuspendedError3
1214
+ isTerminalWorkflowRunStatus
920
1215
  } from "@aikirun/types/workflow-run";
1216
+ import { WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError6, WorkflowRunSuspendedError as WorkflowRunSuspendedError5 } from "@aikirun/types/workflow-run-error";
921
1217
  async function childWorkflowRunHandle(client, run, parentRun, childWorkflowRunWaitQueues, logger, eventsDefinition) {
922
1218
  const handle = await workflowRunHandle(client, run, eventsDefinition, logger);
923
1219
  return {
@@ -929,7 +1225,7 @@ async function childWorkflowRunHandle(client, run, parentRun, childWorkflowRunWa
929
1225
  pause: handle.pause.bind(handle),
930
1226
  resume: handle.resume.bind(handle),
931
1227
  awake: handle.awake.bind(handle),
932
- [INTERNAL4]: handle[INTERNAL4]
1228
+ [INTERNAL6]: handle[INTERNAL6]
933
1229
  };
934
1230
  }
935
1231
  function createStatusWaiter(handle, parentRun, childWorkflowRunWaitQueues, logger) {
@@ -939,7 +1235,7 @@ function createStatusWaiter(handle, parentRun, childWorkflowRunWaitQueues, logge
939
1235
  failed: 0
940
1236
  };
941
1237
  async function waitForStatus(expectedStatus, options) {
942
- const parentRunHandle = parentRun[INTERNAL4].handle;
1238
+ const parentRunHandle = parentRun[INTERNAL6].handle;
943
1239
  const nextIndex = nextIndexByStatus[expectedStatus];
944
1240
  const { run } = handle;
945
1241
  const childWorkflowRunWaits = childWorkflowRunWaitQueues[expectedStatus].childWorkflowRunWaits;
@@ -975,7 +1271,7 @@ function createStatusWaiter(handle, parentRun, childWorkflowRunWaitQueues, logge
975
1271
  }
976
1272
  const timeoutInMs = options?.timeout && toMilliseconds(options.timeout);
977
1273
  try {
978
- await parentRunHandle[INTERNAL4].transitionState({
1274
+ await parentRunHandle[INTERNAL6].transitionState({
979
1275
  status: "awaiting_child_workflow",
980
1276
  childWorkflowRunId: run.id,
981
1277
  childWorkflowRunStatus: expectedStatus,
@@ -986,12 +1282,12 @@ function createStatusWaiter(handle, parentRun, childWorkflowRunWaitQueues, logge
986
1282
  ...timeoutInMs !== void 0 ? { "aiki.timeoutInMs": timeoutInMs } : {}
987
1283
  });
988
1284
  } catch (error) {
989
- if (error instanceof WorkflowRunRevisionConflictError4) {
990
- throw new WorkflowRunSuspendedError3(parentRun.id);
1285
+ if (error instanceof WorkflowRunRevisionConflictError6) {
1286
+ throw new WorkflowRunSuspendedError5(parentRun.id);
991
1287
  }
992
1288
  throw error;
993
1289
  }
994
- throw new WorkflowRunSuspendedError3(parentRun.id);
1290
+ throw new WorkflowRunSuspendedError5(parentRun.id);
995
1291
  }
996
1292
  return waitForStatus;
997
1293
  }
@@ -1004,22 +1300,22 @@ var WorkflowVersionImpl = class {
1004
1300
  this.params = params;
1005
1301
  const eventsDefinition = this.params.events ?? {};
1006
1302
  this.events = createEventMulticasters(this.name, this.versionId, eventsDefinition);
1007
- this[INTERNAL5] = {
1303
+ this[INTERNAL7] = {
1008
1304
  eventsDefinition,
1009
1305
  handler: this.handler.bind(this)
1010
1306
  };
1011
1307
  }
1012
1308
  events;
1013
- [INTERNAL5];
1309
+ [INTERNAL7];
1014
1310
  with() {
1015
- const startOpts = this.params.opts ?? {};
1016
- const startOptsOverrider = objectOverrider(startOpts);
1017
- return new WorkflowBuilderImpl(this, startOptsOverrider());
1311
+ const startOptions = this.params.options ?? {};
1312
+ const startOptionsOverrider = objectOverrider(startOptions);
1313
+ return new WorkflowBuilderImpl(this, startOptionsOverrider());
1018
1314
  }
1019
1315
  async start(client, ...args) {
1020
- return this.startWithOpts(client, this.params.opts ?? {}, ...args);
1316
+ return this.startWithOptions(client, this.params.options ?? {}, ...args);
1021
1317
  }
1022
- async startWithOpts(client, startOpts, ...args) {
1318
+ async startWithOptions(client, startOptions, ...args) {
1023
1319
  let input = args[0];
1024
1320
  const schema = this.params.schema?.input;
1025
1321
  if (schema) {
@@ -1035,28 +1331,28 @@ var WorkflowVersionImpl = class {
1035
1331
  name: this.name,
1036
1332
  versionId: this.versionId,
1037
1333
  input,
1038
- options: startOpts
1334
+ options: startOptions
1039
1335
  });
1040
1336
  client.logger.info("Created workflow", {
1041
1337
  "aiki.workflowName": this.name,
1042
1338
  "aiki.workflowVersionId": this.versionId,
1043
1339
  "aiki.workflowRunId": id
1044
1340
  });
1045
- return workflowRunHandle(client, id, this[INTERNAL5].eventsDefinition);
1341
+ return workflowRunHandle(client, id, this[INTERNAL7].eventsDefinition);
1046
1342
  }
1047
1343
  async startAsChild(parentRun, ...args) {
1048
- return this.startAsChildWithOpts(parentRun, this.params.opts ?? {}, ...args);
1344
+ return this.startAsChildWithOptions(parentRun, this.params.options ?? {}, ...args);
1049
1345
  }
1050
- async startAsChildWithOpts(parentRun, startOpts, ...args) {
1051
- const parentRunHandle = parentRun[INTERNAL5].handle;
1052
- parentRunHandle[INTERNAL5].assertExecutionAllowed();
1053
- 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];
1054
1350
  const inputRaw = args[0];
1055
1351
  const input = await this.parse(parentRunHandle, this.params.schema?.input, inputRaw, parentRun.logger);
1056
1352
  const inputHash = await hashInput(input);
1057
- const referenceId = startOpts.reference?.id;
1353
+ const referenceId = startOptions.reference?.id;
1058
1354
  const address = getWorkflowRunAddress(this.name, this.versionId, referenceId ?? inputHash);
1059
- const replayManifest = parentRun[INTERNAL5].replayManifest;
1355
+ const replayManifest = parentRun[INTERNAL7].replayManifest;
1060
1356
  if (replayManifest.hasUnconsumedEntries()) {
1061
1357
  const existingRunInfo = replayManifest.consumeNextChildWorkflowRun(address);
1062
1358
  if (existingRunInfo) {
@@ -1075,7 +1371,7 @@ var WorkflowVersionImpl = class {
1075
1371
  parentRun,
1076
1372
  existingRunInfo.childWorkflowRunWaitQueues,
1077
1373
  logger2,
1078
- this[INTERNAL5].eventsDefinition
1374
+ this[INTERNAL7].eventsDefinition
1079
1375
  );
1080
1376
  }
1081
1377
  await this.throwNonDeterminismError(parentRun, parentRunHandle, inputHash, referenceId, replayManifest);
@@ -1086,7 +1382,7 @@ var WorkflowVersionImpl = class {
1086
1382
  versionId: this.versionId,
1087
1383
  input,
1088
1384
  parentWorkflowRunId: parentRun.id,
1089
- options: shard === void 0 ? startOpts : { ...startOpts, shard }
1385
+ options: shard === void 0 ? startOptions : { ...startOptions, shard }
1090
1386
  });
1091
1387
  const { run: newRun } = await client.api.workflowRun.getByIdV1({ id: newRunId });
1092
1388
  const logger = parentRun.logger.child({
@@ -1105,7 +1401,7 @@ var WorkflowVersionImpl = class {
1105
1401
  failed: { childWorkflowRunWaits: [] }
1106
1402
  },
1107
1403
  logger,
1108
- this[INTERNAL5].eventsDefinition
1404
+ this[INTERNAL7].eventsDefinition
1109
1405
  );
1110
1406
  }
1111
1407
  async throwNonDeterminismError(parentRun, parentRunHandle, inputHash, referenceId, manifest) {
@@ -1119,8 +1415,8 @@ var WorkflowVersionImpl = class {
1119
1415
  logMeta["aiki.referenceId"] = referenceId;
1120
1416
  }
1121
1417
  parentRun.logger.error("Replay divergence", logMeta);
1122
- const error = new NonDeterminismError(parentRun.id, parentRunHandle.run.attempts, unconsumedManifestEntries);
1123
- await parentRunHandle[INTERNAL5].transitionState({
1418
+ const error = new NonDeterminismError3(parentRun.id, parentRunHandle.run.attempts, unconsumedManifestEntries);
1419
+ await parentRunHandle[INTERNAL7].transitionState({
1124
1420
  status: "failed",
1125
1421
  cause: "self",
1126
1422
  error: createSerializableError(error)
@@ -1128,7 +1424,7 @@ var WorkflowVersionImpl = class {
1128
1424
  throw error;
1129
1425
  }
1130
1426
  async getHandleById(client, runId) {
1131
- return workflowRunHandle(client, runId, this[INTERNAL5].eventsDefinition);
1427
+ return workflowRunHandle(client, runId, this[INTERNAL7].eventsDefinition);
1132
1428
  }
1133
1429
  async getHandleByReferenceId(client, referenceId) {
1134
1430
  const { run } = await client.api.workflowRun.getByReferenceIdV1({
@@ -1136,39 +1432,39 @@ var WorkflowVersionImpl = class {
1136
1432
  versionId: this.versionId,
1137
1433
  referenceId
1138
1434
  });
1139
- return workflowRunHandle(client, run, this[INTERNAL5].eventsDefinition);
1435
+ return workflowRunHandle(client, run, this[INTERNAL7].eventsDefinition);
1140
1436
  }
1141
1437
  async handler(run, input, context) {
1142
1438
  const { logger } = run;
1143
- const { handle } = run[INTERNAL5];
1144
- handle[INTERNAL5].assertExecutionAllowed();
1145
- 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" };
1146
1442
  const state = handle.run.state;
1147
1443
  if (state.status === "queued" && state.reason === "retry") {
1148
1444
  await this.assertRetryAllowed(handle, retryStrategy, logger);
1149
1445
  }
1150
1446
  logger.info("Starting workflow");
1151
- await handle[INTERNAL5].transitionState({ status: "running" });
1447
+ await handle[INTERNAL7].transitionState({ status: "running" });
1152
1448
  const output = await this.tryExecuteWorkflow(input, run, context, retryStrategy);
1153
- await handle[INTERNAL5].transitionState({ status: "completed", output });
1449
+ await handle[INTERNAL7].transitionState({ status: "completed", output });
1154
1450
  logger.info("Workflow complete");
1155
1451
  }
1156
1452
  async tryExecuteWorkflow(input, run, context, retryStrategy) {
1157
- const { handle } = run[INTERNAL5];
1453
+ const { handle } = run[INTERNAL7];
1158
1454
  while (true) {
1159
1455
  try {
1160
1456
  const outputRaw = await this.params.handler(run, input, context);
1161
1457
  const output = await this.parse(handle, this.params.schema?.output, outputRaw, run.logger);
1162
1458
  return output;
1163
1459
  } catch (error) {
1164
- 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) {
1165
1461
  throw error;
1166
1462
  }
1167
1463
  const attempts = handle.run.attempts;
1168
1464
  const retryParams = getRetryParams(attempts, retryStrategy);
1169
1465
  if (!retryParams.retriesLeft) {
1170
1466
  const failedState = this.createFailedState(error);
1171
- await handle[INTERNAL5].transitionState(failedState);
1467
+ await handle[INTERNAL7].transitionState(failedState);
1172
1468
  const logMeta2 = {};
1173
1469
  for (const [key, value] of Object.entries(failedState)) {
1174
1470
  logMeta2[`aiki.${key}`] = value;
@@ -1177,10 +1473,10 @@ var WorkflowVersionImpl = class {
1177
1473
  "aiki.attempts": attempts,
1178
1474
  ...logMeta2
1179
1475
  });
1180
- throw new WorkflowRunFailedError2(run.id, attempts);
1476
+ throw new WorkflowRunFailedError4(run.id, attempts);
1181
1477
  }
1182
1478
  const awaitingRetryState = this.createAwaitingRetryState(error, retryParams.delayMs);
1183
- await handle[INTERNAL5].transitionState(awaitingRetryState);
1479
+ await handle[INTERNAL7].transitionState(awaitingRetryState);
1184
1480
  const logMeta = {};
1185
1481
  for (const [key, value] of Object.entries(awaitingRetryState)) {
1186
1482
  logMeta[`aiki.${key}`] = value;
@@ -1189,7 +1485,7 @@ var WorkflowVersionImpl = class {
1189
1485
  "aiki.attempts": attempts,
1190
1486
  ...logMeta
1191
1487
  });
1192
- throw new WorkflowRunSuspendedError4(run.id);
1488
+ throw new WorkflowRunSuspendedError6(run.id);
1193
1489
  }
1194
1490
  }
1195
1491
  }
@@ -1198,8 +1494,8 @@ var WorkflowVersionImpl = class {
1198
1494
  const retryParams = getRetryParams(attempts, retryStrategy);
1199
1495
  if (!retryParams.retriesLeft) {
1200
1496
  logger.error("Workflow retry not allowed", { "aiki.attempts": attempts });
1201
- const error = new WorkflowRunFailedError2(id, attempts);
1202
- await handle[INTERNAL5].transitionState({
1497
+ const error = new WorkflowRunFailedError4(id, attempts);
1498
+ await handle[INTERNAL7].transitionState({
1203
1499
  status: "failed",
1204
1500
  cause: "self",
1205
1501
  error: createSerializableError(error)
@@ -1217,7 +1513,7 @@ var WorkflowVersionImpl = class {
1217
1513
  return schemaValidationResult.value;
1218
1514
  }
1219
1515
  logger.error("Invalid workflow data", { "aiki.issues": schemaValidationResult.issues });
1220
- await handle[INTERNAL5].transitionState({
1516
+ await handle[INTERNAL7].transitionState({
1221
1517
  status: "failed",
1222
1518
  cause: "self",
1223
1519
  error: {
@@ -1225,10 +1521,10 @@ var WorkflowVersionImpl = class {
1225
1521
  message: JSON.stringify(schemaValidationResult.issues)
1226
1522
  }
1227
1523
  });
1228
- throw new WorkflowRunFailedError2(handle.run.id, handle.run.attempts);
1524
+ throw new WorkflowRunFailedError4(handle.run.id, handle.run.attempts);
1229
1525
  }
1230
1526
  createFailedState(error) {
1231
- if (error instanceof TaskFailedError) {
1527
+ if (error instanceof TaskFailedError2) {
1232
1528
  return {
1233
1529
  status: "failed",
1234
1530
  cause: "task",
@@ -1242,7 +1538,7 @@ var WorkflowVersionImpl = class {
1242
1538
  };
1243
1539
  }
1244
1540
  createAwaitingRetryState(error, nextAttemptInMs) {
1245
- if (error instanceof TaskFailedError) {
1541
+ if (error instanceof TaskFailedError2) {
1246
1542
  return {
1247
1543
  status: "awaiting_retry",
1248
1544
  cause: "task",
@@ -1259,18 +1555,18 @@ var WorkflowVersionImpl = class {
1259
1555
  }
1260
1556
  };
1261
1557
  var WorkflowBuilderImpl = class _WorkflowBuilderImpl {
1262
- constructor(workflow2, startOptsBuilder) {
1558
+ constructor(workflow2, startOptionsBuilder) {
1263
1559
  this.workflow = workflow2;
1264
- this.startOptsBuilder = startOptsBuilder;
1560
+ this.startOptionsBuilder = startOptionsBuilder;
1265
1561
  }
1266
1562
  opt(path, value) {
1267
- return new _WorkflowBuilderImpl(this.workflow, this.startOptsBuilder.with(path, value));
1563
+ return new _WorkflowBuilderImpl(this.workflow, this.startOptionsBuilder.with(path, value));
1268
1564
  }
1269
1565
  start(client, ...args) {
1270
- return this.workflow.startWithOpts(client, this.startOptsBuilder.build(), ...args);
1566
+ return this.workflow.startWithOptions(client, this.startOptionsBuilder.build(), ...args);
1271
1567
  }
1272
1568
  startAsChild(parentRun, ...args) {
1273
- return this.workflow.startAsChildWithOpts(parentRun, this.startOptsBuilder.build(), ...args);
1569
+ return this.workflow.startAsChildWithOptions(parentRun, this.startOptionsBuilder.build(), ...args);
1274
1570
  }
1275
1571
  };
1276
1572
 
@@ -1280,11 +1576,11 @@ function workflow(params) {
1280
1576
  }
1281
1577
  var WorkflowImpl = class {
1282
1578
  name;
1283
- [INTERNAL6];
1579
+ [INTERNAL8];
1284
1580
  workflowVersions = /* @__PURE__ */ new Map();
1285
1581
  constructor(params) {
1286
1582
  this.name = params.name;
1287
- this[INTERNAL6] = {
1583
+ this[INTERNAL8] = {
1288
1584
  getAllVersions: this.getAllVersions.bind(this),
1289
1585
  getVersion: this.getVersion.bind(this)
1290
1586
  };
@@ -1294,10 +1590,7 @@ var WorkflowImpl = class {
1294
1590
  throw new Error(`Workflow "${this.name}:${versionId}" already exists`);
1295
1591
  }
1296
1592
  const workflowVersion = new WorkflowVersionImpl(this.name, versionId, params);
1297
- this.workflowVersions.set(
1298
- versionId,
1299
- workflowVersion
1300
- );
1593
+ this.workflowVersions.set(versionId, workflowVersion);
1301
1594
  return workflowVersion;
1302
1595
  }
1303
1596
  getAllVersions() {
@@ -1307,13 +1600,49 @@ var WorkflowImpl = class {
1307
1600
  return this.workflowVersions.get(versionId);
1308
1601
  }
1309
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
+ }
1310
1638
  export {
1311
- WorkflowVersionImpl,
1312
1639
  createEventSenders,
1313
1640
  createEventWaiters,
1314
1641
  createReplayManifest,
1315
1642
  createSleeper,
1316
1643
  event,
1644
+ executeWorkflowRun,
1645
+ getSystemWorkflows,
1317
1646
  schedule,
1318
1647
  workflow,
1319
1648
  workflowRegistry,