@tagma/sdk 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +573 -573
  3. package/dist/bootstrap.d.ts +11 -1
  4. package/dist/bootstrap.d.ts.map +1 -1
  5. package/dist/bootstrap.js +18 -9
  6. package/dist/bootstrap.js.map +1 -1
  7. package/dist/drivers/opencode.d.ts.map +1 -1
  8. package/dist/drivers/opencode.js +47 -17
  9. package/dist/drivers/opencode.js.map +1 -1
  10. package/dist/engine.d.ts +8 -0
  11. package/dist/engine.d.ts.map +1 -1
  12. package/dist/engine.js +17 -16
  13. package/dist/engine.js.map +1 -1
  14. package/dist/plugin-registry.test.d.ts +2 -0
  15. package/dist/plugin-registry.test.d.ts.map +1 -0
  16. package/dist/plugin-registry.test.js +188 -0
  17. package/dist/plugin-registry.test.js.map +1 -0
  18. package/dist/registry.d.ts +52 -28
  19. package/dist/registry.d.ts.map +1 -1
  20. package/dist/registry.js +126 -91
  21. package/dist/registry.js.map +1 -1
  22. package/dist/sdk.d.ts +1 -1
  23. package/dist/sdk.d.ts.map +1 -1
  24. package/dist/sdk.js +1 -1
  25. package/dist/sdk.js.map +1 -1
  26. package/package.json +2 -2
  27. package/src/bootstrap.ts +46 -37
  28. package/src/completions/output-check.ts +92 -92
  29. package/src/dag.ts +245 -245
  30. package/src/drivers/opencode.ts +410 -371
  31. package/src/engine.ts +1228 -1220
  32. package/src/hooks.ts +193 -193
  33. package/src/middlewares/static-context.ts +49 -49
  34. package/src/pipeline-runner.ts +173 -173
  35. package/src/plugin-registry.test.ts +230 -0
  36. package/src/prompt-doc.ts +49 -49
  37. package/src/registry.ts +316 -267
  38. package/src/runner.ts +460 -460
  39. package/src/schema.test.ts +101 -101
  40. package/src/schema.ts +338 -338
  41. package/src/sdk.ts +120 -118
  42. package/src/task-ref.test.ts +401 -401
  43. package/src/task-ref.ts +120 -120
  44. package/src/validate-raw.ts +412 -412
  45. package/dist/drivers/claude-code.d.ts +0 -3
  46. package/dist/drivers/claude-code.d.ts.map +0 -1
  47. package/dist/drivers/claude-code.js +0 -225
  48. package/dist/drivers/claude-code.js.map +0 -1
