@outputai/core 0.7.1-next.db8ddd7.0 → 0.7.1-next.ed233ce.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 (77) hide show
  1. package/bin/worker.sh +6 -0
  2. package/package.json +1 -1
  3. package/src/consts.js +0 -4
  4. package/src/errors.js +6 -2
  5. package/src/interface/evaluator.js +7 -20
  6. package/src/interface/evaluator.spec.js +117 -1
  7. package/src/interface/step.js +8 -9
  8. package/src/interface/step.spec.js +124 -0
  9. package/src/interface/validations/index.js +108 -0
  10. package/src/interface/validations/index.spec.js +182 -0
  11. package/src/interface/validations/schemas.js +113 -0
  12. package/src/interface/validations/schemas.spec.js +209 -0
  13. package/src/interface/webhook.js +1 -1
  14. package/src/interface/webhook.spec.js +1 -1
  15. package/src/interface/workflow.d.ts +10 -9
  16. package/src/interface/workflow.js +76 -164
  17. package/src/interface/workflow.spec.js +637 -521
  18. package/src/interface/workflow_activity_options.js +16 -0
  19. package/src/interface/workflow_utils.js +1 -1
  20. package/src/interface/zod_integration.spec.js +2 -2
  21. package/src/internal_utils/aggregations.js +0 -10
  22. package/src/internal_utils/aggregations.spec.js +1 -48
  23. package/src/internal_utils/errors.js +14 -8
  24. package/src/internal_utils/errors.spec.js +73 -27
  25. package/src/utils/index.d.ts +19 -0
  26. package/src/utils/utils.js +53 -0
  27. package/src/utils/utils.spec.js +105 -1
  28. package/src/worker/bundle.js +26 -0
  29. package/src/worker/bundle.spec.js +53 -0
  30. package/src/worker/bundler_options.js +1 -1
  31. package/src/worker/bundler_options.spec.js +1 -1
  32. package/src/worker/catalog_workflow/catalog_job.js +148 -0
  33. package/src/worker/catalog_workflow/catalog_job.spec.js +232 -0
  34. package/src/worker/check.js +24 -0
  35. package/src/worker/connection_monitor.js +112 -0
  36. package/src/worker/connection_monitor.spec.js +199 -0
  37. package/src/worker/index.js +146 -41
  38. package/src/worker/index.spec.js +281 -109
  39. package/src/worker/interceptors/activity.js +7 -24
  40. package/src/worker/interceptors/activity.spec.js +97 -66
  41. package/src/worker/interceptors/index.js +4 -7
  42. package/src/worker/interceptors/modules.js +15 -0
  43. package/src/worker/interceptors/workflow.js +6 -8
  44. package/src/worker/interceptors/workflow.spec.js +49 -42
  45. package/src/worker/interruption.js +33 -0
  46. package/src/worker/interruption.spec.js +86 -0
  47. package/src/worker/loader/activities.js +75 -0
  48. package/src/worker/loader/activities.spec.js +213 -0
  49. package/src/worker/loader/hooks.js +28 -0
  50. package/src/worker/loader/hooks.spec.js +64 -0
  51. package/src/worker/loader/matchers.js +46 -0
  52. package/src/worker/loader/matchers.spec.js +140 -0
  53. package/src/worker/{loader_tools.js → loader/tools.js} +19 -67
  54. package/src/worker/{loader_tools.spec.js → loader/tools.spec.js} +53 -85
  55. package/src/worker/loader/workflows.js +82 -0
  56. package/src/worker/loader/workflows.spec.js +256 -0
  57. package/src/worker/{setup_telemetry.js → telemetry.js} +9 -4
  58. package/src/worker/{setup_telemetry.spec.js → telemetry.spec.js} +3 -3
  59. package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.js +5 -109
  60. package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.spec.js +31 -103
  61. package/src/worker/webpack_loaders/workflow_rewriter/index.mjs +5 -6
  62. package/src/worker/webpack_loaders/workflow_rewriter/index.spec.js +11 -83
  63. package/src/worker/webpack_loaders/workflow_rewriter/rewrite_fn_bodies.js +8 -11
  64. package/src/worker/webpack_loaders/workflow_rewriter/rewrite_fn_bodies.spec.js +9 -9
  65. package/src/interface/validations/runtime.js +0 -20
  66. package/src/interface/validations/runtime.spec.js +0 -29
  67. package/src/interface/validations/schema_utils.js +0 -8
  68. package/src/interface/validations/schema_utils.spec.js +0 -67
  69. package/src/interface/validations/static.js +0 -137
  70. package/src/interface/validations/static.spec.js +0 -397
  71. package/src/interface/workflow.replay_compatibility.spec.js +0 -254
  72. package/src/worker/loader.js +0 -202
  73. package/src/worker/loader.spec.js +0 -498
  74. package/src/worker/shutdown.js +0 -26
  75. package/src/worker/shutdown.spec.js +0 -82
  76. package/src/worker/start_catalog.js +0 -96
  77. package/src/worker/start_catalog.spec.js +0 -179
