@aiready/cli 0.14.9 → 0.14.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/.turbo/turbo-build.log +28 -29
- package/.turbo/turbo-test.log +74 -76
- package/dist/chunk-HBPSESJV.mjs +289 -0
- package/dist/chunk-JRRBBFYB.mjs +307 -0
- package/dist/chunk-YP2EVXQN.mjs +303 -0
- package/dist/chunk-ZQOTGPK4.mjs +289 -0
- package/dist/cli.js +64 -60
- package/dist/cli.mjs +41 -41
- package/dist/index.js +25 -21
- package/dist/index.mjs +1 -1
- package/package.json +12 -12
- package/src/commands/bug.ts +1 -1
- package/src/commands/consistency.ts +5 -5
- package/src/commands/context.ts +4 -4
- package/src/commands/patterns.ts +3 -3
- package/src/commands/report-formatter.ts +6 -6
- package/src/commands/scan.ts +18 -18
- package/src/commands/upload.ts +6 -6
- package/src/commands/visualize.ts +4 -4
- package/src/index.ts +35 -25
package/src/commands/scan.ts
CHANGED
|
@@ -57,7 +57,7 @@ export async function scanAction(directory: string, options: ScanOptions) {
|
|
|
57
57
|
console.log(chalk.blue('🚀 Starting AIReady unified analysis...\n'));
|
|
58
58
|
|
|
59
59
|
const startTime = Date.now();
|
|
60
|
-
const resolvedDir = resolvePath(process.cwd(), directory
|
|
60
|
+
const resolvedDir = resolvePath(process.cwd(), directory ?? '.');
|
|
61
61
|
const repoMetadata = getRepoMetadata(resolvedDir);
|
|
62
62
|
|
|
63
63
|
try {
|
|
@@ -159,7 +159,7 @@ export async function scanAction(directory: string, options: ScanOptions) {
|
|
|
159
159
|
const { getSmartDefaults } = await import('@aiready/pattern-detect');
|
|
160
160
|
const patternSmartDefaults = await getSmartDefaults(
|
|
161
161
|
resolvedDir,
|
|
162
|
-
finalOptions.toolConfigs?.[ToolName.PatternDetect]
|
|
162
|
+
finalOptions.toolConfigs?.[ToolName.PatternDetect] ?? {}
|
|
163
163
|
);
|
|
164
164
|
|
|
165
165
|
// Merge smart defaults into toolConfigs instead of root level
|
|
@@ -173,7 +173,7 @@ export async function scanAction(directory: string, options: ScanOptions) {
|
|
|
173
173
|
console.log(chalk.cyan('\n=== AIReady Run Preview ==='));
|
|
174
174
|
console.log(
|
|
175
175
|
chalk.white('Tools to run:'),
|
|
176
|
-
(finalOptions.tools
|
|
176
|
+
(finalOptions.tools ?? []).join(', ')
|
|
177
177
|
);
|
|
178
178
|
|
|
179
179
|
// Dynamic progress callback
|
|
@@ -202,7 +202,7 @@ export async function scanAction(directory: string, options: ScanOptions) {
|
|
|
202
202
|
|
|
203
203
|
// Determine scoring profile for project-type-aware weighting
|
|
204
204
|
const scoringProfile =
|
|
205
|
-
options.profile
|
|
205
|
+
options.profile ?? baseOptions.scoring?.profile ?? 'default';
|
|
206
206
|
|
|
207
207
|
const results = await analyzeUnified({
|
|
208
208
|
...finalOptions,
|
|
@@ -233,7 +233,7 @@ export async function scanAction(directory: string, options: ScanOptions) {
|
|
|
233
233
|
readFileSync(resolvePath(process.cwd(), options.compareTo), 'utf8')
|
|
234
234
|
);
|
|
235
235
|
const prevScore =
|
|
236
|
-
prevReport.scoring?.overall
|
|
236
|
+
prevReport.scoring?.overall ?? prevReport.scoring?.score;
|
|
237
237
|
if (typeof prevScore === 'number') {
|
|
238
238
|
const diff = scoringResult.overall - prevScore;
|
|
239
239
|
const diffStr = diff > 0 ? `+${diff}` : String(diff);
|
|
@@ -262,19 +262,19 @@ export async function scanAction(directory: string, options: ScanOptions) {
|
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
// Token Budget & Cost Logic
|
|
265
|
-
const totalWastedDuplication = (scoringResult.breakdown
|
|
266
|
-
(sum, s) =>
|
|
267
|
-
sum + (s.tokenBudget?.wastedTokens
|
|
265
|
+
const totalWastedDuplication = (scoringResult.breakdown ?? []).reduce(
|
|
266
|
+
(sum: number, s: any) =>
|
|
267
|
+
sum + (s.tokenBudget?.wastedTokens?.bySource?.duplication ?? 0),
|
|
268
268
|
0
|
|
269
269
|
);
|
|
270
|
-
const totalWastedFragmentation = (scoringResult.breakdown
|
|
271
|
-
(sum, s) =>
|
|
272
|
-
sum + (s.tokenBudget?.wastedTokens
|
|
270
|
+
const totalWastedFragmentation = (scoringResult.breakdown ?? []).reduce(
|
|
271
|
+
(sum: number, s: any) =>
|
|
272
|
+
sum + (s.tokenBudget?.wastedTokens?.bySource?.fragmentation ?? 0),
|
|
273
273
|
0
|
|
274
274
|
);
|
|
275
275
|
const totalContext = Math.max(
|
|
276
|
-
...(scoringResult.breakdown
|
|
277
|
-
(s) => s.tokenBudget?.totalContextTokens
|
|
276
|
+
...(scoringResult.breakdown ?? []).map(
|
|
277
|
+
(s: any) => s.tokenBudget?.totalContextTokens ?? 0
|
|
278
278
|
),
|
|
279
279
|
0
|
|
280
280
|
);
|
|
@@ -300,7 +300,7 @@ export async function scanAction(directory: string, options: ScanOptions) {
|
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
-
const modelId = options.model
|
|
303
|
+
const modelId = options.model ?? 'gpt-5.4-mini';
|
|
304
304
|
const roi = (await import('@aiready/core')).calculateBusinessROI({
|
|
305
305
|
tokenWaste: unifiedBudget.wastedTokens.total,
|
|
306
306
|
issues: allIssues,
|
|
@@ -345,9 +345,9 @@ export async function scanAction(directory: string, options: ScanOptions) {
|
|
|
345
345
|
|
|
346
346
|
// Output persistence
|
|
347
347
|
const outputFormat =
|
|
348
|
-
options.output
|
|
348
|
+
options.output ?? finalOptions.output?.format ?? 'console';
|
|
349
349
|
const outputPath = resolveOutputPath(
|
|
350
|
-
options.outputFile
|
|
350
|
+
options.outputFile ?? finalOptions.output?.file,
|
|
351
351
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
352
352
|
resolvedDir
|
|
353
353
|
);
|
|
@@ -380,8 +380,8 @@ export async function scanAction(directory: string, options: ScanOptions) {
|
|
|
380
380
|
const threshold = options.threshold
|
|
381
381
|
? parseInt(options.threshold)
|
|
382
382
|
: undefined;
|
|
383
|
-
const failOnLevel = options.failOn
|
|
384
|
-
const isCI = options.ci
|
|
383
|
+
const failOnLevel = options.failOn ?? 'critical';
|
|
384
|
+
const isCI = options.ci ?? process.env.CI === 'true';
|
|
385
385
|
|
|
386
386
|
let shouldFail = false;
|
|
387
387
|
let failReason = '';
|
package/src/commands/upload.ts
CHANGED
|
@@ -13,10 +13,10 @@ export async function uploadAction(file: string, options: UploadOptions) {
|
|
|
13
13
|
const startTime = Date.now();
|
|
14
14
|
const filePath = resolvePath(process.cwd(), file);
|
|
15
15
|
const serverUrl =
|
|
16
|
-
options.server
|
|
17
|
-
process.env.AIREADY_SERVER
|
|
16
|
+
options.server ??
|
|
17
|
+
process.env.AIREADY_SERVER ??
|
|
18
18
|
'https://dev.platform.getaiready.dev';
|
|
19
|
-
const apiKey = options.apiKey
|
|
19
|
+
const apiKey = options.apiKey ?? process.env.AIREADY_API_KEY;
|
|
20
20
|
|
|
21
21
|
if (!apiKey) {
|
|
22
22
|
console.error(chalk.red('❌ API Key is required for upload.'));
|
|
@@ -49,7 +49,7 @@ export async function uploadAction(file: string, options: UploadOptions) {
|
|
|
49
49
|
|
|
50
50
|
// Prepare upload payload
|
|
51
51
|
// Note: repoId is optional if the metadata contains it, but for now we'll require it or infer from metadata
|
|
52
|
-
const repoId = options.repoId
|
|
52
|
+
const repoId = options.repoId ?? reportData.repository?.repoId;
|
|
53
53
|
|
|
54
54
|
const response = await fetch(`${serverUrl}/api/analysis/upload`, {
|
|
55
55
|
method: 'POST',
|
|
@@ -70,13 +70,13 @@ export async function uploadAction(file: string, options: UploadOptions) {
|
|
|
70
70
|
uploadResult = await response.json();
|
|
71
71
|
} else {
|
|
72
72
|
const text = await response.text();
|
|
73
|
-
uploadResult = { error: text
|
|
73
|
+
uploadResult = { error: text ?? response.statusText };
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
if (!response.ok) {
|
|
77
77
|
console.error(
|
|
78
78
|
chalk.red(
|
|
79
|
-
`❌ Upload failed: ${uploadResult.error
|
|
79
|
+
`❌ Upload failed: ${uploadResult.error ?? response.statusText}`
|
|
80
80
|
)
|
|
81
81
|
);
|
|
82
82
|
|
|
@@ -30,7 +30,7 @@ export async function visualizeAction(
|
|
|
30
30
|
options: VisualizeOptions
|
|
31
31
|
) {
|
|
32
32
|
try {
|
|
33
|
-
const dirPath = resolvePath(process.cwd(), directory
|
|
33
|
+
const dirPath = resolvePath(process.cwd(), directory ?? '.');
|
|
34
34
|
let reportPath = options.report
|
|
35
35
|
? resolvePath(dirPath, options.report)
|
|
36
36
|
: null;
|
|
@@ -87,7 +87,7 @@ export async function visualizeAction(
|
|
|
87
87
|
const graph = GraphBuilder.buildFromReport(report, dirPath);
|
|
88
88
|
|
|
89
89
|
// Check if --dev mode is requested and available
|
|
90
|
-
let useDevMode = options.dev
|
|
90
|
+
let useDevMode = options.dev ?? false;
|
|
91
91
|
let devServerStarted = false;
|
|
92
92
|
|
|
93
93
|
if (useDevMode) {
|
|
@@ -230,7 +230,7 @@ export async function visualizeAction(
|
|
|
230
230
|
console.log('Generating HTML...');
|
|
231
231
|
const html = generateHTML(graph as any);
|
|
232
232
|
const defaultOutput = 'visualization.html';
|
|
233
|
-
const outPath = resolvePath(dirPath, options.output
|
|
233
|
+
const outPath = resolvePath(dirPath, options.output ?? defaultOutput);
|
|
234
234
|
writeFileSync(outPath, html, 'utf8');
|
|
235
235
|
console.log(chalk.green(`✅ Visualization written to: ${outPath}`));
|
|
236
236
|
|
|
@@ -250,7 +250,7 @@ export async function visualizeAction(
|
|
|
250
250
|
|
|
251
251
|
const server = http.createServer(async (req, res) => {
|
|
252
252
|
try {
|
|
253
|
-
const urlPath = req.url
|
|
253
|
+
const urlPath = req.url ?? '/';
|
|
254
254
|
if (urlPath === '/' || urlPath === '/index.html') {
|
|
255
255
|
const content = await fsp.readFile(outPath, 'utf8');
|
|
256
256
|
res.writeHead(200, {
|
package/src/index.ts
CHANGED
|
@@ -57,6 +57,12 @@ export interface UnifiedAnalysisOptions extends ScanOptions {
|
|
|
57
57
|
total?: number;
|
|
58
58
|
message?: string;
|
|
59
59
|
}) => void;
|
|
60
|
+
/** Files or directories to include in scan */
|
|
61
|
+
include?: string[];
|
|
62
|
+
/** Files or directories to exclude from scan */
|
|
63
|
+
exclude?: string[];
|
|
64
|
+
/** Batch size for comparisons */
|
|
65
|
+
batchSize?: number;
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
/**
|
|
@@ -161,7 +167,7 @@ export async function analyzeUnified(
|
|
|
161
167
|
await initializeParsers();
|
|
162
168
|
|
|
163
169
|
const startTime = Date.now();
|
|
164
|
-
const requestedTools = options.tools
|
|
170
|
+
const requestedTools = options.tools ?? [
|
|
165
171
|
'patterns',
|
|
166
172
|
'context',
|
|
167
173
|
'consistency',
|
|
@@ -186,7 +192,7 @@ export async function analyzeUnified(
|
|
|
186
192
|
// Dynamic Loading: If provider not found, attempt to import the package
|
|
187
193
|
if (!provider) {
|
|
188
194
|
const packageName =
|
|
189
|
-
TOOL_PACKAGE_MAP[toolName]
|
|
195
|
+
TOOL_PACKAGE_MAP[toolName] ??
|
|
190
196
|
(toolName.startsWith('@aiready/') ? toolName : `@aiready/${toolName}`);
|
|
191
197
|
try {
|
|
192
198
|
await import(packageName);
|
|
@@ -301,34 +307,16 @@ export async function analyzeUnified(
|
|
|
301
307
|
|
|
302
308
|
// Track total files analyzed across all tools
|
|
303
309
|
const toolFiles =
|
|
304
|
-
output.summary?.totalFiles
|
|
310
|
+
output.summary?.totalFiles ?? output.summary?.filesAnalyzed ?? 0;
|
|
305
311
|
if (toolFiles > result.summary.totalFiles) {
|
|
306
312
|
result.summary.totalFiles = toolFiles;
|
|
307
313
|
}
|
|
308
314
|
|
|
309
315
|
const issueCount = output.results.reduce(
|
|
310
|
-
(sum: number, file: any) => sum + (file.issues?.length
|
|
316
|
+
(sum: number, file: any) => sum + (file.issues?.length ?? 0),
|
|
311
317
|
0
|
|
312
318
|
);
|
|
313
319
|
result.summary.totalIssues += issueCount;
|
|
314
|
-
|
|
315
|
-
// Robust backward compatibility fallbacks
|
|
316
|
-
// 1. Add all aliases as keys (e.g., 'patterns', 'context', 'consistency')
|
|
317
|
-
if (provider.alias && Array.isArray(provider.alias)) {
|
|
318
|
-
for (const alias of provider.alias) {
|
|
319
|
-
if (!result[alias]) {
|
|
320
|
-
(result as any)[alias] = output;
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// 2. Add camelCase version of canonical ID (e.g., 'patternDetect', 'contextAnalyzer')
|
|
326
|
-
const camelCaseId = provider.id.replace(/-([a-z])/g, (g) =>
|
|
327
|
-
g[1].toUpperCase()
|
|
328
|
-
);
|
|
329
|
-
if (camelCaseId !== provider.id && !result[camelCaseId]) {
|
|
330
|
-
(result as any)[camelCaseId] = output;
|
|
331
|
-
}
|
|
332
320
|
} catch (err) {
|
|
333
321
|
console.error(`❌ Error running tool '${provider.id}':`, err);
|
|
334
322
|
}
|
|
@@ -347,6 +335,28 @@ export async function analyzeUnified(
|
|
|
347
335
|
});
|
|
348
336
|
|
|
349
337
|
result.summary.executionTime = Date.now() - startTime;
|
|
338
|
+
|
|
339
|
+
// Add backward compatibility key mappings (kebab-case -> camelCase and aliases)
|
|
340
|
+
const keyMappings: Record<string, string[]> = {
|
|
341
|
+
'pattern-detect': ['patternDetect', 'patterns'],
|
|
342
|
+
'context-analyzer': ['contextAnalyzer', 'context'],
|
|
343
|
+
'naming-consistency': ['namingConsistency', 'consistency'],
|
|
344
|
+
'ai-signal-clarity': ['aiSignalClarity'],
|
|
345
|
+
'agent-grounding': ['agentGrounding'],
|
|
346
|
+
'testability-index': ['testabilityIndex', 'testability'],
|
|
347
|
+
'doc-drift': ['docDrift'],
|
|
348
|
+
'dependency-health': ['dependencyHealth', 'deps'],
|
|
349
|
+
'change-amplification': ['changeAmplification'],
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
for (const [kebabKey, aliases] of Object.entries(keyMappings)) {
|
|
353
|
+
if (result[kebabKey]) {
|
|
354
|
+
for (const alias of aliases) {
|
|
355
|
+
result[alias] = result[kebabKey];
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
350
360
|
return result;
|
|
351
361
|
}
|
|
352
362
|
|
|
@@ -378,7 +388,7 @@ export async function scoreUnified(
|
|
|
378
388
|
if (!toolScore.tokenBudget) {
|
|
379
389
|
if (toolId === ToolName.PatternDetect && (output as any).duplicates) {
|
|
380
390
|
const wastedTokens = (output as any).duplicates.reduce(
|
|
381
|
-
(sum: number, d: any) => sum + (d.tokenCost
|
|
391
|
+
(sum: number, d: any) => sum + (d.tokenCost ?? 0),
|
|
382
392
|
0
|
|
383
393
|
);
|
|
384
394
|
toolScore.tokenBudget = calculateTokenBudget({
|
|
@@ -394,7 +404,7 @@ export async function scoreUnified(
|
|
|
394
404
|
totalContextTokens: output.summary.totalTokens,
|
|
395
405
|
wastedTokens: {
|
|
396
406
|
duplication: 0,
|
|
397
|
-
fragmentation: output.summary.totalPotentialSavings
|
|
407
|
+
fragmentation: output.summary.totalPotentialSavings ?? 0,
|
|
398
408
|
chattiness: 0,
|
|
399
409
|
},
|
|
400
410
|
});
|
|
@@ -444,7 +454,7 @@ export function generateUnifiedSummary(result: UnifiedAnalysisResult): string {
|
|
|
444
454
|
const toolResult = result[provider.id];
|
|
445
455
|
if (toolResult) {
|
|
446
456
|
const issueCount = toolResult.results.reduce(
|
|
447
|
-
(sum: number, r: any) => sum + (r.issues?.length
|
|
457
|
+
(sum: number, r: any) => sum + (r.issues?.length ?? 0),
|
|
448
458
|
0
|
|
449
459
|
);
|
|
450
460
|
output += `• ${provider.id}: ${issueCount} issues\n`;
|