@renseiai/agentfactory 0.8.12 → 0.8.13

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 (101) hide show
  1. package/dist/src/config/repository-config.d.ts +24 -0
  2. package/dist/src/config/repository-config.d.ts.map +1 -1
  3. package/dist/src/config/repository-config.js +21 -0
  4. package/dist/src/config/repository-config.test.js +202 -0
  5. package/dist/src/governor/decision-engine.d.ts +2 -0
  6. package/dist/src/governor/decision-engine.d.ts.map +1 -1
  7. package/dist/src/governor/decision-engine.js +7 -0
  8. package/dist/src/governor/decision-engine.test.js +63 -0
  9. package/dist/src/governor/governor-types.d.ts +2 -1
  10. package/dist/src/governor/governor-types.d.ts.map +1 -1
  11. package/dist/src/index.d.ts +1 -0
  12. package/dist/src/index.d.ts.map +1 -1
  13. package/dist/src/index.js +1 -0
  14. package/dist/src/merge-queue/conflict-resolver.d.ts +62 -0
  15. package/dist/src/merge-queue/conflict-resolver.d.ts.map +1 -0
  16. package/dist/src/merge-queue/conflict-resolver.js +168 -0
  17. package/dist/src/merge-queue/conflict-resolver.test.d.ts +2 -0
  18. package/dist/src/merge-queue/conflict-resolver.test.d.ts.map +1 -0
  19. package/dist/src/merge-queue/conflict-resolver.test.js +405 -0
  20. package/dist/src/merge-queue/lock-file-regeneration.d.ts +14 -0
  21. package/dist/src/merge-queue/lock-file-regeneration.d.ts.map +1 -0
  22. package/dist/src/merge-queue/lock-file-regeneration.js +82 -0
  23. package/dist/src/merge-queue/lock-file-regeneration.test.d.ts +2 -0
  24. package/dist/src/merge-queue/lock-file-regeneration.test.d.ts.map +1 -0
  25. package/dist/src/merge-queue/lock-file-regeneration.test.js +236 -0
  26. package/dist/src/merge-queue/merge-worker.d.ts +79 -0
  27. package/dist/src/merge-queue/merge-worker.d.ts.map +1 -0
  28. package/dist/src/merge-queue/merge-worker.js +221 -0
  29. package/dist/src/merge-queue/merge-worker.test.d.ts +2 -0
  30. package/dist/src/merge-queue/merge-worker.test.d.ts.map +1 -0
  31. package/dist/src/merge-queue/merge-worker.test.js +883 -0
  32. package/dist/src/merge-queue/strategies/index.d.ts +19 -0
  33. package/dist/src/merge-queue/strategies/index.d.ts.map +1 -0
  34. package/dist/src/merge-queue/strategies/index.js +30 -0
  35. package/dist/src/merge-queue/strategies/merge-commit-strategy.d.ts +14 -0
  36. package/dist/src/merge-queue/strategies/merge-commit-strategy.d.ts.map +1 -0
  37. package/dist/src/merge-queue/strategies/merge-commit-strategy.js +58 -0
  38. package/dist/src/merge-queue/strategies/rebase-strategy.d.ts +14 -0
  39. package/dist/src/merge-queue/strategies/rebase-strategy.d.ts.map +1 -0
  40. package/dist/src/merge-queue/strategies/rebase-strategy.js +62 -0
  41. package/dist/src/merge-queue/strategies/squash-strategy.d.ts +14 -0
  42. package/dist/src/merge-queue/strategies/squash-strategy.d.ts.map +1 -0
  43. package/dist/src/merge-queue/strategies/squash-strategy.js +59 -0
  44. package/dist/src/merge-queue/strategies/strategies.test.d.ts +2 -0
  45. package/dist/src/merge-queue/strategies/strategies.test.d.ts.map +1 -0
  46. package/dist/src/merge-queue/strategies/strategies.test.js +354 -0
  47. package/dist/src/merge-queue/strategies/types.d.ts +62 -0
  48. package/dist/src/merge-queue/strategies/types.d.ts.map +1 -0
  49. package/dist/src/merge-queue/strategies/types.js +7 -0
  50. package/dist/src/orchestrator/parse-work-result.d.ts.map +1 -1
  51. package/dist/src/orchestrator/parse-work-result.js +22 -0
  52. package/dist/src/orchestrator/parse-work-result.test.js +49 -0
  53. package/dist/src/providers/index.d.ts +1 -0
  54. package/dist/src/providers/index.d.ts.map +1 -1
  55. package/dist/src/providers/plugin-types.d.ts +177 -0
  56. package/dist/src/providers/plugin-types.d.ts.map +1 -0
  57. package/dist/src/providers/plugin-types.js +10 -0
  58. package/dist/src/providers/plugin-types.test.d.ts +2 -0
  59. package/dist/src/providers/plugin-types.test.d.ts.map +1 -0
  60. package/dist/src/providers/plugin-types.test.js +810 -0
  61. package/dist/src/registry/index.d.ts +4 -0
  62. package/dist/src/registry/index.d.ts.map +1 -0
  63. package/dist/src/registry/index.js +2 -0
  64. package/dist/src/registry/loader.d.ts +25 -0
  65. package/dist/src/registry/loader.d.ts.map +1 -0
  66. package/dist/src/registry/loader.js +88 -0
  67. package/dist/src/registry/node-type-registry.d.ts +52 -0
  68. package/dist/src/registry/node-type-registry.d.ts.map +1 -0
  69. package/dist/src/registry/node-type-registry.js +130 -0
  70. package/dist/src/registry/types.d.ts +65 -0
  71. package/dist/src/registry/types.d.ts.map +1 -0
  72. package/dist/src/registry/types.js +10 -0
  73. package/dist/src/workflow/expression/ast.d.ts +1 -1
  74. package/dist/src/workflow/expression/ast.d.ts.map +1 -1
  75. package/dist/src/workflow/expression/context.d.ts +4 -0
  76. package/dist/src/workflow/expression/context.d.ts.map +1 -1
  77. package/dist/src/workflow/expression/context.js +5 -1
  78. package/dist/src/workflow/expression/evaluator.d.ts.map +1 -1
  79. package/dist/src/workflow/expression/evaluator.js +24 -1
  80. package/dist/src/workflow/expression/evaluator.test.js +174 -0
  81. package/dist/src/workflow/expression/expression.test.js +140 -1
  82. package/dist/src/workflow/expression/helpers.d.ts +4 -0
  83. package/dist/src/workflow/expression/helpers.d.ts.map +1 -1
  84. package/dist/src/workflow/expression/helpers.js +51 -0
  85. package/dist/src/workflow/expression/index.d.ts +14 -0
  86. package/dist/src/workflow/expression/index.d.ts.map +1 -1
  87. package/dist/src/workflow/expression/index.js +28 -1
  88. package/dist/src/workflow/expression/lexer.d.ts.map +1 -1
  89. package/dist/src/workflow/expression/lexer.js +43 -0
  90. package/dist/src/workflow/expression/parser.js +1 -1
  91. package/dist/src/workflow/index.d.ts +3 -3
  92. package/dist/src/workflow/index.d.ts.map +1 -1
  93. package/dist/src/workflow/index.js +4 -2
  94. package/dist/src/workflow/workflow-loader.d.ts +8 -2
  95. package/dist/src/workflow/workflow-loader.d.ts.map +1 -1
  96. package/dist/src/workflow/workflow-loader.js +21 -2
  97. package/dist/src/workflow/workflow-types.d.ts +781 -12
  98. package/dist/src/workflow/workflow-types.d.ts.map +1 -1
  99. package/dist/src/workflow/workflow-types.js +248 -3
  100. package/dist/src/workflow/workflow-types.test.js +621 -1
  101. package/package.json +3 -2