@@ -15,7 +15,7 @@ const traverse = traverseModule.default ?? traverseModule;
15
15
  * Check whether a CallExpression callee is a simple Identifier.
16
16
  * Only direct identifier calls are rewritten; member/dynamic calls are skipped.
17
17
  *
18
- * We only support rewriting `Foo()` calls that refer to imported steps/flows/evaluators
18
+ * We only support rewriting `Foo()` calls that refer to imported steps/evaluators
19
19
  * or local call-chain functions. Calls like `obj.Foo()` or `(getFn())()` are out of scope.
20
20
  *
21
21
  * Examples:
@@ -31,7 +31,7 @@ const isIdentifierCallee = cPath => isIdentifier( cPath.node.callee );
31
31
  * Convert an ArrowFunctionExpression at the given path into a FunctionExpression
32
32
  * to ensure dynamic `this` semantics inside the function body.
33
33
  *
34
- * Workflow code relies on `this` to invoke steps/flows (e.g., `this.invokeStep(...)`).
34
+ * Workflow code relies on `this` to invoke steps/evaluators (e.g., `this.invokeStep(...)`).
35
35
  * Arrow functions capture `this` lexically, which would break that contract.
36
36
  *
37
37
  * If the node is an arrow, it is replaced by an equivalent FunctionExpression and
@@ -49,7 +49,7 @@ const normalizeArrowToFunctionPath = ( nodePath, state ) => {
49
49
  };
50
50
  /**
51
51
  * Rewrite calls inside a function body and collect call-chain functions discovered within.
52
- * - Imported calls (steps/shared/evaluators/flows) are rewritten to `this.invokeX` or `this.startWorkflow`.
52
+ * - Imported calls (steps/shared/evaluators) are rewritten to `this.invokeX`.
53
53
  * - Local call-chain function calls are rewritten to `fn.call(this, ...)` to bind `this` correctly.
54
54
  * - Returns a map of call-chain function name -> binding path for further recursive processing.
55
55
  *
@@ -67,7 +67,7 @@ const rewriteCallsInBody = ( bodyPath, descriptors, state ) => {
67
67
  }
68
68
  const callee = cPath.node.callee;
69
69
 
70
- // Rewrite imported calls (steps/shared/evaluators/flows)
70
+ // Rewrite imported calls (steps/shared/evaluators)
71
71
  for ( const { list, method, key } of descriptors ) {
72
72
  const found = list.find( x => x.localName === callee.name );
73
73
  if ( found ) {
@@ -143,28 +143,25 @@ const processFunction = ( { name, bindingPath, state, descriptors, processedFns
143
143
  };
144
144
 
145
145
  /**
146
- * Rewrite calls to imported steps/workflows within `fn` object properties.
146
+ * Rewrite calls to imported steps/evaluators within `fn` object properties.
147
147
  * Converts arrow fns to functions and replaces `StepX(...)` with
148
- * `this.invokeStep('name', ...)` and `FlowY(...)` with
149
- * `this.startWorkflow('name', ...)`.
148
+ * `this.invokeStep('name', ...)`.
150
149
  *
151
150
  * @param {object} params
152
151
  * @param {import('@babel/types').File} params.ast - Parsed file AST.
153
152
  * @param {Array<{localName:string,stepName:string}>} params.stepImports - Step imports.
154
153
  * @param {Array<{localName:string,stepName:string}>} params.sharedStepImports - Shared step imports.
155
154
  * @param {Array<{localName:string,evaluatorName:string}>} params.evaluatorImports - Evaluator imports.
156
- * @param {Array<{localName:string,workflowName:string}>} params.flowImports - Workflow imports.
157
155
  * @returns {boolean} True if the AST was modified; false otherwise.
158
156
  */