@@ -0,0 +1,188 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { PluginRegistry, defaultRegistry } from './registry';
3
+ import { bootstrapBuiltins } from './bootstrap';
4
+ import { runPipeline } from './engine';
5
+ import { mkdtempSync, rmSync } from 'node:fs';
6
+ import { tmpdir } from 'node:os';
7
+ import { join } from 'node:path';
8
+ function makeDriver(name, marker) {
9
+ return {
10
+ name,
11
+ capabilities: { sessionResume: false, systemPrompt: false, outputFormat: false },
12
+ async buildCommand() {
13
+ marker.push(`buildCommand:${name}`);
14
+ return { args: ['echo', 'noop'] };
15
+ },
16
+ };
17
+ }
18
+ function makeTrigger(name, marker) {
19
+ return {
20
+ name,
21
+ async watch() {
22
+ marker.push(`watch:${name}`);
23
+ },
24
+ };
25
+ }
26
+ describe('PluginRegistry — instance isolation', () => {
27
+ test('two registries do not share drivers registered under the same type', () => {
28
+ const regA = new PluginRegistry();
29
+ const regB = new PluginRegistry();
30
+ const markerA = [];
31
+ const markerB = [];
32
+ regA.registerPlugin('drivers', 'mock', makeDriver('mockA', markerA));
33
+ regB.registerPlugin('drivers', 'mock', makeDriver('mockB', markerB));
34
+ expect(regA.getHandler('drivers', 'mock').name).toBe('mockA');
35
+ expect(regB.getHandler('drivers', 'mock').name).toBe('mockB');
36
+ expect(regA.hasHandler('drivers', 'mock')).toBe(true);
37
+ expect(regB.hasHandler('drivers', 'mock')).toBe(true);
38
+ expect(regA.hasHandler('triggers', 'mock')).toBe(false);
39
+ });
40
+ test('unregistering in one registry does not affect the other', () => {
41
+ const regA = new PluginRegistry();
42
+ const regB = new PluginRegistry();
43
+ regA.registerPlugin('drivers', 'mock', makeDriver('mockA', []));
44
+ regB.registerPlugin('drivers', 'mock', makeDriver('mockB', []));
45
+ expect(regA.unregisterPlugin('drivers', 'mock')).toBe(true);
46
+ expect(regA.hasHandler('drivers', 'mock')).toBe(false);
47
+ expect(regB.hasHandler('drivers', 'mock')).toBe(true);
48
+ });
49
+ test('listRegistered is scoped per instance', () => {
50
+ const regA = new PluginRegistry();
51
+ const regB = new PluginRegistry();
52
+ regA.registerPlugin('triggers', 'a-only', makeTrigger('a-only', []));
53
+ regB.registerPlugin('triggers', 'b-only', makeTrigger('b-only', []));
54
+ expect(regA.listRegistered('triggers')).toEqual(['a-only']);
55
+ expect(regB.listRegistered('triggers')).toEqual(['b-only']);
56
+ });
57
+ test('registering the same instance twice returns unchanged', () => {
58
+ const reg = new PluginRegistry();
59
+ const driver = makeDriver('same', []);
60
+ expect(reg.registerPlugin('drivers', 'mock', driver)).toBe('registered');
61
+ expect(reg.registerPlugin('drivers', 'mock', driver)).toBe('unchanged');
62
+ });
63
+ test('replacing with a different handler returns replaced', () => {
64
+ const reg = new PluginRegistry();
65
+ expect(reg.registerPlugin('drivers', 'mock', makeDriver('one', []))).toBe('registered');
66
+ expect(reg.registerPlugin('drivers', 'mock', makeDriver('two', []))).toBe('replaced');
67
+ expect(reg.getHandler('drivers', 'mock').name).toBe('two');
68
+ });
69
+ test('bootstrapBuiltins(target) populates a specific instance without touching the default', () => {
70
+ const fresh = new PluginRegistry();
71
+ expect(fresh.hasHandler('drivers', 'opencode')).toBe(false);
72
+ bootstrapBuiltins(fresh);
73
+ expect(fresh.hasHandler('drivers', 'opencode')).toBe(true);
74
+ expect(fresh.hasHandler('triggers', 'file')).toBe(true);
75
+ expect(fresh.hasHandler('triggers', 'manual')).toBe(true);
76
+ expect(fresh.hasHandler('completions', 'exit_code')).toBe(true);
77
+ expect(fresh.hasHandler('middlewares', 'static_context')).toBe(true);
78
+ // Default registry's state is independent of `fresh` — if the default
79
+ // happens to have opencode (because another test bootstrapped it), that
80
+ // is fine; the guarantee is that `fresh.unregister` does not leak.
81
+ fresh.unregisterPlugin('drivers', 'opencode');
82
+ expect(fresh.hasHandler('drivers', 'opencode')).toBe(false);
83
+ });
84
+ });
85
+ describe('PluginRegistry — validation', () => {
86
+ test('rejects unknown category', () => {
87
+ const reg = new PluginRegistry();
88
+ expect(() => reg.registerPlugin('nope', 'x', makeDriver('x', []))).toThrow(/Unknown plugin category/);
89
+ });
90
+ test('rejects driver missing buildCommand', () => {
91
+ const reg = new PluginRegistry();
92
+ expect(() => reg.registerPlugin('drivers', 'broken',
93
+ // deliberately bad: no buildCommand
94
+ { name: 'broken', capabilities: { sessionResume: false, systemPrompt: false, outputFormat: false } })).toThrow(/must export buildCommand/);
95
+ });
96
+ test('rejects handler with missing name', () => {
97
+ const reg = new PluginRegistry();
98
+ expect(() => reg.registerPlugin('drivers', 'x',
99
+ // deliberately bad: no name
100
+ { capabilities: { sessionResume: false, systemPrompt: false, outputFormat: false }, buildCommand: async () => ({ args: [] }) })).toThrow(/non-empty "name"/);
101
+ });
102
+ });
103
+ describe('runPipeline — options.registry isolation', () => {
104
+ test('concurrent runs with different registries see their own drivers', async () => {
105
+ const regA = new PluginRegistry();
106
+ const regB = new PluginRegistry();
107
+ const seenA = [];
108
+ const seenB = [];
109
+ bootstrapBuiltins(regA);
110
+ bootstrapBuiltins(regB);
111
+ regA.registerPlugin('drivers', 'mock', makeDriver('mockA', seenA));
112
+ regB.registerPlugin('drivers', 'mock', makeDriver('mockB', seenB));
113
+ // Command-only pipeline exercises the preflight path (which uses the
114
+ // registry) plus the run-loop path without requiring a real driver
115
+ // invocation. We verify isolation by asserting that preflight with a
116
+ // registry missing `mock` rejects, while the matching registry accepts.
117
+ const config = {
118
+ name: 'isolation-test',
119
+ tracks: [
120
+ {
121
+ id: 't',
122
+ name: 'T',
123
+ tasks: [{ id: 'only', name: 'only', command: 'echo hi' }],
124
+ },
125
+ ],
126
+ };
127
+ const tmpA = mkdtempSync(join(tmpdir(), 'tagma-regA-'));
128
+ const tmpB = mkdtempSync(join(tmpdir(), 'tagma-regB-'));
129
+ try {
130
+ const [resA, resB] = await Promise.all([
131
+ runPipeline(config, tmpA, { registry: regA, skipPluginLoading: true }),
132
+ runPipeline(config, tmpB, { registry: regB, skipPluginLoading: true }),
133
+ ]);
134
+ expect(resA.success).toBe(true);
135
+ expect(resB.success).toBe(true);
136
+ expect(resA.runId).not.toBe(resB.runId);
137
+ }
138
+ finally {
139
+ rmSync(tmpA, { recursive: true, force: true });
140
+ rmSync(tmpB, { recursive: true, force: true });
141
+ }
142
+ });
143
+ test('preflight fails when referenced driver is missing from the passed registry', async () => {
144
+ const regNoOpencode = new PluginRegistry();
145
+ // Deliberately do NOT bootstrap builtins — opencode is not registered.
146
+ const config = {
147
+ name: 'preflight-miss',
148
+ tracks: [
149
+ {
150
+ id: 't',
151
+ name: 'T',
152
+ tasks: [{ id: 'x', name: 'x', prompt: 'hello' }],
153
+ },
154
+ ],
155
+ };
156
+ const tmp = mkdtempSync(join(tmpdir(), 'tagma-miss-'));
157
+ try {
158
+ await expect(runPipeline(config, tmp, { registry: regNoOpencode, skipPluginLoading: true })).rejects.toThrow(/driver "opencode" not registered/);
159
+ }
160
+ finally {
161
+ rmSync(tmp, { recursive: true, force: true });
162
+ }
163
+ });
164
+ test('omitting options.registry falls back to defaultRegistry', async () => {
165
+ // bootstrapBuiltins into default happens in most host callers; do it
166
+ // explicitly here so the test is independent of module-load order.
167
+ bootstrapBuiltins(defaultRegistry);
168
+ const config = {
169
+ name: 'default-fallback',
170
+ tracks: [
171
+ {
172
+ id: 't',
173
+ name: 'T',
174
+ tasks: [{ id: 'only', name: 'only', command: 'echo hi' }],
175
+ },
176
+ ],
177
+ };
178
+ const tmp = mkdtempSync(join(tmpdir(), 'tagma-default-'));
179
+ try {
180
+ const res = await runPipeline(config, tmp, { skipPluginLoading: true });
181
+ expect(res.success).toBe(true);
182
+ }
183
+ finally {
184
+ rmSync(tmp, { recursive: true, force: true });
185
+ }
186
+ });
187
+ });
188
+ //# sourceMappingURL=plugin-registry.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-registry.test.js","sourceRoot":"","sources":["../src/plugin-registry.test.ts"],"names":[],"mappings":"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"}
@@ -1,25 +1,6 @@
1
1
  import type { PluginCategory, DriverPlugin, TriggerPlugin, CompletionPlugin, MiddlewarePlugin, PluginManifest } from './types';
