@wooksjs/event-wf 0.6.2 → 0.6.4
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 +26 -3
- package/dist/index.cjs +38 -5
- package/dist/index.d.ts +37 -6
- package/dist/index.mjs +34 -7
- package/package.json +43 -34
- package/scripts/setup-skills.js +77 -0
- package/skills/wooksjs-event-wf/SKILL.md +42 -0
- package/skills/wooksjs-event-wf/core.md +399 -0
- package/skills/wooksjs-event-wf/event-core.md +562 -0
- package/skills/wooksjs-event-wf/workflows.md +579 -0
package/README.md
CHANGED
|
@@ -62,10 +62,9 @@ app.flow('adding-parametric', [
|
|
|
62
62
|
},
|
|
63
63
|
])
|
|
64
64
|
|
|
65
|
-
app.run()
|
|
66
|
-
|
|
67
65
|
// Run the 'adding' workflow
|
|
68
|
-
app.start('adding', { result: 0 })
|
|
66
|
+
const output = await app.start('adding', { result: 0 })
|
|
67
|
+
console.log(output.state.context) // { result: 14 }
|
|
69
68
|
```
|
|
70
69
|
|
|
71
70
|
## Documentation
|
|
@@ -76,6 +75,30 @@ For more detailed documentation, please visit [wooks.moost.org](https://wooks.mo
|
|
|
76
75
|
|
|
77
76
|
Contributions to the `@wooksjs/event-wf` project are welcome. If you find any bugs or have a feature request, please open an issue on [the GitHub repository](https://github.com/wooksjs/wooksjs).
|
|
78
77
|
|
|
78
|
+
## AI Agent Skills
|
|
79
|
+
|
|
80
|
+
This package ships with structured skill files for AI coding agents (Claude Code, Cursor, Windsurf, Codex, etc.).
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Project-local (recommended — version-locked, commits with your repo)
|
|
84
|
+
npx @wooksjs/event-wf setup-skills
|
|
85
|
+
|
|
86
|
+
# Global (available across all your projects)
|
|
87
|
+
npx @wooksjs/event-wf setup-skills --global
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
To keep skills automatically up-to-date, add a postinstall script to your `package.json`:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"scripts": {
|
|
95
|
+
"postinstall": "npx @wooksjs/event-wf setup-skills --postinstall"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
This ensures the skill files are refreshed whenever dependencies are installed, without needing a separate command.
|
|
101
|
+
|
|
79
102
|
## License
|
|
80
103
|
|
|
81
104
|
`@wooksjs/event-wf` is licensed under the [MIT license](https://github.com/wooksjs/wooksjs/blob/main/LICENSE).
|
package/dist/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ const __prostojs_wf = __toESM(require("@prostojs/wf"));
|
|
|
26
26
|
const wooks = __toESM(require("wooks"));
|
|
27
27
|
|
|
28
28
|
//#region packages/event-wf/src/event-wf.ts
|
|
29
|
+
/** Creates a new async event context for a fresh workflow execution. */
|
|
29
30
|
function createWfContext(data, options) {
|
|
30
31
|
return (0, __wooksjs_event_core.createAsyncEventContext)({
|
|
31
32
|
event: {
|
|
@@ -36,6 +37,7 @@ function createWfContext(data, options) {
|
|
|
36
37
|
options
|
|
37
38
|
});
|
|
38
39
|
}
|
|
40
|
+
/** Creates an async event context for resuming a paused workflow. */
|
|
39
41
|
function resumeWfContext(data, options) {
|
|
40
42
|
return (0, __wooksjs_event_core.createAsyncEventContext)({
|
|
41
43
|
event: {
|
|
@@ -57,6 +59,15 @@ function useWFContext() {
|
|
|
57
59
|
|
|
58
60
|
//#endregion
|
|
59
61
|
//#region packages/event-wf/src/composables/wf-state.ts
|
|
62
|
+
/**
|
|
63
|
+
* Composable that provides access to the current workflow execution state.
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* const { ctx, input, schemaId, stepId } = useWfState()
|
|
67
|
+
* const context = ctx<MyContext>()
|
|
68
|
+
* const stepInput = input<MyInput>()
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
60
71
|
function useWfState() {
|
|
61
72
|
const { store, getCtx } = useWFContext();
|
|
62
73
|
const event = store("event");
|
|
@@ -72,6 +83,7 @@ function useWfState() {
|
|
|
72
83
|
|
|
73
84
|
//#endregion
|
|
74
85
|
//#region packages/event-wf/src/workflow.ts
|
|
86
|
+
/** Workflow engine that resolves steps via Wooks router lookup. */
|
|
75
87
|
var WooksWorkflow = class extends __prostojs_wf.Workflow {
|
|
76
88
|
constructor(wooks$1) {
|
|
77
89
|
super([]);
|
|
@@ -86,7 +98,7 @@ var WooksWorkflow = class extends __prostojs_wf.Workflow {
|
|
|
86
98
|
store.set("stepId", stepIdNorm);
|
|
87
99
|
return found.handlers[0]();
|
|
88
100
|
}
|
|
89
|
-
} catch
|
|
101
|
+
} catch {
|
|
90
102
|
const router = this.wooks.getRouter();
|
|
91
103
|
const found = router.lookup("WF_STEP", stepIdNorm);
|
|
92
104
|
if (found?.route?.handlers.length) return found.route.handlers[0]();
|
|
@@ -97,10 +109,12 @@ var WooksWorkflow = class extends __prostojs_wf.Workflow {
|
|
|
97
109
|
|
|
98
110
|
//#endregion
|
|
99
111
|
//#region packages/event-wf/src/wf-adapter.ts
|
|
112
|
+
/** Shortcut mappings for workflow event methods. */
|
|
100
113
|
const wfShortcuts = {
|
|
101
114
|
flow: "WF_FLOW",
|
|
102
115
|
step: "WF_STEP"
|
|
103
116
|
};
|
|
117
|
+
/** Wooks adapter for defining and executing workflow schemas with step-based routing. */
|
|
104
118
|
var WooksWf = class extends wooks.WooksAdapterBase {
|
|
105
119
|
logger;
|
|
106
120
|
wf;
|
|
@@ -110,16 +124,20 @@ var WooksWf = class extends wooks.WooksAdapterBase {
|
|
|
110
124
|
this.logger = opts?.logger || this.getLogger(`[96m[wooks-wf]`);
|
|
111
125
|
this.wf = new WooksWorkflow(this.wooks);
|
|
112
126
|
}
|
|
127
|
+
/** Attaches a spy function to observe workflow step execution. */
|
|
113
128
|
attachSpy(fn) {
|
|
114
129
|
return this.wf.attachSpy(fn);
|
|
115
130
|
}
|
|
131
|
+
/** Removes a previously attached workflow spy function. */
|
|
116
132
|
detachSpy(fn) {
|
|
117
133
|
this.wf.detachSpy(fn);
|
|
118
134
|
}
|
|
135
|
+
/** Registers a workflow step with the given id and handler. */
|
|
119
136
|
step(id, opts) {
|
|
120
137
|
const step = (0, __prostojs_wf.createStep)(id, opts);
|
|
121
138
|
return this.on("WF_STEP", id, () => step);
|
|
122
139
|
}
|
|
140
|
+
/** Registers a workflow flow schema with the given id. */
|
|
123
141
|
flow(id, schema, prefix, init) {
|
|
124
142
|
this.wf.register(id, schema, prefix);
|
|
125
143
|
return this.on("WF_FLOW", id, () => ({
|
|
@@ -127,9 +145,11 @@ var WooksWf = class extends wooks.WooksAdapterBase {
|
|
|
127
145
|
id
|
|
128
146
|
}));
|
|
129
147
|
}
|
|
148
|
+
/** Starts a new workflow execution from the beginning. */
|
|
130
149
|
start(schemaId, inputContext, input, spy, cleanup) {
|
|
131
150
|
return this._start(schemaId, inputContext, void 0, input, spy, cleanup);
|
|
132
151
|
}
|
|
152
|
+
/** Resumes a previously paused workflow from saved state. */
|
|
133
153
|
resume(state, input, spy, cleanup) {
|
|
134
154
|
return this._start(state.schemaId, state.context, state.indexes, input, spy, cleanup);
|
|
135
155
|
}
|
|
@@ -200,16 +220,29 @@ var WooksWf = class extends wooks.WooksAdapterBase {
|
|
|
200
220
|
}
|
|
201
221
|
};
|
|
202
222
|
/**
|
|
203
|
-
*
|
|
204
|
-
* @param opts
|
|
205
|
-
* @param wooks Wooks
|
|
206
|
-
* @returns WooksWf
|
|
223
|
+
* Creates a new WooksWf application instance for workflow execution.
|
|
224
|
+
* @param opts - Workflow adapter configuration options
|
|
225
|
+
* @param wooks - Optional existing Wooks or adapter instance to attach to
|
|
226
|
+
* @returns A new WooksWf instance
|
|
227
|
+
* @example
|
|
228
|
+
* ```ts
|
|
229
|
+
* const app = createWfApp()
|
|
230
|
+
* app.step('process', { handler: (ctx) => ctx })
|
|
231
|
+
* app.flow('my-flow', [{ step: 'process' }])
|
|
232
|
+
* await app.start('my-flow', { data: 'hello' })
|
|
233
|
+
* ```
|
|
207
234
|
*/
|
|
208
235
|
function createWfApp(opts, wooks$1) {
|
|
209
236
|
return new WooksWf(opts, wooks$1);
|
|
210
237
|
}
|
|
211
238
|
|
|
212
239
|
//#endregion
|
|
240
|
+
Object.defineProperty(exports, 'StepRetriableError', {
|
|
241
|
+
enumerable: true,
|
|
242
|
+
get: function () {
|
|
243
|
+
return __prostojs_wf.StepRetriableError;
|
|
244
|
+
}
|
|
245
|
+
});
|
|
213
246
|
exports.WooksWf = WooksWf;
|
|
214
247
|
exports.createWfApp = createWfApp;
|
|
215
248
|
exports.createWfContext = createWfContext;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,17 @@ import * as wooks from 'wooks';
|
|
|
4
4
|
import { Wooks, TWooksHandler, TWooksOptions, WooksAdapterBase } from 'wooks';
|
|
5
5
|
import { TConsoleBase } from '@prostojs/logger';
|
|
6
6
|
import { Workflow, Step, TWorkflowSpy, TStepHandler, TWorkflowSchema, TFlowOutput } from '@prostojs/wf';
|
|
7
|
-
export { TStepHandler, TWorkflowSchema } from '@prostojs/wf';
|
|
7
|
+
export { StepRetriableError, TStepHandler, TWorkflowSchema } from '@prostojs/wf';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Composable that provides access to the current workflow execution state.
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const { ctx, input, schemaId, stepId } = useWfState()
|
|
14
|
+
* const context = ctx<MyContext>()
|
|
15
|
+
* const stepInput = input<MyInput>()
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
9
18
|
declare function useWfState(): {
|
|
10
19
|
ctx: <T>() => T;
|
|
11
20
|
input: <I>() => I | undefined;
|
|
@@ -15,6 +24,7 @@ declare function useWfState(): {
|
|
|
15
24
|
resume: boolean;
|
|
16
25
|
};
|
|
17
26
|
|
|
27
|
+
/** Event data describing a workflow execution instance. */
|
|
18
28
|
interface TWFEventData {
|
|
19
29
|
schemaId: string;
|
|
20
30
|
stepId: string | null;
|
|
@@ -23,11 +33,14 @@ interface TWFEventData {
|
|
|
23
33
|
input?: unknown;
|
|
24
34
|
type: 'WF';
|
|
25
35
|
}
|
|
36
|
+
/** Context store for workflow events, tracking resume state. */
|
|
26
37
|
interface TWFContextStore {
|
|
27
38
|
resume: boolean;
|
|
28
39
|
}
|
|
29
40
|
|
|
41
|
+
/** Creates a new async event context for a fresh workflow execution. */
|
|
30
42
|
declare function createWfContext(data: Omit<TWFEventData, 'type'>, options: TEventOptions): <T>(cb: (...a: any[]) => T) => T;
|
|
43
|
+
/** Creates an async event context for resuming a paused workflow. */
|
|
31
44
|
declare function resumeWfContext(data: Omit<TWFEventData, 'type'>, options: TEventOptions): <T>(cb: (...a: any[]) => T) => T;
|
|
32
45
|
/**
|
|
33
46
|
* Wrapper on top of useEventContext that provides
|
|
@@ -36,16 +49,19 @@ declare function resumeWfContext(data: Omit<TWFEventData, 'type'>, options: TEve
|
|
|
36
49
|
*/
|
|
37
50
|
declare function useWFContext<T extends TEmpty>(): _wooksjs_event_core.TCtxHelpers<TWFContextStore & T & _wooksjs_event_core.TGenericContextStore<TWFEventData>>;
|
|
38
51
|
|
|
52
|
+
/** Workflow engine that resolves steps via Wooks router lookup. */
|
|
39
53
|
declare class WooksWorkflow<T, IR> extends Workflow<T, IR> {
|
|
40
54
|
protected wooks: Wooks;
|
|
41
55
|
constructor(wooks: Wooks);
|
|
42
56
|
protected resolveStep<I, IR2>(stepId: string): Step<T, I, IR2>;
|
|
43
57
|
}
|
|
44
58
|
|
|
59
|
+
/** Shortcut mappings for workflow event methods. */
|
|
45
60
|
declare const wfShortcuts: {
|
|
46
61
|
flow: string;
|
|
47
62
|
step: string;
|
|
48
63
|
};
|
|
64
|
+
/** Configuration options for the WooksWf adapter. */
|
|
49
65
|
interface TWooksWfOptions {
|
|
50
66
|
onError?: (e: Error) => void;
|
|
51
67
|
onNotFound?: TWooksHandler;
|
|
@@ -54,19 +70,26 @@ interface TWooksWfOptions {
|
|
|
54
70
|
eventOptions?: TEventOptions;
|
|
55
71
|
router?: TWooksOptions['router'];
|
|
56
72
|
}
|
|
73
|
+
/** Wooks adapter for defining and executing workflow schemas with step-based routing. */
|
|
57
74
|
declare class WooksWf<T = any, IR = any> extends WooksAdapterBase {
|
|
58
75
|
protected opts?: TWooksWfOptions | undefined;
|
|
59
76
|
protected logger: TConsoleBase;
|
|
60
77
|
protected wf: WooksWorkflow<T, IR>;
|
|
61
78
|
constructor(opts?: TWooksWfOptions | undefined, wooks?: Wooks | WooksAdapterBase);
|
|
79
|
+
/** Attaches a spy function to observe workflow step execution. */
|
|
62
80
|
attachSpy<I>(fn: TWorkflowSpy<T, I, IR>): () => void;
|
|
81
|
+
/** Removes a previously attached workflow spy function. */
|
|
63
82
|
detachSpy<I>(fn: TWorkflowSpy<T, I, IR>): void;
|
|
83
|
+
/** Registers a workflow step with the given id and handler. */
|
|
64
84
|
step<I = any>(id: string, opts: {
|
|
65
85
|
input?: I;
|
|
66
86
|
handler: string | TStepHandler<T, I, IR>;
|
|
67
87
|
}): wooks.TProstoRouterPathHandle<Record<string, string | string[]>>;
|
|
88
|
+
/** Registers a workflow flow schema with the given id. */
|
|
68
89
|
flow(id: string, schema: TWorkflowSchema<T>, prefix?: string, init?: () => void | Promise<void>): wooks.TProstoRouterPathHandle<Record<string, string | string[]>>;
|
|
90
|
+
/** Starts a new workflow execution from the beginning. */
|
|
69
91
|
start<I>(schemaId: string, inputContext: T, input?: I, spy?: TWorkflowSpy<T, I, IR>, cleanup?: () => void): Promise<TFlowOutput<T, I, IR>>;
|
|
92
|
+
/** Resumes a previously paused workflow from saved state. */
|
|
70
93
|
resume<I>(state: {
|
|
71
94
|
schemaId: string;
|
|
72
95
|
indexes: number[];
|
|
@@ -77,11 +100,19 @@ declare class WooksWf<T = any, IR = any> extends WooksAdapterBase {
|
|
|
77
100
|
protected error(e: string | Error): void;
|
|
78
101
|
}
|
|
79
102
|
/**
|
|
80
|
-
*
|
|
81
|
-
* @param opts
|
|
82
|
-
* @param wooks Wooks
|
|
83
|
-
* @returns WooksWf
|
|
103
|
+
* Creates a new WooksWf application instance for workflow execution.
|
|
104
|
+
* @param opts - Workflow adapter configuration options
|
|
105
|
+
* @param wooks - Optional existing Wooks or adapter instance to attach to
|
|
106
|
+
* @returns A new WooksWf instance
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* const app = createWfApp()
|
|
110
|
+
* app.step('process', { handler: (ctx) => ctx })
|
|
111
|
+
* app.flow('my-flow', [{ step: 'process' }])
|
|
112
|
+
* await app.start('my-flow', { data: 'hello' })
|
|
113
|
+
* ```
|
|
84
114
|
*/
|
|
85
115
|
declare function createWfApp<T>(opts?: TWooksWfOptions, wooks?: Wooks | WooksAdapterBase): WooksWf<T, any>;
|
|
86
116
|
|
|
87
|
-
export {
|
|
117
|
+
export { WooksWf, createWfApp, createWfContext, resumeWfContext, useWFContext, useWfState, wfShortcuts };
|
|
118
|
+
export type { TWFContextStore, TWFEventData, TWooksWfOptions };
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createAsyncEventContext, useAsyncEventContext } from "@wooksjs/event-core";
|
|
2
|
-
import { Workflow, createStep } from "@prostojs/wf";
|
|
2
|
+
import { StepRetriableError, Workflow, createStep } from "@prostojs/wf";
|
|
3
3
|
import { WooksAdapterBase } from "wooks";
|
|
4
4
|
|
|
5
5
|
//#region packages/event-wf/src/event-wf.ts
|
|
6
|
+
/** Creates a new async event context for a fresh workflow execution. */
|
|
6
7
|
function createWfContext(data, options) {
|
|
7
8
|
return createAsyncEventContext({
|
|
8
9
|
event: {
|
|
@@ -13,6 +14,7 @@ function createWfContext(data, options) {
|
|
|
13
14
|
options
|
|
14
15
|
});
|
|
15
16
|
}
|
|
17
|
+
/** Creates an async event context for resuming a paused workflow. */
|
|
16
18
|
function resumeWfContext(data, options) {
|
|
17
19
|
return createAsyncEventContext({
|
|
18
20
|
event: {
|
|
@@ -34,6 +36,15 @@ function useWFContext() {
|
|
|
34
36
|
|
|
35
37
|
//#endregion
|
|
36
38
|
//#region packages/event-wf/src/composables/wf-state.ts
|
|
39
|
+
/**
|
|
40
|
+
* Composable that provides access to the current workflow execution state.
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* const { ctx, input, schemaId, stepId } = useWfState()
|
|
44
|
+
* const context = ctx<MyContext>()
|
|
45
|
+
* const stepInput = input<MyInput>()
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
37
48
|
function useWfState() {
|
|
38
49
|
const { store, getCtx } = useWFContext();
|
|
39
50
|
const event = store("event");
|
|
@@ -49,6 +60,7 @@ function useWfState() {
|
|
|
49
60
|
|
|
50
61
|
//#endregion
|
|
51
62
|
//#region packages/event-wf/src/workflow.ts
|
|
63
|
+
/** Workflow engine that resolves steps via Wooks router lookup. */
|
|
52
64
|
var WooksWorkflow = class extends Workflow {
|
|
53
65
|
constructor(wooks) {
|
|
54
66
|
super([]);
|
|
@@ -63,7 +75,7 @@ var WooksWorkflow = class extends Workflow {
|
|
|
63
75
|
store.set("stepId", stepIdNorm);
|
|
64
76
|
return found.handlers[0]();
|
|
65
77
|
}
|
|
66
|
-
} catch
|
|
78
|
+
} catch {
|
|
67
79
|
const router = this.wooks.getRouter();
|
|
68
80
|
const found = router.lookup("WF_STEP", stepIdNorm);
|
|
69
81
|
if (found?.route?.handlers.length) return found.route.handlers[0]();
|
|
@@ -74,10 +86,12 @@ var WooksWorkflow = class extends Workflow {
|
|
|
74
86
|
|
|
75
87
|
//#endregion
|
|
76
88
|
//#region packages/event-wf/src/wf-adapter.ts
|
|
89
|
+
/** Shortcut mappings for workflow event methods. */
|
|
77
90
|
const wfShortcuts = {
|
|
78
91
|
flow: "WF_FLOW",
|
|
79
92
|
step: "WF_STEP"
|
|
80
93
|
};
|
|
94
|
+
/** Wooks adapter for defining and executing workflow schemas with step-based routing. */
|
|
81
95
|
var WooksWf = class extends WooksAdapterBase {
|
|
82
96
|
logger;
|
|
83
97
|
wf;
|
|
@@ -87,16 +101,20 @@ var WooksWf = class extends WooksAdapterBase {
|
|
|
87
101
|
this.logger = opts?.logger || this.getLogger(`[96m[wooks-wf]`);
|
|
88
102
|
this.wf = new WooksWorkflow(this.wooks);
|
|
89
103
|
}
|
|
104
|
+
/** Attaches a spy function to observe workflow step execution. */
|
|
90
105
|
attachSpy(fn) {
|
|
91
106
|
return this.wf.attachSpy(fn);
|
|
92
107
|
}
|
|
108
|
+
/** Removes a previously attached workflow spy function. */
|
|
93
109
|
detachSpy(fn) {
|
|
94
110
|
this.wf.detachSpy(fn);
|
|
95
111
|
}
|
|
112
|
+
/** Registers a workflow step with the given id and handler. */
|
|
96
113
|
step(id, opts) {
|
|
97
114
|
const step = createStep(id, opts);
|
|
98
115
|
return this.on("WF_STEP", id, () => step);
|
|
99
116
|
}
|
|
117
|
+
/** Registers a workflow flow schema with the given id. */
|
|
100
118
|
flow(id, schema, prefix, init) {
|
|
101
119
|
this.wf.register(id, schema, prefix);
|
|
102
120
|
return this.on("WF_FLOW", id, () => ({
|
|
@@ -104,9 +122,11 @@ var WooksWf = class extends WooksAdapterBase {
|
|
|
104
122
|
id
|
|
105
123
|
}));
|
|
106
124
|
}
|
|
125
|
+
/** Starts a new workflow execution from the beginning. */
|
|
107
126
|
start(schemaId, inputContext, input, spy, cleanup) {
|
|
108
127
|
return this._start(schemaId, inputContext, void 0, input, spy, cleanup);
|
|
109
128
|
}
|
|
129
|
+
/** Resumes a previously paused workflow from saved state. */
|
|
110
130
|
resume(state, input, spy, cleanup) {
|
|
111
131
|
return this._start(state.schemaId, state.context, state.indexes, input, spy, cleanup);
|
|
112
132
|
}
|
|
@@ -177,14 +197,21 @@ var WooksWf = class extends WooksAdapterBase {
|
|
|
177
197
|
}
|
|
178
198
|
};
|
|
179
199
|
/**
|
|
180
|
-
*
|
|
181
|
-
* @param opts
|
|
182
|
-
* @param wooks Wooks
|
|
183
|
-
* @returns WooksWf
|
|
200
|
+
* Creates a new WooksWf application instance for workflow execution.
|
|
201
|
+
* @param opts - Workflow adapter configuration options
|
|
202
|
+
* @param wooks - Optional existing Wooks or adapter instance to attach to
|
|
203
|
+
* @returns A new WooksWf instance
|
|
204
|
+
* @example
|
|
205
|
+
* ```ts
|
|
206
|
+
* const app = createWfApp()
|
|
207
|
+
* app.step('process', { handler: (ctx) => ctx })
|
|
208
|
+
* app.flow('my-flow', [{ step: 'process' }])
|
|
209
|
+
* await app.start('my-flow', { data: 'hello' })
|
|
210
|
+
* ```
|
|
184
211
|
*/
|
|
185
212
|
function createWfApp(opts, wooks) {
|
|
186
213
|
return new WooksWf(opts, wooks);
|
|
187
214
|
}
|
|
188
215
|
|
|
189
216
|
//#endregion
|
|
190
|
-
export { WooksWf, createWfApp, createWfContext, resumeWfContext, useWFContext, useWfState, wfShortcuts };
|
|
217
|
+
export { StepRetriableError, WooksWf, createWfApp, createWfContext, resumeWfContext, useWFContext, useWfState, wfShortcuts };
|
package/package.json
CHANGED
|
@@ -1,54 +1,63 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wooksjs/event-wf",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "@wooksjs/event-wf",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
5
|
+
"keywords": [
|
|
6
|
+
"app",
|
|
7
|
+
"composables",
|
|
8
|
+
"framework",
|
|
9
|
+
"http",
|
|
10
|
+
"prostojs",
|
|
11
|
+
"wooks",
|
|
12
|
+
"workflow"
|
|
10
13
|
],
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
"require": "./dist/index.cjs",
|
|
15
|
-
"import": "./dist/index.mjs",
|
|
16
|
-
"types": "./dist/index.d.ts"
|
|
17
|
-
}
|
|
14
|
+
"homepage": "https://github.com/wooksjs/wooksjs/tree/main/packages/event-wf#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/wooksjs/wooksjs/issues"
|
|
18
17
|
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "Artem Maltsev",
|
|
19
20
|
"repository": {
|
|
20
21
|
"type": "git",
|
|
21
22
|
"url": "git+https://github.com/wooksjs/wooksjs.git",
|
|
22
23
|
"directory": "packages/event-wf"
|
|
23
24
|
},
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"prostojs"
|
|
25
|
+
"bin": {
|
|
26
|
+
"setup-skills": "scripts/setup-skills.js"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"skills",
|
|
31
|
+
"scripts"
|
|
32
32
|
],
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
33
|
+
"main": "dist/index.cjs",
|
|
34
|
+
"module": "dist/index.mjs",
|
|
35
|
+
"types": "dist/index.d.ts",
|
|
36
|
+
"exports": {
|
|
37
|
+
"./package.json": "./package.json",
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
40
|
+
"require": "./dist/index.cjs",
|
|
41
|
+
"import": "./dist/index.mjs"
|
|
42
|
+
}
|
|
39
43
|
},
|
|
40
44
|
"dependencies": {
|
|
41
45
|
"@prostojs/wf": "^0.0.18"
|
|
42
46
|
},
|
|
43
|
-
"bugs": {
|
|
44
|
-
"url": "https://github.com/wooksjs/wooksjs/issues"
|
|
45
|
-
},
|
|
46
|
-
"homepage": "https://github.com/wooksjs/wooksjs/tree/main/packages/event-wf#readme",
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"typescript": "^5.
|
|
49
|
-
"vitest": "^3.2.4"
|
|
48
|
+
"typescript": "^5.9.3",
|
|
49
|
+
"vitest": "^3.2.4",
|
|
50
|
+
"@wooksjs/event-core": "^0.6.4",
|
|
51
|
+
"wooks": "^0.6.4"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"@prostojs/logger": "^0.4.3",
|
|
55
|
+
"@wooksjs/event-core": "^0.6.4",
|
|
56
|
+
"wooks": "^0.6.4"
|
|
50
57
|
},
|
|
51
58
|
"scripts": {
|
|
52
|
-
"build": "rolldown -c ../../rolldown.config.mjs"
|
|
59
|
+
"build": "rolldown -c ../../rolldown.config.mjs",
|
|
60
|
+
"postinstall": "node scripts/setup-skills.js",
|
|
61
|
+
"setup-skills": "node scripts/setup-skills.js"
|
|
53
62
|
}
|
|
54
63
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* prettier-ignore */
|
|
3
|
+
'use strict'
|
|
4
|
+
|
|
5
|
+
const fs = require('fs')
|
|
6
|
+
const path = require('path')
|
|
7
|
+
const os = require('os')
|
|
8
|
+
|
|
9
|
+
const SKILL_NAME = 'wooksjs-event-wf'
|
|
10
|
+
const SKILL_SRC = path.join(__dirname, '..', 'skills', SKILL_NAME)
|
|
11
|
+
|
|
12
|
+
if (!fs.existsSync(SKILL_SRC)) {
|
|
13
|
+
console.error(`No skills found at ${SKILL_SRC}`)
|
|
14
|
+
console.error('Add your SKILL.md files to the skills/' + SKILL_NAME + '/ directory first.')
|
|
15
|
+
process.exit(1)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const AGENTS = {
|
|
19
|
+
'Claude Code': { dir: '.claude/skills', global: path.join(os.homedir(), '.claude', 'skills') },
|
|
20
|
+
'Cursor': { dir: '.cursor/skills', global: path.join(os.homedir(), '.cursor', 'skills') },
|
|
21
|
+
'Windsurf': { dir: '.windsurf/skills', global: path.join(os.homedir(), '.windsurf', 'skills') },
|
|
22
|
+
'Codex': { dir: '.codex/skills', global: path.join(os.homedir(), '.codex', 'skills') },
|
|
23
|
+
'OpenCode': { dir: '.opencode/skills', global: path.join(os.homedir(), '.opencode', 'skills') },
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const args = process.argv.slice(2)
|
|
27
|
+
const isGlobal = args.includes('--global') || args.includes('-g')
|
|
28
|
+
const isPostinstall = args.includes('--postinstall')
|
|
29
|
+
let installed = 0, skipped = 0
|
|
30
|
+
const installedDirs = []
|
|
31
|
+
|
|
32
|
+
for (const [agentName, cfg] of Object.entries(AGENTS)) {
|
|
33
|
+
const targetBase = isGlobal ? cfg.global : path.join(process.cwd(), cfg.dir)
|
|
34
|
+
const agentRootDir = path.dirname(cfg.global) // Check if the agent has ever been installed globally
|
|
35
|
+
|
|
36
|
+
// In postinstall mode: silently skip agents that aren't set up globally
|
|
37
|
+
if (isPostinstall || isGlobal) {
|
|
38
|
+
if (!fs.existsSync(agentRootDir)) { skipped++; continue }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const dest = path.join(targetBase, SKILL_NAME)
|
|
42
|
+
try {
|
|
43
|
+
fs.mkdirSync(dest, { recursive: true })
|
|
44
|
+
fs.cpSync(SKILL_SRC, dest, { recursive: true })
|
|
45
|
+
console.log(`✅ ${agentName}: installed to ${dest}`)
|
|
46
|
+
installed++
|
|
47
|
+
if (!isGlobal) installedDirs.push(cfg.dir + '/' + SKILL_NAME)
|
|
48
|
+
} catch (err) {
|
|
49
|
+
console.warn(`⚠️ ${agentName}: failed — ${err.message}`)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Add locally-installed skill dirs to .gitignore
|
|
54
|
+
if (!isGlobal && installedDirs.length > 0) {
|
|
55
|
+
const gitignorePath = path.join(process.cwd(), '.gitignore')
|
|
56
|
+
let gitignoreContent = ''
|
|
57
|
+
try { gitignoreContent = fs.readFileSync(gitignorePath, 'utf8') } catch {}
|
|
58
|
+
const linesToAdd = installedDirs.filter(d => !gitignoreContent.includes(d))
|
|
59
|
+
if (linesToAdd.length > 0) {
|
|
60
|
+
const hasHeader = gitignoreContent.includes('# AI agent skills')
|
|
61
|
+
const block = (gitignoreContent && !gitignoreContent.endsWith('\n') ? '\n' : '')
|
|
62
|
+
+ (hasHeader ? '' : '\n# AI agent skills (auto-generated by setup-skills)\n')
|
|
63
|
+
+ linesToAdd.join('\n') + '\n'
|
|
64
|
+
fs.appendFileSync(gitignorePath, block)
|
|
65
|
+
console.log(`📝 Added ${linesToAdd.length} entries to .gitignore`)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (installed === 0 && isPostinstall) {
|
|
70
|
+
// Silence is fine — no agents present, nothing to do
|
|
71
|
+
} else if (installed === 0 && skipped === Object.keys(AGENTS).length) {
|
|
72
|
+
console.log('No agent directories detected. Try --global or run without it for project-local install.')
|
|
73
|
+
} else if (installed === 0) {
|
|
74
|
+
console.log('Nothing installed. Run without --global to install project-locally.')
|
|
75
|
+
} else {
|
|
76
|
+
console.log(`\n✨ Done! Restart your AI agent to pick up the "${SKILL_NAME}" skill.`)
|
|
77
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wooksjs-event-wf
|
|
3
|
+
description: Wooks Workflow framework — composable, step-based workflow engine for Node.js. Load when building workflow/process automation with wooks; defining workflow steps and flows; using workflow composables (useWfState, useRouteParams); working with @wooksjs/event-core context store (init, get, set, hook); creating conditional and looping flows; resuming paused workflows; handling user input requirements; using string-based step handlers; attaching workflow spies; working with StepRetriableError; creating custom event context composables for workflows.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @wooksjs/event-wf
|
|
7
|
+
|
|
8
|
+
A composable workflow framework for Node.js built on async context (AsyncLocalStorage) and `@prostojs/wf`. Define steps and flows as composable units — steps execute sequentially with conditional branching, loops, pause/resume, and user input handling. Context is scoped per workflow execution.
|
|
9
|
+
|
|
10
|
+
## How to use this skill
|
|
11
|
+
|
|
12
|
+
Read the domain file that matches the task. Do not load all files — only what you need.
|
|
13
|
+
|
|
14
|
+
| Domain | File | Load when... |
|
|
15
|
+
|--------|------|------------|
|
|
16
|
+
| Event context (core machinery) | [event-core.md](event-core.md) | Understanding the context store API (`init`/`get`/`set`/`hook`), creating custom composables, lazy evaluation and caching, building your own `use*()` functions |
|
|
17
|
+
| Workflow app setup | [core.md](core.md) | Creating a workflow app, `createWfApp`, starting/resuming workflows, error handling, spies, testing, logging |
|
|
18
|
+
| Steps & flows | [workflows.md](workflows.md) | Defining steps (`app.step`), defining flows (`app.flow`), workflow schemas, conditions, loops, user input, parametric steps, `useWfState`, `StepRetriableError`, string-based handlers |
|
|
19
|
+
|
|
20
|
+
## Quick reference
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { createWfApp } from '@wooksjs/event-wf'
|
|
24
|
+
|
|
25
|
+
const app = createWfApp<{ result: number }>()
|
|
26
|
+
|
|
27
|
+
app.step('add', {
|
|
28
|
+
input: 'number',
|
|
29
|
+
handler: 'ctx.result += input',
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
app.flow('calculate', [
|
|
33
|
+
{ id: 'add', input: 5 },
|
|
34
|
+
{ id: 'add', input: 2 },
|
|
35
|
+
{ condition: 'result < 10', steps: [{ id: 'add', input: 3 }] },
|
|
36
|
+
])
|
|
37
|
+
|
|
38
|
+
const output = await app.start('calculate', { result: 0 })
|
|
39
|
+
console.log(output.state.context) // { result: 10 }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Key exports: `createWfApp()`, `useWfState()`, `useWFContext()`, `useRouteParams()`, `StepRetriableError`.
|