@output.ai/core 0.0.7 → 0.0.9
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 +85 -59
- package/package.json +10 -3
- package/src/configs.js +1 -1
- package/src/consts.js +4 -3
- package/src/errors.js +11 -0
- package/src/index.d.ts +302 -30
- package/src/index.js +3 -2
- package/src/interface/metadata.js +3 -3
- package/src/interface/step.js +18 -4
- package/src/interface/utils.js +41 -4
- package/src/interface/utils.spec.js +71 -0
- package/src/interface/validations/ajv_provider.js +3 -0
- package/src/interface/validations/runtime.js +69 -0
- package/src/interface/validations/runtime.spec.js +50 -0
- package/src/interface/validations/static.js +67 -0
- package/src/interface/validations/static.spec.js +101 -0
- package/src/interface/webhook.js +15 -14
- package/src/interface/workflow.js +45 -40
- package/src/internal_activities/index.js +16 -5
- package/src/worker/catalog_workflow/catalog.js +105 -0
- package/src/worker/catalog_workflow/index.js +21 -0
- package/src/worker/catalog_workflow/index.spec.js +139 -0
- package/src/worker/catalog_workflow/workflow.js +13 -0
- package/src/worker/index.js +41 -5
- package/src/worker/interceptors/activity.js +3 -2
- package/src/worker/internal_utils.js +60 -0
- package/src/worker/internal_utils.spec.js +134 -0
- package/src/worker/loader.js +30 -44
- package/src/worker/loader.spec.js +68 -0
- package/src/worker/sinks.js +2 -1
- package/src/worker/tracer/index.js +35 -3
- package/src/worker/tracer/index.test.js +115 -0
- package/src/worker/tracer/tracer_tree.js +29 -5
- package/src/worker/tracer/tracer_tree.test.js +116 -0
- package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.js +133 -0
- package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.spec.js +77 -0
- package/src/worker/webpack_loaders/workflow_rewriter/consts.js +3 -0
- package/src/worker/webpack_loaders/workflow_rewriter/index.mjs +58 -0
- package/src/worker/webpack_loaders/workflow_rewriter/index.spec.js +129 -0
- package/src/worker/webpack_loaders/workflow_rewriter/rewrite_fn_bodies.js +70 -0
- package/src/worker/webpack_loaders/workflow_rewriter/rewrite_fn_bodies.spec.js +33 -0
- package/src/worker/webpack_loaders/workflow_rewriter/tools.js +245 -0
- package/src/worker/webpack_loaders/workflow_rewriter/tools.spec.js +144 -0
- package/src/errors.d.ts +0 -3
- package/src/worker/temp/__workflows_entrypoint.js +0 -6
package/README.md
CHANGED
|
@@ -1,64 +1,100 @@
|
|
|
1
1
|
# Core
|
|
2
2
|
|
|
3
|
-
Provides tools to run a workflow, which is a well defined logical unit of work.
|
|
3
|
+
Provides tools to develop and run a workflow, which is a well defined logical unit of work.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Structure
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Workflows are defined using core functions "workflow" and "step", separate files:
|
|
8
8
|
|
|
9
|
-
```
|
|
10
|
-
|
|
9
|
+
```
|
|
10
|
+
└ workflows
|
|
11
|
+
└ example
|
|
12
|
+
├ workflow.ts|js <- workflow entry point
|
|
13
|
+
├ steps.ts|js <- file with each step of this workflow
|
|
14
|
+
└ prompt.prompt <- a prompt file
|
|
15
|
+
└ other-example
|
|
11
16
|
|
|
12
|
-
export const aSingleStep = step( {
|
|
13
|
-
name: 'aSingleStep',
|
|
14
|
-
fn: async (): Promise<string> => {
|
|
15
|
-
// do stuff
|
|
16
|
-
}
|
|
17
|
-
} );
|
|
18
17
|
```
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
Think that workflows is the orchestrator and steps are executors. So the workflow only call the steps and the steps call the IO operations, like APIs, DBs, LLMs, etc.
|
|
21
20
|
|
|
22
|
-
##
|
|
21
|
+
## Workflow code
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
### workflow.js
|
|
25
24
|
|
|
26
|
-
```
|
|
27
|
-
import { workflow } from '
|
|
28
|
-
import
|
|
29
|
-
import type { PromptWorkflowInput, PromptWorkflowOutput } from './types';
|
|
25
|
+
```js
|
|
26
|
+
import { workflow } from '@output.ai/workflow';
|
|
27
|
+
import { guessByName } from './steps.js';
|
|
30
28
|
|
|
31
29
|
export default workflow( {
|
|
32
|
-
name: '
|
|
33
|
-
description: '
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
name: 'guessMyProfession',
|
|
31
|
+
description: 'Guess a person profession by its name',
|
|
32
|
+
inputSchema: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
required: [ 'name' ],
|
|
35
|
+
properties: {
|
|
36
|
+
name: { type: 'string'}
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
outputSchema: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
required: [ 'profession' ],
|
|
42
|
+
properties: {
|
|
43
|
+
profession: { type: 'string'}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
fn: async input => {
|
|
47
|
+
const profession = await guessByName( input.name );
|
|
48
|
+
return { profession };
|
|
38
49
|
}
|
|
39
|
-
}
|
|
50
|
+
})
|
|
40
51
|
```
|
|
41
52
|
|
|
42
|
-
|
|
53
|
+
### steps.js
|
|
43
54
|
|
|
44
|
-
|
|
55
|
+
```js
|
|
56
|
+
import { api } from './api.js'
|
|
45
57
|
|
|
46
|
-
|
|
58
|
+
export const guessByName = step( {
|
|
59
|
+
name: 'guessByName',
|
|
60
|
+
inputSchema: {
|
|
61
|
+
type: 'string'
|
|
62
|
+
},
|
|
63
|
+
outputSchema: {
|
|
64
|
+
type: 'string'
|
|
65
|
+
},
|
|
66
|
+
fn: async name => {
|
|
67
|
+
const res = await api.consumer( name );
|
|
68
|
+
return res.body;
|
|
69
|
+
}
|
|
70
|
+
} )
|
|
71
|
+
```
|
|
47
72
|
|
|
48
|
-
|
|
73
|
+
## webhooks
|
|
49
74
|
|
|
50
|
-
|
|
75
|
+
workflows can call webhooks that will stop their execution until an answer is given back.
|
|
51
76
|
|
|
52
77
|
```js
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
78
|
+
import { workflow, createWebhook } from '@output.ai/workflow';
|
|
79
|
+
import { guessByName } from './steps.js';
|
|
80
|
+
|
|
81
|
+
export default workflow( {
|
|
82
|
+
...
|
|
83
|
+
fn: async input => {
|
|
84
|
+
...
|
|
85
|
+
|
|
86
|
+
const result = await createWebhook( {
|
|
87
|
+
url: 'http://xxx.xxx/feedback',
|
|
88
|
+
payload: {
|
|
89
|
+
progressSoFar: 'plenty'
|
|
90
|
+
}
|
|
91
|
+
} );
|
|
92
|
+
|
|
93
|
+
}
|
|
94
|
+
})
|
|
59
95
|
```
|
|
60
96
|
|
|
61
|
-
|
|
97
|
+
The url of the example will receive the payload, plus the workflowId:
|
|
62
98
|
|
|
63
99
|
```js
|
|
64
100
|
{
|
|
@@ -67,38 +103,28 @@ the url will receive the following payload:
|
|
|
67
103
|
}
|
|
68
104
|
```
|
|
69
105
|
|
|
70
|
-
To resume the workflow, a POST has to be made
|
|
106
|
+
To resume the workflow, a POST has to be made with a response payload and the workflowId.
|
|
71
107
|
|
|
72
|
-
|
|
108
|
+
- Production: `https://output-api-production.onrender.com/workflow/feedback`
|
|
109
|
+
- Staging: `https://output-api-staging.onrender.com/workflow/feedback`
|
|
110
|
+
- Local: `http://localhost:3001/workflow/feedback`
|
|
73
111
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
112
|
+
Example:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
POST http://locahost:3001/workflow/feedback
|
|
77
116
|
{
|
|
78
117
|
workflowId,
|
|
79
118
|
payload: {}
|
|
80
119
|
}
|
|
81
120
|
```
|
|
82
121
|
|
|
83
|
-
##
|
|
84
|
-
|
|
85
|
-
```
|
|
86
|
-
└ workflows
|
|
87
|
-
└ my workflow
|
|
88
|
-
├ index.ts // contains the workflow()
|
|
89
|
-
├ types.ts // contains input, output types, and other misc types
|
|
90
|
-
└ steps.ts // contains all steps
|
|
91
|
-
```
|
|
122
|
+
## Developing
|
|
92
123
|
|
|
93
|
-
|
|
124
|
+
To develop workflows you need the code, which will be called the worker, the API and the engine (Temporal).
|
|
94
125
|
|
|
95
|
-
|
|
126
|
+
After having the API and the engine running, to start the worker just run:
|
|
96
127
|
|
|
97
|
-
_package.json_
|
|
98
128
|
```js
|
|
99
|
-
|
|
100
|
-
"scripts": {
|
|
101
|
-
"start": "npx flow-worker"
|
|
102
|
-
},
|
|
103
|
-
...
|
|
129
|
+
`outputai`
|
|
104
130
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@output.ai/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "The core module of the output framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -13,20 +13,27 @@
|
|
|
13
13
|
"worker": "node ./src/worker/index.js"
|
|
14
14
|
},
|
|
15
15
|
"bin": {
|
|
16
|
-
"flow-worker": "./bin/worker.sh"
|
|
16
|
+
"flow-worker": "./bin/worker.sh",
|
|
17
|
+
"outputai": "./bin/worker.sh"
|
|
17
18
|
},
|
|
18
19
|
"repository": {
|
|
19
20
|
"type": "git",
|
|
20
21
|
"url": "git+https://github.com/growthxai/flow-sdk"
|
|
21
22
|
},
|
|
22
23
|
"dependencies": {
|
|
24
|
+
"@babel/generator": "7.26.5",
|
|
25
|
+
"@babel/parser": "7.26.7",
|
|
26
|
+
"@babel/traverse": "7.25.9",
|
|
27
|
+
"@babel/types": "7.26.7",
|
|
23
28
|
"@temporalio/worker": "1.13.0",
|
|
24
29
|
"@temporalio/workflow": "1.13.0",
|
|
25
|
-
"
|
|
30
|
+
"ajv": "8.17.1",
|
|
31
|
+
"zod": "4.1.9"
|
|
26
32
|
},
|
|
27
33
|
"imports": {
|
|
28
34
|
"#consts": "./src/consts.js",
|
|
29
35
|
"#configs": "./src/configs.js",
|
|
36
|
+
"#errors": "./src/errors.js",
|
|
30
37
|
"#internal_activities": "./src/internal_activities/index.js"
|
|
31
38
|
}
|
|
32
39
|
}
|
package/src/configs.js
CHANGED
package/src/consts.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export const
|
|
2
|
-
export const
|
|
3
|
-
export const
|
|
1
|
+
export const SEND_WEBHOOK_ACTIVITY_NAME = '__internal#sendWebhookPost';
|
|
2
|
+
export const METADATA_ACCESS_SYMBOL = Symbol( '__metadata' );
|
|
3
|
+
export const WORKFLOWS_INDEX_FILENAME = '__workflows_entrypoint.js';
|
|
4
|
+
export const THIS_LIB_NAME = 'core';
|
package/src/errors.js
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* These are errors exposed as tools for the user to break their flow
|
|
3
|
+
* They work in both steps and workflows
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Any generic fatal errors
|
|
8
|
+
*/
|
|
1
9
|
export class FatalError extends Error { }
|
|
2
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Any validation error
|
|
13
|
+
*/
|
|
3
14
|
export class ValidationError extends Error { }
|
package/src/index.d.ts
CHANGED
|
@@ -1,38 +1,310 @@
|
|
|
1
|
-
|
|
1
|
+
// JSON Schema → TypeScript type mapping (subset sufficient for IntelliSense)
|
|
2
|
+
type Simplify<T> = { [K in keyof T]: T[K] };
|
|
3
|
+
type EnumValues = readonly ( string | number | boolean | null )[];
|
|
4
|
+
|
|
5
|
+
type JSONSchema = {
|
|
6
|
+
type?: 'string' | 'number' | 'integer' | 'boolean' | 'null' | 'object' | 'array';
|
|
7
|
+
enum?: EnumValues;
|
|
8
|
+
const?: string | number | boolean | null;
|
|
9
|
+
anyOf?: readonly JSONSchema[];
|
|
10
|
+
oneOf?: readonly JSONSchema[];
|
|
11
|
+
allOf?: readonly JSONSchema[];
|
|
12
|
+
// object
|
|
13
|
+
properties?: { [key: string]: JSONSchema };
|
|
14
|
+
required?: readonly string[];
|
|
15
|
+
additionalProperties?: boolean | JSONSchema;
|
|
16
|
+
// array
|
|
17
|
+
items?: JSONSchema | readonly JSONSchema[];
|
|
18
|
+
// ignore $ref & others for typing purposes
|
|
19
|
+
$ref?: string;
|
|
20
|
+
} & Record<string, unknown>;
|
|
21
|
+
|
|
22
|
+
type UnionToIntersection<U> = ( U extends unknown ? ( k: U ) => void : never ) extends ( k: infer I ) => void ? I : never;
|
|
23
|
+
|
|
24
|
+
type FromEnum<S> = S extends { enum: infer E extends EnumValues } ? E[number] : never;
|
|
25
|
+
type FromConst<S> = S extends { const: infer C } ? C : never;
|
|
26
|
+
|
|
27
|
+
type FromPrimitive<S> =
|
|
28
|
+
S extends { type: 'string' } ? string :
|
|
29
|
+
S extends { type: 'number' | 'integer' } ? number :
|
|
30
|
+
S extends { type: 'boolean' } ? boolean :
|
|
31
|
+
S extends { type: 'null' } ? null :
|
|
32
|
+
never;
|
|
33
|
+
|
|
34
|
+
type ObjectProps<S extends JSONSchema> = S extends { properties: infer P extends Record<string, JSONSchema> }
|
|
35
|
+
? { [K in keyof P]: FromSchema<P[K]> }
|
|
36
|
+
: Record<never, never>;
|
|
37
|
+
|
|
38
|
+
type ObjectRequiredKeys<S extends JSONSchema> = S extends { required: readonly ( infer R )[] }
|
|
39
|
+
? Extract<R & string, keyof ObjectProps<S>>
|
|
40
|
+
: never;
|
|
41
|
+
|
|
42
|
+
type ObjectFrom<S extends JSONSchema> = Simplify<
|
|
43
|
+
Pick<ObjectProps<S>, ObjectRequiredKeys<S>> &
|
|
44
|
+
Partial<Omit<ObjectProps<S>, ObjectRequiredKeys<S>>>
|
|
45
|
+
>;
|
|
46
|
+
|
|
47
|
+
type ArrayFrom<S extends JSONSchema> = S extends { items: infer I }
|
|
48
|
+
? I extends readonly unknown[]
|
|
49
|
+
? FromSchema<I[number]>[]
|
|
50
|
+
: FromSchema<I>[]
|
|
51
|
+
: unknown[];
|
|
52
|
+
|
|
53
|
+
export type FromSchema<S extends JSONSchema> =
|
|
54
|
+
// combinators first
|
|
55
|
+
S extends { anyOf: infer A extends readonly JSONSchema[] } ? FromSchema<A[number]> :
|
|
56
|
+
S extends { oneOf: infer A extends readonly JSONSchema[] } ? FromSchema<A[number]> :
|
|
57
|
+
S extends { allOf: infer A extends readonly JSONSchema[] } ? UnionToIntersection<FromSchema<A[number]>> :
|
|
58
|
+
// enum/const
|
|
59
|
+
FromEnum<S> extends never ? ( FromConst<S> extends never ? (
|
|
60
|
+
// object (explicit or by presence of properties)
|
|
61
|
+
S extends { type: 'object' } | { properties: Record<string, JSONSchema> } ? ObjectFrom<S> :
|
|
62
|
+
// array
|
|
63
|
+
S extends { type: 'array' } ? ArrayFrom<S> :
|
|
64
|
+
// primitives
|
|
65
|
+
FromPrimitive<S> extends never ? unknown : FromPrimitive<S>
|
|
66
|
+
) : FromConst<S> ) : FromEnum<S>;
|
|
67
|
+
|
|
68
|
+
export type OutputFrom<O extends JSONSchema> = FromSchema<O>;
|
|
69
|
+
|
|
70
|
+
// Utility to strip readonly from inferred types
|
|
71
|
+
/** Recursively removes readonly modifiers from object and array types. */
|
|
72
|
+
type DeepMutable<T> =
|
|
73
|
+
T extends readonly ( infer U )[] ? DeepMutable<U>[] :
|
|
74
|
+
T extends object ? { -readonly [K in keyof T]: DeepMutable<T[K]> } :
|
|
75
|
+
T;
|
|
76
|
+
|
|
77
|
+
/*
|
|
78
|
+
* There is 4 overrides of the "step" function"
|
|
79
|
+
* - with fn receiving input and returning output;
|
|
80
|
+
* - with fn receiving input and returning void;
|
|
81
|
+
* - with fn receiving void and returning outout;
|
|
82
|
+
* - with fn receiving void and returning void;
|
|
83
|
+
*/
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @callback StepFn
|
|
87
|
+
* @param {any} input - The input, defined by the inputSchema
|
|
88
|
+
* @returns {any} The output defined by the outputSchema
|
|
89
|
+
*/
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Creates logical unit of work, called "step", which will be invoked from workflows.
|
|
93
|
+
*
|
|
94
|
+
* @param {object} options - Step options
|
|
95
|
+
* @param {string} options.name - Human-readable step name (only letters, numbers and "_")
|
|
96
|
+
* @param {string} [options.description] - Description of the step
|
|
97
|
+
* @param {JSONSchema} options.inputSchema - JSON Schema for the fn input, will infer a TS type
|
|
98
|
+
* @param {JSONSchema} options.outputSchema - JSON Schema for the fn output, will infer a TS type
|
|
99
|
+
* @param {StepFn} options.fn - The function logic
|
|
100
|
+
* @returns {StepFn} The options.fn function
|
|
101
|
+
*/
|
|
102
|
+
export async function step<
|
|
103
|
+
const InputSchema extends JSONSchema,
|
|
104
|
+
const OutputSchema extends JSONSchema
|
|
105
|
+
>( options: {
|
|
106
|
+
name: string;
|
|
107
|
+
description?: string;
|
|
108
|
+
inputSchema: InputSchema;
|
|
109
|
+
outputSchema: OutputSchema;
|
|
110
|
+
fn: ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<DeepMutable<FromSchema<OutputSchema>>>;
|
|
111
|
+
} ): ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<DeepMutable<FromSchema<OutputSchema>>>;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @callback InputOnlyStepFn
|
|
115
|
+
* @param {any} input - The input, defined by the inputSchema
|
|
116
|
+
*/
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Creates logical unit of work, called "step", which will be invoked from workflows.
|
|
120
|
+
*
|
|
121
|
+
* @param {object} options - Step options
|
|
122
|
+
* @param {string} options.name - Human-readable step name (only letters, numbers and "_")
|
|
123
|
+
* @param {string} [options.description] - Description of the step
|
|
124
|
+
* @param {JSONSchema} options.inputSchema - JSON Schema for the fn input, will infer a TS type
|
|
125
|
+
* @param {InputOnlyStepFn} options.fn - The function logic
|
|
126
|
+
* @returns {InputOnlyStepFn} The options.fn function
|
|
127
|
+
*/
|
|
128
|
+
export async function step<
|
|
129
|
+
const InputSchema extends JSONSchema
|
|
130
|
+
>( options: {
|
|
131
|
+
name: string;
|
|
132
|
+
description?: string;
|
|
133
|
+
inputSchema: InputSchema;
|
|
134
|
+
fn: ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<void>;
|
|
135
|
+
} ): ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<void>;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @callback OutputOnlyStepFn
|
|
139
|
+
* @returns {any} The output defined by the outputSchema
|
|
140
|
+
*/
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Creates logical unit of work, called "step", which will be invoked from workflows.
|
|
144
|
+
*
|
|
145
|
+
* @param {object} options - Step options
|
|
146
|
+
* @param {string} options.name - Human-readable step name (only letters, numbers and "_")
|
|
147
|
+
* @param {string} [options.description] - Description of the step
|
|
148
|
+
* @param {JSONSchema} options.outputSchema - JSON Schema for the fn output, will infer a TS type
|
|
149
|
+
* @param {OutputOnlyStepFn} options.fn - The function logic
|
|
150
|
+
* @returns {OutputOnlyStepFn} The options.fn function
|
|
151
|
+
*/
|
|
152
|
+
export async function step<
|
|
153
|
+
const OutputSchema extends JSONSchema
|
|
154
|
+
>( options: {
|
|
2
155
|
name: string;
|
|
3
156
|
description?: string;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
export interface WorkflowDefinition<TInput = unknown, TOutput = unknown> {
|
|
157
|
+
outputSchema: OutputSchema;
|
|
158
|
+
fn: () => Promise<DeepMutable<FromSchema<OutputSchema>>>;
|
|
159
|
+
} ): () => Promise<DeepMutable<FromSchema<OutputSchema>>>;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @callback VoidStepFn
|
|
163
|
+
*/
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Creates logical unit of work, called "step", which will be invoked from workflows.
|
|
167
|
+
*
|
|
168
|
+
* @param {object} options - Step options
|
|
169
|
+
* @param {string} options.name - Human-readable step name (only letters, numbers and "_")
|
|
170
|
+
* @param {string} [options.description] - Description of the step
|
|
171
|
+
* @param {VoidStepFn} options.fn - The function logic
|
|
172
|
+
* @returns {VoidStepFn} The options.fn function
|
|
173
|
+
*/
|
|
174
|
+
export async function step( options: {
|
|
23
175
|
name: string;
|
|
24
176
|
description?: string;
|
|
25
|
-
fn: (
|
|
26
|
-
}
|
|
177
|
+
fn: () => Promise<void>;
|
|
178
|
+
} ): () => Promise<void>;
|
|
179
|
+
|
|
180
|
+
/*
|
|
181
|
+
* There is 4 overrides of the "workflow" function"
|
|
182
|
+
* - with fn receiving input and returning output;
|
|
183
|
+
* - with fn receiving input and returning void;
|
|
184
|
+
* - with fn receiving void and returning outout;
|
|
185
|
+
* - with fn receiving void and returning void;
|
|
186
|
+
*/
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @callback WorkflowFn
|
|
190
|
+
* @param {any} input - The input, defined by the inputSchema
|
|
191
|
+
* @returns {any} The output defined by the outputSchema
|
|
192
|
+
*/
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Creates a workflow orchestrator which can invoke steps.
|
|
196
|
+
*
|
|
197
|
+
* @param {object} options - Workflow options
|
|
198
|
+
* @param {string} options.name - Unique workflow name
|
|
199
|
+
* @param {string} [options.description] - Description of the workflow
|
|
200
|
+
* @param {JSONSchema} [options.inputSchema] - JSON Schema for workflow input
|
|
201
|
+
* @param {JSONSchema} [options.outputSchema] - JSON Schema for workflow output
|
|
202
|
+
* @param {WorkflowFn} options.fn - Workflow logic
|
|
203
|
+
* @returns {WorkflowFn} Callable workflow function
|
|
204
|
+
*/
|
|
205
|
+
export function workflow<
|
|
206
|
+
const InputSchema extends JSONSchema,
|
|
207
|
+
const OutputSchema extends JSONSchema
|
|
208
|
+
>( options : {
|
|
209
|
+
name: string,
|
|
210
|
+
description?: string,
|
|
211
|
+
inputSchema: InputSchema,
|
|
212
|
+
outputSchema: OutputSchema,
|
|
213
|
+
fn: ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<DeepMutable<FromSchema<OutputSchema>>>
|
|
214
|
+
} ): ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<DeepMutable<FromSchema<OutputSchema>>>;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* @callback InputOnlyWorkflowFn
|
|
218
|
+
* @param {any} input - The input, defined by the inputSchema
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Creates a workflow orchestrator which can invoke steps.
|
|
223
|
+
*
|
|
224
|
+
* @param {object} options - Workflow options
|
|
225
|
+
* @param {string} options.name - Unique workflow name
|
|
226
|
+
* @param {string} [options.description] - Description of the workflow
|
|
227
|
+
* @param {JSONSchema} [options.inputSchema] - JSON Schema for workflow input
|
|
228
|
+
* @param {InputOnlyWorkflowFn} options.fn - Workflow logic
|
|
229
|
+
* @returns {InputOnlyWorkflowFn} Callable workflow function
|
|
230
|
+
*/
|
|
231
|
+
export function workflow<
|
|
232
|
+
const InputSchema extends JSONSchema
|
|
233
|
+
>( options : {
|
|
234
|
+
name: string,
|
|
235
|
+
description?: string,
|
|
236
|
+
inputSchema: InputSchema,
|
|
237
|
+
fn: ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<void>
|
|
238
|
+
} ): ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<void>;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* @callback OutputOnlyWorkflowFn
|
|
242
|
+
* @returns {any} The output defined by the outputSchema
|
|
243
|
+
*/
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Creates a workflow orchestrator which can invoke steps.
|
|
247
|
+
*
|
|
248
|
+
* @param {object} options - Workflow options
|
|
249
|
+
* @param {string} options.name - Unique workflow name
|
|
250
|
+
* @param {string} [options.description] - Description of the workflow
|
|
251
|
+
* @param {JSONSchema} [options.outputSchema] - JSON Schema for workflow output
|
|
252
|
+
* @param {OutputOnlyWorkflowFn} options.fn - Workflow logic
|
|
253
|
+
* @returns {OutputOnlyWorkflowFn} Callable workflow function
|
|
254
|
+
*/
|
|
255
|
+
export function workflow<
|
|
256
|
+
const OutputSchema extends JSONSchema
|
|
257
|
+
>( options : {
|
|
258
|
+
name: string,
|
|
259
|
+
description?: string,
|
|
260
|
+
outputSchema: OutputSchema,
|
|
261
|
+
fn: () => Promise<DeepMutable<FromSchema<OutputSchema>>>
|
|
262
|
+
} ): () => Promise<DeepMutable<FromSchema<OutputSchema>>>;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* @callback VoidWorkflowFn
|
|
266
|
+
* @param {any} input - The input, defined by the inputSchema
|
|
267
|
+
* @returns {any} The output defined by the outputSchema
|
|
268
|
+
*/
|
|
27
269
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
270
|
+
/**
|
|
271
|
+
* Creates a workflow orchestrator which can invoke steps.
|
|
272
|
+
*
|
|
273
|
+
* @param {object} options - Workflow options
|
|
274
|
+
* @param {string} options.name - Unique workflow name
|
|
275
|
+
* @param {string} [options.description] - Description of the workflow
|
|
276
|
+
* @param {VoidWorkflowFn} options.fn - Workflow logic
|
|
277
|
+
* @returns {VoidWorkflowFn} Callable workflow function
|
|
278
|
+
*/
|
|
279
|
+
export function workflow( options : {
|
|
280
|
+
name: string,
|
|
281
|
+
description?: string,
|
|
282
|
+
fn: () => Promise<void>
|
|
283
|
+
} ): () => Promise<void>;
|
|
31
284
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
285
|
+
/**
|
|
286
|
+
* Create a webhook call that pauses the workflow until resumed via signal.
|
|
287
|
+
*
|
|
288
|
+
* Sends a request via an activity; the workflow will await a corresponding
|
|
289
|
+
* resume signal to continue and return the response payload.
|
|
290
|
+
*
|
|
291
|
+
* @param {object} options - Webhook request options
|
|
292
|
+
* @param {string} options.url - Webhook request url (POST)
|
|
293
|
+
* @param {object} [options.payload] - Webhook request payload
|
|
294
|
+
* @returns {Promise<object>} Resolves with the response payload when resumed
|
|
295
|
+
*/
|
|
296
|
+
export function createWebhook( options: { url: string; payload?: object } ): Promise<object>;
|
|
35
297
|
|
|
36
|
-
|
|
298
|
+
/**
|
|
299
|
+
* Error indicating a non-recoverable failure.
|
|
300
|
+
*
|
|
301
|
+
* Use for failures that should not be retried by the workflow runtime.
|
|
302
|
+
*/
|
|
303
|
+
export class FatalError extends Error {}
|
|
37
304
|
|
|
38
|
-
|
|
305
|
+
/**
|
|
306
|
+
* Error indicating invalid input or schema validation issues.
|
|
307
|
+
*
|
|
308
|
+
* Use for problems detected during input validation or contract checks.
|
|
309
|
+
*/
|
|
310
|
+
export class ValidationError extends Error {}
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { step } from './interface/step.js';
|
|
2
|
-
import {
|
|
2
|
+
import { workflow } from './interface/workflow.js';
|
|
3
|
+
import { createWebhook } from './interface/webhook.js';
|
|
3
4
|
import { FatalError, ValidationError } from './errors.js';
|
|
4
5
|
|
|
5
|
-
export { step,
|
|
6
|
+
export { step, workflow, createWebhook, FatalError, ValidationError };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { METADATA_ACCESS_SYMBOL } from '#consts';
|
|
2
2
|
|
|
3
|
-
export const
|
|
4
|
-
Object.defineProperty( target,
|
|
3
|
+
export const setMetadata = ( target, values ) =>
|
|
4
|
+
Object.defineProperty( target, METADATA_ACCESS_SYMBOL, { value: values, writable: false, enumerable: false, configurable: false } );
|
package/src/interface/step.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { setMetadata } from './metadata.js';
|
|
2
|
+
import { validateStep } from './validations/static.js';
|
|
3
|
+
import { validateStepInput, validateStepOutput } from './validations/runtime.js';
|
|
4
|
+
import { invokeFnAndValidateOutputPreservingExecutionModel } from './utils.js';
|
|
2
5
|
|
|
3
|
-
export function step( { name, description
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
export function step( { name, description, inputSchema, outputSchema, fn } ) {
|
|
7
|
+
validateStep( { name, description, inputSchema, outputSchema, fn } );
|
|
8
|
+
const wrapper = input => {
|
|
9
|
+
if ( inputSchema ) {
|
|
10
|
+
validateStepInput( name, inputSchema, input );
|
|
11
|
+
}
|
|
12
|
+
if ( !outputSchema ) {
|
|
13
|
+
return fn( input );
|
|
14
|
+
}
|
|
15
|
+
return invokeFnAndValidateOutputPreservingExecutionModel( fn, input, validateStepOutput.bind( null, name, outputSchema ) );
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
setMetadata( wrapper, { name, description, inputSchema, outputSchema } );
|
|
19
|
+
return wrapper;
|
|
6
20
|
};
|