2
2
  type PluginType = DriverPlugin | TriggerPlugin | CompletionPlugin | MiddlewarePlugin;
3
3
  export type RegisterResult = 'registered' | 'replaced' | 'unchanged';
4
- /**
5
- * Register a plugin under (category, type). Returns:
6
- * - 'registered' on first registration
7
- * - 'replaced' when an existing entry was overwritten with a different handler
8
- * - 'unchanged' when the same handler instance was already present
9
- *
10
- * Throws if `category` is unknown, `type` is empty, or `handler` violates the
11
- * minimum interface contract for the category.
12
- */
13
- export declare function registerPlugin<T extends PluginType>(category: PluginCategory, type: string, handler: T): RegisterResult;
14
- /**
15
- * Remove a plugin from the in-process registry. Returns true if a plugin
16
- * was actually removed. Note: ESM module caching is not affected, so
17
- * re-importing the same file after unregister will yield the cached module —
18
- * callers wanting a fresh load must restart the host process.
19
- */
20
- export declare function unregisterPlugin(category: PluginCategory, type: string): boolean;
21
- export declare function getHandler<T extends PluginType>(category: PluginCategory, type: string): T;
22
- export declare function hasHandler(category: PluginCategory, type: string): boolean;
23
4
  export declare const PLUGIN_NAME_RE: RegExp;
