ai-workflows 2.1.3 → 2.4.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.
Files changed (188) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +14 -1
  3. package/README.md +2 -0
  4. package/dist/barrier.d.ts +6 -0
  5. package/dist/barrier.d.ts.map +1 -1
  6. package/dist/barrier.js +45 -7
  7. package/dist/barrier.js.map +1 -1
  8. package/dist/cascade-context.d.ts.map +1 -1
  9. package/dist/cascade-context.js +25 -25
  10. package/dist/cascade-context.js.map +1 -1
  11. package/dist/cascade-executor.d.ts.map +1 -1
  12. package/dist/cascade-executor.js +1 -1
  13. package/dist/cascade-executor.js.map +1 -1
  14. package/dist/context.d.ts.map +1 -1
  15. package/dist/context.js +23 -7
  16. package/dist/context.js.map +1 -1
  17. package/dist/cron-parser.d.ts +65 -0
  18. package/dist/cron-parser.d.ts.map +1 -0
  19. package/dist/cron-parser.js +294 -0
  20. package/dist/cron-parser.js.map +1 -0
  21. package/dist/cron-scheduler.d.ts +117 -0
  22. package/dist/cron-scheduler.d.ts.map +1 -0
  23. package/dist/cron-scheduler.js +176 -0
  24. package/dist/cron-scheduler.js.map +1 -0
  25. package/dist/database-context.d.ts +184 -0
  26. package/dist/database-context.d.ts.map +1 -0
  27. package/dist/database-context.js +428 -0
  28. package/dist/database-context.js.map +1 -0
  29. package/dist/digital-objects-adapter.d.ts +159 -0
  30. package/dist/digital-objects-adapter.d.ts.map +1 -0
  31. package/dist/digital-objects-adapter.js +229 -0
  32. package/dist/digital-objects-adapter.js.map +1 -0
  33. package/dist/durable-execution-cloudflare.d.ts +427 -0
  34. package/dist/durable-execution-cloudflare.d.ts.map +1 -0
  35. package/dist/durable-execution-cloudflare.js +510 -0
  36. package/dist/durable-execution-cloudflare.js.map +1 -0
  37. package/dist/durable-execution.d.ts +482 -0
  38. package/dist/durable-execution.d.ts.map +1 -0
  39. package/dist/durable-execution.js +594 -0
  40. package/dist/durable-execution.js.map +1 -0
  41. package/dist/durable-workflow.d.ts +176 -0
  42. package/dist/durable-workflow.d.ts.map +1 -0
  43. package/dist/durable-workflow.js +552 -0
  44. package/dist/durable-workflow.js.map +1 -0
  45. package/dist/graph/topological-sort.d.ts.map +1 -1
  46. package/dist/graph/topological-sort.js +5 -5
  47. package/dist/graph/topological-sort.js.map +1 -1
  48. package/dist/index.d.ts +4 -0
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +15 -0
  51. package/dist/index.js.map +1 -1
  52. package/dist/logger.d.ts +101 -0
  53. package/dist/logger.d.ts.map +1 -0
  54. package/dist/logger.js +115 -0
  55. package/dist/logger.js.map +1 -0
  56. package/dist/on.d.ts.map +1 -1
  57. package/dist/on.js +3 -3
  58. package/dist/on.js.map +1 -1
  59. package/dist/runtime.d.ts +169 -0
  60. package/dist/runtime.d.ts.map +1 -0
  61. package/dist/runtime.js +275 -0
  62. package/dist/runtime.js.map +1 -0
  63. package/dist/send.d.ts.map +1 -1
  64. package/dist/send.js +4 -3
  65. package/dist/send.js.map +1 -1
  66. package/dist/telemetry.d.ts +150 -0
  67. package/dist/telemetry.d.ts.map +1 -0
  68. package/dist/telemetry.js +388 -0
  69. package/dist/telemetry.js.map +1 -0
  70. package/dist/timer-registry.d.ts +25 -0
  71. package/dist/timer-registry.d.ts.map +1 -1
  72. package/dist/timer-registry.js +42 -8
  73. package/dist/timer-registry.js.map +1 -1
  74. package/dist/types.d.ts +17 -6
  75. package/dist/types.d.ts.map +1 -1
  76. package/dist/types.js +1 -1
  77. package/dist/types.js.map +1 -1
  78. package/dist/worker/durable-step.d.ts +481 -0
  79. package/dist/worker/durable-step.d.ts.map +1 -0
  80. package/dist/worker/durable-step.js +606 -0
  81. package/dist/worker/durable-step.js.map +1 -0
  82. package/dist/worker/index.d.ts +106 -0
  83. package/dist/worker/index.d.ts.map +1 -0
  84. package/dist/worker/index.js +124 -0
  85. package/dist/worker/index.js.map +1 -0
  86. package/dist/worker/state-adapter.d.ts +230 -0
  87. package/dist/worker/state-adapter.d.ts.map +1 -0
  88. package/dist/worker/state-adapter.js +409 -0
  89. package/dist/worker/state-adapter.js.map +1 -0
  90. package/dist/worker/topological-executor.d.ts +282 -0
  91. package/dist/worker/topological-executor.d.ts.map +1 -0
  92. package/dist/worker/topological-executor.js +396 -0
  93. package/dist/worker/topological-executor.js.map +1 -0
  94. package/dist/worker/workflow-builder.d.ts +286 -0
  95. package/dist/worker/workflow-builder.d.ts.map +1 -0
  96. package/dist/worker/workflow-builder.js +565 -0
  97. package/dist/worker/workflow-builder.js.map +1 -0
  98. package/dist/worker.d.ts +800 -0
  99. package/dist/worker.d.ts.map +1 -0
  100. package/dist/worker.js +2428 -0
  101. package/dist/worker.js.map +1 -0
  102. package/dist/workflow-builder.d.ts +287 -0
  103. package/dist/workflow-builder.d.ts.map +1 -0
  104. package/dist/workflow-builder.js +762 -0
  105. package/dist/workflow-builder.js.map +1 -0
  106. package/dist/workflow.d.ts +14 -30
  107. package/dist/workflow.d.ts.map +1 -1
  108. package/dist/workflow.js +132 -292
  109. package/dist/workflow.js.map +1 -1
  110. package/examples/01-ecommerce-order-pipeline.ts +358 -0
  111. package/examples/02-content-moderation-cascade.ts +454 -0
  112. package/examples/03-scheduled-reporting-dependencies.ts +479 -0
  113. package/examples/04-database-persistence.ts +518 -0
  114. package/examples/README.md +173 -0
  115. package/package.json +30 -13
  116. package/src/__tests__/digital-objects-adapter.test.ts +274 -0
  117. package/src/__tests__/durable-workflow.test.ts +297 -0
  118. package/src/barrier.ts +48 -7
  119. package/src/cascade-context.ts +36 -29
  120. package/src/cascade-executor.ts +3 -2
  121. package/src/context.ts +41 -12
  122. package/src/cron-parser.ts +347 -0
  123. package/src/cron-scheduler.ts +239 -0
  124. package/src/database-context.ts +658 -0
  125. package/src/digital-objects-adapter.ts +351 -0
  126. package/src/durable-execution-cloudflare.ts +855 -0
  127. package/src/durable-execution.ts +1042 -0
  128. package/src/durable-workflow.ts +717 -0
  129. package/src/graph/topological-sort.ts +6 -8
  130. package/src/index.ts +69 -0
  131. package/src/logger.ts +148 -0
  132. package/src/on.ts +8 -9
  133. package/src/runtime.ts +436 -0
  134. package/src/send.ts +4 -5
  135. package/src/telemetry.ts +577 -0
  136. package/src/timer-registry.ts +44 -10
  137. package/src/types.ts +32 -17
  138. package/src/worker/durable-step.ts +976 -0
  139. package/src/worker/index.ts +216 -0
  140. package/src/worker/state-adapter.ts +589 -0
  141. package/src/worker/topological-executor.ts +625 -0
  142. package/src/worker/workflow-builder.ts +871 -0
  143. package/src/worker.ts +2906 -0
  144. package/src/workflow-builder.ts +1068 -0
  145. package/src/workflow.ts +188 -351
  146. package/test/barrier-join.test.ts +32 -24
  147. package/test/cascade-executor.test.ts +9 -16
  148. package/test/cron-parser.test.ts +314 -0
  149. package/test/cron-scheduler.test.ts +291 -0
  150. package/test/database-context.test.ts +770 -0
  151. package/test/db-provider-adapter.test.ts +862 -0
  152. package/test/durable-execution-cloudflare.test.ts +606 -0
  153. package/test/durable-execution-in-process.test.ts +286 -0
  154. package/test/durable-execution.test.ts +247 -0
  155. package/test/e2e/workflow-scenarios.e2e.test.ts +1039 -0
  156. package/test/integration.test.ts +442 -0
  157. package/test/rpc-surface.test.ts +946 -0
  158. package/test/runtime.test.ts +262 -0
  159. package/test/schedule-timer-cleanup.test.ts +30 -21
  160. package/test/send-race-conditions.test.ts +30 -40
  161. package/test/worker/durable-cascade.test.ts +1117 -0
  162. package/test/worker/durable-step.test.ts +723 -0
  163. package/test/worker/topological-executor.test.ts +1240 -0
  164. package/test/worker/workflow-builder.test.ts +1067 -0
  165. package/test/worker.test.ts +608 -0
  166. package/test/workflow-builder.test.ts +1670 -0
  167. package/test/workflow-cron.test.ts +256 -0
  168. package/test/workflow-state-adapter.test.ts +923 -0
  169. package/test/workflow.test.ts +25 -22
  170. package/tsconfig.json +3 -1
  171. package/vitest.config.ts +38 -1
  172. package/vitest.workers.config.ts +44 -0
  173. package/wrangler.jsonc +22 -0
  174. package/.turbo/turbo-test.log +0 -169
  175. package/LICENSE +0 -21
  176. package/src/context.js +0 -83
  177. package/src/every.js +0 -267
  178. package/src/index.js +0 -71
  179. package/src/on.js +0 -79
  180. package/src/send.js +0 -111
  181. package/src/types.js +0 -4
  182. package/src/workflow.js +0 -455
  183. package/test/context.test.js +0 -116
  184. package/test/every.test.js +0 -282
  185. package/test/on.test.js +0 -80
  186. package/test/send.test.js +0 -89
  187. package/test/workflow.test.js +0 -224
  188. package/vitest.config.js +0 -7
