@deimoscloud/coreai 0.1.9 → 0.1.10

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 (196) hide show
  1. package/dist/cli/index.js +1 -1
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/package.json +6 -1
  6. package/.prettierrc +0 -9
  7. package/AGENT_SPEC.md +0 -347
  8. package/ARCHITECTURE.md +0 -547
  9. package/DRAFT_PRD.md +0 -1440
  10. package/IMPLEMENTATION_PLAN.md +0 -256
  11. package/PRODUCT.md +0 -473
  12. package/WORKFLOWS.md +0 -295
  13. package/commands/core/check-inbox.md +0 -34
  14. package/commands/core/delegate.md +0 -30
  15. package/commands/core/git-commit.md +0 -144
  16. package/commands/core/pr-create.md +0 -193
  17. package/commands/core/review.md +0 -56
  18. package/commands/core/sprint-status.md +0 -65
  19. package/commands/optional/docs-update.md +0 -200
  20. package/commands/optional/jira-create.md +0 -200
  21. package/commands/optional/jira-transition.md +0 -184
  22. package/commands/optional/worktree-cleanup.md +0 -167
  23. package/commands/optional/worktree-setup.md +0 -110
  24. package/eslint.config.js +0 -29
  25. package/jest.config.js +0 -22
  26. package/knowledge-library/README.md +0 -118
  27. package/knowledge-library/android-engineer/context/current.txt +0 -42
  28. package/knowledge-library/android-engineer/control/decisions.txt +0 -9
  29. package/knowledge-library/android-engineer/control/dependencies.txt +0 -19
  30. package/knowledge-library/android-engineer/control/objectives.txt +0 -26
  31. package/knowledge-library/android-engineer/history/.gitkeep +0 -0
  32. package/knowledge-library/android-engineer/inbox/processed/.gitkeep +0 -0
  33. package/knowledge-library/android-engineer/outbox/.gitkeep +0 -0
  34. package/knowledge-library/android-engineer/tech/.gitkeep +0 -0
  35. package/knowledge-library/architecture.txt +0 -61
  36. package/knowledge-library/backend-engineer/context/current.txt +0 -42
  37. package/knowledge-library/backend-engineer/control/decisions.txt +0 -9
  38. package/knowledge-library/backend-engineer/control/dependencies.txt +0 -19
  39. package/knowledge-library/backend-engineer/control/objectives.txt +0 -26
  40. package/knowledge-library/backend-engineer/history/.gitkeep +0 -0
  41. package/knowledge-library/backend-engineer/inbox/processed/.gitkeep +0 -0
  42. package/knowledge-library/backend-engineer/outbox/.gitkeep +0 -0
  43. package/knowledge-library/backend-engineer/tech/.gitkeep +0 -0
  44. package/knowledge-library/context.txt +0 -52
  45. package/knowledge-library/devops-engineer/context/current.txt +0 -42
  46. package/knowledge-library/devops-engineer/control/decisions.txt +0 -9
  47. package/knowledge-library/devops-engineer/control/dependencies.txt +0 -19
  48. package/knowledge-library/devops-engineer/control/objectives.txt +0 -26
  49. package/knowledge-library/devops-engineer/history/.gitkeep +0 -0
  50. package/knowledge-library/devops-engineer/inbox/processed/.gitkeep +0 -0
  51. package/knowledge-library/devops-engineer/outbox/.gitkeep +0 -0
  52. package/knowledge-library/devops-engineer/tech/.gitkeep +0 -0
  53. package/knowledge-library/engineering-manager/context/current.txt +0 -40
  54. package/knowledge-library/engineering-manager/control/decisions.txt +0 -9
  55. package/knowledge-library/engineering-manager/control/objectives.txt +0 -27
  56. package/knowledge-library/engineering-manager/history/.gitkeep +0 -0
  57. package/knowledge-library/engineering-manager/inbox/processed/.gitkeep +0 -0
  58. package/knowledge-library/engineering-manager/outbox/.gitkeep +0 -0
  59. package/knowledge-library/engineering-manager/tech/.gitkeep +0 -0
  60. package/knowledge-library/prd.txt +0 -81
  61. package/knowledge-library/product-manager/context/current.txt +0 -42
  62. package/knowledge-library/product-manager/control/decisions.txt +0 -9
  63. package/knowledge-library/product-manager/control/dependencies.txt +0 -19
  64. package/knowledge-library/product-manager/control/objectives.txt +0 -26
  65. package/knowledge-library/product-manager/history/.gitkeep +0 -0
  66. package/knowledge-library/product-manager/inbox/processed/.gitkeep +0 -0
  67. package/knowledge-library/product-manager/outbox/.gitkeep +0 -0
  68. package/knowledge-library/product-manager/tech/.gitkeep +0 -0
  69. package/knowledge-library/qa-engineer/context/current.txt +0 -42
  70. package/knowledge-library/qa-engineer/control/decisions.txt +0 -9
  71. package/knowledge-library/qa-engineer/control/dependencies.txt +0 -19
  72. package/knowledge-library/qa-engineer/control/objectives.txt +0 -26
  73. package/knowledge-library/qa-engineer/history/.gitkeep +0 -0
  74. package/knowledge-library/qa-engineer/inbox/processed/.gitkeep +0 -0
  75. package/knowledge-library/qa-engineer/outbox/.gitkeep +0 -0
  76. package/knowledge-library/qa-engineer/tech/.gitkeep +0 -0
  77. package/knowledge-library/security-engineer/context/current.txt +0 -42
  78. package/knowledge-library/security-engineer/control/decisions.txt +0 -9
  79. package/knowledge-library/security-engineer/control/dependencies.txt +0 -19
  80. package/knowledge-library/security-engineer/control/objectives.txt +0 -26
  81. package/knowledge-library/security-engineer/history/.gitkeep +0 -0
  82. package/knowledge-library/security-engineer/inbox/processed/.gitkeep +0 -0
  83. package/knowledge-library/security-engineer/outbox/.gitkeep +0 -0
  84. package/knowledge-library/security-engineer/tech/.gitkeep +0 -0
  85. package/knowledge-library/solutions-architect/context/current.txt +0 -42
  86. package/knowledge-library/solutions-architect/control/decisions.txt +0 -9
  87. package/knowledge-library/solutions-architect/control/dependencies.txt +0 -19
  88. package/knowledge-library/solutions-architect/control/objectives.txt +0 -26
  89. package/knowledge-library/solutions-architect/history/.gitkeep +0 -0
  90. package/knowledge-library/solutions-architect/inbox/processed/.gitkeep +0 -0
  91. package/knowledge-library/solutions-architect/outbox/.gitkeep +0 -0
  92. package/knowledge-library/solutions-architect/tech/.gitkeep +0 -0
  93. package/knowledge-library/wearos-engineer/context/current.txt +0 -42
  94. package/knowledge-library/wearos-engineer/control/decisions.txt +0 -9
  95. package/knowledge-library/wearos-engineer/control/dependencies.txt +0 -19
  96. package/knowledge-library/wearos-engineer/control/objectives.txt +0 -26
  97. package/knowledge-library/wearos-engineer/history/.gitkeep +0 -0
  98. package/knowledge-library/wearos-engineer/inbox/processed/.gitkeep +0 -0
  99. package/knowledge-library/wearos-engineer/outbox/.gitkeep +0 -0
  100. package/knowledge-library/wearos-engineer/tech/.gitkeep +0 -0
  101. package/scripts/add-agent.sh +0 -323
  102. package/scripts/install.sh +0 -354
  103. package/src/adapters/factory.test.ts +0 -386
  104. package/src/adapters/factory.ts +0 -305
  105. package/src/adapters/index.ts +0 -113
  106. package/src/adapters/interfaces.ts +0 -268
  107. package/src/adapters/mcp/client.test.ts +0 -130
  108. package/src/adapters/mcp/client.ts +0 -451
  109. package/src/adapters/mcp/discovery.test.ts +0 -315
  110. package/src/adapters/mcp/discovery.ts +0 -340
  111. package/src/adapters/mcp/index.ts +0 -66
  112. package/src/adapters/mcp/mapper.test.ts +0 -218
  113. package/src/adapters/mcp/mapper.ts +0 -536
  114. package/src/adapters/mcp/registry.test.ts +0 -433
  115. package/src/adapters/mcp/registry.ts +0 -550
  116. package/src/adapters/mcp/types.ts +0 -258
  117. package/src/adapters/native/filesystem.test.ts +0 -350
  118. package/src/adapters/native/filesystem.ts +0 -393
  119. package/src/adapters/native/github.test.ts +0 -173
  120. package/src/adapters/native/github.ts +0 -627
  121. package/src/adapters/native/index.ts +0 -22
  122. package/src/adapters/native/selector.test.ts +0 -224
  123. package/src/adapters/native/selector.ts +0 -150
  124. package/src/adapters/types.ts +0 -270
  125. package/src/agents/compiler.test.ts +0 -410
  126. package/src/agents/compiler.ts +0 -424
  127. package/src/agents/index.ts +0 -37
  128. package/src/agents/loader.test.ts +0 -319
  129. package/src/agents/loader.ts +0 -143
  130. package/src/agents/resolver.test.ts +0 -282
  131. package/src/agents/resolver.ts +0 -262
  132. package/src/agents/types.ts +0 -97
  133. package/src/cache/index.ts +0 -38
  134. package/src/cache/interfaces.ts +0 -283
  135. package/src/cache/manager.test.ts +0 -266
  136. package/src/cache/manager.ts +0 -388
  137. package/src/cache/provider.test.ts +0 -485
  138. package/src/cache/provider.ts +0 -745
  139. package/src/cache/types.test.ts +0 -192
  140. package/src/cache/types.ts +0 -313
  141. package/src/cli/commands/build.test.ts +0 -248
  142. package/src/cli/commands/build.ts +0 -284
  143. package/src/cli/commands/cache.test.ts +0 -221
  144. package/src/cli/commands/cache.ts +0 -229
  145. package/src/cli/commands/index.ts +0 -63
  146. package/src/cli/commands/init.test.ts +0 -173
  147. package/src/cli/commands/init.ts +0 -296
  148. package/src/cli/commands/skills.test.ts +0 -272
  149. package/src/cli/commands/skills.ts +0 -348
  150. package/src/cli/commands/status.test.ts +0 -392
  151. package/src/cli/commands/status.ts +0 -332
  152. package/src/cli/commands/sync.test.ts +0 -213
  153. package/src/cli/commands/sync.ts +0 -251
  154. package/src/cli/commands/validate.test.ts +0 -216
  155. package/src/cli/commands/validate.ts +0 -340
  156. package/src/cli/index.test.ts +0 -190
  157. package/src/cli/index.ts +0 -493
  158. package/src/commands/context.test.ts +0 -163
  159. package/src/commands/context.ts +0 -111
  160. package/src/commands/index.ts +0 -56
  161. package/src/commands/loader.test.ts +0 -273
  162. package/src/commands/loader.ts +0 -355
  163. package/src/commands/registry.test.ts +0 -384
  164. package/src/commands/registry.ts +0 -248
  165. package/src/commands/runner.test.ts +0 -297
  166. package/src/commands/runner.ts +0 -222
  167. package/src/commands/types.ts +0 -361
  168. package/src/config/index.ts +0 -19
  169. package/src/config/loader.test.ts +0 -262
  170. package/src/config/loader.ts +0 -188
  171. package/src/config/types.ts +0 -154
  172. package/src/context/index.ts +0 -14
  173. package/src/context/loader.test.ts +0 -334
  174. package/src/context/loader.ts +0 -357
  175. package/src/index.test.ts +0 -13
  176. package/src/index.ts +0 -268
  177. package/src/knowledge-library/index.ts +0 -44
  178. package/src/knowledge-library/manager.test.ts +0 -536
  179. package/src/knowledge-library/manager.ts +0 -804
  180. package/src/knowledge-library/types.ts +0 -432
  181. package/src/skills/generator.test.ts +0 -602
  182. package/src/skills/generator.ts +0 -491
  183. package/src/skills/index.ts +0 -27
  184. package/src/skills/templates.ts +0 -520
  185. package/src/skills/types.ts +0 -251
  186. package/templates/completion-report.md +0 -72
  187. package/templates/feedback.md +0 -56
  188. package/templates/project-files/CLAUDE.md.template +0 -109
  189. package/templates/project-files/coreai.json.example +0 -47
  190. package/templates/project-files/mcp.json.template +0 -20
  191. package/templates/review-complete.md +0 -64
  192. package/templates/review-request.md +0 -67
  193. package/templates/task-assignment.md +0 -51
  194. package/tsconfig.build.json +0 -4
  195. package/tsconfig.json +0 -26
  196. package/tsup.config.ts +0 -23
