@gobing-ai/ts-dual-workflow-engine 0.2.9 → 0.3.1

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/dist/host.d.ts CHANGED
@@ -1,13 +1,26 @@
1
1
  import { type ProcessExecutor } from '@gobing-ai/ts-runtime';
2
+ import { type CapabilityOrigin } from '@gobing-ai/ts-runtime/plugin';
2
3
  import type { ActionResult, ActionRunContext, ActionRunner, GuardContext, GuardRunner } from './types';
3
4
  /** Registry owner for workflow actions and guards. */
4
5
  export declare class WorkflowEngineHost {
5
6
  private readonly actions;
6
7
  private readonly guards;
7
8
  /** Register or replace an action runner. */
8
- registerAction(action: ActionRunner): this;
9
+ registerAction(action: ActionRunner, origin?: CapabilityOrigin): this;
9
10
  /** Register or replace a guard runner. */
10
- registerGuard(guard: GuardRunner): this;
11
+ registerGuard(guard: GuardRunner, origin?: CapabilityOrigin): this;
12
+ /** Return true when an action of `kind` is registered. */
13
+ hasAction(kind: string): boolean;
14
+ /** Return true when a guard of `kind` is registered. */
15
+ hasGuard(kind: string): boolean;
16
+ /** List registered action kinds in registration order. */
17
+ listActions(): string[];
18
+ /** List registered guard kinds in registration order. */
19
+ listGuards(): string[];
20
+ /** Origin of a registered action, or undefined if none. Lets 0010 distinguish builtin from extension overrides. */
21
+ actionOrigin(kind: string): CapabilityOrigin | undefined;
22
+ /** Origin of a registered guard, or undefined if none. */
23
+ guardOrigin(kind: string): CapabilityOrigin | undefined;
11
24
  /** Execute a registered action. */
12
25
  runAction(kind: string, options: Record<string, unknown>, context: ActionRunContext): Promise<ActionResult>;
13
26
  /** Evaluate a registered guard. */
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAElF,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEvG,sDAAsD;AACtD,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAC3D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IAEzD,4CAA4C;IAC5C,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAK1C,0CAA0C;IAC1C,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAKvC,mCAAmC;IAC7B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;IAMjH,mCAAmC;IAC7B,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;CAK/G;AAED,4FAA4F;AAC5F,wBAAgB,+BAA+B,CAC3C,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,eAAe,CAAA;CAAO,GACpD,kBAAkB,CAWpB;AAED,0DAA0D;AAC1D,qBAAa,gBAAiB,YAAW,YAAY;IACjD,QAAQ,CAAC,IAAI,UAAU;IAEvB,mCAAmC;IAC7B,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;CAGzE;AAED,kEAAkE;AAClE,qBAAa,iBAAkB,YAAW,YAAY;IAGtC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAF5C,QAAQ,CAAC,IAAI,WAAW;gBAEK,eAAe,EAAE,eAAe;IAE7D,0DAA0D;IACpD,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;CAgBpG"}
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAE,KAAK,gBAAgB,EAAsB,MAAM,8BAA8B,CAAC;AAEzF,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEvG,sDAAsD;AACtD,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2D;IACnF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyD;IAEhF,4CAA4C;IAC5C,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,GAAE,gBAA8B,GAAG,IAAI;IAKlF,0CAA0C;IAC1C,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,GAAE,gBAA8B,GAAG,IAAI;IAK/E,0DAA0D;IAC1D,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIhC,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI/B,0DAA0D;IAC1D,WAAW,IAAI,MAAM,EAAE;IAIvB,yDAAyD;IACzD,UAAU,IAAI,MAAM,EAAE;IAItB,mHAAmH;IACnH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAIxD,0DAA0D;IAC1D,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAIvD,mCAAmC;IAC7B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;IAOjH,mCAAmC;IAC7B,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;CAI/G;AAED,4FAA4F;AAC5F,wBAAgB,+BAA+B,CAC3C,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,eAAe,CAAA;CAAO,GACpD,kBAAkB,CAcpB;AAED,0DAA0D;AAC1D,qBAAa,gBAAiB,YAAW,YAAY;IACjD,QAAQ,CAAC,IAAI,UAAU;IAEvB,mCAAmC;IAC7B,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;CAGzE;AAED,kEAAkE;AAClE,qBAAa,iBAAkB,YAAW,YAAY;IAGtC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAF5C,QAAQ,CAAC,IAAI,WAAW;gBAEK,eAAe,EAAE,eAAe;IAE7D,0DAA0D;IACpD,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;CAgBpG"}
package/dist/host.js CHANGED
@@ -1,45 +1,70 @@
1
1
  import { NodeProcessExecutor } from '@gobing-ai/ts-runtime';
2
+ import { CapabilityRegistry } from '@gobing-ai/ts-runtime/plugin';
2
3
  import { WorkflowValidationError } from './errors.js';
3
4
  /** Registry owner for workflow actions and guards. */
4
5
  export class WorkflowEngineHost {
5
- actions = new Map();
6
- guards = new Map();
6
+ actions = new CapabilityRegistry('workflow action');
7
+ guards = new CapabilityRegistry('workflow guard');
7
8
  /** Register or replace an action runner. */
8
- registerAction(action) {
9
- this.actions.set(action.kind, action);
9
+ registerAction(action, origin = 'extension') {
10
+ this.actions.register(action.kind, action, origin);
10
11
  return this;
11
12
  }
12
13
  /** Register or replace a guard runner. */
13
- registerGuard(guard) {
14
- this.guards.set(guard.kind, guard);
14
+ registerGuard(guard, origin = 'extension') {
15
+ this.guards.register(guard.kind, guard, origin);
15
16
  return this;
16
17
  }
18
+ /** Return true when an action of `kind` is registered. */
19
+ hasAction(kind) {
20
+ return this.actions.has(kind);
21
+ }
22
+ /** Return true when a guard of `kind` is registered. */
23
+ hasGuard(kind) {
24
+ return this.guards.has(kind);
25
+ }
26
+ /** List registered action kinds in registration order. */
27
+ listActions() {
28
+ return this.actions.list();
29
+ }
30
+ /** List registered guard kinds in registration order. */
31
+ listGuards() {
32
+ return this.guards.list();
33
+ }
34
+ /** Origin of a registered action, or undefined if none. Lets 0010 distinguish builtin from extension overrides. */
35
+ actionOrigin(kind) {
36
+ return this.actions.getEntry(kind)?.origin;
37
+ }
38
+ /** Origin of a registered guard, or undefined if none. */
39
+ guardOrigin(kind) {
40
+ return this.guards.getEntry(kind)?.origin;
41
+ }
17
42
  /** Execute a registered action. */
18
43
  async runAction(kind, options, context) {
19
- const action = this.actions.get(kind);
20
- if (action === undefined)
44
+ // Guard at the host boundary so unknown kinds surface as WorkflowValidationError,
45
+ // not the shared registry's generic Error (ADR-010 R13).
46
+ if (!this.actions.has(kind))
21
47
  throw new WorkflowValidationError(`Unknown workflow action "${kind}"`);
22
- return await action.execute(options, context);
48
+ return await this.actions.get(kind).execute(options, context);
23
49
  }
24
50
  /** Evaluate a registered guard. */
25
51
  async evaluateGuard(kind, options, context) {
26
- const guard = this.guards.get(kind);
27
- if (guard === undefined)
52
+ if (!this.guards.has(kind))
28
53
  throw new WorkflowValidationError(`Unknown workflow guard "${kind}"`);
29
- return await guard.evaluate(options, context);
54
+ return await this.guards.get(kind).evaluate(options, context);
30
55
  }
31
56
  }
32
57
  /** Create a workflow host with built-in note, shell, always, and action-ok capabilities. */
33
58
  export function createDefaultWorkflowEngineHost(options = {}) {
34
59
  const host = new WorkflowEngineHost();
35
- host.registerAction(new NoteActionRunner());
36
- host.registerAction(new ShellActionRunner(options.processExecutor ?? new NodeProcessExecutor()));
37
- host.registerGuard({ kind: 'always', evaluate: async () => true });
38
- host.registerGuard({ kind: 'never', evaluate: async () => false });
60
+ host.registerAction(new NoteActionRunner(), 'builtin');
61
+ host.registerAction(new ShellActionRunner(options.processExecutor ?? new NodeProcessExecutor()), 'builtin');
62
+ host.registerGuard({ kind: 'always', evaluate: async () => true }, 'builtin');
63
+ host.registerGuard({ kind: 'never', evaluate: async () => false }, 'builtin');
39
64
  host.registerGuard({
40
65
  kind: 'action-ok',
41
66
  evaluate: async (_options, context) => context.lastActionResult?.ok === true,
42
- });
67
+ }, 'builtin');
43
68
  return host;
44
69
  }
45
70
  /** Built-in action that records a note in result data. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/ts-dual-workflow-engine",
3
- "version": "0.2.9",
3
+ "version": "0.3.1",
4
4
  "description": "@gobing-ai/ts-dual-workflow-engine — State-machine and transition-flow workflow runtime.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -48,9 +48,9 @@
48
48
  "release": "echo 'Manual publish is disabled. Releases go through GitHub Actions via Trusted Publishing — push a tag: git tag @gobing-ai/ts-dual-workflow-engine-v<version> && git push --tags' && exit 1"
49
49
  },
50
50
  "dependencies": {
51
- "@gobing-ai/ts-db": "^0.2.9",
52
- "@gobing-ai/ts-runtime": "^0.2.9",
53
- "@gobing-ai/ts-utils": "^0.2.9",
51
+ "@gobing-ai/ts-db": "^0.3.1",
52
+ "@gobing-ai/ts-runtime": "^0.3.1",
53
+ "@gobing-ai/ts-utils": "^0.3.1",
54
54
  "zod": "^4.1.0"
55
55
  },
56
56
  "devDependencies": {
package/src/host.ts CHANGED
@@ -1,36 +1,67 @@
1
1
  import { NodeProcessExecutor, type ProcessExecutor } from '@gobing-ai/ts-runtime';
2
+ import { type CapabilityOrigin, CapabilityRegistry } from '@gobing-ai/ts-runtime/plugin';
2
3
  import { WorkflowValidationError } from './errors';
3
4
  import type { ActionResult, ActionRunContext, ActionRunner, GuardContext, GuardRunner } from './types';
4
5
 
5
6
  /** Registry owner for workflow actions and guards. */
6
7
  export class WorkflowEngineHost {
7
- private readonly actions = new Map<string, ActionRunner>();
8
- private readonly guards = new Map<string, GuardRunner>();
8
+ private readonly actions = new CapabilityRegistry<ActionRunner>('workflow action');
9
+ private readonly guards = new CapabilityRegistry<GuardRunner>('workflow guard');
9
10
 
10
11
  /** Register or replace an action runner. */
11
- registerAction(action: ActionRunner): this {
12
- this.actions.set(action.kind, action);
12
+ registerAction(action: ActionRunner, origin: CapabilityOrigin = 'extension'): this {
13
+ this.actions.register(action.kind, action, origin);
13
14
  return this;
14
15
  }
15
16
 
16
17
  /** Register or replace a guard runner. */
17
- registerGuard(guard: GuardRunner): this {
18
- this.guards.set(guard.kind, guard);
18
+ registerGuard(guard: GuardRunner, origin: CapabilityOrigin = 'extension'): this {
19
+ this.guards.register(guard.kind, guard, origin);
19
20
  return this;
20
21
  }
21
22
 
23
+ /** Return true when an action of `kind` is registered. */
24
+ hasAction(kind: string): boolean {
25
+ return this.actions.has(kind);
26
+ }
27
+
28
+ /** Return true when a guard of `kind` is registered. */
29
+ hasGuard(kind: string): boolean {
30
+ return this.guards.has(kind);
31
+ }
32
+
33
+ /** List registered action kinds in registration order. */
34
+ listActions(): string[] {
35
+ return this.actions.list();
36
+ }
37
+
38
+ /** List registered guard kinds in registration order. */
39
+ listGuards(): string[] {
40
+ return this.guards.list();
41
+ }
42
+
43
+ /** Origin of a registered action, or undefined if none. Lets 0010 distinguish builtin from extension overrides. */
44
+ actionOrigin(kind: string): CapabilityOrigin | undefined {
45
+ return this.actions.getEntry(kind)?.origin;
46
+ }
47
+
48
+ /** Origin of a registered guard, or undefined if none. */
49
+ guardOrigin(kind: string): CapabilityOrigin | undefined {
50
+ return this.guards.getEntry(kind)?.origin;
51
+ }
52
+
22
53
  /** Execute a registered action. */
23
54
  async runAction(kind: string, options: Record<string, unknown>, context: ActionRunContext): Promise<ActionResult> {
24
- const action = this.actions.get(kind);
25
- if (action === undefined) throw new WorkflowValidationError(`Unknown workflow action "${kind}"`);
26
- return await action.execute(options, context);
55
+ // Guard at the host boundary so unknown kinds surface as WorkflowValidationError,
56
+ // not the shared registry's generic Error (ADR-010 R13).
57
+ if (!this.actions.has(kind)) throw new WorkflowValidationError(`Unknown workflow action "${kind}"`);
58
+ return await this.actions.get(kind).execute(options, context);
27
59
  }
28
60
 
29
61
  /** Evaluate a registered guard. */
30
62
  async evaluateGuard(kind: string, options: Record<string, unknown>, context: GuardContext): Promise<boolean> {
31
- const guard = this.guards.get(kind);
32
- if (guard === undefined) throw new WorkflowValidationError(`Unknown workflow guard "${kind}"`);
33
- return await guard.evaluate(options, context);
63
+ if (!this.guards.has(kind)) throw new WorkflowValidationError(`Unknown workflow guard "${kind}"`);
64
+ return await this.guards.get(kind).evaluate(options, context);
34
65
  }
35
66
  }
36
67
 
@@ -39,14 +70,17 @@ export function createDefaultWorkflowEngineHost(
39
70
  options: { processExecutor?: ProcessExecutor } = {},
40
71
  ): WorkflowEngineHost {
41
72
  const host = new WorkflowEngineHost();
42
- host.registerAction(new NoteActionRunner());
43
- host.registerAction(new ShellActionRunner(options.processExecutor ?? new NodeProcessExecutor()));
44
- host.registerGuard({ kind: 'always', evaluate: async () => true });
45
- host.registerGuard({ kind: 'never', evaluate: async () => false });
46
- host.registerGuard({
47
- kind: 'action-ok',
48
- evaluate: async (_options, context) => context.lastActionResult?.ok === true,
49
- });
73
+ host.registerAction(new NoteActionRunner(), 'builtin');
74
+ host.registerAction(new ShellActionRunner(options.processExecutor ?? new NodeProcessExecutor()), 'builtin');
75
+ host.registerGuard({ kind: 'always', evaluate: async () => true }, 'builtin');
76
+ host.registerGuard({ kind: 'never', evaluate: async () => false }, 'builtin');
77
+ host.registerGuard(
78
+ {
79
+ kind: 'action-ok',
80
+ evaluate: async (_options, context) => context.lastActionResult?.ok === true,
81
+ },
82
+ 'builtin',
83
+ );
50
84
  return host;
51
85
  }
52
86