Skip to content

Commit 24eebfe

Browse files
mylukinclaude
andcommitted
fix(cli): add --json option to detect-ai-save command
Complete CLI consistency - all commands now support --json output: - detect-ai-save: added --json with proper error handling - Updated tests to match new error message format Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 80e28ba commit 24eebfe

File tree

2 files changed

+36
-32
lines changed

2 files changed

+36
-32
lines changed

cli/src/commands/detect-ai.ts

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import chalk from 'chalk';
33
import * as path from 'path';
44
import { FileSystemIndexRepository } from '../repositories/index-repository.service';
55
import { FileSystemService } from '../infrastructure/file-system.service';
6+
import { successResponse, outputResponse } from '../core/response-wrapper';
7+
import { handleError, Errors } from '../core/error-handler';
68

79
/**
810
* AI-powered language detection command
@@ -69,15 +71,15 @@ export function registerDetectAICommand(program: Command, workspaceDir: string):
6971
program
7072
.command('detect-ai-save <result>')
7173
.description('Save AI detection result to index metadata')
72-
.action(async (result) => {
74+
.option('--json', 'Output as JSON')
75+
.action(async (result, options) => {
7376
try {
7477
const languageConfig = JSON.parse(result);
7578

7679
// Validate required fields
7780
if (!languageConfig.language || !languageConfig.verifyCommands) {
78-
console.error(chalk.red('❌ Invalid detection result format'));
79-
console.error(chalk.gray('Required fields: language, verifyCommands'));
80-
process.exit(1);
81+
handleError(Errors.validationError('Invalid detection result format. Required fields: language, verifyCommands'), options.json);
82+
return;
8183
}
8284

8385
// Save to index using FileSystemIndexRepository
@@ -86,35 +88,37 @@ export function registerDetectAICommand(program: Command, workspaceDir: string):
8688
const indexRepository = new FileSystemIndexRepository(fileSystem, tasksDir);
8789
await indexRepository.updateMetadata({ languageConfig });
8890

89-
console.log(chalk.green('✅ Language configuration saved to index metadata'));
90-
console.log(chalk.bold('\nDetected Configuration:'));
91-
console.log(`Language: ${chalk.cyan(languageConfig.language)}`);
92-
if (languageConfig.framework) {
93-
console.log(`Framework: ${chalk.green(languageConfig.framework)}`);
94-
}
95-
if (languageConfig.confidence) {
96-
console.log(`Confidence: ${chalk.yellow((languageConfig.confidence * 100).toFixed(0) + '%')}`);
97-
}
98-
console.log(chalk.bold('\nVerification Commands:'));
99-
languageConfig.verifyCommands.forEach((cmd: string) => {
100-
console.log(` ${chalk.gray('$')} ${cmd}`);
91+
const response = successResponse({
92+
saved: true,
93+
languageConfig,
10194
});
10295

103-
if (languageConfig.evidence) {
104-
console.log(chalk.bold('\nEvidence:'));
105-
languageConfig.evidence.forEach((ev: string) => {
106-
console.log(` • ${ev}`);
96+
outputResponse(response, options.json, (data) => {
97+
console.log(chalk.green('✅ Language configuration saved to index metadata'));
98+
console.log(chalk.bold('\nDetected Configuration:'));
99+
console.log(`Language: ${chalk.cyan(data.languageConfig.language)}`);
100+
if (data.languageConfig.framework) {
101+
console.log(`Framework: ${chalk.green(data.languageConfig.framework)}`);
102+
}
103+
if (data.languageConfig.confidence) {
104+
console.log(`Confidence: ${chalk.yellow((data.languageConfig.confidence * 100).toFixed(0) + '%')}`);
105+
}
106+
console.log(chalk.bold('\nVerification Commands:'));
107+
data.languageConfig.verifyCommands.forEach((cmd: string) => {
108+
console.log(` ${chalk.gray('$')} ${cmd}`);
107109
});
108-
}
110+
111+
if (data.languageConfig.evidence) {
112+
console.log(chalk.bold('\nEvidence:'));
113+
data.languageConfig.evidence.forEach((ev: string) => {
114+
console.log(` • ${ev}`);
115+
});
116+
}
117+
});
109118

110119
process.exit(0);
111120
} catch (error) {
112-
console.error(chalk.red('❌ Failed to parse detection result'));
113-
console.error(chalk.gray('Expected JSON string with language configuration'));
114-
if (error instanceof Error) {
115-
console.error(chalk.red(error.message));
116-
}
117-
process.exit(1);
121+
handleError(Errors.parsingError('Failed to parse detection result. Expected JSON string with language configuration', error), options.json);
118122
}
119123
});
120124
}

cli/tests/commands/detect-ai.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ describe('detect-ai commands', () => {
202202
registerDetectAICommand(program, testDir);
203203
await program.parseAsync(['node', 'test', 'detect-ai-save', JSON.stringify(invalidResult)]);
204204

205-
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Invalid detection result format'));
205+
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Invalid detection result format'));
206206
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Required fields: language, verifyCommands'));
207207
expect(processExitSpy).toHaveBeenCalledWith(1);
208208
});
@@ -215,15 +215,15 @@ describe('detect-ai commands', () => {
215215
registerDetectAICommand(program, testDir);
216216
await program.parseAsync(['node', 'test', 'detect-ai-save', JSON.stringify(invalidResult)]);
217217

218-
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Invalid detection result format'));
218+
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Invalid detection result format'));
219219
expect(processExitSpy).toHaveBeenCalledWith(1);
220220
});
221221

222222
it('should handle invalid JSON', async () => {
223223
registerDetectAICommand(program, testDir);
224224
await program.parseAsync(['node', 'test', 'detect-ai-save', 'invalid-json{']);
225225

226-
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Failed to parse detection result'));
226+
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Failed to parse detection result'));
227227
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Expected JSON string'));
228228
expect(processExitSpy).toHaveBeenCalledWith(1);
229229
});
@@ -232,7 +232,7 @@ describe('detect-ai commands', () => {
232232
registerDetectAICommand(program, testDir);
233233
await program.parseAsync(['node', 'test', 'detect-ai-save', '']);
234234

235-
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Failed to parse detection result'));
235+
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Failed to parse detection result'));
236236
expect(processExitSpy).toHaveBeenCalledWith(1);
237237
});
238238

@@ -249,7 +249,7 @@ describe('detect-ai commands', () => {
249249
registerDetectAICommand(program, testDir);
250250
await program.parseAsync(['node', 'test', 'detect-ai-save', JSON.stringify(validResult)]);
251251

252-
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Failed to parse detection result'));
252+
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Failed to parse detection result'));
253253
expect(processExitSpy).toHaveBeenCalledWith(1);
254254
});
255255

0 commit comments

Comments
 (0)