@deimoscloud/coreai 0.1.8 → 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.
- package/dist/cli/index.js +5 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
- package/.prettierrc +0 -9
- package/AGENT_SPEC.md +0 -347
- package/ARCHITECTURE.md +0 -547
- package/DRAFT_PRD.md +0 -1440
- package/IMPLEMENTATION_PLAN.md +0 -256
- package/PRODUCT.md +0 -473
- package/WORKFLOWS.md +0 -295
- package/commands/core/check-inbox.md +0 -34
- package/commands/core/delegate.md +0 -30
- package/commands/core/git-commit.md +0 -144
- package/commands/core/pr-create.md +0 -193
- package/commands/core/review.md +0 -56
- package/commands/core/sprint-status.md +0 -65
- package/commands/optional/docs-update.md +0 -200
- package/commands/optional/jira-create.md +0 -200
- package/commands/optional/jira-transition.md +0 -184
- package/commands/optional/worktree-cleanup.md +0 -167
- package/commands/optional/worktree-setup.md +0 -110
- package/eslint.config.js +0 -29
- package/jest.config.js +0 -22
- package/knowledge-library/README.md +0 -118
- package/knowledge-library/android-engineer/context/current.txt +0 -42
- package/knowledge-library/android-engineer/control/decisions.txt +0 -9
- package/knowledge-library/android-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/android-engineer/control/objectives.txt +0 -26
- package/knowledge-library/android-engineer/history/.gitkeep +0 -0
- package/knowledge-library/android-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/android-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/android-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/architecture.txt +0 -61
- package/knowledge-library/backend-engineer/context/current.txt +0 -42
- package/knowledge-library/backend-engineer/control/decisions.txt +0 -9
- package/knowledge-library/backend-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/backend-engineer/control/objectives.txt +0 -26
- package/knowledge-library/backend-engineer/history/.gitkeep +0 -0
- package/knowledge-library/backend-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/backend-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/backend-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/context.txt +0 -52
- package/knowledge-library/devops-engineer/context/current.txt +0 -42
- package/knowledge-library/devops-engineer/control/decisions.txt +0 -9
- package/knowledge-library/devops-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/devops-engineer/control/objectives.txt +0 -26
- package/knowledge-library/devops-engineer/history/.gitkeep +0 -0
- package/knowledge-library/devops-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/devops-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/devops-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/context/current.txt +0 -40
- package/knowledge-library/engineering-manager/control/decisions.txt +0 -9
- package/knowledge-library/engineering-manager/control/objectives.txt +0 -27
- package/knowledge-library/engineering-manager/history/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/outbox/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/tech/.gitkeep +0 -0
- package/knowledge-library/prd.txt +0 -81
- package/knowledge-library/product-manager/context/current.txt +0 -42
- package/knowledge-library/product-manager/control/decisions.txt +0 -9
- package/knowledge-library/product-manager/control/dependencies.txt +0 -19
- package/knowledge-library/product-manager/control/objectives.txt +0 -26
- package/knowledge-library/product-manager/history/.gitkeep +0 -0
- package/knowledge-library/product-manager/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/product-manager/outbox/.gitkeep +0 -0
- package/knowledge-library/product-manager/tech/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/context/current.txt +0 -42
- package/knowledge-library/qa-engineer/control/decisions.txt +0 -9
- package/knowledge-library/qa-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/qa-engineer/control/objectives.txt +0 -26
- package/knowledge-library/qa-engineer/history/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/security-engineer/context/current.txt +0 -42
- package/knowledge-library/security-engineer/control/decisions.txt +0 -9
- package/knowledge-library/security-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/security-engineer/control/objectives.txt +0 -26
- package/knowledge-library/security-engineer/history/.gitkeep +0 -0
- package/knowledge-library/security-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/security-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/security-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/context/current.txt +0 -42
- package/knowledge-library/solutions-architect/control/decisions.txt +0 -9
- package/knowledge-library/solutions-architect/control/dependencies.txt +0 -19
- package/knowledge-library/solutions-architect/control/objectives.txt +0 -26
- package/knowledge-library/solutions-architect/history/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/outbox/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/tech/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/context/current.txt +0 -42
- package/knowledge-library/wearos-engineer/control/decisions.txt +0 -9
- package/knowledge-library/wearos-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/wearos-engineer/control/objectives.txt +0 -26
- package/knowledge-library/wearos-engineer/history/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/tech/.gitkeep +0 -0
- package/scripts/add-agent.sh +0 -323
- package/scripts/install.sh +0 -354
- package/src/adapters/factory.test.ts +0 -386
- package/src/adapters/factory.ts +0 -305
- package/src/adapters/index.ts +0 -113
- package/src/adapters/interfaces.ts +0 -268
- package/src/adapters/mcp/client.test.ts +0 -130
- package/src/adapters/mcp/client.ts +0 -451
- package/src/adapters/mcp/discovery.test.ts +0 -315
- package/src/adapters/mcp/discovery.ts +0 -340
- package/src/adapters/mcp/index.ts +0 -66
- package/src/adapters/mcp/mapper.test.ts +0 -218
- package/src/adapters/mcp/mapper.ts +0 -536
- package/src/adapters/mcp/registry.test.ts +0 -433
- package/src/adapters/mcp/registry.ts +0 -550
- package/src/adapters/mcp/types.ts +0 -258
- package/src/adapters/native/filesystem.test.ts +0 -350
- package/src/adapters/native/filesystem.ts +0 -393
- package/src/adapters/native/github.test.ts +0 -173
- package/src/adapters/native/github.ts +0 -627
- package/src/adapters/native/index.ts +0 -22
- package/src/adapters/native/selector.test.ts +0 -224
- package/src/adapters/native/selector.ts +0 -150
- package/src/adapters/types.ts +0 -270
- package/src/agents/compiler.test.ts +0 -399
- package/src/agents/compiler.ts +0 -422
- package/src/agents/index.ts +0 -37
- package/src/agents/loader.test.ts +0 -319
- package/src/agents/loader.ts +0 -143
- package/src/agents/resolver.test.ts +0 -282
- package/src/agents/resolver.ts +0 -262
- package/src/agents/types.ts +0 -97
- package/src/cache/index.ts +0 -38
- package/src/cache/interfaces.ts +0 -283
- package/src/cache/manager.test.ts +0 -266
- package/src/cache/manager.ts +0 -388
- package/src/cache/provider.test.ts +0 -485
- package/src/cache/provider.ts +0 -745
- package/src/cache/types.test.ts +0 -192
- package/src/cache/types.ts +0 -313
- package/src/cli/commands/build.test.ts +0 -248
- package/src/cli/commands/build.ts +0 -284
- package/src/cli/commands/cache.test.ts +0 -221
- package/src/cli/commands/cache.ts +0 -229
- package/src/cli/commands/index.ts +0 -63
- package/src/cli/commands/init.test.ts +0 -173
- package/src/cli/commands/init.ts +0 -296
- package/src/cli/commands/skills.test.ts +0 -272
- package/src/cli/commands/skills.ts +0 -348
- package/src/cli/commands/status.test.ts +0 -392
- package/src/cli/commands/status.ts +0 -332
- package/src/cli/commands/sync.test.ts +0 -213
- package/src/cli/commands/sync.ts +0 -251
- package/src/cli/commands/validate.test.ts +0 -216
- package/src/cli/commands/validate.ts +0 -340
- package/src/cli/index.test.ts +0 -190
- package/src/cli/index.ts +0 -493
- package/src/commands/context.test.ts +0 -163
- package/src/commands/context.ts +0 -111
- package/src/commands/index.ts +0 -56
- package/src/commands/loader.test.ts +0 -273
- package/src/commands/loader.ts +0 -355
- package/src/commands/registry.test.ts +0 -384
- package/src/commands/registry.ts +0 -248
- package/src/commands/runner.test.ts +0 -297
- package/src/commands/runner.ts +0 -222
- package/src/commands/types.ts +0 -361
- package/src/config/index.ts +0 -19
- package/src/config/loader.test.ts +0 -262
- package/src/config/loader.ts +0 -188
- package/src/config/types.ts +0 -154
- package/src/context/index.ts +0 -14
- package/src/context/loader.test.ts +0 -334
- package/src/context/loader.ts +0 -357
- package/src/index.test.ts +0 -13
- package/src/index.ts +0 -268
- package/src/knowledge-library/index.ts +0 -44
- package/src/knowledge-library/manager.test.ts +0 -536
- package/src/knowledge-library/manager.ts +0 -804
- package/src/knowledge-library/types.ts +0 -432
- package/src/skills/generator.test.ts +0 -602
- package/src/skills/generator.ts +0 -491
- package/src/skills/index.ts +0 -27
- package/src/skills/templates.ts +0 -520
- package/src/skills/types.ts +0 -251
- package/templates/completion-report.md +0 -72
- package/templates/feedback.md +0 -56
- package/templates/project-files/CLAUDE.md.template +0 -109
- package/templates/project-files/coreai.json.example +0 -47
- package/templates/project-files/mcp.json.template +0 -20
- package/templates/review-complete.md +0 -64
- package/templates/review-request.md +0 -67
- package/templates/task-assignment.md +0 -51
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -26
- package/tsup.config.ts +0 -23
package/src/cli/commands/init.ts
DELETED
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Init Command
|
|
3
|
-
*
|
|
4
|
-
* Initializes a new CoreAI project with configuration file and directory structure.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { existsSync, writeFileSync, mkdirSync, readFileSync } from 'fs';
|
|
8
|
-
import { join, basename } from 'path';
|
|
9
|
-
import { execSync } from 'child_process';
|
|
10
|
-
import type { ProjectType, GitProvider } from '../../config/types.js';
|
|
11
|
-
import { configExists } from '../../config/loader.js';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Options for init command
|
|
15
|
-
*/
|
|
16
|
-
export interface InitCommandOptions {
|
|
17
|
-
/**
|
|
18
|
-
* Project root directory
|
|
19
|
-
*/
|
|
20
|
-
projectRoot?: string;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Overwrite existing configuration
|
|
24
|
-
*/
|
|
25
|
-
force?: boolean;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Skip interactive prompts
|
|
29
|
-
*/
|
|
30
|
-
nonInteractive?: boolean;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Project name (for non-interactive mode)
|
|
34
|
-
*/
|
|
35
|
-
name?: string;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Project type (for non-interactive mode)
|
|
39
|
-
*/
|
|
40
|
-
type?: ProjectType;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Skip creating directory structure
|
|
44
|
-
*/
|
|
45
|
-
skipDirs?: boolean;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Result of init command
|
|
50
|
-
*/
|
|
51
|
-
export interface InitCommandResult {
|
|
52
|
-
success: boolean;
|
|
53
|
-
configPath?: string;
|
|
54
|
-
createdDirs?: string[];
|
|
55
|
-
error?: string;
|
|
56
|
-
gitInfo?: {
|
|
57
|
-
provider?: GitProvider;
|
|
58
|
-
owner?: string;
|
|
59
|
-
repo?: string;
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Detect git remote information
|
|
65
|
-
*/
|
|
66
|
-
function detectGitInfo(): { provider?: GitProvider; owner?: string; repo?: string } | null {
|
|
67
|
-
try {
|
|
68
|
-
const remoteUrl = execSync('git remote get-url origin', { encoding: 'utf-8' }).trim();
|
|
69
|
-
|
|
70
|
-
// GitHub HTTPS: https://github.com/owner/repo.git
|
|
71
|
-
const httpsMatch = remoteUrl.match(/https:\/\/github\.com\/([^/]+)\/([^/.]+)/);
|
|
72
|
-
if (httpsMatch) {
|
|
73
|
-
return { provider: 'github', owner: httpsMatch[1], repo: httpsMatch[2] };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// GitHub SSH: git@github.com:owner/repo.git
|
|
77
|
-
const sshMatch = remoteUrl.match(/git@github\.com:([^/]+)\/([^/.]+)/);
|
|
78
|
-
if (sshMatch) {
|
|
79
|
-
return { provider: 'github', owner: sshMatch[1], repo: sshMatch[2] };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// GitLab HTTPS
|
|
83
|
-
const gitlabHttps = remoteUrl.match(/https:\/\/gitlab\.com\/([^/]+)\/([^/.]+)/);
|
|
84
|
-
if (gitlabHttps) {
|
|
85
|
-
return { provider: 'gitlab', owner: gitlabHttps[1], repo: gitlabHttps[2] };
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// GitLab SSH
|
|
89
|
-
const gitlabSsh = remoteUrl.match(/git@gitlab\.com:([^/]+)\/([^/.]+)/);
|
|
90
|
-
if (gitlabSsh) {
|
|
91
|
-
return { provider: 'gitlab', owner: gitlabSsh[1], repo: gitlabSsh[2] };
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return null;
|
|
95
|
-
} catch {
|
|
96
|
-
// Not a git repo or no remote
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Detect project name from directory or package.json
|
|
103
|
-
*/
|
|
104
|
-
function detectProjectName(projectRoot: string): string {
|
|
105
|
-
// Try package.json first
|
|
106
|
-
const packageJsonPath = join(projectRoot, 'package.json');
|
|
107
|
-
if (existsSync(packageJsonPath)) {
|
|
108
|
-
try {
|
|
109
|
-
const content = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as { name?: string };
|
|
110
|
-
if (content.name) {
|
|
111
|
-
return content.name;
|
|
112
|
-
}
|
|
113
|
-
} catch {
|
|
114
|
-
// Ignore parse errors
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Fall back to directory name
|
|
119
|
-
return basename(projectRoot);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Generate config file content
|
|
124
|
-
*/
|
|
125
|
-
function generateConfigYaml(options: {
|
|
126
|
-
name: string;
|
|
127
|
-
type: ProjectType;
|
|
128
|
-
gitInfo?: { provider?: GitProvider; owner?: string; repo?: string } | null;
|
|
129
|
-
}): string {
|
|
130
|
-
let yaml = `# CoreAI Configuration
|
|
131
|
-
# See https://coreai.dev/docs/config for full schema
|
|
132
|
-
|
|
133
|
-
version: "1.0"
|
|
134
|
-
|
|
135
|
-
project:
|
|
136
|
-
name: "${options.name}"
|
|
137
|
-
type: ${options.type}
|
|
138
|
-
|
|
139
|
-
team:
|
|
140
|
-
agents:
|
|
141
|
-
- backend-engineer
|
|
142
|
-
- frontend-engineer
|
|
143
|
-
- devops-engineer
|
|
144
|
-
- engineering-manager
|
|
145
|
-
`;
|
|
146
|
-
|
|
147
|
-
if (options.gitInfo?.provider) {
|
|
148
|
-
yaml += `
|
|
149
|
-
integrations:
|
|
150
|
-
git:
|
|
151
|
-
provider: ${options.gitInfo.provider}
|
|
152
|
-
config:
|
|
153
|
-
owner: "${options.gitInfo.owner}"
|
|
154
|
-
repo: "${options.gitInfo.repo}"
|
|
155
|
-
`;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
yaml += `
|
|
159
|
-
# quality_gates:
|
|
160
|
-
# lint:
|
|
161
|
-
# command: npm run lint
|
|
162
|
-
# required: true
|
|
163
|
-
# test:
|
|
164
|
-
# command: npm test
|
|
165
|
-
# required: true
|
|
166
|
-
# build:
|
|
167
|
-
# command: npm run build
|
|
168
|
-
# required: true
|
|
169
|
-
|
|
170
|
-
# tech_stack:
|
|
171
|
-
# primary_language: typescript
|
|
172
|
-
# frameworks:
|
|
173
|
-
# - node.js
|
|
174
|
-
# - express
|
|
175
|
-
`;
|
|
176
|
-
|
|
177
|
-
return yaml;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Create directory structure for CoreAI
|
|
182
|
-
*/
|
|
183
|
-
function createDirectories(projectRoot: string): string[] {
|
|
184
|
-
const dirs = [
|
|
185
|
-
join(projectRoot, 'coreai', 'agents'),
|
|
186
|
-
join(projectRoot, 'coreai', 'commands'),
|
|
187
|
-
join(projectRoot, '.coreai', 'cache'),
|
|
188
|
-
];
|
|
189
|
-
|
|
190
|
-
const created: string[] = [];
|
|
191
|
-
|
|
192
|
-
for (const dir of dirs) {
|
|
193
|
-
if (!existsSync(dir)) {
|
|
194
|
-
mkdirSync(dir, { recursive: true });
|
|
195
|
-
created.push(dir);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return created;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Initialize a new CoreAI project
|
|
204
|
-
*/
|
|
205
|
-
export function init(options: InitCommandOptions = {}): InitCommandResult {
|
|
206
|
-
const projectRoot = options.projectRoot ?? process.cwd();
|
|
207
|
-
|
|
208
|
-
// Check if config already exists
|
|
209
|
-
if (configExists(projectRoot) && !options.force) {
|
|
210
|
-
return {
|
|
211
|
-
success: false,
|
|
212
|
-
error: 'CoreAI configuration already exists. Use --force to overwrite.',
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Detect git info
|
|
217
|
-
const gitInfo = detectGitInfo();
|
|
218
|
-
|
|
219
|
-
// Determine project name
|
|
220
|
-
const name = options.name ?? detectProjectName(projectRoot);
|
|
221
|
-
|
|
222
|
-
// Determine project type
|
|
223
|
-
const type = options.type ?? 'software';
|
|
224
|
-
|
|
225
|
-
// Generate config
|
|
226
|
-
const configContent = generateConfigYaml({ name, type, gitInfo });
|
|
227
|
-
|
|
228
|
-
// Write config file
|
|
229
|
-
const configPath = join(projectRoot, 'coreai.config.yaml');
|
|
230
|
-
try {
|
|
231
|
-
writeFileSync(configPath, configContent, 'utf-8');
|
|
232
|
-
} catch (error) {
|
|
233
|
-
return {
|
|
234
|
-
success: false,
|
|
235
|
-
error: `Failed to write config file: ${error instanceof Error ? error.message : String(error)}`,
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Create directories unless skipped
|
|
240
|
-
let createdDirs: string[] = [];
|
|
241
|
-
if (!options.skipDirs) {
|
|
242
|
-
try {
|
|
243
|
-
createdDirs = createDirectories(projectRoot);
|
|
244
|
-
} catch (error) {
|
|
245
|
-
return {
|
|
246
|
-
success: false,
|
|
247
|
-
configPath,
|
|
248
|
-
error: `Failed to create directories: ${error instanceof Error ? error.message : String(error)}`,
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return {
|
|
254
|
-
success: true,
|
|
255
|
-
configPath,
|
|
256
|
-
createdDirs,
|
|
257
|
-
gitInfo: gitInfo ?? undefined,
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Format init result for display
|
|
263
|
-
*/
|
|
264
|
-
export function formatInitResult(result: InitCommandResult): string {
|
|
265
|
-
if (!result.success) {
|
|
266
|
-
return `Error: ${result.error}`;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const lines: string[] = [];
|
|
270
|
-
|
|
271
|
-
lines.push('CoreAI project initialized successfully!\n');
|
|
272
|
-
|
|
273
|
-
if (result.configPath) {
|
|
274
|
-
lines.push(`Created: ${result.configPath}`);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
if (result.createdDirs && result.createdDirs.length > 0) {
|
|
278
|
-
lines.push('\nCreated directories:');
|
|
279
|
-
for (const dir of result.createdDirs) {
|
|
280
|
-
lines.push(` - ${dir}`);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
if (result.gitInfo?.provider) {
|
|
285
|
-
lines.push(
|
|
286
|
-
`\nDetected ${result.gitInfo.provider} repository: ${result.gitInfo.owner}/${result.gitInfo.repo}`
|
|
287
|
-
);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
lines.push('\nNext steps:');
|
|
291
|
-
lines.push(' 1. Edit coreai.config.yaml to configure your project');
|
|
292
|
-
lines.push(' 2. Run `coreai build` to compile agents');
|
|
293
|
-
lines.push(' 3. Run `coreai validate` to check your setup');
|
|
294
|
-
|
|
295
|
-
return lines.join('\n');
|
|
296
|
-
}
|
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skills Command Tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { promises as fs } from 'fs';
|
|
6
|
-
import { join } from 'path';
|
|
7
|
-
import { tmpdir } from 'os';
|
|
8
|
-
import {
|
|
9
|
-
skillsGenerate,
|
|
10
|
-
formatSkillsGenerateResult,
|
|
11
|
-
skillsList,
|
|
12
|
-
formatSkillsListResult,
|
|
13
|
-
} from './skills.js';
|
|
14
|
-
|
|
15
|
-
describe('Skills Command', () => {
|
|
16
|
-
let testDir: string;
|
|
17
|
-
|
|
18
|
-
beforeEach(async () => {
|
|
19
|
-
testDir = join(
|
|
20
|
-
tmpdir(),
|
|
21
|
-
`skills-cmd-test-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
22
|
-
);
|
|
23
|
-
await fs.mkdir(testDir, { recursive: true });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
afterEach(async () => {
|
|
27
|
-
try {
|
|
28
|
-
await fs.rm(testDir, { recursive: true, force: true });
|
|
29
|
-
} catch {
|
|
30
|
-
// Ignore cleanup errors
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
describe('skillsGenerate', () => {
|
|
35
|
-
it('should generate skills with defaults', () => {
|
|
36
|
-
const result = skillsGenerate({
|
|
37
|
-
projectRoot: testDir,
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
expect(result.success).toBe(true);
|
|
41
|
-
expect(result.result).toBeDefined();
|
|
42
|
-
expect(result.result?.generated.length).toBeGreaterThan(0);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should generate skills without config', () => {
|
|
46
|
-
const result = skillsGenerate({
|
|
47
|
-
projectRoot: testDir,
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
expect(result.success).toBe(true);
|
|
51
|
-
expect(result.warnings).toContain(
|
|
52
|
-
'No configuration file found. Generating skills with defaults.'
|
|
53
|
-
);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('should generate only core skills', () => {
|
|
57
|
-
const result = skillsGenerate({
|
|
58
|
-
projectRoot: testDir,
|
|
59
|
-
includeCoreSkills: true,
|
|
60
|
-
includeOptionalSkills: false,
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
expect(result.success).toBe(true);
|
|
64
|
-
const generated = result.result?.generated ?? [];
|
|
65
|
-
expect(generated.every((g) => g.category === 'core')).toBe(true);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('should generate specific skills', () => {
|
|
69
|
-
const result = skillsGenerate({
|
|
70
|
-
projectRoot: testDir,
|
|
71
|
-
skills: ['check-inbox', 'delegate'],
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
expect(result.success).toBe(true);
|
|
75
|
-
expect(result.result?.generated).toHaveLength(2);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('should fail with invalid config', async () => {
|
|
79
|
-
// Create invalid config
|
|
80
|
-
await fs.writeFile(join(testDir, 'coreai.config.yaml'), 'invalid: yaml: syntax:::');
|
|
81
|
-
|
|
82
|
-
const result = skillsGenerate({
|
|
83
|
-
projectRoot: testDir,
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
expect(result.success).toBe(false);
|
|
87
|
-
expect(result.error).toContain('Configuration error');
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('should use custom output directory', async () => {
|
|
91
|
-
const customOutputDir = join(testDir, 'custom', 'skills');
|
|
92
|
-
|
|
93
|
-
const result = skillsGenerate({
|
|
94
|
-
projectRoot: testDir,
|
|
95
|
-
outputDir: customOutputDir,
|
|
96
|
-
skills: ['check-inbox'],
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
expect(result.success).toBe(true);
|
|
100
|
-
|
|
101
|
-
// Verify file created in custom directory
|
|
102
|
-
const stat = await fs.stat(join(customOutputDir, 'check-inbox.md'));
|
|
103
|
-
expect(stat.isFile()).toBe(true);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it('should pass custom variables', () => {
|
|
107
|
-
const result = skillsGenerate({
|
|
108
|
-
projectRoot: testDir,
|
|
109
|
-
skills: ['check-inbox'],
|
|
110
|
-
variables: {
|
|
111
|
-
CUSTOM_VAR: 'custom-value',
|
|
112
|
-
},
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
expect(result.success).toBe(true);
|
|
116
|
-
expect(result.result?.variables.CUSTOM_VAR).toBe('custom-value');
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
describe('formatSkillsGenerateResult', () => {
|
|
121
|
-
it('should format success result', () => {
|
|
122
|
-
const result = skillsGenerate({
|
|
123
|
-
projectRoot: testDir,
|
|
124
|
-
skills: ['check-inbox'],
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
const output = formatSkillsGenerateResult(result);
|
|
128
|
-
expect(output).toContain('Created');
|
|
129
|
-
expect(output).toContain('check-inbox');
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it('should format error result', () => {
|
|
133
|
-
const result = {
|
|
134
|
-
success: false,
|
|
135
|
-
error: 'Something went wrong',
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
const output = formatSkillsGenerateResult(result);
|
|
139
|
-
expect(output).toContain('failed');
|
|
140
|
-
expect(output).toContain('Something went wrong');
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('should include warnings', () => {
|
|
144
|
-
const result = skillsGenerate({
|
|
145
|
-
projectRoot: testDir,
|
|
146
|
-
skills: ['check-inbox'],
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
const output = formatSkillsGenerateResult(result);
|
|
150
|
-
// Should show warning about missing config
|
|
151
|
-
expect(output.includes('warning') || output.includes('No configuration')).toBe(false);
|
|
152
|
-
// This should have the created message
|
|
153
|
-
expect(output).toContain('Created');
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
describe('skillsList', () => {
|
|
158
|
-
it('should list all built-in skills', () => {
|
|
159
|
-
const result = skillsList();
|
|
160
|
-
|
|
161
|
-
expect(result.success).toBe(true);
|
|
162
|
-
expect(result.skills).toBeDefined();
|
|
163
|
-
expect(result.skills?.length).toBeGreaterThan(0);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it('should list only core skills', () => {
|
|
167
|
-
const result = skillsList({
|
|
168
|
-
includeCoreSkills: true,
|
|
169
|
-
includeOptionalSkills: false,
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
expect(result.success).toBe(true);
|
|
173
|
-
expect(result.skills?.every((s) => s.category === 'core')).toBe(true);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('should list only optional skills', () => {
|
|
177
|
-
const result = skillsList({
|
|
178
|
-
includeCoreSkills: false,
|
|
179
|
-
includeOptionalSkills: true,
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
expect(result.success).toBe(true);
|
|
183
|
-
expect(result.skills?.every((s) => s.category === 'optional')).toBe(true);
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
it('should include skill metadata', () => {
|
|
187
|
-
const result = skillsList();
|
|
188
|
-
|
|
189
|
-
expect(result.success).toBe(true);
|
|
190
|
-
const skill = result.skills?.[0];
|
|
191
|
-
expect(skill?.name).toBeDefined();
|
|
192
|
-
expect(skill?.description).toBeDefined();
|
|
193
|
-
expect(skill?.category).toBeDefined();
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it('should load custom templates when directory provided', async () => {
|
|
197
|
-
const customDir = join(testDir, 'templates');
|
|
198
|
-
await fs.mkdir(customDir, { recursive: true });
|
|
199
|
-
await fs.writeFile(
|
|
200
|
-
join(customDir, 'custom-skill.md'),
|
|
201
|
-
'---\ndescription: My custom skill\n---\nContent'
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
const result = skillsList({
|
|
205
|
-
customTemplatesDir: customDir,
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
expect(result.success).toBe(true);
|
|
209
|
-
const customSkill = result.skills?.find((s) => s.name === 'custom-skill');
|
|
210
|
-
expect(customSkill).toBeDefined();
|
|
211
|
-
expect(customSkill?.description).toBe('My custom skill');
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
describe('formatSkillsListResult', () => {
|
|
216
|
-
it('should format skills list', () => {
|
|
217
|
-
const result = skillsList();
|
|
218
|
-
const output = formatSkillsListResult(result);
|
|
219
|
-
|
|
220
|
-
expect(output).toContain('Available skills');
|
|
221
|
-
expect(output).toContain('Core skills');
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it('should format error result', () => {
|
|
225
|
-
const result = {
|
|
226
|
-
success: false,
|
|
227
|
-
error: 'Failed to list skills',
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
const output = formatSkillsListResult(result);
|
|
231
|
-
expect(output).toContain('Error');
|
|
232
|
-
expect(output).toContain('Failed to list skills');
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it('should show no skills message', () => {
|
|
236
|
-
const result = {
|
|
237
|
-
success: true,
|
|
238
|
-
skills: [],
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
const output = formatSkillsListResult(result);
|
|
242
|
-
expect(output).toContain('No skills available');
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
it('should group skills by category', () => {
|
|
246
|
-
const result = skillsList();
|
|
247
|
-
const output = formatSkillsListResult(result);
|
|
248
|
-
|
|
249
|
-
// Should have at least core skills section
|
|
250
|
-
expect(output).toContain('Core skills');
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
it('should show argument hints', () => {
|
|
254
|
-
const result = skillsList();
|
|
255
|
-
const output = formatSkillsListResult(result);
|
|
256
|
-
|
|
257
|
-
// Many skills have argument hints
|
|
258
|
-
expect(output).toContain('Argument:');
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
it('should show dependencies for optional skills', () => {
|
|
262
|
-
const result = skillsList({
|
|
263
|
-
includeCoreSkills: false,
|
|
264
|
-
includeOptionalSkills: true,
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
const output = formatSkillsListResult(result);
|
|
268
|
-
// Optional skills have dependencies
|
|
269
|
-
expect(output).toContain('requires:');
|
|
270
|
-
});
|
|
271
|
-
});
|
|
272
|
-
});
|