ai-workflows 2.0.2 → 2.1.3

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.
Files changed (98) hide show
  1. package/.turbo/turbo-build.log +4 -5
  2. package/.turbo/turbo-test.log +169 -0
  3. package/CHANGELOG.md +29 -0
  4. package/LICENSE +21 -0
  5. package/README.md +303 -184
  6. package/dist/barrier.d.ts +153 -0
  7. package/dist/barrier.d.ts.map +1 -0
  8. package/dist/barrier.js +339 -0
  9. package/dist/barrier.js.map +1 -0
  10. package/dist/cascade-context.d.ts +149 -0
  11. package/dist/cascade-context.d.ts.map +1 -0
  12. package/dist/cascade-context.js +324 -0
  13. package/dist/cascade-context.js.map +1 -0
  14. package/dist/cascade-executor.d.ts +196 -0
  15. package/dist/cascade-executor.d.ts.map +1 -0
  16. package/dist/cascade-executor.js +384 -0
  17. package/dist/cascade-executor.js.map +1 -0
  18. package/dist/context.d.ts.map +1 -1
  19. package/dist/context.js +4 -1
  20. package/dist/context.js.map +1 -1
  21. package/dist/dependency-graph.d.ts +157 -0
  22. package/dist/dependency-graph.d.ts.map +1 -0
  23. package/dist/dependency-graph.js +382 -0
  24. package/dist/dependency-graph.js.map +1 -0
  25. package/dist/every.d.ts +31 -2
  26. package/dist/every.d.ts.map +1 -1
  27. package/dist/every.js +63 -32
  28. package/dist/every.js.map +1 -1
  29. package/dist/graph/index.d.ts +8 -0
  30. package/dist/graph/index.d.ts.map +1 -0
  31. package/dist/graph/index.js +8 -0
  32. package/dist/graph/index.js.map +1 -0
  33. package/dist/graph/topological-sort.d.ts +121 -0
  34. package/dist/graph/topological-sort.d.ts.map +1 -0
  35. package/dist/graph/topological-sort.js +292 -0
  36. package/dist/graph/topological-sort.js.map +1 -0
  37. package/dist/index.d.ts +6 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +10 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/on.d.ts +35 -10
  42. package/dist/on.d.ts.map +1 -1
  43. package/dist/on.js +52 -18
  44. package/dist/on.js.map +1 -1
  45. package/dist/send.d.ts +0 -5
  46. package/dist/send.d.ts.map +1 -1
  47. package/dist/send.js +1 -14
  48. package/dist/send.js.map +1 -1
  49. package/dist/timer-registry.d.ts +52 -0
  50. package/dist/timer-registry.d.ts.map +1 -0
  51. package/dist/timer-registry.js +120 -0
  52. package/dist/timer-registry.js.map +1 -0
  53. package/dist/types.d.ts +171 -9
  54. package/dist/types.d.ts.map +1 -1
  55. package/dist/types.js +17 -1
  56. package/dist/types.js.map +1 -1
  57. package/dist/workflow.d.ts.map +1 -1
  58. package/dist/workflow.js +22 -18
  59. package/dist/workflow.js.map +1 -1
  60. package/package.json +12 -16
  61. package/src/barrier.ts +466 -0
  62. package/src/cascade-context.ts +488 -0
  63. package/src/cascade-executor.ts +587 -0
  64. package/src/context.js +83 -0
  65. package/src/context.ts +12 -7
  66. package/src/dependency-graph.ts +518 -0
  67. package/src/every.js +267 -0
  68. package/src/every.ts +104 -35
  69. package/src/graph/index.ts +19 -0
  70. package/src/graph/topological-sort.ts +414 -0
  71. package/src/index.js +71 -0
  72. package/src/index.ts +78 -0
  73. package/src/on.js +79 -0
  74. package/src/on.ts +81 -25
  75. package/src/send.js +111 -0
  76. package/src/send.ts +1 -16
  77. package/src/timer-registry.ts +145 -0
  78. package/src/types.js +4 -0
  79. package/src/types.ts +218 -11
  80. package/src/workflow.js +455 -0
  81. package/src/workflow.ts +32 -23
  82. package/test/barrier-join.test.ts +434 -0
  83. package/test/barrier-unhandled-rejections.test.ts +359 -0
  84. package/test/cascade-context.test.ts +390 -0
  85. package/test/cascade-executor.test.ts +859 -0
  86. package/test/context.test.js +116 -0
  87. package/test/dependency-graph.test.ts +512 -0
  88. package/test/every.test.js +282 -0
  89. package/test/graph/topological-sort.test.ts +586 -0
  90. package/test/on.test.js +80 -0
  91. package/test/schedule-timer-cleanup.test.ts +344 -0
  92. package/test/send-race-conditions.test.ts +410 -0
  93. package/test/send.test.js +89 -0
  94. package/test/type-safety-every.test.ts +303 -0
  95. package/test/types-event-handler.test.ts +225 -0
  96. package/test/types-proxy-autocomplete.test.ts +345 -0
  97. package/test/workflow.test.js +224 -0
  98. package/vitest.config.js +7 -0