@@ -0,0 +1,4 @@
1
+ export { NodeTypeRegistry } from './node-type-registry.js';
2
+ export { loadProviderPlugins } from './loader.js';
3
+ export type { NodeTypeMetadata, ProviderCategory, NodeTypeQuery, DynamicOption, DynamicOptionResult, DynamicOptionLoader, } from './types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/registry/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { NodeTypeRegistry } from './node-type-registry.js';
2
+ export { loadProviderPlugins } from './loader.js';
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Provider Plugin Loader
3
+ *
4
+ * Discovers and loads provider plugins into the NodeTypeRegistry at startup.
5
+ * Plugins are passed explicitly via dependency injection — no filesystem scanning.
6
+ */
7
+ import type { NodeTypeRegistry } from './node-type-registry.js';
8
+ import type { DynamicOptionLoader } from './types.js';
9
+ import type { ProviderPlugin } from '../providers/plugin-types.js';
10
+ /**
11
+ * Load an array of provider plugins into the registry.
12
+ *
13
+ * For each plugin:
14
+ * 1. Auto-generates a provider category from plugin metadata
15
+ * 2. Maps each action definition to NodeTypeMetadata
16
+ * 3. Registers each node type in the store
17
+ * 4. Registers a dynamic option loader if provided
18
+ *
19
+ * Malformed plugins are logged and skipped — loading never throws.
20
+ *
21
+ * @param dynamicOptionLoaders - Optional map of provider ID → loader callback
22
+ * for runtime dynamic option fetching. If omitted, dynamic options are not available.
23
+ */
24
+ export declare function loadProviderPlugins(registry: NodeTypeRegistry, plugins: ProviderPlugin[], dynamicOptionLoaders?: Map<string, DynamicOptionLoader>): void;
25
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/registry/loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,KAAK,EAAoB,mBAAmB,EAAE,MAAM,YAAY,CAAA;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAGlE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,cAAc,EAAE,EACzB,oBAAoB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,GACtD,IAAI,CAwEN"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Provider Plugin Loader
3
+ *
4
+ * Discovers and loads provider plugins into the NodeTypeRegistry at startup.
5
+ * Plugins are passed explicitly via dependency injection — no filesystem scanning.
6
+ */
7
+ import { logger } from '../logger.js';
8
+ /**
9
+ * Load an array of provider plugins into the registry.
10
+ *
11
+ * For each plugin:
12
+ * 1. Auto-generates a provider category from plugin metadata
13
+ * 2. Maps each action definition to NodeTypeMetadata
14
+ * 3. Registers each node type in the store
15
+ * 4. Registers a dynamic option loader if provided
16
+ *
17
+ * Malformed plugins are logged and skipped — loading never throws.
18
+ *
19
+ * @param dynamicOptionLoaders - Optional map of provider ID → loader callback
20
+ * for runtime dynamic option fetching. If omitted, dynamic options are not available.
21
+ */
22
+ export function loadProviderPlugins(registry, plugins, dynamicOptionLoaders) {
23
+ for (const plugin of plugins) {
24
+ try {
25
+ if (!plugin.id) {
26
+ logger.warn('Skipping malformed plugin: missing id', {
27
+ plugin: 'unknown',
28
+ });
29
+ continue;
30
+ }
31
+ // Auto-generate a provider category from the plugin metadata
32
+ registry.registerCategory({
33
+ id: plugin.id,
34
+ displayName: plugin.displayName,
35
+ description: plugin.description ?? '',
36
+ icon: plugin.icon,
37
+ });
38
+ // Register dynamic option loader if provided
39
+ const loader = dynamicOptionLoaders?.get(plugin.id);
40
+ if (loader) {
41
+ registry.registerDynamicOptionLoader(plugin.id, loader);
42
+ }
43
+ // Map each action to NodeTypeMetadata and register
44
+ if (!Array.isArray(plugin.actions)) {
45
+ logger.warn('Skipping plugin with no actions array', { plugin: plugin.id });
46
+ continue;
47
+ }
48
+ for (const action of plugin.actions) {
49
+ try {
50
+ if (!action.id) {
51
+ logger.warn('Skipping action with missing id', { plugin: plugin.id });
52
+ continue;
53
+ }
54
+ const category = action.category ?? plugin.id;
55
+ const metadata = {
56
+ id: `${plugin.id}:${action.id}`,
57
+ providerId: plugin.id,
58
+ actionId: action.id,
59
+ displayName: action.displayName || action.id,
60
+ description: action.description || '',
61
+ category,
62
+ inputSchema: action.inputSchema || {},
63
+ outputSchema: action.outputSchema,
64
+ dynamicOptionFields: action.dynamicOptions?.map((d) => d.fieldPath),
65
+ };
66
+ registry.register(metadata);
67
+ }
68
+ catch (actionError) {
69
+ logger.warn('Skipping malformed action', {
70
+ plugin: plugin.id,
71
+ action: action.id,
72
+ error: actionError instanceof Error ? actionError.message : String(actionError),
73
+ });
74
+ }
75
+ }
76
+ logger.info('Loaded provider plugin', {
77
+ plugin: plugin.id,
78
+ actions: plugin.actions.length,
79
+ });
80
+ }
81
+ catch (error) {
82
+ logger.warn('Skipping malformed plugin', {
83
+ plugin: plugin.id ?? 'unknown',
84
+ error: error instanceof Error ? error.message : String(error),
85
+ });
86
+ }
87
+ }
88
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Node Type Registry
3
+ *
4
+ * In-memory store that holds provider plugin metadata and serves it
5
+ * to the canvas UI and execution engine. Synchronous for reads,
6
+ * with a single async method for dynamic option loading.
7
+ */
8
+ import type { JSONSchema7 } from 'json-schema';
9
+ import type { NodeTypeMetadata, ProviderCategory, DynamicOptionResult, DynamicOptionLoader } from './types.js';
10
+ export declare class NodeTypeRegistry {
11
+ private nodeTypes;
12
+ private categories;
13
+ private dynamicOptionLoaders;
14
+ private dynamicOptionsCache;
15
+ private cacheTtlMs;
16
+ constructor(options?: {
17
+ cacheTtlMs?: number;
18
+ });
19
+ static create(options?: {
20
+ cacheTtlMs?: number;
21
+ }): NodeTypeRegistry;
22
+ /** Register a node type metadata entry */
23
+ register(metadata: NodeTypeMetadata): void;
24
+ /** Register a provider category */
25
+ registerCategory(category: ProviderCategory): void;
26
+ /** Register a dynamic option loader for a provider */
27
+ registerDynamicOptionLoader(providerId: string, loader: DynamicOptionLoader): void;
28
+ /** List all registered provider categories */
29
+ getCategories(): ProviderCategory[];
30
+ /** List node types, optionally filtered by category */
31
+ getNodeTypes(category?: string): NodeTypeMetadata[];
32
+ /** Get a specific node type by provider and action ID */
33
+ getNodeType(providerId: string, actionId: string): NodeTypeMetadata | undefined;
34
+ /** Get the input schema for a specific node type */
35
+ getInputSchema(providerId: string, actionId: string): JSONSchema7 | undefined;
36
+ /**
37
+ * Load dynamic options for a dropdown field by delegating to the provider's
38
+ * registered dynamic option loader. This is the only async method on the registry.
39
+ *
40
+ * @param providerId - The provider plugin ID
41
+ * @param actionId - The action ID within the provider
42
+ * @param fieldPath - The field path that needs dynamic options
43
+ * @param context - Optional dependent field values
44
+ * @returns Array of options, or empty array on error
45
+ */
46
+ loadDynamicOptions(providerId: string, actionId: string, fieldPath: string, context?: Record<string, unknown>): Promise<DynamicOptionResult>;
47
+ /** Reset the store (for testing) */
48
+ clear(): void;
49
+ private makeNodeTypeKey;
50
+ private makeCacheKey;
51
+ }
52
+ //# sourceMappingURL=node-type-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-type-registry.d.ts","sourceRoot":"","sources":["../../../src/registry/node-type-registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,YAAY,CAAA;AAGnB,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAsC;IACvD,OAAO,CAAC,UAAU,CAAsC;IACxD,OAAO,CAAC,oBAAoB,CAAyC;IACrE,OAAO,CAAC,mBAAmB,CAAwE;IACnG,OAAO,CAAC,UAAU,CAAQ;gBAEd,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;IAI7C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,gBAAgB;IAQlE,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAK1C,mCAAmC;IACnC,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAIlD,sDAAsD;IACtD,2BAA2B,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,GAAG,IAAI;IAQlF,8CAA8C;IAC9C,aAAa,IAAI,gBAAgB,EAAE;IAInC,uDAAuD;IACvD,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,gBAAgB,EAAE;IAMnD,yDAAyD;IACzD,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAK/E,oDAAoD;IACpD,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAS7E;;;;;;;;;OASG;IACG,kBAAkB,CACtB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,OAAO,CAAC,mBAAmB,CAAC;IAiD/B,oCAAoC;IACpC,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,YAAY;CAUrB"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Node Type Registry
3
+ *
4
+ * In-memory store that holds provider plugin metadata and serves it
5
+ * to the canvas UI and execution engine. Synchronous for reads,
6
+ * with a single async method for dynamic option loading.
7
+ */
8
+ import { logger } from '../logger.js';
9
+ export class NodeTypeRegistry {
10
+ nodeTypes = new Map();
11
+ categories = new Map();
12
+ dynamicOptionLoaders = new Map();
13
+ dynamicOptionsCache = new Map();
14
+ cacheTtlMs;
15
+ constructor(options) {
16
+ this.cacheTtlMs = options?.cacheTtlMs ?? 60_000;
17
+ }
18
+ static create(options) {
19
+ return new NodeTypeRegistry(options);
20
+ }
21
+ // ---------------------------------------------------------------------------
22
+ // Registration
23
+ // ---------------------------------------------------------------------------
24
+ /** Register a node type metadata entry */
25
+ register(metadata) {
26
+ const key = this.makeNodeTypeKey(metadata.providerId, metadata.actionId);
27
+ this.nodeTypes.set(key, metadata);
28
+ }
29
+ /** Register a provider category */
30
+ registerCategory(category) {
31
+ this.categories.set(category.id, category);
32
+ }
33
+ /** Register a dynamic option loader for a provider */
34
+ registerDynamicOptionLoader(providerId, loader) {
35
+ this.dynamicOptionLoaders.set(providerId, loader);
36
+ }
37
+ // ---------------------------------------------------------------------------
38
+ // Queries
39
+ // ---------------------------------------------------------------------------
40
+ /** List all registered provider categories */
41
+ getCategories() {
42
+ return Array.from(this.categories.values());
43
+ }
44
+ /** List node types, optionally filtered by category */
45
+ getNodeTypes(category) {
46
+ const all = Array.from(this.nodeTypes.values());
47
+ if (!category)
48
+ return all;
49
+ return all.filter((nt) => nt.category === category);
50
+ }
51
+ /** Get a specific node type by provider and action ID */
52
+ getNodeType(providerId, actionId) {
53
+ const key = this.makeNodeTypeKey(providerId, actionId);
54
+ return this.nodeTypes.get(key);
55
+ }
56
+ /** Get the input schema for a specific node type */
57
+ getInputSchema(providerId, actionId) {
58
+ const nodeType = this.getNodeType(providerId, actionId);
59
+ return nodeType?.inputSchema;
60
+ }
61
+ // ---------------------------------------------------------------------------
62
+ // Dynamic Options
63
+ // ---------------------------------------------------------------------------
64
+ /**
65
+ * Load dynamic options for a dropdown field by delegating to the provider's
66
+ * registered dynamic option loader. This is the only async method on the registry.
67
+ *
68
+ * @param providerId - The provider plugin ID
69
+ * @param actionId - The action ID within the provider
70
+ * @param fieldPath - The field path that needs dynamic options
71
+ * @param context - Optional dependent field values
72
+ * @returns Array of options, or empty array on error
73
+ */
74
+ async loadDynamicOptions(providerId, actionId, fieldPath, context) {
75
+ const cacheKey = this.makeCacheKey(providerId, actionId, fieldPath, context);
76
+ const cached = this.dynamicOptionsCache.get(cacheKey);
77
+ if (cached && cached.expiresAt > Date.now()) {
78
+ return cached.result;
79
+ }
80
+ const loader = this.dynamicOptionLoaders.get(providerId);
81
+ if (!loader) {
82
+ logger.warn('No dynamic option loader registered', { providerId, actionId, fieldPath });
83
+ return [];
84
+ }
85
+ try {
86
+ const controller = new AbortController();
87
+ const timeout = setTimeout(() => controller.abort(), 10_000);
88
+ const result = await Promise.race([
89
+ loader(actionId, fieldPath, context),
90
+ new Promise((_, reject) => {
91
+ controller.signal.addEventListener('abort', () => reject(new Error('Dynamic options request timed out')));
92
+ }),
93
+ ]);
94
+ clearTimeout(timeout);
95
+ this.dynamicOptionsCache.set(cacheKey, {
96
+ result,
97
+ expiresAt: Date.now() + this.cacheTtlMs,
98
+ });
99
+ return result;
100
+ }
101
+ catch (error) {
102
+ logger.warn('Failed to load dynamic options', {
103
+ providerId,
104
+ actionId,
105
+ fieldPath,
106
+ error: error instanceof Error ? error.message : String(error),
107
+ });
108
+ return [];
109
+ }
110
+ }
111
+ // ---------------------------------------------------------------------------
112
+ // Utilities
113
+ // ---------------------------------------------------------------------------
114
+ /** Reset the store (for testing) */
115
+ clear() {
116
+ this.nodeTypes.clear();
117
+ this.categories.clear();
118
+ this.dynamicOptionLoaders.clear();
119
+ this.dynamicOptionsCache.clear();
120
+ }
121
+ makeNodeTypeKey(providerId, actionId) {
122
+ return `${providerId}:${actionId}`;
123
+ }
124
+ makeCacheKey(providerId, actionId, fieldPath, context) {
125
+ const base = `${providerId}:${actionId}:${fieldPath}`;
126
+ if (!context || Object.keys(context).length === 0)
127
+ return base;
128
+ return `${base}:${JSON.stringify(context)}`;
129
+ }
130
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Node Type Registry Types
3
+ *
4
+ * Interfaces for the node type metadata store that serves
5
+ * canvas UI and execution engine with provider plugin information.
6
+ *
7
+ * Provider plugin types (ProviderPlugin, ActionDefinition) are imported
8
+ * from providers/plugin-types.ts (defined by SUP-1511).
9
+ */
10
+ import type { JSONSchema7 } from 'json-schema';
11
+ /** Provider category grouping (e.g., "Communication", "Project Management") */
12
+ export interface ProviderCategory {
13
+ /** Unique category identifier */
14
+ id: string;
15
+ /** Human-readable name */
16
+ displayName: string;
17
+ /** Category description */
18
+ description: string;
19
+ /** Icon identifier for the canvas UI */
20
+ icon?: string;
21
+ }
22
+ /** Metadata for a single node type (action/trigger/condition) in the registry */
23
+ export interface NodeTypeMetadata {
24
+ /** Unique identifier for this node type */
25
+ id: string;
26
+ /** Provider identifier (e.g., "linear", "slack") */
27
+ providerId: string;
28
+ /** Action identifier within the provider (e.g., "create-issue", "send-message") */
29
+ actionId: string;
30
+ /** Human-readable name */
31
+ displayName: string;
32
+ /** Description of what this node type does */
33
+ description: string;
34
+ /** Category this node type belongs to */
35
+ category: string;
36
+ /** JSON Schema for the node's input fields */
37
+ inputSchema: JSONSchema7;
38
+ /** JSON Schema for the node's output */
39
+ outputSchema?: JSONSchema7;
40
+ /** Fields that support dynamic option loading */
41
+ dynamicOptionFields?: string[];
42
+ }
43
+ /** Filter parameters for querying node types */
44
+ export interface NodeTypeQuery {
45
+ /** Filter by category */
46
+ category?: string;
47
+ /** Filter by provider */
48
+ providerId?: string;
49
+ }
50
+ /** A single option returned from dynamic option loading */
51
+ export interface DynamicOption {
52
+ /** Value to store when selected */
53
+ value: string;
54
+ /** Human-readable label to display */
55
+ label: string;
56
+ }
57
+ /** Result of a dynamic option loading call */
58
+ export type DynamicOptionResult = DynamicOption[];
59
+ /**
60
+ * Callback for fetching dynamic options at runtime.
61
+ * Registered per-provider to allow the registry to delegate dynamic option
62
+ * loading without coupling to a specific method on ActionDefinition.
63
+ */
64
+ export type DynamicOptionLoader = (actionId: string, fieldPath: string, context?: Record<string, unknown>) => Promise<DynamicOptionResult>;
65
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/registry/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,+EAA+E;AAC/E,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAA;IACnB,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,iFAAiF;AACjF,MAAM,WAAW,gBAAgB;IAC/B,2CAA2C;IAC3C,EAAE,EAAE,MAAM,CAAA;IACV,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAA;IAClB,mFAAmF;IACnF,QAAQ,EAAE,MAAM,CAAA;IAChB,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAA;IACnB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAA;IAChB,8CAA8C;IAC9C,WAAW,EAAE,WAAW,CAAA;IACxB,wCAAwC;IACxC,YAAY,CAAC,EAAE,WAAW,CAAA;IAC1B,iDAAiD;IACjD,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC/B;AAED,gDAAgD;AAChD,MAAM,WAAW,aAAa;IAC5B,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yBAAyB;IACzB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,2DAA2D;AAC3D,MAAM,WAAW,aAAa;IAC5B,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAA;CACd;AAED,8CAA8C;AAC9C,MAAM,MAAM,mBAAmB,GAAG,aAAa,EAAE,CAAA;AAEjD;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAChC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,OAAO,CAAC,mBAAmB,CAAC,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Node Type Registry Types
3
+ *
4
+ * Interfaces for the node type metadata store that serves
5
+ * canvas UI and execution engine with provider plugin information.
6
+ *
7
+ * Provider plugin types (ProviderPlugin, ActionDefinition) are imported
8
+ * from providers/plugin-types.ts (defined by SUP-1511).
9
+ */
10
+ export {};
@@ -28,7 +28,7 @@ export interface NumberLiteral {
28
28
  /** Unary operators */
29
29
  export type UnaryOperator = 'not';
30
30
  /** Binary logical/comparison operators */
31
- export type BinaryOperator = 'and' | 'or' | 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte';
31
+ export type BinaryOperator = 'and' | 'or' | 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte' | 'in';
32
32
  /** A unary operation, e.g. `not <expr>` */
33
33
  export interface UnaryOp {
34
34
  readonly type: 'UnaryOp';
@@ -1 +1 @@
1
- {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../../../src/workflow/expression/ast.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,wEAAwE;AACxE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,2CAA2C;AAC3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;IAC/B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CACxB;AAED,mDAAmD;AACnD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,yCAAyC;AACzC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAMD,sBAAsB;AACtB,MAAM,MAAM,aAAa,GAAG,KAAK,CAAA;AAEjC,0CAA0C;AAC1C,MAAM,MAAM,cAAc,GACtB,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,KAAK,CAAA;AAET,2CAA2C;AAC3C,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAA;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAED,uEAAuE;AACvE,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CACxB;AAMD,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,CAAA;CACzB;AAMD,gDAAgD;AAChD,MAAM,MAAM,OAAO,GACf,WAAW,GACX,cAAc,GACd,aAAa,GACb,aAAa,GACb,OAAO,GACP,QAAQ,GACR,YAAY,CAAA"}
1
+ {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../../../src/workflow/expression/ast.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,wEAAwE;AACxE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,2CAA2C;AAC3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;IAC/B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CACxB;AAED,mDAAmD;AACnD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,yCAAyC;AACzC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAMD,sBAAsB;AACtB,MAAM,MAAM,aAAa,GAAG,KAAK,CAAA;AAEjC,0CAA0C;AAC1C,MAAM,MAAM,cAAc,GACtB,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,KAAK,GACL,IAAI,CAAA;AAER,2CAA2C;AAC3C,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAA;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAED,uEAAuE;AACvE,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CACxB;AAMD,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,CAAA;CACzB;AAMD,gDAAgD;AAChD,MAAM,MAAM,OAAO,GACf,WAAW,GACX,cAAc,GACd,aAAa,GACb,aAAa,GACb,OAAO,GACP,QAAQ,GACR,YAAY,CAAA"}
@@ -21,6 +21,10 @@ export interface EvaluationContext {
21
21
  export interface BuildContextOptions {
22
22
  /** Whether the issue has sub-issues (i.e., it is a parent issue) */
23
23
  hasSubIssues?: boolean;
24
+ /** Whether the issue is assigned to a human user (vs unassigned or bot) */
25
+ isAssignedToHuman?: boolean;
26
+ /** Whether the issue has incomplete blocking relations */
27
+ hasBlockingIncomplete?: boolean;
24
28
  }
25
29
  /**
26
30
  * Build an EvaluationContext from a GovernorIssue and optional phase state.
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/workflow/expression/context.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAA;AAOrE;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC3C,kCAAkC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAA;CACpE;AAMD,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,aAAa,EACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,IAAI,CAAC,EAAE,mBAAmB,GACzB,iBAAiB,CAkBnB"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/workflow/expression/context.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAA;AAOrE;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC3C,kCAAkC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAA;CACpE;AAMD,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,0DAA0D;IAC1D,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAChC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,aAAa,EACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,IAAI,CAAC,EAAE,mBAAmB,GACzB,iBAAiB,CAsBnB"}
@@ -32,6 +32,10 @@ export function buildEvaluationContext(issue, phaseState, opts) {
32
32
  // `researchCompleted and not backlogCreationCompleted` work directly.
33
33
  ...phaseState,
34
34
  };
35
- const functions = createBuiltinHelpers(issue, { hasSubIssues });
35
+ const functions = createBuiltinHelpers(issue, {
36
+ hasSubIssues,
37
+ isAssignedToHuman: opts?.isAssignedToHuman ?? false,
38
+ hasBlockingIncomplete: opts?.hasBlockingIncomplete ?? false,
39
+ });
36
40
  return { variables, functions };
37
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../../../src/workflow/expression/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAMrD;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAiBD;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CA6D1E"}
1
+ {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../../../src/workflow/expression/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAMrD;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAiBD;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAyE1E"}
@@ -55,7 +55,19 @@ export function evaluate(ast, context) {
55
55
  // Variable reference — look up in context, default to false
56
56
  // -------------------------------------------------------------------
57
57
  case 'VariableRef': {
58
- const value = context.variables[ast.name];
58
+ const name = ast.name;
59
+ if (name.includes('.')) {
60
+ const parts = name.split('.');
61
+ let current = context.variables;
62
+ for (const part of parts) {
63
+ if (current === null || current === undefined || typeof current !== 'object') {
64
+ return false;
65
+ }
66
+ current = current[part];
67
+ }
68
+ return current === undefined ? false : current;
69
+ }
70
+ const value = context.variables[name];
59
71
  // Undefined variables resolve to `false` (no crash)
60
72
  if (value === undefined) {
61
73
  return false;
@@ -131,6 +143,17 @@ function evaluateBinaryOp(operator, left, right, context) {
131
143
  const rightVal = evaluate(right, context);
132
144
  return evaluateOrdering(operator, leftVal, rightVal);
133
145
  }
146
+ case 'in': {
147
+ const leftVal = evaluate(left, context);
148
+ const rightVal = evaluate(right, context);
149
+ if (Array.isArray(rightVal)) {
150
+ return rightVal.includes(leftVal);
151
+ }
152
+ if (typeof rightVal === 'string' && typeof leftVal === 'string') {
153
+ return rightVal.includes(leftVal);
154
+ }
155
+ throw new EvaluationError(`'in' operator requires right operand to be an array or string, got ${typeLabel(rightVal)}.`);
156
+ }
134
157
  default:
135
158
  throw new EvaluationError(`Unknown operator '${operator}'`);
136
159
  }