@@ -1,384 +0,0 @@
1
- /**
2
- * Command Registry Tests
3
- */
4
-
5
- import type { CommandRegistry } from './registry.js';
6
- import { createCommandRegistry, getGlobalRegistry, resetGlobalRegistry } from './registry.js';
7
- import type { CommandDefinition, MarkdownCommand } from './types.js';
8
-
9
- describe('Command Registry', () => {
10
- let registry: CommandRegistry;
11
-
12
- beforeEach(() => {
13
- registry = createCommandRegistry();
14
- resetGlobalRegistry();
15
- });
16
-
17
- describe('createCommandRegistry', () => {
18
- it('should create an empty registry', () => {
19
- expect(registry.size).toBe(0);
20
- expect(registry.getAll()).toHaveLength(0);
21
- });
22
- });
23
-
24
- describe('register', () => {
25
- it('should register a command definition', () => {
26
- const cmd: CommandDefinition = {
27
- name: 'test-cmd',
28
- description: 'A test command',
29
- category: 'core',
30
- handler: async () => ({ success: true }),
31
- };
32
-
33
- registry.register(cmd);
34
-
35
- expect(registry.has('test-cmd')).toBe(true);
36
- expect(registry.size).toBe(1);
37
- });
38
-
39
- it('should register with dependencies', () => {
40
- const cmd: CommandDefinition = {
41
- name: 'jira-cmd',
42
- description: 'Jira command',
43
- category: 'optional',
44
- dependencies: [{ type: 'issue_tracker', required: true, description: 'Needs Jira' }],
45
- handler: async () => ({ success: true }),
46
- };
47
-
48
- registry.register(cmd);
49
-
50
- const entry = registry.get('jira-cmd');
51
- expect(entry?.metadata.dependencies).toHaveLength(1);
52
- expect(entry?.metadata.dependencies[0].type).toBe('issue_tracker');
53
- });
54
-
55
- it('should mark command unavailable if required dep missing', () => {
56
- const cmd: CommandDefinition = {
57
- name: 'jira-cmd',
58
- description: 'Jira command',
59
- category: 'optional',
60
- dependencies: [{ type: 'issue_tracker', required: true }],
61
- handler: async () => ({ success: true }),
62
- };
63
-
64
- registry.register(cmd);
65
-
66
- const entry = registry.get('jira-cmd');
67
- // Without adapter factory, required deps are considered missing
68
- expect(entry?.metadata.available).toBe(false);
69
- expect(entry?.metadata.unavailableReason).toContain('issue_tracker');
70
- });
71
-
72
- it('should mark command available if only optional deps missing', () => {
73
- const cmd: CommandDefinition = {
74
- name: 'enhanced-cmd',
75
- description: 'Enhanced command',
76
- category: 'core',
77
- dependencies: [{ type: 'documentation', required: false }],
78
- handler: async () => ({ success: true }),
79
- };
80
-
81
- registry.register(cmd);
82
-
83
- const entry = registry.get('enhanced-cmd');
84
- expect(entry?.metadata.available).toBe(true);
85
- });
86
- });
87
-
88
- describe('registerMarkdown', () => {
89
- it('should register a markdown command', () => {
90
- const cmd: MarkdownCommand = {
91
- metadata: {
92
- name: 'delegate',
93
- description: 'Delegate work',
94
- category: 'core',
95
- dependencies: [],
96
- sourcePath: '/path/to/delegate.md',
97
- available: true,
98
- },
99
- content: '# Delegate\n\nInstructions here.',
100
- sections: {
101
- title: 'Delegate',
102
- },
103
- };
104
-
105
- registry.registerMarkdown(cmd);
106
-
107
- expect(registry.has('delegate')).toBe(true);
108
- const entry = registry.get('delegate');
109
- expect(entry?.source).toBe('markdown');
110
- expect(entry?.markdownCommand).toBe(cmd);
111
- });
112
- });
113
-
114
- describe('registerAll', () => {
115
- it('should register multiple commands', () => {
116
- const cmds: CommandDefinition[] = [
117
- {
118
- name: 'cmd1',
119
- description: 'Cmd 1',
120
- category: 'core',
121
- handler: async () => ({ success: true }),
122
- },
123
- {
124
- name: 'cmd2',
125
- description: 'Cmd 2',
126
- category: 'core',
127
- handler: async () => ({ success: true }),
128
- },
129
- {
130
- name: 'cmd3',
131
- description: 'Cmd 3',
132
- category: 'optional',
133
- handler: async () => ({ success: true }),
134
- },
135
- ];
136
-
137
- registry.registerAll(cmds);
138
-
139
- expect(registry.size).toBe(3);
140
- expect(registry.has('cmd1')).toBe(true);
141
- expect(registry.has('cmd2')).toBe(true);
142
- expect(registry.has('cmd3')).toBe(true);
143
- });
144
- });
145
-
146
- describe('unregister', () => {
147
- it('should unregister a command', () => {
148
- const cmd: CommandDefinition = {
149
- name: 'to-remove',
150
- description: 'Will be removed',
151
- category: 'core',
152
- handler: async () => ({ success: true }),
153
- };
154
-
155
- registry.register(cmd);
156
- expect(registry.has('to-remove')).toBe(true);
157
-
158
- const result = registry.unregister('to-remove');
159
-
160
- expect(result).toBe(true);
161
- expect(registry.has('to-remove')).toBe(false);
162
- });
163
-
164
- it('should return false for non-existent command', () => {
165
- const result = registry.unregister('non-existent');
166
- expect(result).toBe(false);
167
- });
168
- });
169
-
170
- describe('get', () => {
171
- it('should return command entry', () => {
172
- const cmd: CommandDefinition = {
173
- name: 'my-cmd',
174
- description: 'My command',
175
- category: 'core',
176
- handler: async () => ({ success: true }),
177
- };
178
-
179
- registry.register(cmd);
180
- const entry = registry.get('my-cmd');
181
-
182
- expect(entry).toBeDefined();
183
- expect(entry?.metadata.name).toBe('my-cmd');
184
- expect(entry?.definition).toBe(cmd);
185
- });
186
-
187
- it('should return undefined for non-existent command', () => {
188
- const entry = registry.get('non-existent');
189
- expect(entry).toBeUndefined();
190
- });
191
- });
192
-
193
- describe('getAll', () => {
194
- it('should return all registered commands', () => {
195
- registry.registerAll([
196
- {
197
- name: 'cmd1',
198
- description: 'C1',
199
- category: 'core',
200
- handler: async () => ({ success: true }),
201
- },
202
- {
203
- name: 'cmd2',
204
- description: 'C2',
205
- category: 'optional',
206
- handler: async () => ({ success: true }),
207
- },
208
- ]);
209
-
210
- const all = registry.getAll();
211
-
212
- expect(all).toHaveLength(2);
213
- });
214
- });
215
-
216
- describe('getAvailable / getUnavailable', () => {
217
- it('should separate available and unavailable commands', () => {
218
- registry.registerAll([
219
- {
220
- name: 'available',
221
- description: 'Available',
222
- category: 'core',
223
- handler: async () => ({ success: true }),
224
- },
225
- {
226
- name: 'unavailable',
227
- description: 'Unavailable',
228
- category: 'optional',
229
- dependencies: [{ type: 'issue_tracker', required: true }],
230
- handler: async () => ({ success: true }),
231
- },
232
- ]);
233
-
234
- const available = registry.getAvailable();
235
- const unavailable = registry.getUnavailable();
236
-
237
- expect(available).toHaveLength(1);
238
- expect(available[0].metadata.name).toBe('available');
239
- expect(unavailable).toHaveLength(1);
240
- expect(unavailable[0].metadata.name).toBe('unavailable');
241
- });
242
- });
243
-
244
- describe('getByCategory', () => {
245
- it('should filter by category', () => {
246
- registry.registerAll([
247
- {
248
- name: 'core1',
249
- description: 'C1',
250
- category: 'core',
251
- handler: async () => ({ success: true }),
252
- },
253
- {
254
- name: 'core2',
255
- description: 'C2',
256
- category: 'core',
257
- handler: async () => ({ success: true }),
258
- },
259
- {
260
- name: 'opt1',
261
- description: 'O1',
262
- category: 'optional',
263
- handler: async () => ({ success: true }),
264
- },
265
- {
266
- name: 'custom1',
267
- description: 'Cu1',
268
- category: 'custom',
269
- handler: async () => ({ success: true }),
270
- },
271
- ]);
272
-
273
- const core = registry.getByCategory('core');
274
- const optional = registry.getByCategory('optional');
275
- const custom = registry.getByCategory('custom');
276
-
277
- expect(core).toHaveLength(2);
278
- expect(optional).toHaveLength(1);
279
- expect(custom).toHaveLength(1);
280
- });
281
- });
282
-
283
- describe('getNames', () => {
284
- it('should return command names', () => {
285
- registry.registerAll([
286
- {
287
- name: 'alpha',
288
- description: 'A',
289
- category: 'core',
290
- handler: async () => ({ success: true }),
291
- },
292
- {
293
- name: 'beta',
294
- description: 'B',
295
- category: 'core',
296
- handler: async () => ({ success: true }),
297
- },
298
- ]);
299
-
300
- const names = registry.getNames();
301
-
302
- expect(names).toContain('alpha');
303
- expect(names).toContain('beta');
304
- });
305
- });
306
-
307
- describe('clear', () => {
308
- it('should remove all commands', () => {
309
- registry.registerAll([
310
- {
311
- name: 'cmd1',
312
- description: 'C1',
313
- category: 'core',
314
- handler: async () => ({ success: true }),
315
- },
316
- {
317
- name: 'cmd2',
318
- description: 'C2',
319
- category: 'core',
320
- handler: async () => ({ success: true }),
321
- },
322
- ]);
323
-
324
- expect(registry.size).toBe(2);
325
-
326
- registry.clear();
327
-
328
- expect(registry.size).toBe(0);
329
- });
330
- });
331
-
332
- describe('getDependencyStatus', () => {
333
- it('should return dependency status', () => {
334
- registry.register({
335
- name: 'cmd-with-deps',
336
- description: 'Has deps',
337
- category: 'optional',
338
- dependencies: [
339
- { type: 'issue_tracker', required: true },
340
- { type: 'documentation', required: false },
341
- ],
342
- handler: async () => ({ success: true }),
343
- });
344
-
345
- const status = registry.getDependencyStatus('cmd-with-deps');
346
-
347
- expect(status).not.toBeNull();
348
- // Only required deps are counted as missing when no adapter factory
349
- expect(status?.missing).toHaveLength(1);
350
- expect(status?.missing[0].type).toBe('issue_tracker');
351
- expect(status?.satisfied).toHaveLength(1); // Optional dep not counted as missing
352
- });
353
-
354
- it('should return null for non-existent command', () => {
355
- const status = registry.getDependencyStatus('non-existent');
356
- expect(status).toBeNull();
357
- });
358
- });
359
-
360
- describe('Global Registry', () => {
361
- it('should return same instance', () => {
362
- const reg1 = getGlobalRegistry();
363
- const reg2 = getGlobalRegistry();
364
-
365
- expect(reg1).toBe(reg2);
366
- });
367
-
368
- it('should reset global registry', () => {
369
- const reg1 = getGlobalRegistry();
370
- reg1.register({
371
- name: 'test',
372
- description: 'Test',
373
- category: 'core',
374
- handler: async () => ({ success: true }),
375
- });
376
-
377
- resetGlobalRegistry();
378
-
379
- const reg2 = getGlobalRegistry();
380
- expect(reg2).not.toBe(reg1);
381
- expect(reg2.size).toBe(0);
382
- });
383
- });
384
- });
@@ -1,248 +0,0 @@
1
- /**
2
- * Command Registry
3
- *
4
- * Central registry for command registration and discovery.
5
- */
6
-
7
- import type {
8
- CommandDefinition,
9
- CommandMetadata,
10
- MarkdownCommand,
11
- RegistryEntry,
12
- CommandCategory,
13
- IntegrationDependency,
14
- } from './types.js';
15
- import type { AdapterFactory } from '../adapters/factory.js';
16
-
17
- /**
18
- * Command Registry
19
- *
20
- * Manages registration and lookup of commands.
21
- */
22
- export class CommandRegistry {
23
- private commands = new Map<string, RegistryEntry>();
24
- private adapterFactory: AdapterFactory | null = null;
25
-
26
- /**
27
- * Set the adapter factory for dependency checking
28
- */
29
- setAdapterFactory(factory: AdapterFactory | null): void {
30
- this.adapterFactory = factory;
31
- // Re-evaluate availability of all commands
32
- this.updateAvailability();
33
- }
34
-
35
- /**
36
- * Register a programmatic command
37
- */
38
- register(definition: CommandDefinition): void {
39
- const metadata: CommandMetadata = {
40
- name: definition.name,
41
- description: definition.description,
42
- category: definition.category,
43
- dependencies: definition.dependencies ?? [],
44
- sourcePath: '<programmatic>',
45
- available: true,
46
- };
47
-
48
- // Check availability
49
- this.checkAvailability(metadata);
50
-
51
- this.commands.set(definition.name, {
52
- metadata,
53
- definition,
54
- source: 'programmatic',
55
- });
56
- }
57
-
58
- /**
59
- * Register a markdown command
60
- */
61
- registerMarkdown(command: MarkdownCommand): void {
62
- // Check availability
63
- this.checkAvailability(command.metadata);
64
-
65
- this.commands.set(command.metadata.name, {
66
- metadata: command.metadata,
67
- markdownCommand: command,
68
- source: 'markdown',
69
- });
70
- }
71
-
72
- /**
73
- * Register multiple commands
74
- */
75
- registerAll(definitions: CommandDefinition[]): void {
76
- for (const def of definitions) {
77
- this.register(def);
78
- }
79
- }
80
-
81
- /**
82
- * Register multiple markdown commands
83
- */
84
- registerAllMarkdown(commands: MarkdownCommand[]): void {
85
- for (const cmd of commands) {
86
- this.registerMarkdown(cmd);
87
- }
88
- }
89
-
90
- /**
91
- * Unregister a command
92
- */
93
- unregister(name: string): boolean {
94
- return this.commands.delete(name);
95
- }
96
-
97
- /**
98
- * Get a command by name
99
- */
100
- get(name: string): RegistryEntry | undefined {
101
- return this.commands.get(name);
102
- }
103
-
104
- /**
105
- * Check if a command exists
106
- */
107
- has(name: string): boolean {
108
- return this.commands.has(name);
109
- }
110
-
111
- /**
112
- * Get all registered commands
113
- */
114
- getAll(): RegistryEntry[] {
115
- return Array.from(this.commands.values());
116
- }
117
-
118
- /**
119
- * Get available commands (dependencies satisfied)
120
- */
121
- getAvailable(): RegistryEntry[] {
122
- return this.getAll().filter((entry) => entry.metadata.available);
123
- }
124
-
125
- /**
126
- * Get unavailable commands
127
- */
128
- getUnavailable(): RegistryEntry[] {
129
- return this.getAll().filter((entry) => !entry.metadata.available);
130
- }
131
-
132
- /**
133
- * Get commands by category
134
- */
135
- getByCategory(category: CommandCategory): RegistryEntry[] {
136
- return this.getAll().filter((entry) => entry.metadata.category === category);
137
- }
138
-
139
- /**
140
- * Get command names
141
- */
142
- getNames(): string[] {
143
- return Array.from(this.commands.keys());
144
- }
145
-
146
- /**
147
- * Clear all registered commands
148
- */
149
- clear(): void {
150
- this.commands.clear();
151
- }
152
-
153
- /**
154
- * Get the number of registered commands
155
- */
156
- get size(): number {
157
- return this.commands.size;
158
- }
159
-
160
- /**
161
- * Check and update availability for a command metadata
162
- */
163
- private checkAvailability(metadata: CommandMetadata): void {
164
- const missingDeps = this.getMissingDependencies(metadata.dependencies);
165
-
166
- if (missingDeps.length > 0) {
167
- const requiredMissing = missingDeps.filter((d) => d.required);
168
- if (requiredMissing.length > 0) {
169
- metadata.available = false;
170
- metadata.unavailableReason = `Missing required integrations: ${requiredMissing.map((d) => d.type).join(', ')}`;
171
- } else {
172
- // Optional deps missing, still available but may degrade
173
- metadata.available = true;
174
- }
175
- } else {
176
- metadata.available = true;
177
- delete metadata.unavailableReason;
178
- }
179
- }
180
-
181
- /**
182
- * Get missing dependencies
183
- */
184
- private getMissingDependencies(dependencies: IntegrationDependency[]): IntegrationDependency[] {
185
- const factory = this.adapterFactory;
186
- if (!factory) {
187
- // No adapter factory, assume all required deps are missing
188
- return dependencies.filter((d) => d.required);
189
- }
190
-
191
- return dependencies.filter((dep) => !factory.hasIntegration(dep.type));
192
- }
193
-
194
- /**
195
- * Update availability for all commands
196
- */
197
- private updateAvailability(): void {
198
- for (const entry of this.commands.values()) {
199
- this.checkAvailability(entry.metadata);
200
- }
201
- }
202
-
203
- /**
204
- * Get dependency status for a command
205
- */
206
- getDependencyStatus(name: string): {
207
- satisfied: IntegrationDependency[];
208
- missing: IntegrationDependency[];
209
- } | null {
210
- const entry = this.commands.get(name);
211
- if (!entry) return null;
212
-
213
- const deps = entry.metadata.dependencies;
214
- const missing = this.getMissingDependencies(deps);
215
- const satisfied = deps.filter((d) => !missing.includes(d));
216
-
217
- return { satisfied, missing };
218
- }
219
- }
220
-
221
- /**
222
- * Create a new command registry
223
- */
224
- export function createCommandRegistry(): CommandRegistry {
225
- return new CommandRegistry();
226
- }
227
-
228
- /**
229
- * Global command registry instance
230
- */
231
- let globalRegistry: CommandRegistry | null = null;
232
-
233
- /**
234
- * Get or create the global command registry
235
- */
236
- export function getGlobalRegistry(): CommandRegistry {
237
- if (!globalRegistry) {
238
- globalRegistry = new CommandRegistry();
239
- }
240
- return globalRegistry;
241
- }
242
-
243
- /**
244
- * Reset the global registry (primarily for testing)
245
- */
246
- export function resetGlobalRegistry(): void {
247
- globalRegistry = null;
248
- }