24
5
  export declare function isValidPluginName(name: unknown): name is string;
25
6
  /**
@@ -38,16 +19,59 @@ export declare function isValidPluginName(name: unknown): name is string;
38
19
  */
39
20
  export declare function readPluginManifest(pkgJson: unknown): PluginManifest | null;
40
21
  /**
41
- * Load and register a list of plugin packages.
42
- *
43
- * @param pluginNames - Validated npm package names to load.
44
- * @param resolveFrom - Optional absolute path to resolve plugins from (e.g. the
45
- * workspace's working directory). When omitted, the default ESM resolution
46
- * uses the SDK's own `node_modules`, which will fail for plugins installed
47
- * only in the user's workspace. CLI callers should pass `process.cwd()` or
48
- * the workspace root so that workspace-local plugins resolve correctly.
22
+ * Instance-scoped plugin registry. Each workspace in a multi-tenant sidecar
23
+ * owns its own PluginRegistry, so installing/uninstalling a driver in one
24
+ * workspace cannot clobber another. The process-wide `defaultRegistry`
25
+ * exported at the bottom of this file preserves the historical free-function
26
+ * API (registerPlugin / getHandler / …) for CLI and single-tenant hosts.
49
27
  */
50
- export declare function loadPlugins(pluginNames: readonly string[], resolveFrom?: string): Promise<void>;
28
+ export declare class PluginRegistry {
29
+ private readonly registries;
30
+ /**
31
+ * Register a plugin under (category, type). Returns:
32
+ * - 'registered' on first registration
33
+ * - 'replaced' when an existing entry was overwritten with a different handler
34
+ * - 'unchanged' when the same handler instance was already present
35
+ *
36
+ * Throws if `category` is unknown, `type` is empty, or `handler` violates
37
+ * the minimum interface contract for the category.
38
+ */
39
+ registerPlugin<T extends PluginType>(category: PluginCategory, type: string, handler: T): RegisterResult;
40
+ /**
41
+ * Remove a plugin from the in-process registry. Returns true if a plugin
42
+ * was actually removed. Note: ESM module caching is not affected, so
43
+ * re-importing the same file after unregister will yield the cached module —
44
+ * callers wanting a fresh load must restart the host process.
45
+ */
46
+ unregisterPlugin(category: PluginCategory, type: string): boolean;
47
+ getHandler<T extends PluginType>(category: PluginCategory, type: string): T;
48
+ hasHandler(category: PluginCategory, type: string): boolean;
49
+ listRegistered(category: PluginCategory): string[];
50
+ /**
51
+ * Load and register a list of plugin packages into this registry.
52
+ *
53
+ * @param pluginNames - Validated npm package names to load.
54
+ * @param resolveFrom - Optional absolute path to resolve plugins from (e.g.
55
+ * the workspace's working directory). When omitted, the default ESM
56
+ * resolution uses the SDK's own `node_modules`, which will fail for
57
+ * plugins installed only in the user's workspace. CLI callers should
58
+ * pass `process.cwd()` or the workspace root so that workspace-local
59
+ * plugins resolve correctly.
60
+ */
61
+ loadPlugins(pluginNames: readonly string[], resolveFrom?: string): Promise<void>;
62
+ }
63
+ /**
64
+ * Process-wide default registry. Preserves the historical free-function API
65
+ * for CLI and single-tenant hosts. Multi-tenant hosts (the editor sidecar
66
+ * after the one-sidecar refactor) build their own `PluginRegistry` per
67
+ * workspace and pass it through `RunPipelineOptions.registry`.
68
+ */
69
+ export declare const defaultRegistry: PluginRegistry;
70
+ export declare function registerPlugin<T extends PluginType>(category: PluginCategory, type: string, handler: T): RegisterResult;
71
+ export declare function unregisterPlugin(category: PluginCategory, type: string): boolean;
72
+ export declare function getHandler<T extends PluginType>(category: PluginCategory, type: string): T;
73
+ export declare function hasHandler(category: PluginCategory, type: string): boolean;
51
74
  export declare function listRegistered(category: PluginCategory): string[];
