@deimoscloud/coreai 0.1.9 → 0.1.11

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 +7 -0
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/index.js +7 -0
  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,111 +0,0 @@
1
- /**
2
- * Command Context
3
- *
4
- * Runtime context for command execution with graceful degradation support.
5
- */
6
-
7
- import type { ResolvedCoreAIConfig } from '../config/types.js';
8
- import type { AdapterType } from '../adapters/types.js';
9
- import type { AdapterFactory } from '../adapters/factory.js';
10
- import { createAdapterFactory } from '../adapters/factory.js';
11
- import { loadConfig, configExists } from '../config/loader.js';
12
- import type { CommandContext } from './types.js';
13
-
14
- /**
15
- * Options for creating a command context
16
- */
17
- export interface CreateContextOptions {
18
- /**
19
- * Project root directory
20
- */
21
- projectRoot?: string;
22
-
23
- /**
24
- * Pre-loaded configuration (if already loaded)
25
- */
26
- config?: ResolvedCoreAIConfig;
27
-
28
- /**
29
- * Pre-created adapter factory (if already created)
30
- */
31
- adapterFactory?: AdapterFactory;
32
- }
33
-
34
- /**
35
- * Create a command execution context
36
- *
37
- * Handles configuration loading and adapter factory creation with graceful fallbacks.
38
- */
39
- export function createCommandContext(options: CreateContextOptions = {}): CommandContext {
40
- const projectRoot = options.projectRoot ?? process.cwd();
41
-
42
- // Load config if not provided
43
- let config: ResolvedCoreAIConfig | null = options.config ?? null;
44
- if (!config && configExists(projectRoot)) {
45
- try {
46
- config = loadConfig(projectRoot);
47
- } catch {
48
- // Config loading failed, continue without config
49
- config = null;
50
- }
51
- }
52
-
53
- // Create adapter factory if config is available and factory not provided
54
- let adapterFactory: AdapterFactory | null = options.adapterFactory ?? null;
55
- if (!adapterFactory && config) {
56
- try {
57
- adapterFactory = createAdapterFactory(config);
58
- } catch {
59
- // Factory creation failed, continue without adapters
60
- adapterFactory = null;
61
- }
62
- }
63
-
64
- return {
65
- config,
66
- adapterFactory,
67
- projectRoot,
68
-
69
- hasIntegration(type: AdapterType): boolean {
70
- if (!adapterFactory) return false;
71
- return adapterFactory.hasIntegration(type);
72
- },
73
-
74
- async getAdapterSafe<T>(type: AdapterType): Promise<T | null> {
75
- if (!adapterFactory) return null;
76
- if (!adapterFactory.hasIntegration(type)) return null;
77
-
78
- try {
79
- const adapter = await adapterFactory.getAdapter(type);
80
- return adapter as T;
81
- } catch {
82
- // Adapter creation failed, return null for graceful degradation
83
- return null;
84
- }
85
- },
86
- };
87
- }
88
-
89
- /**
90
- * Cleanup resources in a command context
91
- */
92
- export async function cleanupContext(context: CommandContext): Promise<void> {
93
- if (context.adapterFactory) {
94
- await context.adapterFactory.disconnectAll();
95
- }
96
- }
97
-
98
- /**
99
- * Execute a function with automatic context cleanup
100
- */
101
- export async function withContext<T>(
102
- options: CreateContextOptions,
103
- fn: (context: CommandContext) => Promise<T>
104
- ): Promise<T> {
105
- const context = createCommandContext(options);
106
- try {
107
- return await fn(context);
108
- } finally {
109
- await cleanupContext(context);
110
- }
111
- }
@@ -1,56 +0,0 @@
1
- /**
2
- * Command Framework
3
- *
4
- * Registration, discovery, and execution of CoreAI commands.
5
- */
6
-
7
- // Types
8
- export type {
9
- CommandCategory,
10
- IntegrationDependency,
11
- CommandMetadata,
12
- CommandContext,
13
- BaseCommandOptions,
14
- CommandResult,
15
- CommandHandler,
16
- CommandDefinition,
17
- CommandOptionDefinition,
18
- CommandArgumentDefinition,
19
- MarkdownCommand,
20
- RegistryEntry,
21
- CommandLoaderOptions,
22
- CommandLoadResult,
23
- } from './types.js';
24
-
25
- // Context
26
- export {
27
- createCommandContext,
28
- cleanupContext,
29
- withContext,
30
- type CreateContextOptions,
31
- } from './context.js';
32
-
33
- // Registry
34
- export {
35
- CommandRegistry,
36
- createCommandRegistry,
37
- getGlobalRegistry,
38
- resetGlobalRegistry,
39
- } from './registry.js';
40
-
41
- // Loader
42
- export {
43
- loadCommandFromFile,
44
- loadCommandsFromDirectory,
45
- loadCoreAICommands,
46
- loadAllCommands,
47
- } from './loader.js';
48
-
49
- // Runner
50
- export {
51
- runCommand,
52
- executeWithDegradation,
53
- createDegradingHandler,
54
- StepTracker,
55
- type RunCommandOptions,
56
- } from './runner.js';
@@ -1,273 +0,0 @@
1
- /**
2
- * Command Loader Tests
3
- */
4
-
5
- import { promises as fs } from 'fs';
6
- import { join } from 'path';
7
- import { tmpdir } from 'os';
8
- import { loadCommandFromFile, loadCommandsFromDirectory, loadAllCommands } from './loader.js';
9
-
10
- describe('Command Loader', () => {
11
- let testDir: string;
12
-
13
- beforeEach(async () => {
14
- testDir = join(
15
- tmpdir(),
16
- `cmd-loader-test-${Date.now()}-${Math.random().toString(36).slice(2)}`
17
- );
18
- await fs.mkdir(testDir, { recursive: true });
19
- });
20
-
21
- afterEach(async () => {
22
- try {
23
- await fs.rm(testDir, { recursive: true, force: true });
24
- } catch {
25
- // Ignore cleanup errors
26
- }
27
- });
28
-
29
- describe('loadCommandFromFile', () => {
30
- it('should load command with frontmatter', async () => {
31
- const cmdPath = join(testDir, 'test-command.md');
32
- await fs.writeFile(
33
- cmdPath,
34
- `---
35
- description: A test command
36
- argument-hint: <task>
37
- ---
38
-
39
- # Test Command
40
-
41
- Instructions for the command.
42
- `
43
- );
44
-
45
- const cmd = await loadCommandFromFile(cmdPath, testDir);
46
-
47
- expect(cmd.metadata.name).toBe('test-command');
48
- expect(cmd.metadata.description).toBe('A test command');
49
- expect(cmd.metadata.argumentHint).toBe('<task>');
50
- expect(cmd.sections.title).toBe('Test Command');
51
- });
52
-
53
- it('should load command without frontmatter', async () => {
54
- const cmdPath = join(testDir, 'simple.md');
55
- await fs.writeFile(cmdPath, '# Simple Command\n\nJust instructions.');
56
-
57
- const cmd = await loadCommandFromFile(cmdPath, testDir);
58
-
59
- expect(cmd.metadata.name).toBe('simple');
60
- expect(cmd.metadata.description).toBe('Simple Command');
61
- expect(cmd.content).toContain('Just instructions');
62
- });
63
-
64
- it('should parse dependencies from frontmatter', async () => {
65
- const cmdPath = join(testDir, 'with-deps.md');
66
- await fs.writeFile(
67
- cmdPath,
68
- `---
69
- description: Command with deps
70
- requires: [jira, github]
71
- optional: [confluence]
72
- ---
73
-
74
- # With Dependencies
75
- `
76
- );
77
-
78
- const cmd = await loadCommandFromFile(cmdPath, testDir);
79
-
80
- expect(cmd.metadata.dependencies).toHaveLength(3);
81
-
82
- const jiraDep = cmd.metadata.dependencies.find((d) => d.type === 'issue_tracker');
83
- expect(jiraDep?.required).toBe(true);
84
-
85
- const gitDep = cmd.metadata.dependencies.find((d) => d.type === 'git');
86
- expect(gitDep?.required).toBe(true);
87
-
88
- const docsDep = cmd.metadata.dependencies.find((d) => d.type === 'documentation');
89
- expect(docsDep?.required).toBe(false);
90
- });
91
-
92
- it('should extract sections from markdown', async () => {
93
- const cmdPath = join(testDir, 'sectioned.md');
94
- await fs.writeFile(
95
- cmdPath,
96
- `---
97
- description: Sectioned command
98
- ---
99
-
100
- # Sectioned Command
101
-
102
- ## Instructions
103
-
104
- Do this thing.
105
-
106
- ## Fallbacks
107
-
108
- If integration missing, do this instead.
109
-
110
- ## Output Format
111
-
112
- Return JSON.
113
- `
114
- );
115
-
116
- const cmd = await loadCommandFromFile(cmdPath, testDir);
117
-
118
- expect(cmd.sections.title).toBe('Sectioned Command');
119
- expect(cmd.sections.instructions).toContain('Do this thing');
120
- expect(cmd.sections.fallbacks).toContain('integration missing');
121
- expect(cmd.sections.outputFormat).toContain('JSON');
122
- });
123
-
124
- it('should derive category from path', async () => {
125
- // Create core subdirectory
126
- const coreDir = join(testDir, 'core');
127
- await fs.mkdir(coreDir, { recursive: true });
128
- const corePath = join(coreDir, 'core-cmd.md');
129
- await fs.writeFile(corePath, '# Core Command');
130
-
131
- // Create optional subdirectory
132
- const optDir = join(testDir, 'optional');
133
- await fs.mkdir(optDir, { recursive: true });
134
- const optPath = join(optDir, 'opt-cmd.md');
135
- await fs.writeFile(optPath, '# Optional Command');
136
-
137
- const coreCmd = await loadCommandFromFile(corePath, testDir);
138
- const optCmd = await loadCommandFromFile(optPath, testDir);
139
-
140
- expect(coreCmd.metadata.category).toBe('core');
141
- expect(optCmd.metadata.category).toBe('optional');
142
- });
143
-
144
- it('should use category override', async () => {
145
- const cmdPath = join(testDir, 'cmd.md');
146
- await fs.writeFile(cmdPath, '# Command');
147
-
148
- const cmd = await loadCommandFromFile(cmdPath, testDir, 'custom');
149
-
150
- expect(cmd.metadata.category).toBe('custom');
151
- });
152
- });
153
-
154
- describe('loadCommandsFromDirectory', () => {
155
- it('should load all markdown files', async () => {
156
- await fs.writeFile(join(testDir, 'cmd1.md'), '# Command 1');
157
- await fs.writeFile(join(testDir, 'cmd2.md'), '# Command 2');
158
- await fs.writeFile(join(testDir, 'not-md.txt'), 'Not a command');
159
-
160
- const result = await loadCommandsFromDirectory({
161
- directory: testDir,
162
- category: 'core',
163
- });
164
-
165
- expect(result.loaded).toHaveLength(2);
166
- expect(result.errors).toHaveLength(0);
167
- expect(result.loaded.map((c) => c.metadata.name)).toContain('cmd1');
168
- expect(result.loaded.map((c) => c.metadata.name)).toContain('cmd2');
169
- });
170
-
171
- it('should load recursively by default', async () => {
172
- await fs.writeFile(join(testDir, 'root.md'), '# Root');
173
-
174
- const subDir = join(testDir, 'sub');
175
- await fs.mkdir(subDir, { recursive: true });
176
- await fs.writeFile(join(subDir, 'nested.md'), '# Nested');
177
-
178
- const result = await loadCommandsFromDirectory({
179
- directory: testDir,
180
- category: 'core',
181
- recursive: true,
182
- });
183
-
184
- expect(result.loaded).toHaveLength(2);
185
- });
186
-
187
- it('should not load recursively when disabled', async () => {
188
- await fs.writeFile(join(testDir, 'root.md'), '# Root');
189
-
190
- const subDir = join(testDir, 'sub');
191
- await fs.mkdir(subDir, { recursive: true });
192
- await fs.writeFile(join(subDir, 'nested.md'), '# Nested');
193
-
194
- const result = await loadCommandsFromDirectory({
195
- directory: testDir,
196
- category: 'core',
197
- recursive: false,
198
- });
199
-
200
- expect(result.loaded).toHaveLength(1);
201
- expect(result.loaded[0].metadata.name).toBe('root');
202
- });
203
-
204
- it('should apply filter', async () => {
205
- await fs.writeFile(join(testDir, 'include-me.md'), '# Include');
206
- await fs.writeFile(join(testDir, 'exclude-me.md'), '# Exclude');
207
-
208
- const result = await loadCommandsFromDirectory({
209
- directory: testDir,
210
- category: 'core',
211
- filter: (metadata) => metadata.name.startsWith('include'),
212
- });
213
-
214
- expect(result.loaded).toHaveLength(1);
215
- expect(result.loaded[0].metadata.name).toBe('include-me');
216
- });
217
-
218
- it('should handle non-existent directory', async () => {
219
- const result = await loadCommandsFromDirectory({
220
- directory: join(testDir, 'non-existent'),
221
- category: 'core',
222
- });
223
-
224
- expect(result.loaded).toHaveLength(0);
225
- expect(result.errors).toHaveLength(0);
226
- });
227
-
228
- it('should handle directories with .md extension gracefully', async () => {
229
- // Create a valid file
230
- await fs.writeFile(join(testDir, 'valid.md'), '# Valid');
231
-
232
- // Create a directory with .md name (should be skipped, not errored)
233
- await fs.mkdir(join(testDir, 'not-a-file.md'), { recursive: true });
234
-
235
- const result = await loadCommandsFromDirectory({
236
- directory: testDir,
237
- category: 'core',
238
- recursive: false,
239
- });
240
-
241
- // Only the valid file should be loaded, directory should be ignored
242
- expect(result.loaded).toHaveLength(1);
243
- expect(result.loaded[0].metadata.name).toBe('valid');
244
- expect(result.errors).toHaveLength(0);
245
- });
246
- });
247
-
248
- describe('loadAllCommands', () => {
249
- it('should load from multiple directories', async () => {
250
- const coreDir = join(testDir, 'core');
251
- const customDir = join(testDir, 'custom');
252
- await fs.mkdir(coreDir, { recursive: true });
253
- await fs.mkdir(customDir, { recursive: true });
254
-
255
- await fs.writeFile(join(coreDir, 'core-cmd.md'), '# Core');
256
- await fs.writeFile(join(customDir, 'custom-cmd.md'), '# Custom');
257
-
258
- const result = await loadAllCommands(coreDir, customDir);
259
-
260
- expect(result.loaded).toHaveLength(2);
261
- });
262
-
263
- it('should work without custom directory', async () => {
264
- const coreDir = join(testDir, 'core');
265
- await fs.mkdir(coreDir, { recursive: true });
266
- await fs.writeFile(join(coreDir, 'cmd.md'), '# Command');
267
-
268
- const result = await loadAllCommands(coreDir);
269
-
270
- expect(result.loaded).toHaveLength(1);
271
- });
272
- });
273
- });