@@ -16,7 +16,7 @@ describe('Workflow - unified $ API', () => {
16
16
 
17
17
  describe('Workflow()', () => {
18
18
  it('should create a workflow with $ context', () => {
19
- const workflow = Workflow($ => {
19
+ const workflow = Workflow(($) => {
20
20
  // Just accessing $ to verify it works
21
21
  expect($).toBeDefined()
22
22
  expect($.on).toBeDefined()
@@ -36,7 +36,7 @@ describe('Workflow - unified $ API', () => {
36
36
  })
37
37
 
38
38
  it('should capture event handlers registered via $.on', () => {
39
- const workflow = Workflow($ => {
39
+ const workflow = Workflow(($) => {
40
40
  $.on.Customer.created(() => {})
41
41
  $.on.Order.completed(() => {})
42
42
  })
@@ -49,7 +49,7 @@ describe('Workflow - unified $ API', () => {
49
49
  })
50
50
 
51
51
  it('should capture schedule handlers registered via $.every', () => {
52
- const workflow = Workflow($ => {
52
+ const workflow = Workflow(($) => {
53
53
  $.every.hour(() => {})
54
54
  $.every.Monday.at9am(() => {})
55
55
  })
@@ -58,7 +58,7 @@ describe('Workflow - unified $ API', () => {
58
58
  })
59
59
 
60
60
  it('should capture function source code', () => {
61
- const workflow = Workflow($ => {
61
+ const workflow = Workflow(($) => {
62
62
  $.on.Test.event(async (data, ctx) => {
63
63
  ctx.log('Test event', data)
64
64
  })
@@ -73,7 +73,7 @@ describe('Workflow - unified $ API', () => {
73
73
  it('should deliver events to registered handlers', async () => {
74
74
  const handler = vi.fn()
75
75
 
76
- const workflow = Workflow($ => {
76
+ const workflow = Workflow(($) => {
77
77
  $.on.Customer.created(handler)
78
78
  })
79
79
 
@@ -82,7 +82,7 @@ describe('Workflow - unified $ API', () => {
82
82
 
83
83
  expect(handler).toHaveBeenCalledTimes(1)
84
84
  expect(handler).toHaveBeenCalledWith(
85
- { id: '123', name: 'John' },
85
+ expect.objectContaining({ id: '123', name: 'John' }),
86
86
  expect.objectContaining({
87
87
  send: expect.any(Function),
88
88
  log: expect.any(Function),
@@ -93,7 +93,7 @@ describe('Workflow - unified $ API', () => {
93
93
  it('should allow chained event sending from handlers', async () => {
94
94
  const welcomeHandler = vi.fn()
95
95
 
96
- const workflow = Workflow($ => {
96
+ const workflow = Workflow(($) => {
97
97
  $.on.Customer.created(async (customer, $) => {
98
98
  await $.send('Email.welcome', { to: customer.email })
99
99
  })
@@ -105,13 +105,13 @@ describe('Workflow - unified $ API', () => {
105
105
  await workflow.send('Customer.created', { name: 'John', email: 'john@example.com' })
106
106
 
107
107
  expect(welcomeHandler).toHaveBeenCalledWith(
108
- { to: 'john@example.com' },
108
+ expect.objectContaining({ to: 'john@example.com' }),
109
109
  expect.anything()
110
110
  )
111
111
  })
112
112
 
113
113
  it('should track events in state history', async () => {
114
- const workflow = Workflow($ => {
114
+ const workflow = Workflow(($) => {
115
115
  $.on.Test.event(() => {})
116
116
  })
117
117
 
@@ -129,7 +129,7 @@ describe('Workflow - unified $ API', () => {
129
129
  it('should trigger schedule handlers', async () => {
130
130
  const handler = vi.fn()
131
131
 
132
- const workflow = Workflow($ => {
132
+ const workflow = Workflow(($) => {
133
133
  $.every.seconds(1)(handler)
134
134
  })
135
135
 
@@ -147,7 +147,7 @@ describe('Workflow - unified $ API', () => {
147
147
  it('should stop schedule handlers on stop', async () => {
148
148
  const handler = vi.fn()
149
149
 
150
- const workflow = Workflow($ => {
150
+ const workflow = Workflow(($) => {
151
151
  $.every.seconds(1)(handler)
152
152
  })
153
153
 
@@ -161,7 +161,7 @@ describe('Workflow - unified $ API', () => {
161
161
  })
162
162
 
163
163
  it('should support $.set and $.get for context data', async () => {
164
- const workflow = Workflow($ => {
164
+ const workflow = Workflow(($) => {
165
165
  $.on.Test.set(async (data, $) => {
166
166
  $.set('value', data.value)
167
167
  })
@@ -180,10 +180,7 @@ describe('Workflow - unified $ API', () => {
180
180
  })
181
181
 
182
182
  it('should use initial context from options', () => {
183
- const workflow = Workflow(
184
- $ => {},
185
- { context: { counter: 100 } }
186
- )
183
+ const workflow = Workflow(($) => {}, { context: { counter: 100 } })
187
184
 
188
185
  expect(workflow.state.context.counter).toBe(100)
189
186
  })
@@ -225,8 +222,14 @@ describe('Workflow - unified $ API', () => {
225
222
  await $.send('Test.event2', { b: 2 })
226
223
 
227
224
  expect($.emittedEvents).toHaveLength(2)
228
- expect($.emittedEvents[0]).toEqual({ event: 'Test.event1', data: { a: 1 } })
229
- expect($.emittedEvents[1]).toEqual({ event: 'Test.event2', data: { b: 2 } })
225
+ expect($.emittedEvents[0]).toEqual({
226
+ event: 'Test.event1',
227
+ data: expect.objectContaining({ a: 1 }),
228
+ })
229
+ expect($.emittedEvents[1]).toEqual({
230
+ event: 'Test.event2',
231
+ data: expect.objectContaining({ b: 2 }),
232
+ })
230
233
  })
231
234
 
232
235
  it('should support get/set', () => {
@@ -239,7 +242,7 @@ describe('Workflow - unified $ API', () => {
239
242
 
240
243
  describe('$.every patterns', () => {
241
244
  it('should support $.every.hour', () => {
242
- const workflow = Workflow($ => {
245
+ const workflow = Workflow(($) => {
243
246
  $.every.hour(() => {})
244
247
  })
245
248
 
@@ -251,7 +254,7 @@ describe('Workflow - unified $ API', () => {
251
254
  })
252
255
 
253
256
  it('should support $.every.Monday.at9am', () => {
254
- const workflow = Workflow($ => {
257
+ const workflow = Workflow(($) => {
255
258
  $.every.Monday.at9am(() => {})
256
259
  })
257
260
 
@@ -263,7 +266,7 @@ describe('Workflow - unified $ API', () => {
263
266
  })
264
267
 
265
268
  it('should support $.every.minutes(30)', () => {
266
- const workflow = Workflow($ => {
269
+ const workflow = Workflow(($) => {
267
270
  $.every.minutes(30)(() => {})
268
271
  })
269
272
 
@@ -275,7 +278,7 @@ describe('Workflow - unified $ API', () => {
275
278
  })
276
279
 
277
280
  it('should support $.every("natural language")', () => {
278
- const workflow = Workflow($ => {
281
+ const workflow = Workflow(($) => {
279
282
  $.every('first Monday of the month', () => {})
280
283
  })
281
284
 
package/tsconfig.json CHANGED
@@ -2,7 +2,9 @@
2
2
  "extends": "../../tsconfig.base.json",
3
3
  "compilerOptions": {
4
4
  "rootDir": "src",
5
- "outDir": "dist"
5
+ "outDir": "dist",
6
+ "lib": ["ES2022", "ESNext.Disposable"],
7
+ "types": ["@cloudflare/workers-types", "node"]
6
8
  },
7
9
  "include": ["src/**/*"],
8
10
  "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
package/vitest.config.ts CHANGED
@@ -2,7 +2,44 @@ import { defineConfig } from 'vitest/config'
2
2
 
3
3
  export default defineConfig({
4
4
  test: {
5
+ // CRITICAL: Limit concurrency to prevent resource exhaustion
6
+ maxConcurrency: 1,
7
+ maxWorkers: 1,
8
+ minWorkers: 1,
9
+ fileParallelism: false,
10
+
5
11
  globals: true,
6
- include: ['test/**/*.test.ts'],
12
+ environment: 'node',
13
+ include: ['test/**/*.test.ts', 'src/**/*.test.ts'],
14
+ testTimeout: 30000,
15
+ hookTimeout: 15000,
16
+
17
+ // Run tests sequentially with better memory isolation
18
+ pool: 'forks',
19
+ poolOptions: {
20
+ forks: {
21
+ singleFork: true,
22
+ },
23
+ },
24
+
25
+ // Coverage configuration
26
+ coverage: {
27
+ provider: 'v8',
28
+ reporter: ['text', 'json', 'html'],
29
+ include: ['src/**/*.ts'],
30
+ exclude: ['**/*.test.ts', '**/__tests__/**', '**/node_modules/**'],
31
+ thresholds: {
32
+ statements: 65,
33
+ branches: 60,
34
+ functions: 60,
35
+ lines: 65,
36
+ },
37
+ },
38
+
39
+ // Alias for cloudflare:workers mock (shared across monorepo)
40
+ alias: {
41
+ 'cloudflare:workers': new URL('../config/mocks/cloudflare-workers.ts', import.meta.url)
42
+ .pathname,
43
+ },
7
44
  },
8
45
  })
@@ -0,0 +1,44 @@
1
+ import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config'
2
+
3
+ export default defineWorkersConfig({
4
+ test: {
5
+ // CRITICAL: Limit concurrency to prevent resource exhaustion
6
+ maxConcurrency: 1,
7
+ maxWorkers: 1,
8
+ minWorkers: 1,
9
+ fileParallelism: false,
10
+
11
+ poolOptions: {
12
+ workers: {
13
+ wrangler: { configPath: './wrangler.jsonc' },
14
+ // Disable isolated storage for Workflows tests
15
+ // Workflows require non-isolated mode due to how miniflare handles them
16
+ isolatedStorage: false,
17
+ singleWorker: true,
18
+ miniflare: {
19
+ compatibilityDate: '2025-01-20',
20
+ compatibilityFlags: ['nodejs_compat_v2'],
21
+ },
22
+ },
23
+ },
24
+
25
+ // Only include worker-specific tests
26
+ include: ['test/worker/**/*.test.ts'],
27
+ testTimeout: 60000,
28
+ hookTimeout: 30000,
29
+
30
+ // Coverage configuration
31
+ coverage: {
32
+ provider: 'v8',
33
+ reporter: ['text', 'json', 'html'],
34
+ include: ['src/**/*.ts'],
35
+ exclude: ['**/*.test.ts', '**/__tests__/**', '**/node_modules/**'],
36
+ thresholds: {
37
+ statements: 65,
38
+ branches: 60,
39
+ functions: 60,
40
+ lines: 65,
41
+ },
42
+ },
43
+ },
44
+ })
package/wrangler.jsonc ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ // Wrangler configuration for ai-workflows worker tests
3
+ // Used by @cloudflare/vitest-pool-workers for testing
4
+ //
5
+ // Configures Cloudflare Workflows binding for testing DurableStep
6
+ // with real Workflows runtime semantics.
7
+
8
+ "name": "ai-workflows",
9
+ "main": "src/worker.ts",
10
+ "compatibility_date": "2025-01-20",
11
+ "compatibility_flags": ["nodejs_compat_v2"],
12
+
13
+ // Cloudflare Workflows binding
14
+ // This binds the TestWorkflow class to WORKFLOW for testing DurableStep
15
+ "workflows": [
16
+ {
17
+ "name": "test-workflow",
18
+ "binding": "WORKFLOW",
19
+ "class_name": "TestWorkflow"
20
+ }
21
+ ]
22
+ }
@@ -1,169 +0,0 @@
1
-
2
- > ai-workflows@2.1.1 test /Users/nathanclevenger/projects/primitives.org.ai/packages/ai-workflows
3
- > vitest
4
-
5
-
6
- DEV v2.1.9 /Users/nathanclevenger/projects/primitives.org.ai/packages/ai-workflows
7
-
8
- ✓ test/context.test.ts (11 tests) 5ms
9
- ✓ test/on.test.ts (8 tests) 3ms
10
- ✓ test/every.test.ts (39 tests) 6ms
11
- ✓ test/types-event-handler.test.ts (10 tests) 3ms
12
- stdout | test/types-event-handler.test.ts > EventHandler generic order - TDD RED > Type inference consistency > should support EventHandler<void, InputType> for fire-and-forget handlers
13
- Processing John (john@example.com)
14
-
15
- ✓ test/cascade-context.test.ts (29 tests) 7ms
16
- stdout | test/types-proxy-autocomplete.test.ts > OnProxy/EveryProxy autocomplete - TDD RED > $.send type safety > should type-check send call with data
17
- [workflow] Welcome email sent
18
- [workflow] Welcome email sent
19
-
20
- ✓ test/types-proxy-autocomplete.test.ts (18 tests) 4ms
21
- ✓ test/dependency-graph.test.ts (41 tests) 7ms
22
- stdout | test/workflow.test.ts > Workflow - unified $ API > Workflow() > should deliver events to registered handlers
23
- [workflow] Starting with 1 event handlers and 0 schedules
24
-
25
- stdout | test/workflow.test.ts > Workflow - unified $ API > Workflow() > should allow chained event sending from handlers
26
- [workflow] Starting with 2 event handlers and 0 schedules
27
-
28
- stdout | test/workflow.test.ts > Workflow - unified $ API > Workflow() > should track events in state history
29
- [workflow] Starting with 1 event handlers and 0 schedules
30
-
31
- stdout | test/workflow.test.ts > Workflow - unified $ API > Workflow() > should trigger schedule handlers
32
- [workflow] Starting with 0 event handlers and 1 schedules
33
-
34
- stdout | test/workflow.test.ts > Workflow - unified $ API > Workflow() > should trigger schedule handlers
35
- [workflow] Stopping
36
-
37
- stdout | test/workflow.test.ts > Workflow - unified $ API > Workflow() > should stop schedule handlers on stop
38
- [workflow] Starting with 0 event handlers and 1 schedules
39
-
40
- stdout | test/workflow.test.ts > Workflow - unified $ API > Workflow() > should stop schedule handlers on stop
41
- [workflow] Stopping
42
-
43
- stdout | test/workflow.test.ts > Workflow - unified $ API > Workflow() > should support $.set and $.get for context data
44
- [workflow] Starting with 2 event handlers and 0 schedules
45
-
46
- (node:43941) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 2)
47
- (Use `node --trace-warnings ...` to show where the warning was created)
48
- ✓ test/workflow.test.ts (20 tests) 10ms
49
- (node:43941) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 5)
50
- (node:43941) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 6)
51
- stderr | test/send.test.ts > send - event emission > send > should continue with other handlers if one throws
52
- Error in handler for Customer.created: Error: Handler 1 failed
53
- at /Users/nathanclevenger/projects/primitives.org.ai/packages/ai-workflows/test/send.test.ts:104:50
54
- at file:///Users/nathanclevenger/projects/primitives.org.ai/node_modules/.pnpm/@vitest+runner@2.1.9/node_modules/@vitest/runner/dist/index.js:146:14
55
- at file:///Users/nathanclevenger/projects/primitives.org.ai/node_modules/.pnpm/@vitest+runner@2.1.9/node_modules/@vitest/runner/dist/index.js:533:11
56
- at runWithTimeout (file:///Users/nathanclevenger/projects/primitives.org.ai/node_modules/.pnpm/@vitest+runner@2.1.9/node_modules/@vitest/runner/dist/index.js:39:7)
57
- at runTest (file:///Users/nathanclevenger/projects/primitives.org.ai/node_modules/.pnpm/@vitest+runner@2.1.9/node_modules/@vitest/runner/dist/index.js:1056:17)
58
- at runSuite (file:///Users/nathanclevenger/projects/primitives.org.ai/node_modules/.pnpm/@vitest+runner@2.1.9/node_modules/@vitest/runner/dist/index.js:1205:15)
59
- at runSuite (file:///Users/nathanclevenger/projects/primitives.org.ai/node_modules/.pnpm/@vitest+runner@2.1.9/node_modules/@vitest/runner/dist/index.js:1205:15)
60
- at runSuite (file:///Users/nathanclevenger/projects/primitives.org.ai/node_modules/.pnpm/@vitest+runner@2.1.9/node_modules/@vitest/runner/dist/index.js:1205:15)
61
- at runFiles (file:///Users/nathanclevenger/projects/primitives.org.ai/node_modules/.pnpm/@vitest+runner@2.1.9/node_modules/@vitest/runner/dist/index.js:1262:5)
62
- at startTests (file:///Users/nathanclevenger/projects/primitives.org.ai/node_modules/.pnpm/@vitest+runner@2.1.9/node_modules/@vitest/runner/dist/index.js:1271:3)
63
-
64
- ✓ test/send.test.ts (9 tests) 18ms
65
- (node:43941) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 10)
66
- ✓ test/barrier-join.test.ts (29 tests) 19ms
67
-
68
- ⎯⎯⎯⎯⎯⎯ Unhandled Errors ⎯⎯⎯⎯⎯⎯
69
-
70
- Vitest caught 4 unhandled errors during the test run.
71
- This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.
72
-
73
- ⎯⎯⎯⎯ Unhandled Rejection ⎯⎯⎯⎯⎯
74
- BarrierTimeoutError: Barrier timeout after 1000ms: 0/1 participants arrived
75
- ❯ src/barrier.ts:302:16
76
- 300| const timeoutPromise = new Promise<never>((_, reject) => {
77
- 301| setTimeout(() => {
78
- 302| reject(new BarrierTimeoutError(timeout, 0, promises.length))
79
- | ^
80
- 303| }, timeout)
81
- 304| })
82
- ❯ callTimer ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2300:25
83
- ❯ doTickInner ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2886:30
84
- ❯ doTick ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2967:21
85
- ❯ Immediate.<anonymous> ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2987:30
86
- ❯ processImmediate node:internal/timers:485:21
87
-
88
- ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
89
- Serialized Error: { timeout: 1000, arrived: +0 }
90
- This error originated in "test/barrier-join.test.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.
91
- The latest test that might've caused the error is "should support timeout option". It might mean one of the following:
92
- - The error was thrown, while Vitest was running this test.
93
- - If the error occurred after the test had been completed, this was the last documented test before it was thrown.
94
-
95
- ⎯⎯⎯⎯ Unhandled Rejection ⎯⎯⎯⎯⎯
96
- BarrierTimeoutError: Barrier timeout after 1000ms: 0/2 participants arrived
97
- ❯ src/barrier.ts:397:18
98
- 395| } else {
99
- 396| resolved = true
100
- 397| reject(new BarrierTimeoutError(timeout, completed.length, n))
101
- | ^
102
- 398| }
103
- 399| }, timeout)
104
- ❯ callTimer ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2300:25
105
- ❯ doTickInner ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2886:30
106
- ❯ doTick ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2967:21
107
- ❯ Immediate.<anonymous> ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2987:30
108
- ❯ processImmediate node:internal/timers:485:21
109
-
110
- ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
111
- Serialized Error: { timeout: 1000, arrived: +0 }
112
- This error originated in "test/barrier-join.test.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.
113
- The latest test that might've caused the error is "should support timeout". It might mean one of the following:
114
- - The error was thrown, while Vitest was running this test.
115
- - If the error occurred after the test had been completed, this was the last documented test before it was thrown.
116
-
117
- ⎯⎯⎯⎯ Unhandled Rejection ⎯⎯⎯⎯⎯
118
- BarrierTimeoutError: Barrier timeout after 1000ms: 1/3 participants arrived
119
- ❯ src/barrier.ts:194:27
120
- 192| this._timeoutId = setTimeout(() => {
121
- 193| if (this._waitReject) {
122
- 194| const error = new BarrierTimeoutError(
123
- | ^
124
- 195| this._options.timeout!,
125
- 196| this._arrived.length,
126
- ❯ callTimer ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2300:25
127
- ❯ doTickInner ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2886:30
128
- ❯ doTick ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2967:21
129
- ❯ Immediate.<anonymous> ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2987:30
130
- ❯ processImmediate node:internal/timers:485:21
131
-
132
- ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
133
- Serialized Error: { timeout: 1000, arrived: 1 }
134
- This error originated in "test/barrier-join.test.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.
135
- The latest test that might've caused the error is "should support timeout on wait()". It might mean one of the following:
136
- - The error was thrown, while Vitest was running this test.
137
- - If the error occurred after the test had been completed, this was the last documented test before it was thrown.
138
-
139
- ⎯⎯⎯⎯ Unhandled Rejection ⎯⎯⎯⎯⎯
140
- BarrierTimeoutError: Barrier timeout after 1000ms: 1/3 participants arrived
141
- ❯ src/barrier.ts:194:27
142
- 192| this._timeoutId = setTimeout(() => {
143
- 193| if (this._waitReject) {
144
- 194| const error = new BarrierTimeoutError(
145
- | ^
146
- 195| this._options.timeout!,
147
- 196| this._arrived.length,
148
- ❯ callTimer ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2300:25
149
- ❯ doTickInner ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2886:30
150
- ❯ doTick ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2967:21
151
- ❯ Immediate.<anonymous> ../../node_modules/.pnpm/vitest@2.1.9_@types+node@24.10.1_lightningcss@1.30.2_terser@5.16.9/node_modules/vitest/dist/chunks/vi.DgezovHB.js:2987:30
152
- ❯ processImmediate node:internal/timers:485:21
153
-
154
- ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
155
- Serialized Error: { timeout: 1000, arrived: 1 }
156
- This error originated in "test/barrier-join.test.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.
157
- The latest test that might've caused the error is "should include timeout details". It might mean one of the following:
158
- - The error was thrown, while Vitest was running this test.
159
- - If the error occurred after the test had been completed, this was the last documented test before it was thrown.
160
- ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
161
-
162
- Test Files 10 passed (10)
163
- Tests 214 passed (214)
164
- Errors 4 errors
165
- Start at 06:45:30
166
- Duration 357ms (transform 361ms, setup 0ms, collect 657ms, tests 83ms, environment 1ms, prepare 624ms)
167
-
168
- FAIL Tests failed. Watching for file changes...
169
- press h to show help, press q to quit
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 .org.ai
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/src/context.js DELETED
@@ -1,83 +0,0 @@
1
- /**
2
- * Workflow context implementation
3
- */
4
- /**
5
- * Create a workflow context
6
- */
7
- export function createWorkflowContext(eventBus) {
8
- const workflowState = {
9
- context: {},
10
- history: [],
11
- };
12
- const addHistory = (entry) => {
13
- workflowState.history.push({
14
- ...entry,
15
- timestamp: Date.now(),
16
- });
17
- };
18
- // Create no-op proxies for on/every (these are used in send context, not workflow setup)
19
- const noOpOnProxy = new Proxy({}, {
20
- get() {
21
- return new Proxy({}, {
22
- get() {
23
- return () => { };
24
- }
25
- });
26
- }
27
- });
28
- const noOpEveryProxy = new Proxy(function () { }, {
29
- get() {
30
- return () => () => { };
31
- },
32
- apply() { }
33
- });
34
- return {
35
- async send(event, data) {
36
- addHistory({ type: 'event', name: event, data });
37
- await eventBus.emit(event, data);
38
- },
39
- async do(_event, _data) {
40
- throw new Error('$.do not available in this context');
41
- },
42
- async try(_event, _data) {
43
- throw new Error('$.try not available in this context');
44
- },
45
- on: noOpOnProxy,
46
- every: noOpEveryProxy,
47
- state: workflowState.context,
48
- getState() {
49
- // Return a deep copy to prevent mutation
50
- return {
51
- current: workflowState.current,
52
- context: { ...workflowState.context },
53
- history: [...workflowState.history],
54
- };
55
- },
56
- set(key, value) {
57
- workflowState.context[key] = value;
58
- },
59
- get(key) {
60
- return workflowState.context[key];
61
- },
62
- log(message, data) {
63
- addHistory({ type: 'action', name: 'log', data: { message, data } });
64
- console.log(`[workflow] ${message}`, data ?? '');
65
- },
66
- };
67
- }
68
- /**
69
- * Create an isolated workflow context (not connected to event bus)
70
- * Useful for testing or standalone execution
71
- */
72
- export function createIsolatedContext() {
73
- const emittedEvents = [];
74
- const ctx = createWorkflowContext({
75
- async emit(event, data) {
76
- emittedEvents.push({ event, data });
77
- },
78
- });
79
- return {
80
- ...ctx,
81
- getEmittedEvents: () => [...emittedEvents],
82
- };
83
- }