75
+ export declare function loadPlugins(pluginNames: readonly string[], resolveFrom?: string): Promise<void>;
52
76
  export {};
53
77
  //# sourceMappingURL=registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB,KAAK,UAAU,GAAG,YAAY,GAAG,aAAa,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;AAoGrF,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,UAAU,GAAG,WAAW,CAAC;AAErE;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,UAAU,EACjD,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,GACT,cAAc,CA0BhB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAGhF;AAED,wBAAgB,UAAU,CAAC,CAAC,SAAS,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAS1F;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1E;AAKD,eAAO,MAAM,cAAc,QAA4D,CAAC;AAExF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,CAE/D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAmB1E;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,EAAE,CAEjE"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB,KAAK,UAAU,GAAG,YAAY,GAAG,aAAa,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;AA6FrF,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,UAAU,GAAG,WAAW,CAAC;AAKrE,eAAO,MAAM,cAAc,QAA4D,CAAC;AAExF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,CAE/D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAmB1E;AAED;;;;;;GAMG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAKzB;IAEF;;;;;;;;OAQG;IACH,cAAc,CAAC,CAAC,SAAS,UAAU,EACjC,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,GACT,cAAc;IA4BjB;;;;;OAKG;IACH,gBAAgB,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAKjE,UAAU,CAAC,CAAC,SAAS,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC;IAW3E,UAAU,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAI3D,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,EAAE;IAIlD;;;;;;;;;;OAUG;IACG,WAAW,CACf,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC;CA0BjB;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,gBAAuB,CAAC;AAEpD,wBAAgB,cAAc,CAAC,CAAC,SAAS,UAAU,EACjD,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,GACT,cAAc,CAEhB;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhF;AAED,wBAAgB,UAAU,CAAC,CAAC,SAAS,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAE1F;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1E;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,EAAE,CAEjE;AAED,wBAAgB,WAAW,CACzB,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAEf"}
package/dist/registry.js CHANGED
@@ -6,12 +6,6 @@ const VALID_CATEGORIES = new Set([
6
6
  'completions',
7
7
  'middlewares',
8
8
  ]);
9
- const registries = {
10
- drivers: new Map(),
11
- triggers: new Map(),
12
- completions: new Map(),
13
- middlewares: new Map(),
14
- };
15
9
  /**
16
10
  * Minimal contract enforcement so a malformed plugin fails fast at
17
11
  * registration time rather than crashing the engine mid-run.
@@ -90,63 +84,6 @@ function validateContract(category, handler) {
90
84
  break;
91
85
  }
92
86
  }
93
- /**
94
- * Register a plugin under (category, type). Returns:
95
- * - 'registered' on first registration
96
- * - 'replaced' when an existing entry was overwritten with a different handler
97
- * - 'unchanged' when the same handler instance was already present
98
- *
99
- * Throws if `category` is unknown, `type` is empty, or `handler` violates the
100
- * minimum interface contract for the category.
101
- */
102
- export function registerPlugin(category, type, handler) {
103
- if (!VALID_CATEGORIES.has(category)) {
104
- throw new Error(`Unknown plugin category "${category}"`);
105
- }
106
- if (typeof type !== 'string' || type.length === 0) {
107
- throw new Error(`Plugin type must be a non-empty string (category="${category}")`);
108
- }
109
- validateContract(category, handler);
110
- const registry = registries[category];
111
- const existing = registry.get(type);
112
- if (existing === handler)
113
- return 'unchanged';
114
- const wasReplaced = existing !== undefined;
115
- registry.set(type, handler);
116
- if (wasReplaced) {
117
- // D18: surface silent shadowing. Hot-reload flows legitimately replace
118
- // handlers; installing two different plugin packages that both claim
119
- // the same (category, type) does not — the second wins and breaks the
120
- // first's consumers with no audit trail. A console.warn is cheap,
121
- // respects existing callers that rely on 'replaced', and gives ops a
122
- // grep-able signal when registrations collide unexpectedly.
123
- console.warn(`[tagma-sdk] registerPlugin: replaced existing ${category}/${type} — ` +
124
- `check for duplicate plugin packages claiming the same type.`);
125
- }
126
- return wasReplaced ? 'replaced' : 'registered';
127
- }
128
- /**
129
- * Remove a plugin from the in-process registry. Returns true if a plugin
130
- * was actually removed. Note: ESM module caching is not affected, so
131
- * re-importing the same file after unregister will yield the cached module —
132
- * callers wanting a fresh load must restart the host process.
133
- */
134
- export function unregisterPlugin(category, type) {
135
- if (!VALID_CATEGORIES.has(category))
136
- return false;
137
- return registries[category].delete(type);
138
- }
139
- export function getHandler(category, type) {
140
- const handler = registries[category].get(type);
141
- if (!handler) {
142
- throw new Error(`${category} type "${type}" not registered.\n` +
143
- `Install the plugin: bun add @tagma/${category.replace(/s$/, '')}-${type}`);
144
- }
145
- return handler;
146
- }
147
- export function hasHandler(category, type) {
148
- return registries[category].has(type);
149
- }
150
87
  // Plugin name must be a scoped npm package or a tagma-prefixed package.