package/src/types.ts CHANGED
@@ -17,11 +17,15 @@ export interface HandlerFunction<T = unknown> {
17
17
  /**
18
18
  * Event handler function type
19
19
  * Can return void (for send) or a result (for do/try)
20
+ *
21
+ * Generic order follows Promise<T> convention:
22
+ * - TOutput (first) is what the handler returns
23
+ * - TInput (second) is what the handler receives
20
24
  */
21
- export type EventHandler<T = unknown, R = unknown> = (
22
- data: T,
25
+ export type EventHandler<TOutput = unknown, TInput = unknown> = (
26
+ data: TInput,
23
27
  $: WorkflowContext
24
- ) => R | void | Promise<R | void>
28
+ ) => TOutput | void | Promise<TOutput | void>
25
29
 
26
30
  /**
27
31
  * Schedule handler function type
@@ -43,14 +47,22 @@ export interface WorkflowContext {
43
47
  /**
44
48
  * Do an action (durable, waits for result)
45
49
  * Retries on failure, stores result durably
50
+ *
51
+ * Generic order follows Promise<T> convention:
52
+ * - TResult (first) is what the action returns
53
+ * - TInput (second) is what data is passed to the action
46
54
  */
47
- do: <TData = unknown, TResult = unknown>(event: string, data: TData) => Promise<TResult>
55
+ do: <TResult = unknown, TInput = unknown>(event: string, data: TInput) => Promise<TResult>
48
56
 
49
57
  /**
50
58
  * Try an action (non-durable, waits for result)
51
59
  * Simple execution without durability guarantees
60
+ *
61
+ * Generic order follows Promise<T> convention:
62
+ * - TResult (first) is what the action returns
63
+ * - TInput (second) is what data is passed to the action
52
64
  */
53
- try: <TData = unknown, TResult = unknown>(event: string, data: TData) => Promise<TResult>
65
+ try: <TResult = unknown, TInput = unknown>(event: string, data: TInput) => Promise<TResult>
54
66
 
55
67
  /** Register event handler ($.on.Noun.event) */
56
68
  on: OnProxy
@@ -142,24 +154,151 @@ export interface ArtifactData {
142
154
  metadata?: Record<string, unknown>
143
155
  }
144
156
 
157
+ /**
158
+ * Event handler proxy for a specific noun
159
+ * Allows $.on.Noun.event(handler) pattern
160
+ */
161
+ export type NounEventProxy = {
162
+ [event: string]: (handler: EventHandler) => void
163
+ }
164
+
145
165
  /**
146
166
  * Event proxy type for $.on.Noun.event pattern
167
+ *
168
+ * Includes explicit known nouns for IDE autocomplete while
169
+ * preserving index signature for dynamic noun access.
147
170
  */
148
171
  export type OnProxy = {
149
- [noun: string]: {
150
- [event: string]: (handler: EventHandler) => void
151
- }
172
+ // Known nouns (for autocomplete)
173
+ Customer: NounEventProxy
174
+ Order: NounEventProxy
175
+ Payment: NounEventProxy
176
+ User: NounEventProxy
177
+ Email: NounEventProxy
178
+ Invoice: NounEventProxy
179
+ Product: NounEventProxy
180
+ Subscription: NounEventProxy
181
+ // Index signature for dynamic nouns
182
+ [noun: string]: NounEventProxy
183
+ }
184
+
185
+ /**
186
+ * Schedule handler with optional time modifiers
187
+ * Allows $.every.Monday.at9am(handler) pattern
188
+ */
189
+ export type DayScheduleProxy = ((handler: ScheduleHandler) => void) & {
190
+ at6am: (handler: ScheduleHandler) => void
191
+ at7am: (handler: ScheduleHandler) => void
192
+ at8am: (handler: ScheduleHandler) => void
193
+ at9am: (handler: ScheduleHandler) => void
194
+ at10am: (handler: ScheduleHandler) => void
195
+ at11am: (handler: ScheduleHandler) => void
196
+ at12pm: (handler: ScheduleHandler) => void
197
+ atnoon: (handler: ScheduleHandler) => void
198
+ at1pm: (handler: ScheduleHandler) => void
199
+ at2pm: (handler: ScheduleHandler) => void
200
+ at3pm: (handler: ScheduleHandler) => void
201
+ at4pm: (handler: ScheduleHandler) => void
202
+ at5pm: (handler: ScheduleHandler) => void
203
+ at6pm: (handler: ScheduleHandler) => void
204
+ atmidnight: (handler: ScheduleHandler) => void
205
+ [timeKey: string]: (handler: ScheduleHandler) => void
152
206
  }
153
207
 
154
208
  /**
155
209
  * Every proxy type for $.every patterns
210
+ *
211
+ * Includes explicit known schedule patterns for IDE autocomplete while
212
+ * preserving index signature for dynamic patterns.
156
213
  */
157
214
  export type EveryProxy = {
215
+ // Callable for natural language schedules
158
216
  (description: string, handler: ScheduleHandler): void
159
217
  } & {
160
- [key: string]: ((handler: ScheduleHandler) => void) | ((value: number) => (handler: ScheduleHandler) => void) | {
161
- [timeKey: string]: (handler: ScheduleHandler) => void
162
- }
218
+ // Known time units (for autocomplete)
219
+ second: (handler: ScheduleHandler) => void
220
+ minute: (handler: ScheduleHandler) => void
221
+ hour: (handler: ScheduleHandler) => void
222
+ day: (handler: ScheduleHandler) => void
223
+ week: (handler: ScheduleHandler) => void
224
+ month: (handler: ScheduleHandler) => void
225
+ year: (handler: ScheduleHandler) => void
226
+
227
+ // Known days of week with time modifiers
228
+ Monday: DayScheduleProxy
229
+ Tuesday: DayScheduleProxy
230
+ Wednesday: DayScheduleProxy
231
+ Thursday: DayScheduleProxy
232
+ Friday: DayScheduleProxy
233
+ Saturday: DayScheduleProxy
234
+ Sunday: DayScheduleProxy
235
+ weekday: DayScheduleProxy
236
+ weekend: DayScheduleProxy
237
+ midnight: (handler: ScheduleHandler) => void
238
+ noon: (handler: ScheduleHandler) => void
239
+
240
+ // Plural forms for specifying intervals
241
+ seconds: (value: number) => (handler: ScheduleHandler) => void
242
+ minutes: (value: number) => (handler: ScheduleHandler) => void
243
+ hours: (value: number) => (handler: ScheduleHandler) => void
244
+ days: (value: number) => (handler: ScheduleHandler) => void
245
+ weeks: (value: number) => (handler: ScheduleHandler) => void
246
+
247
+ // Index signature for dynamic patterns
248
+ [key: string]: ((handler: ScheduleHandler) => void) | ((value: number) => (handler: ScheduleHandler) => void) | DayScheduleProxy
249
+ }
250
+
251
+ /**
252
+ * Callable target type for EveryProxy
253
+ * Used as a properly-typed Proxy target that supports both call and property access
254
+ */
255
+ export type EveryProxyTarget = {
256
+ (description: string, handler: ScheduleHandler): void
257
+ }
258
+
259
+ /**
260
+ * ProxyHandler type for OnProxy
261
+ * Provides proper typing for the two-level noun.event proxy pattern
262
+ */
263
+ export interface OnProxyHandler extends ProxyHandler<Record<string, NounEventProxy>> {
264
+ get(target: Record<string, NounEventProxy>, noun: string, receiver: unknown): NounEventProxy
265
+ }
266
+
267
+ /**
268
+ * ProxyHandler type for the inner noun level (event accessors)
269
+ */
270
+ export interface NounEventProxyHandler extends ProxyHandler<Record<string, (handler: EventHandler, dependencies?: DependencyConfig) => void>> {
271
+ get(
272
+ target: Record<string, (handler: EventHandler, dependencies?: DependencyConfig) => void>,
273
+ event: string,
274
+ receiver: unknown
275
+ ): (handler: EventHandler, dependencies?: DependencyConfig) => void
276
+ }
277
+
278
+ /**
279
+ * ProxyHandler type for EveryProxy
280
+ * Handles both function calls and property access for schedule patterns
281
+ */
282
+ export interface EveryProxyHandler extends ProxyHandler<EveryProxyTarget> {
283
+ get(target: EveryProxyTarget, prop: string, receiver: unknown): unknown
284
+ apply(target: EveryProxyTarget, thisArg: unknown, args: [string, ScheduleHandler]): void
285
+ }
286
+
287
+ /**
288
+ * ProxyHandler type for day schedule patterns with time modifiers
289
+ * Handles $.every.Monday.at9am pattern
290
+ */
291
+ export interface DayScheduleProxyHandler extends ProxyHandler<(handler: ScheduleHandler) => void> {
292
+ get(
293
+ target: (handler: ScheduleHandler) => void,
294
+ timeKey: string,
295
+ receiver: unknown
296
+ ): ((handler: ScheduleHandler) => void) | undefined
297
+ apply(
298
+ target: (handler: ScheduleHandler) => void,
299
+ thisArg: unknown,
300
+ args: [ScheduleHandler]
301
+ ): void
163
302
  }
164
303
 
165
304
  /**
@@ -184,6 +323,30 @@ export interface WorkflowHistoryEntry {
184
323
  data?: unknown
185
324
  }
186
325
 
326
+ /**
327
+ * Dependency type: hard (must succeed) or soft (can proceed on failure)
328
+ */
329
+ export type DependencyType = 'hard' | 'soft'
330
+
331
+ /**
332
+ * Configuration for step dependencies
333
+ */
334
+ export interface DependencyConfig {
335
+ /**
336
+ * Step(s) that must complete before this step runs
337
+ * Can be a single step ID or array of step IDs
338
+ * Format: 'Noun.event' (e.g., 'Step1.complete')
339
+ */
340
+ dependsOn: string | string[]
341
+
342
+ /**
343
+ * Type of dependency (default: 'hard')
344
+ * - 'hard': Dependency must complete successfully
345
+ * - 'soft': Step can proceed even if dependency fails
346
+ */
347
+ type?: DependencyType
348
+ }
349
+
187
350
  /**
188
351
  * Event registration with source
189
352
  */
@@ -192,6 +355,8 @@ export interface EventRegistration {
192
355
  event: string
193
356
  handler: EventHandler
194
357
  source: string
358
+ /** Optional dependency configuration for workflow step ordering */
359
+ dependencies?: DependencyConfig
195
360
  }
196
361
 
197
362
  /**
@@ -203,6 +368,48 @@ export interface ScheduleRegistration {
203
368
  source: string
204
369
  }
205
370
 
371
+ /**
372
+ * Time-based interval types (singular form)
373
+ * Used as discriminant values in ScheduleInterval
374
+ */
375
+ export type TimeIntervalType = 'second' | 'minute' | 'hour' | 'day' | 'week'
376
+
377
+ /**
378
+ * Mapping from plural unit names to their singular interval types
379
+ * Used for type-safe conversion in every.units(value) patterns
380
+ */
381
+ export type PluralUnitMapping = {
382
+ seconds: 'second'
383
+ minutes: 'minute'
384
+ hours: 'hour'
385
+ days: 'day'
386
+ weeks: 'week'
387
+ }
388
+
389
+ /**
390
+ * Plural unit keys
391
+ */
392
+ export type PluralUnitKey = keyof PluralUnitMapping
393
+
394
+ /**
395
+ * Type guard to check if a string is a valid plural unit key
396
+ */
397
+ export function isPluralUnitKey(key: string): key is PluralUnitKey {
398
+ return key === 'seconds' || key === 'minutes' || key === 'hours' || key === 'days' || key === 'weeks'
399
+ }
400
+
401
+ /**
402
+ * Constant mapping object with strict typing
403
+ * Maps plural forms to their singular interval type values
404
+ */
405
+ export const PLURAL_UNITS: Readonly<PluralUnitMapping> = {
406
+ seconds: 'second',
407
+ minutes: 'minute',
408
+ hours: 'hour',
409
+ days: 'day',
410
+ weeks: 'week',
411
+ } as const
412
+
206
413
  /**
207
414
  * Schedule intervals
208
415
  */