@aikirun/workflow 0.6.0 → 0.8.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/README.md CHANGED
@@ -16,10 +16,10 @@ npm install @aikirun/workflow
16
16
  import { workflow } from "@aikirun/workflow";
17
17
  import { markUserVerified, sendVerificationEmail } from "./tasks.ts";
18
18
 
19
- export const onboardingWorkflow = workflow({ id: "user-onboarding" });
19
+ export const onboardingWorkflow = workflow({ name: "user-onboarding" });
20
20
 
21
- export const onboardingWorkflowV1 = onboardingWorkflow.v("1.0", {
22
- async handler(input: { email: string }, run) {
21
+ export const onboardingWorkflowV1 = onboardingWorkflow.v("1.0.0", {
22
+ async handler(run, input: { email: string }) {
23
23
  run.logger.info("Starting onboarding", { email: input.email });
24
24
 
25
25
  // Execute a task to send verification email
@@ -30,7 +30,7 @@ export const onboardingWorkflowV1 = onboardingWorkflow.v("1.0", {
30
30
  await markUserVerified.start(run, { email: input.email });
31
31
 
32
32
  // Sleep for 24 hours before sending tips
33
- await run.sleep({ id: "onboarding-delay", days: 1 });
33
+ await run.sleep("onboarding-delay", { days: 1 });
34
34
 
35
35
  // Send usage tips
36
36
  await sendUsageTips.start(run, { email: input.email });
@@ -64,9 +64,9 @@ const result = await createUserProfile.start(run, {
64
64
 
65
65
  ```typescript
66
66
  // Sleep requires a unique id for memoization
67
- await run.sleep({ id: "daily-delay", days: 1 });
68
- await run.sleep({ id: "processing-delay", hours: 2, minutes: 30 });
69
- await run.sleep({ id: "short-pause", seconds: 30 });
67
+ await run.sleep("daily-delay", { days: 1 });
68
+ await run.sleep("processing-delay", { hours: 2, minutes: 30 });
69
+ await run.sleep("short-pause", { seconds: 30 });
70
70
  ```
71
71
 
72
72
  ### Sleep Cancellation
@@ -81,7 +81,7 @@ await handle.wake(); // Wakes the workflow if sleeping
81
81
  The sleep returns a result indicating whether it was cancelled:
82
82
 
83
83
  ```typescript
84
- const { cancelled } = await run.sleep({ id: "wait-period", hours: 1 });
84
+ const { cancelled } = await run.sleep("wait-period", { hours: 1 });
85
85
  if (cancelled) {
86
86
  // Handle early wake-up
87
87
  }
@@ -106,7 +106,7 @@ run.logger.debug("User created", { userId: result.userId });
106
106
  ### Delayed Trigger
107
107
 
108
108
  ```typescript
109
- export const morningWorkflowV1 = morningWorkflow.v("1.0", {
109
+ export const morningWorkflowV1 = morningWorkflow.v("1.0.0", {
110
110
  // ... workflow definition
111
111
  opts: {
112
112
  trigger: {
@@ -120,7 +120,7 @@ export const morningWorkflowV1 = morningWorkflow.v("1.0", {
120
120
  ### Retry Strategy
121
121
 
122
122
  ```typescript
123
- export const paymentWorkflowV1 = paymentWorkflow.v("1.0", {
123
+ export const paymentWorkflowV1 = paymentWorkflow.v("1.0.0", {
124
124
  // ... workflow definition
125
125
  opts: {
126
126
  retry: {
@@ -133,15 +133,18 @@ export const paymentWorkflowV1 = paymentWorkflow.v("1.0", {
133
133
  });
134
134
  ```
135
135
 
136
- ### Idempotency Key
136
+ ### Reference ID
137
137
 
138
138
  ```typescript
139
- export const orderWorkflowV1 = orderWorkflow.v("1.0", {
140
- // ... workflow definition
141
- opts: {
142
- idempotencyKey: "order-${orderId}",
143
- },
144
- });
139
+ // Assign a reference ID for tracking and lookup
140
+ const handle = await orderWorkflowV1
141
+ .with().opt("reference.id", `order-${orderId}`)
142
+ .start(client, { orderId });
143
+
144
+ // Configure conflict handling: "error" (default) or "return_existing"
145
+ const handle = await orderWorkflowV1
146
+ .with().opt("reference", { id: `order-${orderId}`, onConflict: "return_existing" })
147
+ .start(client, { orderId });
145
148
  ```
146
149
 
147
150
  ## Running Workflows
@@ -153,7 +156,7 @@ import { client } from "@aikirun/client";
153
156
  import { onboardingWorkflowV1 } from "./workflows.ts";
154
157
 
155
158
  const aikiClient = await client({
156
- url: "http://localhost:9090",
159
+ url: "http://localhost:9876",
157
160
  redis: { host: "localhost", port: 6379 },
158
161
  });
159
162
 
@@ -180,7 +183,7 @@ With a worker:
180
183
  import { worker } from "@aikirun/worker";
181
184
 
182
185
  const aikiWorker = worker({
183
- id: "my-worker",
186
+ name: "my-worker",
184
187
  workflows: [onboardingWorkflowV1],
185
188
  opts: {
186
189
  maxConcurrentWorkflowRuns: 10,
@@ -199,7 +202,7 @@ interface WorkflowRunContext<Input, Output> {
199
202
  id: WorkflowRunId; // Unique run ID
200
203
  name: WorkflowName; // Workflow name
201
204
  versionId: WorkflowVersionId; // Version ID
202
- options: WorkflowOptions; // Execution options (trigger, retry, idempotencyKey)
205
+ options: WorkflowOptions; // Execution options (trigger, retry, reference)
203
206
  handle: WorkflowRunHandle<Input, Output>; // Advanced state management
204
207
  logger: Logger; // Logging (info, debug, warn, error, trace)
205
208
  sleep(params: SleepParams): Promise<SleepResult>; // Durable sleep
@@ -210,7 +213,7 @@ Sleep parameters:
210
213
  - `id` (required): Unique identifier for memoization
211
214
  - Duration fields: `days`, `hours`, `minutes`, `seconds`, `milliseconds`
212
215
 
213
- Example: `run.sleep({ id: "my-sleep", days: 1, hours: 2 })`
216
+ Example: `run.sleep("my-sleep", { days: 1, hours: 2 })`
214
217
 
215
218
  ## Error Handling
216
219
 
@@ -229,9 +232,11 @@ Failed workflows transition to `awaiting_retry` state and are automatically retr
229
232
 
230
233
  ### Expected Errors
231
234
 
232
- `WorkflowRunSuspendedError` is thrown when a workflow suspends (e.g., during sleep).
233
- This is expected behavior - the worker catches this error and the workflow resumes
234
- when the sleep completes. Do not catch this error in workflow code.
235
+ These errors are thrown during normal workflow execution and should not be caught in workflow code:
236
+
237
+ - `WorkflowRunSuspendedError` - Thrown when a workflow suspends (e.g., during sleep or awaiting events). The worker catches this error and the workflow resumes when the condition is met.
238
+
239
+ - `WorkflowRunConflictError` - Thrown when another worker has already claimed the workflow execution. This prevents duplicate execution when workers race to process the same workflow.
235
240
 
236
241
  ## Best Practices
237
242
 
package/dist/index.d.ts CHANGED
@@ -1,13 +1,15 @@
1
- import { WorkflowId, WorkflowVersionId } from '@aikirun/types/workflow';
1
+ import { WorkflowName, WorkflowVersionId } from '@aikirun/types/workflow';
2
2
  import { Client, Logger, ApiClient } from '@aikirun/types/client';
3
3
  import { INTERNAL } from '@aikirun/types/symbols';
4
- import { WorkflowRun, WorkflowRunStatus, WorkflowRunStateCompleted, WorkflowRunStateInComplete, WorkflowRunState, WorkflowRunId, WorkflowOptions } from '@aikirun/types/workflow-run';
5
- import { SleepParams, SleepResult } from '@aikirun/types/sleep';
6
- import { DurationObject } from '@aikirun/types/duration';
4
+ import { Schema } from '@aikirun/types/validator';
5
+ import { WorkflowRun, TerminalWorkflowRunStatus, WorkflowRunState, WorkflowRunId, WorkflowOptions } from '@aikirun/types/workflow-run';
6
+ import { DurationObject, Duration } from '@aikirun/types/duration';
7
+ import { SleepResult } from '@aikirun/types/sleep';
7
8
  import { EventSendOptions, EventWaitOptions, EventWaitState } from '@aikirun/types/event';
8
- import { TaskPath } from '@aikirun/types/task';
9
- import { WorkflowRunStateRequest, TaskStateRequest } from '@aikirun/types/workflow-run-api';
10
- import { SerializableInput } from '@aikirun/types/error';
9
+ import { Serializable } from '@aikirun/types/serializable';
10
+ import { DistributiveOmit, RequireAtLeastOneProp } from '@aikirun/types/utils';
11
+ import { TaskId } from '@aikirun/types/task';
12
+ import { WorkflowRunStateRequest, WorkflowRunTransitionTaskStateRequestV1 } from '@aikirun/types/workflow-run-api';
11
13
 
12
14
  type NonEmptyArray<T> = [T, ...T[]];
13
15
 
@@ -28,46 +30,89 @@ type PathFromObjectInternal<T, IncludeArrayKeys extends boolean> = And<[
28
30
  type ExtractObjectType<T> = T extends object ? T : never;
29
31
  type TypeOfValueAtPath<T extends object, Path extends PathFromObject<T>> = Path extends keyof T ? T[Path] : Path extends `${infer First}.${infer Rest}` ? First extends keyof T ? undefined extends T[First] ? Rest extends PathFromObject<ExtractObjectType<T[First]>> ? TypeOfValueAtPath<ExtractObjectType<T[First]>, Rest> | undefined : never : Rest extends PathFromObject<ExtractObjectType<T[First]>> ? TypeOfValueAtPath<ExtractObjectType<T[First]>, Rest> : never : never : never;
30
32
 
31
- declare function workflowRunHandle<Input, Output, TEventsDefinition extends EventsDefinition>(client: Client, id: WorkflowRunId, eventsDefinition?: TEventsDefinition, logger?: Logger): Promise<WorkflowRunHandle<Input, Output, TEventsDefinition>>;
32
- declare function workflowRunHandle<Input, Output, TEventsDefinition extends EventsDefinition>(client: Client, run: WorkflowRun<Input, Output>, eventsDefinition?: TEventsDefinition, logger?: Logger): Promise<WorkflowRunHandle<Input, Output, TEventsDefinition>>;
33
- interface WorkflowRunHandle<Input, Output, TEventsDefinition extends EventsDefinition = EventsDefinition> {
33
+ declare function workflowRunHandle<Input, Output, AppContext, TEventsDefinition extends EventsDefinition>(client: Client<AppContext>, id: WorkflowRunId, eventsDefinition?: TEventsDefinition, logger?: Logger): Promise<WorkflowRunHandle<Input, Output, AppContext, TEventsDefinition>>;
34
+ declare function workflowRunHandle<Input, Output, AppContext, TEventsDefinition extends EventsDefinition>(client: Client<AppContext>, run: WorkflowRun<Input, Output>, eventsDefinition?: TEventsDefinition, logger?: Logger): Promise<WorkflowRunHandle<Input, Output, AppContext, TEventsDefinition>>;
35
+ interface WorkflowRunHandle<Input, Output, AppContext, TEventsDefinition extends EventsDefinition = EventsDefinition> {
34
36
  run: Readonly<WorkflowRun<Input, Output>>;
35
37
  events: EventSenders<TEventsDefinition>;
36
38
  refresh: () => Promise<void>;
37
- wait<S extends WorkflowRunStatus>(condition: {
38
- type: "status";
39
- status: S;
40
- }, options: WorkflowRunWaitOptions): Promise<{
41
- success: false;
42
- cause: "timeout" | "aborted";
43
- } | {
44
- success: true;
45
- state: S extends "completed" ? WorkflowRunStateCompleted<Output> : WorkflowRunStateInComplete;
46
- }>;
47
- wait(condition: {
48
- type: "event";
49
- event: string;
50
- }, options: WorkflowRunWaitOptions): Promise<{
51
- success: false;
52
- cause: "timeout" | "aborted";
53
- } | {
54
- success: true;
55
- state: WorkflowRunState<Output>;
56
- }>;
39
+ /**
40
+ * Waits for the child workflow run to reach a terminal status by polling.
41
+ *
42
+ * Returns a result object:
43
+ * - `{ success: true, state }` - workflow reached the expected status
44
+ * - `{ success: false, cause }` - workflow did not reach status
45
+ *
46
+ * Possible failure causes:
47
+ * - `"run_terminated"` - workflow reached a terminal state other than expected
48
+ * - `"timeout"` - timeout elapsed (only when timeout option provided)
49
+ * - `"aborted"` - abort signal triggered (only when abortSignal option provided)
50
+ *
51
+ * @param status - The target status to wait for
52
+ * @param options - Optional configuration for polling interval, timeout, and abort signal
53
+ *
54
+ * @example
55
+ * // Wait indefinitely until completed or the workflow reaches another terminal state
56
+ * const result = await handle.waitForStatus("completed");
57
+ * if (result.success) {
58
+ * console.log(result.state.output);
59
+ * } else {
60
+ * console.log(`Workflow terminated: ${result.cause}`);
61
+ * }
62
+ *
63
+ * @example
64
+ * // Wait with a timeout
65
+ * const result = await handle.waitForStatus("completed", {
66
+ * timeout: { seconds: 30 }
67
+ * });
68
+ * if (result.success) {
69
+ * console.log(result.state.output);
70
+ * } else if (result.cause === "timeout") {
71
+ * console.log("Timed out waiting for completion");
72
+ * }
73
+ *
74
+ * @example
75
+ * // Wait with an abort signal
76
+ * const controller = new AbortController();
77
+ * const result = await handle.waitForStatus("completed", {
78
+ * abortSignal: controller.signal
79
+ * });
80
+ * if (!result.success) {
81
+ * console.log(`Wait ended: ${result.cause}`);
82
+ * }
83
+ */
84
+ waitForStatus<Status extends TerminalWorkflowRunStatus>(status: Status, options?: WorkflowRunWaitOptions<false, false>): Promise<WorkflowRunWaitResult<Status, Output, false, false>>;
85
+ waitForStatus<Status extends TerminalWorkflowRunStatus>(status: Status, options: WorkflowRunWaitOptions<true, false>): Promise<WorkflowRunWaitResult<Status, Output, true, false>>;
86
+ waitForStatus<Status extends TerminalWorkflowRunStatus>(status: Status, options: WorkflowRunWaitOptions<false, true>): Promise<WorkflowRunWaitResult<Status, Output, false, true>>;
87
+ waitForStatus<Status extends TerminalWorkflowRunStatus>(status: Status, options: WorkflowRunWaitOptions<true, true>): Promise<WorkflowRunWaitResult<Status, Output, true, true>>;
57
88
  cancel: (reason?: string) => Promise<void>;
58
89
  pause: () => Promise<void>;
59
90
  resume: () => Promise<void>;
91
+ awake: () => Promise<void>;
60
92
  [INTERNAL]: {
93
+ client: Client<AppContext>;
61
94
  transitionState: (state: WorkflowRunStateRequest) => Promise<void>;
62
- transitionTaskState: (taskPath: TaskPath, taskState: TaskStateRequest) => Promise<void>;
95
+ transitionTaskState: (request: DistributiveOmit<WorkflowRunTransitionTaskStateRequestV1, "id" | "expectedRevision">) => Promise<{
96
+ taskId: TaskId;
97
+ }>;
63
98
  assertExecutionAllowed: () => void;
64
99
  };
65
100
  }
66
- interface WorkflowRunWaitOptions {
67
- maxDurationMs: number;
68
- pollIntervalMs?: number;
69
- abortSignal?: AbortSignal;
101
+ interface WorkflowRunWaitOptions<Timed extends boolean, Abortable extends boolean> {
102
+ interval?: DurationObject;
103
+ timeout?: Timed extends true ? DurationObject : never;
104
+ abortSignal?: Abortable extends true ? AbortSignal : never;
70
105
  }
106
+ type WorkflowRunWaitResultSuccess<Status extends TerminalWorkflowRunStatus, Output> = Extract<WorkflowRunState<Output>, {
107
+ status: Status;
108
+ }>;
109
+ type WorkflowRunWaitResult<Status extends TerminalWorkflowRunStatus, Output, Timed extends boolean, Abortable extends boolean> = {
110
+ success: false;
111
+ cause: "run_terminated" | (Timed extends true ? "timeout" : never) | (Abortable extends true ? "aborted" : never);
112
+ } | {
113
+ success: true;
114
+ state: WorkflowRunWaitResultSuccess<Status, Output>;
115
+ };
71
116
 
72
117
  /**
73
118
  * Defines an event type that can be sent to and waited for by workflows.
@@ -90,13 +135,11 @@ interface WorkflowRunWaitOptions {
90
135
  * });
91
136
  * ```
92
137
  */
93
- declare function event<Data>(params?: EventParams<Data>): EventDefinition<Data>;
138
+ declare function event(): EventDefinition<void>;
139
+ declare function event<Data extends Serializable>(params?: EventParams<Data>): EventDefinition<Data>;
94
140
  interface EventParams<Data> {
95
141
  schema?: Schema<Data>;
96
142
  }
97
- interface Schema<Data> {
98
- parse: (data: unknown) => Data;
99
- }
100
143
  interface EventDefinition<Data> {
101
144
  _type: Data;
102
145
  schema?: Schema<Data>;
@@ -107,63 +150,134 @@ type EventWaiters<TEventsDefinition extends EventsDefinition> = {
107
150
  [K in keyof TEventsDefinition]: EventWaiter<EventData<TEventsDefinition[K]>>;
108
151
  };
109
152
  interface EventWaiter<Data> {
110
- wait(options?: EventWaitOptions<undefined>): Promise<EventWaitState<Data, false>>;
111
- wait(options: EventWaitOptions<DurationObject>): Promise<EventWaitState<Data, true>>;
153
+ wait(options?: EventWaitOptions<false>): Promise<EventWaitState<Data, false>>;
154
+ wait(options: EventWaitOptions<true>): Promise<EventWaitState<Data, true>>;
112
155
  }
113
156
  type EventSenders<TEventsDefinition extends EventsDefinition> = {
114
157
  [K in keyof TEventsDefinition]: EventSender<EventData<TEventsDefinition[K]>>;
115
158
  };
116
159
  interface EventSender<Data> {
117
- send: (data: Data, options?: EventSendOptions) => Promise<void>;
160
+ with(): EventSenderBuilder<Data>;
161
+ send: (...args: Data extends void ? [] : [Data]) => Promise<void>;
162
+ }
163
+ interface EventSenderBuilder<Data> {
164
+ opt<Path extends PathFromObject<EventSendOptions>>(path: Path, value: TypeOfValueAtPath<EventSendOptions, Path>): EventSenderBuilder<Data>;
165
+ send: (...args: Data extends void ? [] : [Data]) => Promise<void>;
118
166
  }
119
- declare function createEventWaiters<TEventsDefinition extends EventsDefinition>(handle: WorkflowRunHandle<unknown, unknown, TEventsDefinition>, eventsDefinition: TEventsDefinition, logger: Logger): EventWaiters<TEventsDefinition>;
167
+ type EventMulticasters<TEventsDefinition extends EventsDefinition> = {
168
+ [K in keyof TEventsDefinition]: EventMulticaster<EventData<TEventsDefinition[K]>>;
169
+ };
170
+ interface EventMulticaster<Data> {
171
+ with(): EventMulticasterBuilder<Data>;
172
+ send: <AppContext>(client: Client<AppContext>, runId: string | string[], ...args: Data extends void ? [] : [Data]) => Promise<void>;
173
+ }
174
+ interface EventMulticasterBuilder<Data> {
175
+ opt<Path extends PathFromObject<EventSendOptions>>(path: Path, value: TypeOfValueAtPath<EventSendOptions, Path>): EventMulticasterBuilder<Data>;
176
+ send: <AppContext>(client: Client<AppContext>, runId: string | string[], ...args: Data extends void ? [] : [Data]) => Promise<void>;
177
+ }
178
+ declare function createEventWaiters<TEventsDefinition extends EventsDefinition>(handle: WorkflowRunHandle<unknown, unknown, unknown, TEventsDefinition>, eventsDefinition: TEventsDefinition, logger: Logger): EventWaiters<TEventsDefinition>;
120
179
  declare function createEventSenders<TEventsDefinition extends EventsDefinition>(api: ApiClient, workflowRunId: string, eventsDefinition: TEventsDefinition, logger: Logger, onSend: (run: WorkflowRun<unknown, unknown>) => void): EventSenders<TEventsDefinition>;
121
180
 
122
- interface WorkflowRunContext<Input, Output, TEventDefinition extends EventsDefinition> {
181
+ interface WorkflowRunContext<Input, AppContext, TEventDefinition extends EventsDefinition> {
123
182
  id: WorkflowRunId;
124
- workflowId: WorkflowId;
125
- workflowVersionId: WorkflowVersionId;
183
+ name: WorkflowName;
184
+ versionId: WorkflowVersionId;
126
185
  options: WorkflowOptions;
127
186
  logger: Logger;
128
- sleep: (params: SleepParams) => Promise<SleepResult>;
187
+ sleep: (name: string, duration: Duration) => Promise<SleepResult>;
129
188
  events: EventWaiters<TEventDefinition>;
130
189
  [INTERNAL]: {
131
- handle: WorkflowRunHandle<Input, Output, TEventDefinition>;
190
+ handle: WorkflowRunHandle<Input, unknown, AppContext, TEventDefinition>;
132
191
  options: {
133
192
  spinThresholdMs: number;
134
193
  };
135
194
  };
136
195
  }
137
196
 
197
+ type ChildWorkflowRunHandle<Input, Output, AppContext, TEventsDefinition extends EventsDefinition = EventsDefinition> = Omit<WorkflowRunHandle<Input, Output, AppContext, TEventsDefinition>, "waitForStatus"> & {
198
+ /**
199
+ * Waits for the child workflow run to reach a terminal status.
200
+ *
201
+ * This method suspends the parent workflow until the child reaches the expected terminal status
202
+ * or the optional timeout elapses.
203
+ *
204
+ * When the parent resumes, the result is deterministically replayed from stored wait results.
205
+ *
206
+ * Returns a result object:
207
+ * - `{ success: true, state }` - child reached the expected status
208
+ * - `{ success: false, cause }` - child did not reach status
209
+ *
210
+ * Possible failure causes:
211
+ * - `"run_terminated"` - child reached a different terminal state than expected
212
+ * - `"timeout"` - timeout elapsed (only when timeout option provided)
213
+ *
214
+ * @param status - The target terminal status to wait for
215
+ * @param options - Optional configuration with timeout
216
+ *
217
+ * @example
218
+ * // Wait indefinitely for child to complete
219
+ * const result = await childHandle.waitForStatus("completed");
220
+ * if (result.success) {
221
+ * console.log(result.state.output);
222
+ * } else {
223
+ * console.log(`Child terminated: ${result.cause}`);
224
+ * }
225
+ *
226
+ * @example
227
+ * // Wait with a timeout
228
+ * const result = await childHandle.waitForStatus("completed", {
229
+ * timeout: { minutes: 5 }
230
+ * });
231
+ * if (!result.success && result.cause === "timeout") {
232
+ * console.log("Child workflow took too long");
233
+ * }
234
+ */
235
+ waitForStatus<Status extends TerminalWorkflowRunStatus>(status: Status, options?: ChildWorkflowRunWaitOptions<false>): Promise<WorkflowRunWaitResult<Status, Output, false, false>>;
236
+ waitForStatus<Status extends TerminalWorkflowRunStatus>(status: Status, options: ChildWorkflowRunWaitOptions<true>): Promise<WorkflowRunWaitResult<Status, Output, true, false>>;
237
+ };
238
+ interface ChildWorkflowRunWaitOptions<Timed extends boolean> {
239
+ timeout?: Timed extends true ? DurationObject : never;
240
+ }
241
+
138
242
  interface WorkflowVersionParams<Input, Output, AppContext, TEventsDefinition extends EventsDefinition> {
243
+ handler: (run: Readonly<WorkflowRunContext<Input, AppContext, TEventsDefinition>>, input: Input, context: AppContext) => Promise<Output>;
139
244
  events?: TEventsDefinition;
140
245
  opts?: WorkflowOptions;
141
- handler: (input: Input, run: Readonly<WorkflowRunContext<Input, Output, TEventsDefinition>>, context: AppContext) => Promise<Output>;
142
- }
143
- interface WorkflowBuilder<Input, Output, AppContext, TEventsDefinition extends EventsDefinition> {
144
- opt<Path extends PathFromObject<WorkflowOptions>>(path: Path, value: TypeOfValueAtPath<WorkflowOptions, Path>): WorkflowBuilder<Input, Output, AppContext, TEventsDefinition>;
145
- start: WorkflowVersion<Input, Output, AppContext, TEventsDefinition>["start"];
246
+ schema?: RequireAtLeastOneProp<{
247
+ input?: Schema<Input>;
248
+ output?: Schema<Output>;
249
+ }>;
146
250
  }
147
251
  interface WorkflowVersion<Input, Output, AppContext, TEventsDefinition extends EventsDefinition = EventsDefinition> {
148
- id: WorkflowId;
252
+ name: WorkflowName;
149
253
  versionId: WorkflowVersionId;
254
+ events: EventMulticasters<TEventsDefinition>;
150
255
  with(): WorkflowBuilder<Input, Output, AppContext, TEventsDefinition>;
151
- start: (client: Client<AppContext>, ...args: Input extends null ? [] : [Input]) => Promise<WorkflowRunHandle<Input, Output, TEventsDefinition>>;
152
- getHandle: (client: Client<AppContext>, runId: WorkflowRunId) => Promise<WorkflowRunHandle<Input, Output, TEventsDefinition>>;
256
+ start: (client: Client<AppContext>, ...args: Input extends void ? [] : [Input]) => Promise<WorkflowRunHandle<Input, Output, AppContext, TEventsDefinition>>;
257
+ startAsChild: <ParentInput, ParentEventsDefinition extends EventsDefinition>(parentRun: WorkflowRunContext<ParentInput, AppContext, ParentEventsDefinition>, ...args: Input extends void ? [] : [Input]) => Promise<ChildWorkflowRunHandle<Input, Output, AppContext, TEventsDefinition>>;
258
+ getHandle: (client: Client<AppContext>, runId: WorkflowRunId) => Promise<WorkflowRunHandle<Input, Output, AppContext, TEventsDefinition>>;
153
259
  [INTERNAL]: {
154
260
  eventsDefinition: TEventsDefinition;
155
- handler: (input: Input, run: WorkflowRunContext<Input, Output, TEventsDefinition>, context: AppContext) => Promise<void>;
261
+ handler: (run: WorkflowRunContext<Input, AppContext, TEventsDefinition>, input: Input, context: AppContext) => Promise<void>;
156
262
  };
157
263
  }
264
+ interface WorkflowBuilder<Input, Output, AppContext, TEventsDefinition extends EventsDefinition> {
265
+ opt<Path extends PathFromObject<WorkflowOptions>>(path: Path, value: TypeOfValueAtPath<WorkflowOptions, Path>): WorkflowBuilder<Input, Output, AppContext, TEventsDefinition>;
266
+ start: WorkflowVersion<Input, Output, AppContext, TEventsDefinition>["start"];
267
+ startAsChild: WorkflowVersion<Input, Output, AppContext, TEventsDefinition>["startAsChild"];
268
+ }
158
269
  declare class WorkflowVersionImpl<Input, Output, AppContext, TEventsDefinition extends EventsDefinition> implements WorkflowVersion<Input, Output, AppContext, TEventsDefinition> {
159
- readonly id: WorkflowId;
270
+ readonly name: WorkflowName;
160
271
  readonly versionId: WorkflowVersionId;
161
272
  private readonly params;
273
+ readonly events: EventMulticasters<TEventsDefinition>;
162
274
  readonly [INTERNAL]: WorkflowVersion<Input, Output, AppContext, TEventsDefinition>[typeof INTERNAL];
163
- constructor(id: WorkflowId, versionId: WorkflowVersionId, params: WorkflowVersionParams<Input, Output, AppContext, TEventsDefinition>);
275
+ constructor(name: WorkflowName, versionId: WorkflowVersionId, params: WorkflowVersionParams<Input, Output, AppContext, TEventsDefinition>);
164
276
  with(): WorkflowBuilder<Input, Output, AppContext, TEventsDefinition>;
165
- start(client: Client<AppContext>, ...args: Input extends null ? [] : [Input]): Promise<WorkflowRunHandle<Input, Output, TEventsDefinition>>;
166
- getHandle(client: Client<AppContext>, runId: WorkflowRunId): Promise<WorkflowRunHandle<Input, Output, TEventsDefinition>>;
277
+ start(client: Client<AppContext>, ...args: Input extends void ? [] : [Input]): Promise<WorkflowRunHandle<Input, Output, AppContext, TEventsDefinition>>;
278
+ startAsChild(parentRun: WorkflowRunContext<unknown, AppContext, EventsDefinition>, ...args: Input extends void ? [] : [Input]): Promise<ChildWorkflowRunHandle<Input, Output, AppContext, TEventsDefinition>>;
279
+ private assertUniqueChildRunReferenceId;
280
+ getHandle(client: Client<AppContext>, runId: WorkflowRunId): Promise<WorkflowRunHandle<Input, Output, AppContext, TEventsDefinition>>;
167
281
  private handler;
168
282
  private tryExecuteWorkflow;
169
283
  private assertRetryAllowed;
@@ -180,13 +294,10 @@ interface WorkflowRegistry {
180
294
  removeMany: (workflows: Workflow$1[]) => WorkflowRegistry;
181
295
  removeAll: () => WorkflowRegistry;
182
296
  getAll(): Workflow$1[];
183
- get: (id: WorkflowId, versionId: WorkflowVersionId) => Workflow$1 | undefined;
297
+ get: (name: WorkflowName, versionId: WorkflowVersionId) => Workflow$1 | undefined;
184
298
  }
185
299
 
186
- interface SleeperOptions {
187
- spinThresholdMs: number;
188
- }
189
- declare function createSleeper(handle: WorkflowRunHandle<unknown, unknown>, logger: Logger, options: SleeperOptions): (params: SleepParams) => Promise<SleepResult>;
300
+ declare function createSleeper(handle: WorkflowRunHandle<unknown, unknown, unknown>, logger: Logger): (name: string, duration: Duration) => Promise<SleepResult>;
190
301
 
191
302
  /**
192
303
  * Defines a durable workflow with versioning and multiple task execution.
@@ -196,17 +307,17 @@ declare function createSleeper(handle: WorkflowRunHandle<unknown, unknown>, logg
196
307
  * Multiple versions of a workflow can run simultaneously, allowing safe deployments.
197
308
  *
198
309
  * @param params - Workflow configuration
199
- * @param params.id - Unique workflow id used for identification and routing
310
+ * @param params.name - Unique workflow name used for identification and routing
200
311
  * @returns Workflow instance with version management methods
201
312
  *
202
313
  * @example
203
314
  * ```typescript
204
315
  * // Define a workflow
205
- * export const userOnboarding = workflow({ id: "user-onboarding" });
316
+ * export const userOnboarding = workflow({ name: "user-onboarding" });
206
317
  *
207
318
  * // Define version 1.0
208
- * export const userOnboardingV1 = userOnboarding.v("1.0", {
209
- * async handler(input: { email: string }, run) {
319
+ * export const userOnboardingV1 = userOnboarding.v("1.0.0", {
320
+ * async handler(run, input: { email: string }) {
210
321
  * run.logger.info("Starting onboarding", { email: input.email });
211
322
  *
212
323
  * // Execute tasks
@@ -214,7 +325,7 @@ declare function createSleeper(handle: WorkflowRunHandle<unknown, unknown>, logg
214
325
  * await createUserProfile.start(run, { email: input.email });
215
326
  *
216
327
  * // Durable sleep
217
- * await run.sleep({ id: "onboarding-delay", days: 1 });
328
+ * await run.sleep("onboarding-delay", { days: 1 });
218
329
  *
219
330
  * // More tasks
220
331
  * await sendUsageTips.start(run, { email: input.email });
@@ -224,8 +335,8 @@ declare function createSleeper(handle: WorkflowRunHandle<unknown, unknown>, logg
224
335
  * });
225
336
  *
226
337
  * // Deploy version 2.0 alongside 1.0 (no downtime)
227
- * export const userOnboardingV2 = userOnboarding.v("2.0", {
228
- * async handler(input: { email: string; trial: boolean }, run) {
338
+ * export const userOnboardingV2 = userOnboarding.v("2.0.0", {
339
+ * async handler(run, input: { email: string; trial: boolean }) {
229
340
  * // Enhanced version with different logic
230
341
  * // Existing v1.0 workflows continue with their version
231
342
  * // New workflows use v2.0
@@ -237,15 +348,15 @@ declare function createSleeper(handle: WorkflowRunHandle<unknown, unknown>, logg
237
348
  */
238
349
  declare function workflow(params: WorkflowParams): Workflow;
239
350
  interface WorkflowParams {
240
- id: string;
351
+ name: string;
241
352
  }
242
353
  interface Workflow {
243
- id: WorkflowId;
244
- v: <Input extends SerializableInput = null, Output = void, AppContext = null, TEventsDefinition extends EventsDefinition = Record<string, never>>(versionId: string, params: WorkflowVersionParams<Input, Output, AppContext, TEventsDefinition>) => WorkflowVersion<Input, Output, AppContext, TEventsDefinition>;
354
+ name: WorkflowName;
355
+ v: <Input extends Serializable, Output extends Serializable, AppContext = null, TEventsDefinition extends EventsDefinition = Record<string, never>>(versionId: string, params: WorkflowVersionParams<Input, Output, AppContext, TEventsDefinition>) => WorkflowVersion<Input, Output, AppContext, TEventsDefinition>;
245
356
  [INTERNAL]: {
246
357
  getAllVersions: () => WorkflowVersion<unknown, unknown, unknown>[];
247
358
  getVersion: (versionId: WorkflowVersionId) => WorkflowVersion<unknown, unknown, unknown> | undefined;
248
359
  };
249
360
  }
250
361
 
251
- export { type EventDefinition, type EventSender, type EventSenders, type EventWaiter, type EventWaiters, type Workflow, type WorkflowParams, type WorkflowRegistry, type WorkflowRunContext, type WorkflowRunHandle, type WorkflowRunWaitOptions, type WorkflowVersion, WorkflowVersionImpl, type WorkflowVersionParams, createEventSenders, createEventWaiters, createSleeper, event, workflow, workflowRegistry, workflowRunHandle };
362
+ export { type EventMulticaster, type EventMulticasters, type EventSender, type EventSenders, type EventWaiter, type EventWaiters, type Workflow, type WorkflowParams, type WorkflowRegistry, type WorkflowRunContext, type WorkflowRunHandle, type WorkflowRunWaitOptions, type WorkflowVersion, WorkflowVersionImpl, type WorkflowVersionParams, createEventSenders, createEventWaiters, createSleeper, event, workflow, workflowRegistry, workflowRunHandle };