151
88
  // Reject absolute/relative paths and suspicious patterns to prevent
152
89
  // arbitrary code execution via crafted YAML configs.
@@ -189,40 +126,138 @@ export function readPluginManifest(pkgJson) {
189
126
  return { category: category, type };
190
127
  }
191
128
  /**
192
- * Load and register a list of plugin packages.
193
- *
194
- * @param pluginNames - Validated npm package names to load.
195
- * @param resolveFrom - Optional absolute path to resolve plugins from (e.g. the
196
- * workspace's working directory). When omitted, the default ESM resolution
197
- * uses the SDK's own `node_modules`, which will fail for plugins installed
198
- * only in the user's workspace. CLI callers should pass `process.cwd()` or
199
- * the workspace root so that workspace-local plugins resolve correctly.
129
+ * Instance-scoped plugin registry. Each workspace in a multi-tenant sidecar
130
+ * owns its own PluginRegistry, so installing/uninstalling a driver in one
131
+ * workspace cannot clobber another. The process-wide `defaultRegistry`
132
+ * exported at the bottom of this file preserves the historical free-function
133
+ * API (registerPlugin / getHandler / …) for CLI and single-tenant hosts.
200
134
  */
201
- export async function loadPlugins(pluginNames, resolveFrom) {
202
- for (const name of pluginNames) {
203
- if (!isValidPluginName(name)) {
204
- throw new Error(`Plugin "${name}" rejected: plugin names must be scoped npm packages ` +
205
- `(e.g. @tagma/trigger-xyz) or tagma-plugin-* packages. ` +
206
- `Relative/absolute paths are not allowed.`);
135
+ export class PluginRegistry {
136
+ registries = {
137
+ drivers: new Map(),
138
+ triggers: new Map(),
139
+ completions: new Map(),
140
+ middlewares: new Map(),
141
+ };
142
+ /**
143
+ * Register a plugin under (category, type). Returns:
144
+ * - 'registered' on first registration
145
+ * - 'replaced' when an existing entry was overwritten with a different handler
146
+ * - 'unchanged' when the same handler instance was already present
147
+ *
148
+ * Throws if `category` is unknown, `type` is empty, or `handler` violates
149
+ * the minimum interface contract for the category.
150
+ */
151
+ registerPlugin(category, type, handler) {
152
+ if (!VALID_CATEGORIES.has(category)) {
153
+ throw new Error(`Unknown plugin category "${category}"`);
154
+ }
155
+ if (typeof type !== 'string' || type.length === 0) {
156
+ throw new Error(`Plugin type must be a non-empty string (category="${category}")`);
207
157
  }
208
- let moduleUrl = name;
209
- if (resolveFrom) {
210
- // Resolve the package entry point relative to the caller's directory so
211
- // plugins installed in the workspace's node_modules are found even when
212
- // the SDK itself lives elsewhere (e.g. a global install or a monorepo
213
- // sibling package).
214
- const req = createRequire(resolveFrom.endsWith('/') ? resolveFrom : resolveFrom + '/');
215
- const resolved = req.resolve(name);
216
- moduleUrl = pathToFileURL(resolved).href;
158
+ validateContract(category, handler);
159
+ const registry = this.registries[category];
160
+ const existing = registry.get(type);
161
+ if (existing === handler)
162
+ return 'unchanged';
163
+ const wasReplaced = existing !== undefined;
164
+ registry.set(type, handler);
165
+ if (wasReplaced) {
166
+ // D18: surface silent shadowing. Hot-reload flows legitimately replace
167
+ // handlers; installing two different plugin packages that both claim
168
+ // the same (category, type) does not — the second wins and breaks the
169
+ // first's consumers with no audit trail. A console.warn is cheap,
170
+ // respects existing callers that rely on 'replaced', and gives ops a
171
+ // grep-able signal when registrations collide unexpectedly.
172
+ console.warn(`[tagma-sdk] registerPlugin: replaced existing ${category}/${type} — ` +
173
+ `check for duplicate plugin packages claiming the same type.`);
217
174
  }
218
- const mod = await import(moduleUrl);
219
- if (!mod.pluginCategory || !mod.pluginType || !mod.default) {
220
- throw new Error(`Plugin "${name}" must export pluginCategory, pluginType, and default`);
175
+ return wasReplaced ? 'replaced' : 'registered';
176
+ }
177
+ /**
178
+ * Remove a plugin from the in-process registry. Returns true if a plugin
179
+ * was actually removed. Note: ESM module caching is not affected, so
180
+ * re-importing the same file after unregister will yield the cached module —
181
+ * callers wanting a fresh load must restart the host process.
182
+ */
183
+ unregisterPlugin(category, type) {
184
+ if (!VALID_CATEGORIES.has(category))
185
+ return false;
186
+ return this.registries[category].delete(type);
187
+ }
188
+ getHandler(category, type) {
189
+ const handler = this.registries[category].get(type);
190
+ if (!handler) {
191
+ throw new Error(`${category} type "${type}" not registered.\n` +
192
+ `Install the plugin: bun add @tagma/${category.replace(/s$/, '')}-${type}`);
193
+ }
194
+ return handler;
195
+ }
196
+ hasHandler(category, type) {
197
+ return this.registries[category].has(type);
198
+ }
199
+ listRegistered(category) {
200
+ return [...this.registries[category].keys()];
201
+ }
202
+ /**
203
+ * Load and register a list of plugin packages into this registry.
204
+ *
205
+ * @param pluginNames - Validated npm package names to load.
206
+ * @param resolveFrom - Optional absolute path to resolve plugins from (e.g.
207
+ * the workspace's working directory). When omitted, the default ESM
208
+ * resolution uses the SDK's own `node_modules`, which will fail for
209
+ * plugins installed only in the user's workspace. CLI callers should
210
+ * pass `process.cwd()` or the workspace root so that workspace-local
211
+ * plugins resolve correctly.
212
+ */
213
+ async loadPlugins(pluginNames, resolveFrom) {
214
+ for (const name of pluginNames) {
215
+ if (!isValidPluginName(name)) {
216
+ throw new Error(`Plugin "${name}" rejected: plugin names must be scoped npm packages ` +
217
+ `(e.g. @tagma/trigger-xyz) or tagma-plugin-* packages. ` +
218
+ `Relative/absolute paths are not allowed.`);
219
+ }
220
+ let moduleUrl = name;
221
+ if (resolveFrom) {
222
+ // Resolve the package entry point relative to the caller's directory
223
+ // so plugins installed in the workspace's node_modules are found
224
+ // even when the SDK itself lives elsewhere (e.g. a global install
225
+ // or a monorepo sibling package).
226
+ const req = createRequire(resolveFrom.endsWith('/') ? resolveFrom : resolveFrom + '/');
227
+ const resolved = req.resolve(name);
228
+ moduleUrl = pathToFileURL(resolved).href;
229
+ }
230
+ const mod = await import(moduleUrl);
231
+ if (!mod.pluginCategory || !mod.pluginType || !mod.default) {
232
+ throw new Error(`Plugin "${name}" must export pluginCategory, pluginType, and default`);
233
+ }
234
+ this.registerPlugin(mod.pluginCategory, mod.pluginType, mod.default);
221
235
  }
222
- registerPlugin(mod.pluginCategory, mod.pluginType, mod.default);
223
236
  }
224
237
  }
238
+ /**
239
+ * Process-wide default registry. Preserves the historical free-function API
240
+ * for CLI and single-tenant hosts. Multi-tenant hosts (the editor sidecar
241
+ * after the one-sidecar refactor) build their own `PluginRegistry` per
242
+ * workspace and pass it through `RunPipelineOptions.registry`.
243
+ */
244
+ export const defaultRegistry = new PluginRegistry();
245
+ export function registerPlugin(category, type, handler) {
246
+ return defaultRegistry.registerPlugin(category, type, handler);
247
+ }
248
+ export function unregisterPlugin(category, type) {
249
+ return defaultRegistry.unregisterPlugin(category, type);
250
+ }
251
+ export function getHandler(category, type) {
252
+ return defaultRegistry.getHandler(category, type);
253
+ }
254
+ export function hasHandler(category, type) {
255
+ return defaultRegistry.hasHandler(category, type);
256
+ }
225
257
  export function listRegistered(category) {
226
- return [...registries[category].keys()];
258
+ return defaultRegistry.listRegistered(category);
259
+ }
260
+ export function loadPlugins(pluginNames, resolveFrom) {
261
+ return defaultRegistry.loadPlugins(pluginNames, resolveFrom);
227
262
  }
228
263
  //# sourceMappingURL=registry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
package/dist/sdk.d.ts CHANGED
@@ -9,7 +9,7 @@ export { parseYaml, resolveConfig, loadPipeline, serializePipeline, deresolvePip
9
9
  export { buildDag, buildRawDag } from './dag';
10
10
  export type { DagNode, Dag, RawDagNode, RawDag } from './dag';
11
11
  export { bootstrapBuiltins } from './bootstrap';
12
- export { loadPlugins, registerPlugin, unregisterPlugin, getHandler, hasHandler, listRegistered, isValidPluginName, PLUGIN_NAME_RE, readPluginManifest, } from './registry';
12
+ export { PluginRegistry, defaultRegistry, loadPlugins, registerPlugin, unregisterPlugin, getHandler, hasHandler, listRegistered, isValidPluginName, PLUGIN_NAME_RE, readPluginManifest, } from './registry';
13
13
  export type { RegisterResult } from './registry';
14
14
  export { InMemoryApprovalGateway } from './approval';
15
15
  export type { ApprovalGateway, ApprovalRequest, ApprovalDecision, ApprovalOutcome, ApprovalEvent, ApprovalListener, } from './approval';
package/dist/sdk.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACjF,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAGlF,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAG9D,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,SAAS,EACT,WAAW,EACX,UAAU,EACV,UAAU,EACV,QAAQ,EACR,YAAY,GACb,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EACL,SAAS,EACT,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,GACf,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC9C,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAG9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EACL,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,YAAY,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,YAAY,EACV,wBAAwB,EACxB,+BAA+B,GAChC,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACnD,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGjE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAG7E,OAAO,EACL,aAAa,EACb,YAAY,EACZ,aAAa,EACb,MAAM,EACN,eAAe,EACf,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,UAAU,EACV,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,cAAc,EACd,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG3D,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,aAAa,GACd,MAAM,cAAc,CAAC;AAGtB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACjF,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAGlF,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAG9D,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,SAAS,EACT,WAAW,EACX,UAAU,EACV,UAAU,EACV,QAAQ,EACR,YAAY,GACb,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EACL,SAAS,EACT,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,GACf,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC9C,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAG9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EACL,cAAc,EACd,eAAe,EACf,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,YAAY,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,YAAY,EACV,wBAAwB,EACxB,+BAA+B,GAChC,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACnD,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGjE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAG7E,OAAO,EACL,aAAa,EACb,YAAY,EACZ,aAAa,EACb,MAAM,EACN,eAAe,EACf,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,UAAU,EACV,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,cAAc,EACd,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG3D,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,aAAa,GACd,MAAM,cAAc,CAAC;AAGtB,cAAc,SAAS,CAAC"}
package/dist/sdk.js CHANGED
@@ -16,7 +16,7 @@ export { parseYaml, resolveConfig, loadPipeline, serializePipeline, deresolvePip
16
16
  export { buildDag, buildRawDag } from './dag';
17
17
  // ── Plugin registry ──
18
18
  export { bootstrapBuiltins } from './bootstrap';
19
- export { loadPlugins, registerPlugin, unregisterPlugin, getHandler, hasHandler, listRegistered, isValidPluginName, PLUGIN_NAME_RE, readPluginManifest, } from './registry';
19
+ export { PluginRegistry, defaultRegistry, loadPlugins, registerPlugin, unregisterPlugin, getHandler, hasHandler, listRegistered, isValidPluginName, PLUGIN_NAME_RE, readPluginManifest, } from './registry';
20
20
  // ── Approval gateway ──
21
21
  export { InMemoryApprovalGateway } from './approval';
22
22
  // ── Approval adapters ──