159
- export default function rewriteFnBodies( { ast, stepImports, sharedStepImports = [], evaluatorImports, sharedEvaluatorImports = [], flowImports } ) {
157
+ export default function rewriteFnBodies( { ast, stepImports, sharedStepImports = [], evaluatorImports, sharedEvaluatorImports = [] } ) {
160
158
  const state = { rewrote: false };
161
159
  // Build rewrite descriptors once per traversal
162
160
  const descriptors = [
163
161
  { list: stepImports, method: 'invokeStep', key: 'stepName' },
164
162
  { list: sharedStepImports, method: 'invokeSharedStep', key: 'stepName' },
165
163
  { list: evaluatorImports, method: 'invokeEvaluator', key: 'evaluatorName' },
166
- { list: sharedEvaluatorImports, method: 'invokeSharedEvaluator', key: 'evaluatorName' },
167
- { list: flowImports, method: 'startWorkflow', key: 'workflowName' }
164
+ { list: sharedEvaluatorImports, method: 'invokeSharedEvaluator', key: 'evaluatorName' }
168
165
  ];
169
166
  traverse( ast, {
170
167
  ObjectProperty: path => {
@@ -6,7 +6,7 @@ import rewriteFnBodies from './rewrite_fn_bodies.js';
6
6
  const generate = generatorModule.default ?? generatorModule;
7
7
 
8
8
  describe( 'rewrite_fn_bodies', () => {
9
- it( 'converts arrow to function and rewrites step/workflow calls', () => {
9
+ it( 'converts arrow to function and rewrites step calls without rewriting workflow calls', () => {
10
10
  const src = `
11
11
  const obj = {
12
12
  fn: async x => {
@@ -16,13 +16,13 @@ const obj = {
16
16
  }`;
17
17
  const ast = parse( src, 'file.js' );
18
18
  const stepImports = [ { localName: 'StepA', stepName: 'step.a' } ];
19
- const flowImports = [ { localName: 'FlowB', workflowName: 'flow.b' } ];
20
19
 
21
- const rewrote = rewriteFnBodies( { ast, stepImports, evaluatorImports: [], flowImports } );
20
+ const rewrote = rewriteFnBodies( { ast, stepImports, evaluatorImports: [] } );
22
21
  expect( rewrote ).toBe( true );
23
22
 
24
- const code = ast.program.body.map( n => n.type ).length; // smoke: ast mutated
25
- expect( code ).toBeGreaterThan( 0 );
23
+ const { code } = generate( ast, { quotes: 'single' } );
24
+ expect( code ).toMatch( /this\.invokeStep\(([\"'])step\.a\1,\s*1\)/ );
25
+ expect( code ).toMatch( /FlowB\(2\)/ );
26
26
  } );
27
27
 
28
28
  it( 'rewrites evaluator calls to this.invokeEvaluator', () => {
@@ -34,14 +34,14 @@ const obj = {
34
34
  };`;
35
35
  const ast = parse( src, 'file.js' );
36
36
  const evaluatorImports = [ { localName: 'EvalA', evaluatorName: 'eval.a' } ];
37
- const rewrote = rewriteFnBodies( { ast, stepImports: [], evaluatorImports, flowImports: [] } );
37
+ const rewrote = rewriteFnBodies( { ast, stepImports: [], evaluatorImports } );
38
38
  expect( rewrote ).toBe( true );
39
39
  } );
40
40
 
41
41
  it( 'does nothing when no matching calls are present', () => {
42
42
  const src = [ 'const obj = { fn: function() { other(); } }' ].join( '\n' );
43
43
  const ast = parse( src, 'file.js' );
44
- const rewrote = rewriteFnBodies( { ast, stepImports: [], evaluatorImports: [], flowImports: [] } );
44
+ const rewrote = rewriteFnBodies( { ast, stepImports: [], evaluatorImports: [] } );
45
45
  expect( rewrote ).toBe( false );
46
46
  } );
47
47
 
@@ -66,7 +66,7 @@ const obj = {
66
66
  const stepImports = [ { localName: 'StepA', stepName: 'step.a' } ];
67
67
  const evaluatorImports = [ { localName: 'EvalA', evaluatorName: 'eval.a' } ];
68
68
 
69
- const rewrote = rewriteFnBodies( { ast, stepImports, sharedStepImports: [], evaluatorImports, flowImports: [] } );
69
+ const rewrote = rewriteFnBodies( { ast, stepImports, sharedStepImports: [], evaluatorImports } );
70
70
  expect( rewrote ).toBe( true );
71
71
 
72
72
  const { code } = generate( ast, { quotes: 'single' } );
@@ -105,7 +105,7 @@ const obj = {
105
105
 
106
106
  const ast = parse( src, 'file.js' );
107
107
  const stepImports = [ { localName: 'StepA', stepName: 'step.a' } ];
108
- const rewrote = rewriteFnBodies( { ast, stepImports, evaluatorImports: [], flowImports: [] } );
108
+ const rewrote = rewriteFnBodies( { ast, stepImports, evaluatorImports: [] } );
109
109
  expect( rewrote ).toBe( true );
110
110
 
111
111
  const { code } = generate( ast, { quotes: 'single' } );
@@ -1,20 +0,0 @@
1
- import { ValidationError } from '#errors';
2
-
3
- /**
4
- * Validates data against a Zod schema using safeParse
5
- * @param {unknown} schema - The Zod schema to validate against
6
- * @param {unknown} data - The data to validate
7
- * @param {string} context - Description of what's being validated (for error messages)
8
- * @throws {ValidationError} If validation fails
9
- * @returns {void}
10
- */
11
- export function validateWithSchema( schema, data, context ) {
12
- if ( !schema ) {
13
- return;
14
- }
15
-
16
- const result = schema.safeParse( data );
17
- if ( !result.success ) {
18
- throw new ValidationError( `${context} validation failed: ${result.error.message}` );
19
- }
20
- }
@@ -1,29 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { z } from 'zod';
3
- import { validateWithSchema } from './runtime.js';
4
- import { ValidationError } from '#errors';
5
-
6
- describe( 'runtime validations', () => {
7
- describe( 'validateWithSchema', () => {
8
- it( 'no-ops when schema is falsy', () => {
9
- expect( () => validateWithSchema( undefined, { a: 1 }, 'X' ) ).not.toThrow();
10
- expect( () => validateWithSchema( null, { a: 1 }, 'X' ) ).not.toThrow();
11
- } );
12
-
13
- it( 'passes on valid data', () => {
14
- const schema = z.object( { a: z.string(), b: z.number().optional() } );
15
- expect( () => validateWithSchema( schema, { a: 'ok' }, 'Test' ) ).not.toThrow();
16
- } );
17
-
18
- it( 'throws ValidationError on invalid data and prefixes context', () => {
19
- const schema = z.object( { a: z.string() } );
20
- const call = () => validateWithSchema( schema, { a: 1 }, 'MyCtx' );
21
- expect( call ).toThrow( ValidationError );
22
- try {
23
- call();
24
- } catch ( e ) {
25
- expect( String( e.message ) ).toContain( 'MyCtx validation failed:' );
26
- }
27
- } );
28
- } );
29
- } );
@@ -1,8 +0,0 @@
1
- import { ZodType } from 'zod';
2
-
3
- /**
4
- * Detects if a schema is a ZodType instance
5
- * @param {unknown} schema - The schema to check
6
- * @returns {boolean} True if the schema is a Zod schema
7
- */
8
- export const isZodSchema = schema => schema instanceof ZodType;
@@ -1,67 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { z } from 'zod';
3
-
4
- // Import the actual implementations
5
- import { isZodSchema } from './schema_utils.js';
6
-
7
- describe( 'Schema Detection', () => {
8
- describe( 'isZodSchema', () => {
9
- it( 'should correctly identify Zod schemas', () => {
10
- const zodSchema = z.object( {
11
- name: z.string(),
12
- age: z.number()
13
- } );
14
-
15
- expect( isZodSchema( zodSchema ) ).toBe( true );
16
- } );
17
-
18
- it( 'should correctly identify Zod string schema', () => {
19
- const zodString = z.string();
20
- expect( isZodSchema( zodString ) ).toBe( true );
21
- } );
22
-
23
- it( 'should correctly identify Zod array schema', () => {
24
- const zodArray = z.array( z.number() );
25
- expect( isZodSchema( zodArray ) ).toBe( true );
26
- } );
27
-
28
- it( 'should correctly identify Zod union schema', () => {
29
- const zodUnion = z.union( [ z.string(), z.number() ] );
30
- expect( isZodSchema( zodUnion ) ).toBe( true );
31
- } );
32
-
33
- it( 'should return false for JSON Schema objects', () => {
34
- const jsonSchema = {
35
- type: 'object',
36
- properties: {
37
- name: { type: 'string' },
38
- age: { type: 'number' }
39
- },
40
- required: [ 'name' ]
41
- };
42
-
43
- expect( isZodSchema( jsonSchema ) ).toBe( false );
44
- } );
45
-
46
- it( 'should return false for plain objects', () => {
47
- expect( isZodSchema( {} ) ).toBe( false );
48
- expect( isZodSchema( { type: 'string' } ) ).toBe( false );
49
- } );
50
-
51
- it( 'should return false for null and undefined', () => {
52
- expect( isZodSchema( null ) ).toBeFalsy();
53
- expect( isZodSchema( undefined ) ).toBeFalsy();
54
- } );
55
-
56
- it( 'should return false for primitive values', () => {
57
- expect( isZodSchema( 'string' ) ).toBe( false );
58
- expect( isZodSchema( 123 ) ).toBe( false );
59
- expect( isZodSchema( true ) ).toBe( false );
60
- } );
61
-
62
- it( 'should return false for arrays', () => {
63
- expect( isZodSchema( [] ) ).toBe( false );
64
- expect( isZodSchema( [ 1, 2, 3 ] ) ).toBe( false );
65
- } );
66
- } );
67
- } );
@@ -1,137 +0,0 @@
1
- import * as z from 'zod';
2
- import { isZodSchema } from './schema_utils.js';
3
-
4
- /**
5
- * Error is thrown when the definition of a step/workflow has problems
6
- */
7
- export class StaticValidationError extends Error {};
8
-
9
- const refineSchema = ( value, ctx ) => {
10
- if ( !value || isZodSchema( value ) ) {
11
- return;
12
- }
13
-
14
- ctx.addIssue( {
15
- code: 'invalid_type',
16
- message: 'Schema must be a Zod schema'
17
- } );
18
- };
19
-
20
- export const executeInParallelSchema = z.object( {
21
- jobs: z.array( z.function() ),
22
- concurrency: z.number().min( 1 ).or( z.literal( Infinity ) ),
23
- onJobCompleted: z.function().optional()
24
- } );
25
-
26
- export const durationSchema = z.union( [ z.string().regex(
27
- /^(\d+)(ms|s|m|h|d)$/,
28
- 'Expected duration like "500ms", "10s", "5m", "2h", or "1d"'
29
- ), z.number() ] );
30
-
31
- export const prioritySchema = z.object( {
32
- fairnessKey: z.string().optional(),
33
- fairnessWeight: z.number().min( 0.0001 ).max( 1000 ).optional(),
34
- priorityKey: z.number().min( 1 ).optional()
35
- } );
36
-
37
- const baseSchema = z.strictObject( {
38
- name: z.string().regex( /^[a-z_][a-z0-9_]*$/i ),
39
- description: z.string().optional(),
40
- inputSchema: z.any().optional().superRefine( refineSchema ),
41
- outputSchema: z.any().optional().superRefine( refineSchema ),
42
- fn: z.function(),
43
- options: z.object( {
44
- activityOptions: z.strictObject( {
45
- activityId: z.string().optional(),
46
- cancellationType: z.enum( [ 'TRY_CANCEL', 'WAIT_CANCELLATION_COMPLETED', 'ABANDON' ] ).optional(),
47
- heartbeatTimeout: durationSchema.optional(),
48
- priority: prioritySchema.optional(),
49
- retry: z.strictObject( {
50
- initialInterval: durationSchema.optional(),
51
- backoffCoefficient: z.number().gte( 1 ).optional(),
52
- maximumInterval: durationSchema.optional(),
53
- maximumAttempts: z.number().gte( 1 ).int().optional(),
54
- nonRetryableErrorTypes: z.array( z.string() ).optional()
55
- } ).optional(),
56
- scheduleToCloseTimeout: durationSchema.optional(),
57
- scheduleToStartTimeout: durationSchema.optional(),
58
- startToCloseTimeout: durationSchema.optional(),
59
- summary: z.string().optional()
60
- } ).optional()
61
- } ).optional()
62
- } );
63
-
64
- const stepSchema = baseSchema;
65
-
66
- const workflowSchema = baseSchema.extend( {
67
- aliases: z.array( z.string().regex( /^[a-z_][a-z0-9_]*$/i ) ).optional().default( [] ),
68
- options: baseSchema.shape.options.unwrap().extend( {
69
- disableTrace: z.boolean().optional().default( false )
70
- } ).optional()
71
- } );
72
-
73
- const evaluatorSchema = baseSchema.omit( { outputSchema: true } );
74
-
75
- const httpRequestSchema = z.object( {
76
- url: z.url( { protocol: /^https?$/ } ),
77
- method: z.enum( [ 'GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE' ] ),
78
- payload: z.any().optional(),
79
- headers: z.record( z.string(), z.string() ).optional()
80
- } );
81
-
82
- const validateAgainstSchema = ( schema, args ) => {
83
- const result = schema.safeParse( args );
84
- if ( !result.success ) {
85
- throw new StaticValidationError( z.prettifyError( result.error ) );
86
- }
87
- };
88
-
89
- /**
90
- * Validate step payload
91
- *
92
- * @param {object} args - The step arguments
93
- * @throws {StaticValidationError} Throws if args are invalid
94
- */
95
- export function validateStep( args ) {
96
- validateAgainstSchema( stepSchema, args );
97
- };
98
-
99
- /**
100
- * Validate evaluator payload
101
- *
102
- * @param {object} args - The evaluator arguments
103
- * @throws {StaticValidationError} Throws if args are invalid
104
- */
105
- export function validateEvaluator( args ) {
106
- validateAgainstSchema( evaluatorSchema, args );
107
- };
108
-
109
- /**
110
- * Validate workflow payload
111
- *
112
- * @param {object} args - The workflow arguments
113
- * @throws {StaticValidationError} Throws if args are invalid
114
- */
115
- export function validateWorkflow( args ) {
116
- validateAgainstSchema( workflowSchema, args );
117
- };
118
-
119
- /**
120
- * Validate request payload
121
- *
122
- * @param {object} args - The request arguments
123
- * @throws {StaticValidationError} Throws if args are invalid
124
- */
125
- export function validateRequestPayload( args ) {
126
- validateAgainstSchema( httpRequestSchema, args );
127
- };
128
-
129
- /**
130
- * Validate executeInParallel
131
- *
132
- * @param {object} args - The request arguments
133
- * @throws {StaticValidationError} Throws if args are invalid
134
- */
135
- export function validateExecuteInParallel( args ) {
136
- validateAgainstSchema( executeInParallelSchema, args );
137
- };