@aiready/cli 0.14.8 → 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 +71 -65
- package/dist/cli.mjs +48 -46
- package/dist/index.js +25 -21
- package/dist/index.mjs +1 -1
- package/package.json +12 -12
- package/src/cli.ts +7 -5
- 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 +23 -10
- 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 +49 -28
- package/src/utils/helpers.ts +30 -3
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/index.ts
|
|
9
|
+
import {
|
|
10
|
+
ToolRegistry,
|
|
11
|
+
ToolName,
|
|
12
|
+
calculateOverallScore,
|
|
13
|
+
calculateTokenBudget,
|
|
14
|
+
GLOBAL_INFRA_OPTIONS,
|
|
15
|
+
COMMON_FINE_TUNING_OPTIONS,
|
|
16
|
+
initializeParsers
|
|
17
|
+
} from "@aiready/core";
|
|
18
|
+
import "@aiready/pattern-detect";
|
|
19
|
+
import "@aiready/context-analyzer";
|
|
20
|
+
import "@aiready/consistency";
|
|
21
|
+
import "@aiready/ai-signal-clarity";
|
|
22
|
+
import "@aiready/agent-grounding";
|
|
23
|
+
import "@aiready/testability";
|
|
24
|
+
import "@aiready/doc-drift";
|
|
25
|
+
import "@aiready/deps";
|
|
26
|
+
import "@aiready/change-amplification";
|
|
27
|
+
var TOOL_PACKAGE_MAP = {
|
|
28
|
+
[ToolName.PatternDetect]: "@aiready/pattern-detect",
|
|
29
|
+
[ToolName.ContextAnalyzer]: "@aiready/context-analyzer",
|
|
30
|
+
[ToolName.NamingConsistency]: "@aiready/consistency",
|
|
31
|
+
[ToolName.AiSignalClarity]: "@aiready/ai-signal-clarity",
|
|
32
|
+
[ToolName.AgentGrounding]: "@aiready/agent-grounding",
|
|
33
|
+
[ToolName.TestabilityIndex]: "@aiready/testability",
|
|
34
|
+
[ToolName.DocDrift]: "@aiready/doc-drift",
|
|
35
|
+
[ToolName.DependencyHealth]: "@aiready/deps",
|
|
36
|
+
[ToolName.ChangeAmplification]: "@aiready/change-amplification",
|
|
37
|
+
// Aliases handled by registry
|
|
38
|
+
patterns: "@aiready/pattern-detect",
|
|
39
|
+
duplicates: "@aiready/pattern-detect",
|
|
40
|
+
context: "@aiready/context-analyzer",
|
|
41
|
+
fragmentation: "@aiready/context-analyzer",
|
|
42
|
+
consistency: "@aiready/consistency",
|
|
43
|
+
"ai-signal": "@aiready/ai-signal-clarity",
|
|
44
|
+
grounding: "@aiready/agent-grounding",
|
|
45
|
+
testability: "@aiready/testability",
|
|
46
|
+
"deps-health": "@aiready/deps",
|
|
47
|
+
"change-amp": "@aiready/change-amplification"
|
|
48
|
+
};
|
|
49
|
+
function sanitizeConfigRecursive(obj) {
|
|
50
|
+
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj;
|
|
51
|
+
const sanitized = {};
|
|
52
|
+
const infraToStrip = [
|
|
53
|
+
"rootDir",
|
|
54
|
+
"onProgress",
|
|
55
|
+
"progressCallback",
|
|
56
|
+
"streamResults",
|
|
57
|
+
"batchSize",
|
|
58
|
+
"useSmartDefaults"
|
|
59
|
+
];
|
|
60
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
61
|
+
if (infraToStrip.includes(key)) continue;
|
|
62
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
63
|
+
sanitized[key] = sanitizeConfigRecursive(value);
|
|
64
|
+
} else {
|
|
65
|
+
sanitized[key] = value;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return sanitized;
|
|
69
|
+
}
|
|
70
|
+
function sanitizeToolConfig(config) {
|
|
71
|
+
return sanitizeConfigRecursive(config);
|
|
72
|
+
}
|
|
73
|
+
async function analyzeUnified(options) {
|
|
74
|
+
await initializeParsers();
|
|
75
|
+
const startTime = Date.now();
|
|
76
|
+
const requestedTools = options.tools ?? [
|
|
77
|
+
"patterns",
|
|
78
|
+
"context",
|
|
79
|
+
"consistency"
|
|
80
|
+
];
|
|
81
|
+
const result = {
|
|
82
|
+
summary: {
|
|
83
|
+
totalIssues: 0,
|
|
84
|
+
criticalIssues: 0,
|
|
85
|
+
// Added as per instruction
|
|
86
|
+
majorIssues: 0,
|
|
87
|
+
// Added as per instruction
|
|
88
|
+
totalFiles: 0,
|
|
89
|
+
toolsRun: [],
|
|
90
|
+
executionTime: 0,
|
|
91
|
+
config: options,
|
|
92
|
+
toolConfigs: {}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
for (const toolName of requestedTools) {
|
|
96
|
+
let provider = ToolRegistry.find(toolName);
|
|
97
|
+
if (!provider) {
|
|
98
|
+
const packageName = TOOL_PACKAGE_MAP[toolName] || (toolName.startsWith("@aiready/") ? toolName : `@aiready/${toolName}`);
|
|
99
|
+
try {
|
|
100
|
+
await import(packageName);
|
|
101
|
+
provider = ToolRegistry.find(toolName);
|
|
102
|
+
if (provider) {
|
|
103
|
+
console.log(
|
|
104
|
+
`\u2705 Successfully loaded tool provider: ${toolName} from ${packageName}`
|
|
105
|
+
);
|
|
106
|
+
} else {
|
|
107
|
+
console.log(
|
|
108
|
+
`\u26A0\uFE0F Loaded ${packageName} but provider ${toolName} still not found in registry.`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
} catch (err) {
|
|
112
|
+
console.log(
|
|
113
|
+
`\u274C Failed to dynamically load tool ${toolName} (${packageName}):`,
|
|
114
|
+
err.message
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (!provider) {
|
|
119
|
+
console.warn(
|
|
120
|
+
`\u26A0\uFE0F Warning: Tool provider for '${toolName}' not found. Skipping.`
|
|
121
|
+
);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
const sanitizedOptions = { ...options };
|
|
126
|
+
delete sanitizedOptions.onProgress;
|
|
127
|
+
delete sanitizedOptions.progressCallback;
|
|
128
|
+
const toolOptions = {
|
|
129
|
+
rootDir: options.rootDir
|
|
130
|
+
// Always include rootDir
|
|
131
|
+
};
|
|
132
|
+
[...GLOBAL_INFRA_OPTIONS, ...COMMON_FINE_TUNING_OPTIONS].forEach(
|
|
133
|
+
(key) => {
|
|
134
|
+
if (key in options && key !== "toolConfigs" && key !== "tools") {
|
|
135
|
+
toolOptions[key] = options[key];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
if (options.toolConfigs?.[provider.id]) {
|
|
140
|
+
Object.assign(toolOptions, options.toolConfigs[provider.id]);
|
|
141
|
+
} else if (options.tools && !Array.isArray(options.tools) && typeof options.tools === "object" && options.tools[provider.id]) {
|
|
142
|
+
Object.assign(toolOptions, options.tools[provider.id]);
|
|
143
|
+
} else if (options[provider.id]) {
|
|
144
|
+
Object.assign(toolOptions, options[provider.id]);
|
|
145
|
+
}
|
|
146
|
+
toolOptions.onProgress = (processed, total, message) => {
|
|
147
|
+
if (options.progressCallback) {
|
|
148
|
+
options.progressCallback({
|
|
149
|
+
tool: provider.id,
|
|
150
|
+
processed,
|
|
151
|
+
total,
|
|
152
|
+
message
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
const output = await provider.analyze(toolOptions);
|
|
157
|
+
if (output.metadata) {
|
|
158
|
+
output.metadata.config = sanitizeToolConfig(toolOptions);
|
|
159
|
+
}
|
|
160
|
+
if (options.progressCallback) {
|
|
161
|
+
options.progressCallback({ tool: provider.id, data: output });
|
|
162
|
+
}
|
|
163
|
+
result[provider.id] = output;
|
|
164
|
+
result.summary.toolsRun.push(provider.id);
|
|
165
|
+
if (output.summary?.config) {
|
|
166
|
+
result.summary.toolConfigs[provider.id] = sanitizeToolConfig(
|
|
167
|
+
output.summary.config
|
|
168
|
+
);
|
|
169
|
+
} else if (output.metadata?.config) {
|
|
170
|
+
result.summary.toolConfigs[provider.id] = sanitizeToolConfig(
|
|
171
|
+
output.metadata.config
|
|
172
|
+
);
|
|
173
|
+
} else {
|
|
174
|
+
result.summary.toolConfigs[provider.id] = sanitizeToolConfig(toolOptions);
|
|
175
|
+
}
|
|
176
|
+
const toolFiles = output.summary?.totalFiles ?? output.summary?.filesAnalyzed ?? 0;
|
|
177
|
+
if (toolFiles > result.summary.totalFiles) {
|
|
178
|
+
result.summary.totalFiles = toolFiles;
|
|
179
|
+
}
|
|
180
|
+
const issueCount = output.results.reduce(
|
|
181
|
+
(sum, file) => sum + (file.issues?.length ?? 0),
|
|
182
|
+
0
|
|
183
|
+
);
|
|
184
|
+
result.summary.totalIssues += issueCount;
|
|
185
|
+
} catch (err) {
|
|
186
|
+
console.error(`\u274C Error running tool '${provider.id}':`, err);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
result.summary.config = sanitizeConfigRecursive({
|
|
190
|
+
scan: {
|
|
191
|
+
tools: requestedTools,
|
|
192
|
+
include: options.include,
|
|
193
|
+
exclude: options.exclude
|
|
194
|
+
},
|
|
195
|
+
// Use 'tools' for tool-specific configurations to match AIReadyConfig
|
|
196
|
+
tools: result.summary.toolConfigs
|
|
197
|
+
});
|
|
198
|
+
result.summary.executionTime = Date.now() - startTime;
|
|
199
|
+
return result;
|
|
200
|
+
}
|
|
201
|
+
async function scoreUnified(results, options) {
|
|
202
|
+
const toolScores = /* @__PURE__ */ new Map();
|
|
203
|
+
for (const toolId of results.summary.toolsRun) {
|
|
204
|
+
const provider = ToolRegistry.get(toolId);
|
|
205
|
+
if (!provider) continue;
|
|
206
|
+
const output = results[toolId];
|
|
207
|
+
if (!output) continue;
|
|
208
|
+
try {
|
|
209
|
+
const toolScore = provider.score(output, options);
|
|
210
|
+
if (!toolScore.tokenBudget) {
|
|
211
|
+
if (toolId === ToolName.PatternDetect && output.duplicates) {
|
|
212
|
+
const wastedTokens = output.duplicates.reduce(
|
|
213
|
+
(sum, d) => sum + (d.tokenCost ?? 0),
|
|
214
|
+
0
|
|
215
|
+
);
|
|
216
|
+
toolScore.tokenBudget = calculateTokenBudget({
|
|
217
|
+
totalContextTokens: wastedTokens * 2,
|
|
218
|
+
wastedTokens: {
|
|
219
|
+
duplication: wastedTokens,
|
|
220
|
+
fragmentation: 0,
|
|
221
|
+
chattiness: 0
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
} else if (toolId === ToolName.ContextAnalyzer && output.summary) {
|
|
225
|
+
toolScore.tokenBudget = calculateTokenBudget({
|
|
226
|
+
totalContextTokens: output.summary.totalTokens,
|
|
227
|
+
wastedTokens: {
|
|
228
|
+
duplication: 0,
|
|
229
|
+
fragmentation: output.summary.totalPotentialSavings ?? 0,
|
|
230
|
+
chattiness: 0
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
toolScores.set(toolId, toolScore);
|
|
236
|
+
} catch (err) {
|
|
237
|
+
console.error(`\u274C Error scoring tool '${toolId}':`, err);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (toolScores.size === 0) {
|
|
241
|
+
return {
|
|
242
|
+
overall: 0,
|
|
243
|
+
rating: "Critical",
|
|
244
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
245
|
+
toolsUsed: [],
|
|
246
|
+
breakdown: [],
|
|
247
|
+
calculation: {
|
|
248
|
+
formula: "0 / 0 = 0",
|
|
249
|
+
weights: {},
|
|
250
|
+
normalized: "0 / 0 = 0"
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
return calculateOverallScore(toolScores, options, void 0);
|
|
255
|
+
}
|
|
256
|
+
function generateUnifiedSummary(result) {
|
|
257
|
+
const { summary } = result;
|
|
258
|
+
let output = `\u{1F680} AIReady Analysis Complete
|
|
259
|
+
|
|
260
|
+
`;
|
|
261
|
+
output += `\u{1F4CA} Summary:
|
|
262
|
+
`;
|
|
263
|
+
output += ` Tools run: ${summary.toolsRun.join(", ")}
|
|
264
|
+
`;
|
|
265
|
+
output += ` Total issues found: ${summary.totalIssues}
|
|
266
|
+
`;
|
|
267
|
+
output += ` Execution time: ${(summary.executionTime / 1e3).toFixed(2)}s
|
|
268
|
+
|
|
269
|
+
`;
|
|
270
|
+
for (const provider of ToolRegistry.getAll()) {
|
|
271
|
+
const toolResult = result[provider.id];
|
|
272
|
+
if (toolResult) {
|
|
273
|
+
const issueCount = toolResult.results.reduce(
|
|
274
|
+
(sum, r) => sum + (r.issues?.length ?? 0),
|
|
275
|
+
0
|
|
276
|
+
);
|
|
277
|
+
output += `\u2022 ${provider.id}: ${issueCount} issues
|
|
278
|
+
`;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return output;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export {
|
|
285
|
+
__require,
|
|
286
|
+
analyzeUnified,
|
|
287
|
+
scoreUnified,
|
|
288
|
+
generateUnifiedSummary
|
|
289
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -95,7 +95,7 @@ function sanitizeToolConfig(config) {
|
|
|
95
95
|
async function analyzeUnified(options) {
|
|
96
96
|
await (0, import_core.initializeParsers)();
|
|
97
97
|
const startTime = Date.now();
|
|
98
|
-
const requestedTools = options.tools
|
|
98
|
+
const requestedTools = options.tools ?? [
|
|
99
99
|
"patterns",
|
|
100
100
|
"context",
|
|
101
101
|
"consistency"
|
|
@@ -117,7 +117,7 @@ async function analyzeUnified(options) {
|
|
|
117
117
|
for (const toolName of requestedTools) {
|
|
118
118
|
let provider = import_core.ToolRegistry.find(toolName);
|
|
119
119
|
if (!provider) {
|
|
120
|
-
const packageName = TOOL_PACKAGE_MAP[toolName]
|
|
120
|
+
const packageName = TOOL_PACKAGE_MAP[toolName] ?? (toolName.startsWith("@aiready/") ? toolName : `@aiready/${toolName}`);
|
|
121
121
|
try {
|
|
122
122
|
await import(packageName);
|
|
123
123
|
provider = import_core.ToolRegistry.find(toolName);
|
|
@@ -195,29 +195,15 @@ async function analyzeUnified(options) {
|
|
|
195
195
|
} else {
|
|
196
196
|
result.summary.toolConfigs[provider.id] = sanitizeToolConfig(toolOptions);
|
|
197
197
|
}
|
|
198
|
-
const toolFiles = output.summary?.totalFiles
|
|
198
|
+
const toolFiles = output.summary?.totalFiles ?? output.summary?.filesAnalyzed ?? 0;
|
|
199
199
|
if (toolFiles > result.summary.totalFiles) {
|
|
200
200
|
result.summary.totalFiles = toolFiles;
|
|
201
201
|
}
|
|
202
202
|
const issueCount = output.results.reduce(
|
|
203
|
-
(sum, file) => sum + (file.issues?.length
|
|
203
|
+
(sum, file) => sum + (file.issues?.length ?? 0),
|
|
204
204
|
0
|
|
205
205
|
);
|
|
206
206
|
result.summary.totalIssues += issueCount;
|
|
207
|
-
if (provider.alias && Array.isArray(provider.alias)) {
|
|
208
|
-
for (const alias of provider.alias) {
|
|
209
|
-
if (!result[alias]) {
|
|
210
|
-
result[alias] = output;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
const camelCaseId = provider.id.replace(
|
|
215
|
-
/-([a-z])/g,
|
|
216
|
-
(g) => g[1].toUpperCase()
|
|
217
|
-
);
|
|
218
|
-
if (camelCaseId !== provider.id && !result[camelCaseId]) {
|
|
219
|
-
result[camelCaseId] = output;
|
|
220
|
-
}
|
|
221
207
|
} catch (err) {
|
|
222
208
|
console.error(`\u274C Error running tool '${provider.id}':`, err);
|
|
223
209
|
}
|
|
@@ -232,6 +218,24 @@ async function analyzeUnified(options) {
|
|
|
232
218
|
tools: result.summary.toolConfigs
|
|
233
219
|
});
|
|
234
220
|
result.summary.executionTime = Date.now() - startTime;
|
|
221
|
+
const keyMappings = {
|
|
222
|
+
"pattern-detect": ["patternDetect", "patterns"],
|
|
223
|
+
"context-analyzer": ["contextAnalyzer", "context"],
|
|
224
|
+
"naming-consistency": ["namingConsistency", "consistency"],
|
|
225
|
+
"ai-signal-clarity": ["aiSignalClarity"],
|
|
226
|
+
"agent-grounding": ["agentGrounding"],
|
|
227
|
+
"testability-index": ["testabilityIndex", "testability"],
|
|
228
|
+
"doc-drift": ["docDrift"],
|
|
229
|
+
"dependency-health": ["dependencyHealth", "deps"],
|
|
230
|
+
"change-amplification": ["changeAmplification"]
|
|
231
|
+
};
|
|
232
|
+
for (const [kebabKey, aliases] of Object.entries(keyMappings)) {
|
|
233
|
+
if (result[kebabKey]) {
|
|
234
|
+
for (const alias of aliases) {
|
|
235
|
+
result[alias] = result[kebabKey];
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
235
239
|
return result;
|
|
236
240
|
}
|
|
237
241
|
async function scoreUnified(results, options) {
|
|
@@ -246,7 +250,7 @@ async function scoreUnified(results, options) {
|
|
|
246
250
|
if (!toolScore.tokenBudget) {
|
|
247
251
|
if (toolId === import_core.ToolName.PatternDetect && output.duplicates) {
|
|
248
252
|
const wastedTokens = output.duplicates.reduce(
|
|
249
|
-
(sum, d) => sum + (d.tokenCost
|
|
253
|
+
(sum, d) => sum + (d.tokenCost ?? 0),
|
|
250
254
|
0
|
|
251
255
|
);
|
|
252
256
|
toolScore.tokenBudget = (0, import_core.calculateTokenBudget)({
|
|
@@ -262,7 +266,7 @@ async function scoreUnified(results, options) {
|
|
|
262
266
|
totalContextTokens: output.summary.totalTokens,
|
|
263
267
|
wastedTokens: {
|
|
264
268
|
duplication: 0,
|
|
265
|
-
fragmentation: output.summary.totalPotentialSavings
|
|
269
|
+
fragmentation: output.summary.totalPotentialSavings ?? 0,
|
|
266
270
|
chattiness: 0
|
|
267
271
|
}
|
|
268
272
|
});
|
|
@@ -393,7 +397,7 @@ var import_core4 = require("@aiready/core");
|
|
|
393
397
|
function printScanSummary(results, startTime) {
|
|
394
398
|
console.log(import_chalk2.default.cyan("\n=== AIReady Run Summary ==="));
|
|
395
399
|
console.log(
|
|
396
|
-
` Total issues (all tools): ${import_chalk2.default.bold(String(results.summary.totalIssues
|
|
400
|
+
` Total issues (all tools): ${import_chalk2.default.bold(String(results.summary.totalIssues ?? 0))}`
|
|
397
401
|
);
|
|
398
402
|
console.log(
|
|
399
403
|
` Execution time: ${import_chalk2.default.bold(((Date.now() - startTime) / 1e3).toFixed(2) + "s")}`
|
|
@@ -428,7 +432,7 @@ function printScoring(scoringResult, scoringProfile) {
|
|
|
428
432
|
);
|
|
429
433
|
});
|
|
430
434
|
const allRecs = scoringResult.breakdown.flatMap(
|
|
431
|
-
(t) => (t.recommendations
|
|
435
|
+
(t) => (t.recommendations ?? []).map((r) => ({ ...r, tool: t.toolName }))
|
|
432
436
|
).sort((a, b) => b.estimatedImpact - a.estimatedImpact).slice(0, 3);
|
|
433
437
|
if (allRecs.length > 0) {
|
|
434
438
|
console.log(import_chalk2.default.bold("\n\u{1F3AF} Top Actionable Recommendations:"));
|
|
@@ -482,8 +486,8 @@ var import_core5 = require("@aiready/core");
|
|
|
482
486
|
async function uploadAction(file, options) {
|
|
483
487
|
const startTime = Date.now();
|
|
484
488
|
const filePath = (0, import_path2.resolve)(process.cwd(), file);
|
|
485
|
-
const serverUrl = options.server
|
|
486
|
-
const apiKey = options.apiKey
|
|
489
|
+
const serverUrl = options.server ?? process.env.AIREADY_SERVER ?? "https://dev.platform.getaiready.dev";
|
|
490
|
+
const apiKey = options.apiKey ?? process.env.AIREADY_API_KEY;
|
|
487
491
|
if (!apiKey) {
|
|
488
492
|
console.error(import_chalk3.default.red("\u274C API Key is required for upload."));
|
|
489
493
|
console.log(
|
|
@@ -508,7 +512,7 @@ async function uploadAction(file, options) {
|
|
|
508
512
|
const reportContent = import_fs2.default.readFileSync(filePath, "utf-8");
|
|
509
513
|
const reportData = JSON.parse(reportContent);
|
|
510
514
|
console.log(import_chalk3.default.dim(` Successfully parsed report JSON.`));
|
|
511
|
-
const repoId = options.repoId
|
|
515
|
+
const repoId = options.repoId ?? reportData.repository?.repoId;
|
|
512
516
|
const response = await fetch(`${serverUrl}/api/analysis/upload`, {
|
|
513
517
|
method: "POST",
|
|
514
518
|
headers: {
|
|
@@ -527,12 +531,12 @@ async function uploadAction(file, options) {
|
|
|
527
531
|
uploadResult = await response.json();
|
|
528
532
|
} else {
|
|
529
533
|
const text = await response.text();
|
|
530
|
-
uploadResult = { error: text
|
|
534
|
+
uploadResult = { error: text ?? response.statusText };
|
|
531
535
|
}
|
|
532
536
|
if (!response.ok) {
|
|
533
537
|
console.error(
|
|
534
538
|
import_chalk3.default.red(
|
|
535
|
-
`\u274C Upload failed: ${uploadResult.error
|
|
539
|
+
`\u274C Upload failed: ${uploadResult.error ?? response.statusText}`
|
|
536
540
|
)
|
|
537
541
|
);
|
|
538
542
|
if (contentType?.includes("text/html")) {
|
|
@@ -583,7 +587,7 @@ ENVIRONMENT VARIABLES:
|
|
|
583
587
|
async function scanAction(directory, options) {
|
|
584
588
|
console.log(import_chalk4.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
|
|
585
589
|
const startTime = Date.now();
|
|
586
|
-
const resolvedDir = (0, import_path3.resolve)(process.cwd(), directory
|
|
590
|
+
const resolvedDir = (0, import_path3.resolve)(process.cwd(), directory ?? ".");
|
|
587
591
|
const repoMetadata = (0, import_core6.getRepoMetadata)(resolvedDir);
|
|
588
592
|
try {
|
|
589
593
|
const defaults = {
|
|
@@ -673,7 +677,7 @@ async function scanAction(directory, options) {
|
|
|
673
677
|
const { getSmartDefaults } = await import("@aiready/pattern-detect");
|
|
674
678
|
const patternSmartDefaults = await getSmartDefaults(
|
|
675
679
|
resolvedDir,
|
|
676
|
-
finalOptions.toolConfigs?.[import_core6.ToolName.PatternDetect]
|
|
680
|
+
finalOptions.toolConfigs?.[import_core6.ToolName.PatternDetect] ?? {}
|
|
677
681
|
);
|
|
678
682
|
if (!finalOptions.toolConfigs) finalOptions.toolConfigs = {};
|
|
679
683
|
finalOptions.toolConfigs[import_core6.ToolName.PatternDetect] = {
|
|
@@ -684,7 +688,7 @@ async function scanAction(directory, options) {
|
|
|
684
688
|
console.log(import_chalk4.default.cyan("\n=== AIReady Run Preview ==="));
|
|
685
689
|
console.log(
|
|
686
690
|
import_chalk4.default.white("Tools to run:"),
|
|
687
|
-
(finalOptions.tools
|
|
691
|
+
(finalOptions.tools ?? []).join(", ")
|
|
688
692
|
);
|
|
689
693
|
const progressCallback = (event) => {
|
|
690
694
|
if (event.message) {
|
|
@@ -705,7 +709,7 @@ async function scanAction(directory, options) {
|
|
|
705
709
|
);
|
|
706
710
|
}
|
|
707
711
|
};
|
|
708
|
-
const scoringProfile = options.profile
|
|
712
|
+
const scoringProfile = options.profile ?? baseOptions.scoring?.profile ?? "default";
|
|
709
713
|
const results = await analyzeUnified({
|
|
710
714
|
...finalOptions,
|
|
711
715
|
progressCallback,
|
|
@@ -729,7 +733,7 @@ async function scanAction(directory, options) {
|
|
|
729
733
|
const prevReport = JSON.parse(
|
|
730
734
|
(0, import_fs3.readFileSync)((0, import_path3.resolve)(process.cwd(), options.compareTo), "utf8")
|
|
731
735
|
);
|
|
732
|
-
const prevScore = prevReport.scoring?.overall
|
|
736
|
+
const prevScore = prevReport.scoring?.overall ?? prevReport.scoring?.score;
|
|
733
737
|
if (typeof prevScore === "number") {
|
|
734
738
|
const diff = scoringResult.overall - prevScore;
|
|
735
739
|
const diffStr = diff > 0 ? `+${diff}` : String(diff);
|
|
@@ -756,17 +760,17 @@ async function scanAction(directory, options) {
|
|
|
756
760
|
void e;
|
|
757
761
|
}
|
|
758
762
|
}
|
|
759
|
-
const totalWastedDuplication = (scoringResult.breakdown
|
|
760
|
-
(sum, s) => sum + (s.tokenBudget?.wastedTokens
|
|
763
|
+
const totalWastedDuplication = (scoringResult.breakdown ?? []).reduce(
|
|
764
|
+
(sum, s) => sum + (s.tokenBudget?.wastedTokens?.bySource?.duplication ?? 0),
|
|
761
765
|
0
|
|
762
766
|
);
|
|
763
|
-
const totalWastedFragmentation = (scoringResult.breakdown
|
|
764
|
-
(sum, s) => sum + (s.tokenBudget?.wastedTokens
|
|
767
|
+
const totalWastedFragmentation = (scoringResult.breakdown ?? []).reduce(
|
|
768
|
+
(sum, s) => sum + (s.tokenBudget?.wastedTokens?.bySource?.fragmentation ?? 0),
|
|
765
769
|
0
|
|
766
770
|
);
|
|
767
771
|
const totalContext = Math.max(
|
|
768
|
-
...(scoringResult.breakdown
|
|
769
|
-
(s) => s.tokenBudget?.totalContextTokens
|
|
772
|
+
...(scoringResult.breakdown ?? []).map(
|
|
773
|
+
(s) => s.tokenBudget?.totalContextTokens ?? 0
|
|
770
774
|
),
|
|
771
775
|
0
|
|
772
776
|
);
|
|
@@ -790,7 +794,7 @@ async function scanAction(directory, options) {
|
|
|
790
794
|
});
|
|
791
795
|
}
|
|
792
796
|
}
|
|
793
|
-
const modelId = options.model
|
|
797
|
+
const modelId = options.model ?? "gpt-5.4-mini";
|
|
794
798
|
const roi = (await import("@aiready/core")).calculateBusinessROI({
|
|
795
799
|
tokenWaste: unifiedBudget.wastedTokens.total,
|
|
796
800
|
issues: allIssues,
|
|
@@ -827,9 +831,9 @@ async function scanAction(directory, options) {
|
|
|
827
831
|
...mapToUnifiedReport(results, scoringResult),
|
|
828
832
|
repository: repoMetadata
|
|
829
833
|
};
|
|
830
|
-
const outputFormat = options.output
|
|
834
|
+
const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
|
|
831
835
|
const outputPath = (0, import_core6.resolveOutputPath)(
|
|
832
|
-
options.outputFile
|
|
836
|
+
options.outputFile ?? finalOptions.output?.file,
|
|
833
837
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
834
838
|
resolvedDir
|
|
835
839
|
);
|
|
@@ -856,8 +860,8 @@ async function scanAction(directory, options) {
|
|
|
856
860
|
await warnIfGraphCapExceeded(outputData, resolvedDir);
|
|
857
861
|
if (scoringResult) {
|
|
858
862
|
const threshold = options.threshold ? parseInt(options.threshold) : void 0;
|
|
859
|
-
const failOnLevel = options.failOn
|
|
860
|
-
const isCI = options.ci
|
|
863
|
+
const failOnLevel = options.failOn ?? "critical";
|
|
864
|
+
const isCI = options.ci ?? process.env.CI === "true";
|
|
861
865
|
let shouldFail = false;
|
|
862
866
|
let failReason = "";
|
|
863
867
|
const report = mapToUnifiedReport(results, scoringResult);
|
|
@@ -1041,7 +1045,7 @@ var import_core8 = require("@aiready/core");
|
|
|
1041
1045
|
async function patternsAction(directory, options) {
|
|
1042
1046
|
console.log(import_chalk6.default.blue("\u{1F50D} Analyzing patterns...\n"));
|
|
1043
1047
|
const startTime = Date.now();
|
|
1044
|
-
const resolvedDir = (0, import_path5.resolve)(process.cwd(), directory
|
|
1048
|
+
const resolvedDir = (0, import_path5.resolve)(process.cwd(), directory ?? ".");
|
|
1045
1049
|
try {
|
|
1046
1050
|
const useSmartDefaults = !options.fullScan;
|
|
1047
1051
|
const defaults = {
|
|
@@ -1085,8 +1089,8 @@ async function patternsAction(directory, options) {
|
|
|
1085
1089
|
if (options.score) {
|
|
1086
1090
|
patternScore = calculatePatternScore(duplicates, results.length);
|
|
1087
1091
|
}
|
|
1088
|
-
const outputFormat = options.output
|
|
1089
|
-
const userOutputFile = options.outputFile
|
|
1092
|
+
const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
|
|
1093
|
+
const userOutputFile = options.outputFile ?? finalOptions.output?.file;
|
|
1090
1094
|
if (outputFormat === "json") {
|
|
1091
1095
|
const outputData = {
|
|
1092
1096
|
results,
|
|
@@ -1187,7 +1191,7 @@ var import_core9 = require("@aiready/core");
|
|
|
1187
1191
|
async function contextAction(directory, options) {
|
|
1188
1192
|
console.log(import_chalk7.default.blue("\u{1F9E0} Analyzing context costs...\n"));
|
|
1189
1193
|
const startTime = Date.now();
|
|
1190
|
-
const resolvedDir = (0, import_path6.resolve)(process.cwd(), directory
|
|
1194
|
+
const resolvedDir = (0, import_path6.resolve)(process.cwd(), directory ?? ".");
|
|
1191
1195
|
try {
|
|
1192
1196
|
const defaults = {
|
|
1193
1197
|
maxDepth: 5,
|
|
@@ -1231,8 +1235,8 @@ async function contextAction(directory, options) {
|
|
|
1231
1235
|
if (options.score) {
|
|
1232
1236
|
contextScore = calculateContextScore(summary);
|
|
1233
1237
|
}
|
|
1234
|
-
const outputFormat = options.output
|
|
1235
|
-
const userOutputFile = options.outputFile
|
|
1238
|
+
const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
|
|
1239
|
+
const userOutputFile = options.outputFile ?? finalOptions.output?.file;
|
|
1236
1240
|
if (outputFormat === "json") {
|
|
1237
1241
|
const outputData = {
|
|
1238
1242
|
results,
|
|
@@ -1250,7 +1254,7 @@ async function contextAction(directory, options) {
|
|
|
1250
1254
|
`\u2705 Results saved to ${outputPath}`
|
|
1251
1255
|
);
|
|
1252
1256
|
} else {
|
|
1253
|
-
const terminalWidth = process.stdout.columns
|
|
1257
|
+
const terminalWidth = process.stdout.columns ?? 80;
|
|
1254
1258
|
const dividerWidth = Math.min(60, terminalWidth - 2);
|
|
1255
1259
|
const divider = "\u2501".repeat(dividerWidth);
|
|
1256
1260
|
console.log(import_chalk7.default.cyan(divider));
|
|
@@ -1388,7 +1392,7 @@ var import_core10 = require("@aiready/core");
|
|
|
1388
1392
|
async function consistencyAction(directory, options) {
|
|
1389
1393
|
console.log(import_chalk8.default.blue("\u{1F50D} Analyzing consistency...\n"));
|
|
1390
1394
|
const startTime = Date.now();
|
|
1391
|
-
const resolvedDir = (0, import_path7.resolve)(process.cwd(), directory
|
|
1395
|
+
const resolvedDir = (0, import_path7.resolve)(process.cwd(), directory ?? ".");
|
|
1392
1396
|
try {
|
|
1393
1397
|
const defaults = {
|
|
1394
1398
|
checkNaming: true,
|
|
@@ -1413,14 +1417,14 @@ async function consistencyAction(directory, options) {
|
|
|
1413
1417
|
const elapsedTime = (0, import_core10.getElapsedTime)(startTime);
|
|
1414
1418
|
let consistencyScore;
|
|
1415
1419
|
if (options.score) {
|
|
1416
|
-
const issues = report.results?.flatMap((r) => r.issues)
|
|
1420
|
+
const issues = report.results?.flatMap((r) => r.issues) ?? [];
|
|
1417
1421
|
consistencyScore = calculateConsistencyScore(
|
|
1418
1422
|
issues,
|
|
1419
1423
|
report.summary.filesAnalyzed
|
|
1420
1424
|
);
|
|
1421
1425
|
}
|
|
1422
|
-
const outputFormat = options.output
|
|
1423
|
-
const userOutputFile = options.outputFile
|
|
1426
|
+
const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
|
|
1427
|
+
const userOutputFile = options.outputFile ?? finalOptions.output?.file;
|
|
1424
1428
|
if (outputFormat === "json") {
|
|
1425
1429
|
const outputData = {
|
|
1426
1430
|
...report,
|
|
@@ -1458,7 +1462,7 @@ async function consistencyAction(directory, options) {
|
|
|
1458
1462
|
console.log(` Naming: ${import_chalk8.default.yellow(report.summary.namingIssues)}`);
|
|
1459
1463
|
console.log(` Patterns: ${import_chalk8.default.yellow(report.summary.patternIssues)}`);
|
|
1460
1464
|
console.log(
|
|
1461
|
-
` Architecture: ${import_chalk8.default.yellow(report.summary.architectureIssues
|
|
1465
|
+
` Architecture: ${import_chalk8.default.yellow(report.summary.architectureIssues ?? 0)}`
|
|
1462
1466
|
);
|
|
1463
1467
|
console.log(`Analysis Time: ${import_chalk8.default.gray(elapsedTime + "s")}
|
|
1464
1468
|
`);
|
|
@@ -1557,7 +1561,7 @@ var import_core11 = require("@aiready/core");
|
|
|
1557
1561
|
var import_core12 = require("@aiready/core");
|
|
1558
1562
|
async function visualizeAction(directory, options) {
|
|
1559
1563
|
try {
|
|
1560
|
-
const dirPath = (0, import_path8.resolve)(process.cwd(), directory
|
|
1564
|
+
const dirPath = (0, import_path8.resolve)(process.cwd(), directory ?? ".");
|
|
1561
1565
|
let reportPath = options.report ? (0, import_path8.resolve)(dirPath, options.report) : null;
|
|
1562
1566
|
if (!reportPath || !(0, import_fs6.existsSync)(reportPath)) {
|
|
1563
1567
|
const latestScan = (0, import_core12.findLatestReport)(dirPath);
|
|
@@ -1603,7 +1607,7 @@ Or specify a custom report:
|
|
|
1603
1607
|
console.log("Building graph from report...");
|
|
1604
1608
|
const { GraphBuilder } = await import("@aiready/visualizer/graph");
|
|
1605
1609
|
const graph = GraphBuilder.buildFromReport(report, dirPath);
|
|
1606
|
-
let useDevMode = options.dev
|
|
1610
|
+
let useDevMode = options.dev ?? false;
|
|
1607
1611
|
let devServerStarted = false;
|
|
1608
1612
|
if (useDevMode) {
|
|
1609
1613
|
try {
|
|
@@ -1719,7 +1723,7 @@ Or specify a custom report:
|
|
|
1719
1723
|
console.log("Generating HTML...");
|
|
1720
1724
|
const html = (0, import_core12.generateHTML)(graph);
|
|
1721
1725
|
const defaultOutput = "visualization.html";
|
|
1722
|
-
const outPath = (0, import_path8.resolve)(dirPath, options.output
|
|
1726
|
+
const outPath = (0, import_path8.resolve)(dirPath, options.output ?? defaultOutput);
|
|
1723
1727
|
(0, import_fs6.writeFileSync)(outPath, html, "utf8");
|
|
1724
1728
|
console.log(import_chalk9.default.green(`\u2705 Visualization written to: ${outPath}`));
|
|
1725
1729
|
if (options.open || options.serve) {
|
|
@@ -1731,7 +1735,7 @@ Or specify a custom report:
|
|
|
1731
1735
|
const fsp = await import("fs/promises");
|
|
1732
1736
|
const server = http.createServer(async (req, res) => {
|
|
1733
1737
|
try {
|
|
1734
|
-
const urlPath = req.url
|
|
1738
|
+
const urlPath = req.url ?? "/";
|
|
1735
1739
|
if (urlPath === "/" || urlPath === "/index.html") {
|
|
1736
1740
|
const content = await fsp.readFile(outPath, "utf8");
|
|
1737
1741
|
res.writeHead(200, {
|
|
@@ -1869,7 +1873,7 @@ async function bugAction(message, options) {
|
|
|
1869
1873
|
const repoUrl = "https://github.com/caopengau/aiready-cli";
|
|
1870
1874
|
const repoSlug = "caopengau/aiready-cli";
|
|
1871
1875
|
if (message) {
|
|
1872
|
-
const type = options.type
|
|
1876
|
+
const type = options.type ?? "bug";
|
|
1873
1877
|
const title = `[${type.toUpperCase()}] ${message}`;
|
|
1874
1878
|
const label = type === "bug" ? "bug" : type === "feature" ? "enhancement" : "metric";
|
|
1875
1879
|
const body = `
|
|
@@ -1958,15 +1962,17 @@ AI READINESS SCORING:
|
|
|
1958
1962
|
EXAMPLES:
|
|
1959
1963
|
$ aiready scan # Comprehensive analysis with AI Readiness Score
|
|
1960
1964
|
$ aiready scan --no-score # Run scan without score calculation
|
|
1961
|
-
$ aiready
|
|
1965
|
+
$ aiready init # Create a default aiready.json configuration
|
|
1966
|
+
$ aiready init --full # Create configuration with ALL available options
|
|
1962
1967
|
$ npx @aiready/cli scan # Industry standard way to run standard scan
|
|
1963
1968
|
$ aiready scan --output json # Output raw JSON for piping
|
|
1964
1969
|
|
|
1965
1970
|
GETTING STARTED:
|
|
1966
|
-
1. Run 'aiready
|
|
1967
|
-
2.
|
|
1968
|
-
3.
|
|
1969
|
-
4.
|
|
1971
|
+
1. Run 'aiready init' to create a persistent 'aiready.json' config file
|
|
1972
|
+
2. Run 'aiready scan' to analyze your codebase and get an AI Readiness Score
|
|
1973
|
+
3. Use 'aiready init --full' to see every fine-tuning parameter available
|
|
1974
|
+
4. Use '--profile agentic' for agent-focused analysis
|
|
1975
|
+
5. Set up CI/CD with '--threshold' for quality gates
|
|
1970
1976
|
|
|
1971
1977
|
CONFIGURATION:
|
|
1972
1978
|
Config files (searched upward): aiready.json, .aiready.json, aiready.config.*
|