@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 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 (error) {
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(`[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
- * Factory for WooksWf App
204
- * @param opts TWooksWfOptions
205
- * @param wooks Wooks | WooksAdapterBase
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
- * Factory for WooksWf App
81
- * @param opts TWooksWfOptions
82
- * @param wooks Wooks | WooksAdapterBase
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 { type TWFContextStore, type TWFEventData, type TWooksWfOptions, WooksWf, createWfApp, createWfContext, resumeWfContext, useWFContext, useWfState, wfShortcuts };
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 (error) {
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(`[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
- * Factory for WooksWf App
181
- * @param opts TWooksWfOptions
182
- * @param wooks Wooks | WooksAdapterBase
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.2",
3
+ "version": "0.6.4",
4
4
  "description": "@wooksjs/event-wf",
5
- "main": "dist/index.cjs",
6
- "module": "dist/index.mjs",
7
- "types": "dist/index.d.ts",
8
- "files": [
9
- "dist"
5
+ "keywords": [
6
+ "app",
7
+ "composables",
8
+ "framework",
9
+ "http",
10
+ "prostojs",
11
+ "wooks",
12
+ "workflow"
10
13
  ],
11
- "exports": {
12
- "./package.json": "./package.json",
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
- "keywords": [
25
- "http",
26
- "wooks",
27
- "composables",
28
- "framework",
29
- "app",
30
- "workflow",
31
- "prostojs"
25
+ "bin": {
26
+ "setup-skills": "scripts/setup-skills.js"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "skills",
31
+ "scripts"
32
32
  ],
33
- "author": "Artem Maltsev",
34
- "license": "MIT",
35
- "peerDependencies": {
36
- "@prostojs/logger": "^0.4.3",
37
- "@wooksjs/event-core": "^0.6.2",
38
- "wooks": "^0.6.2"
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.8.3",
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`.