@aiready/cli 0.14.14 → 0.14.15
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/CONTRIBUTING.md +86 -1
- package/LICENSE +21 -0
- package/package.json +33 -12
- package/.aiready/aiready-report-20260227-133806.json +0 -7805
- package/.aiready/aiready-report-20260227-133938.json +0 -7951
- package/.aiready/aiready-report-20260228-003433.json +0 -7939
- package/.aiready/aiready-report-20260228-003613.json +0 -771
- package/.aiready/aiready-report-20260314-164626.json +0 -59
- package/.aiready/aiready-report-20260314-164741.json +0 -59
- package/.aiready/aiready-report-20260319-201106.json +0 -5566
- package/.aiready/aiready-report-20260319-201511.json +0 -5566
- package/.aiready/aiready-report-20260319-202017.json +0 -5708
- package/.github/FUNDING.yml +0 -5
- package/.turbo/turbo-build.log +0 -29
- package/.turbo/turbo-lint.log +0 -0
- package/.turbo/turbo-test.log +0 -76
- package/aiready-report.json +0 -30703
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/clover.xml +0 -865
- package/coverage/coverage-final.json +0 -15
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -146
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/coverage/src/commands/agent-grounding.ts.html +0 -271
- package/coverage/src/commands/ai-signal-clarity.ts.html +0 -253
- package/coverage/src/commands/change-amplification.ts.html +0 -94
- package/coverage/src/commands/consistency.ts.html +0 -781
- package/coverage/src/commands/context.ts.html +0 -871
- package/coverage/src/commands/deps-health.ts.html +0 -280
- package/coverage/src/commands/doc-drift.ts.html +0 -271
- package/coverage/src/commands/index.html +0 -281
- package/coverage/src/commands/patterns.ts.html +0 -745
- package/coverage/src/commands/scan.ts.html +0 -1393
- package/coverage/src/commands/testability.ts.html +0 -304
- package/coverage/src/commands/upload.ts.html +0 -466
- package/coverage/src/commands/visualize.ts.html +0 -1027
- package/coverage/src/index.html +0 -116
- package/coverage/src/index.ts.html +0 -1372
- package/coverage/src/utils/helpers.ts.html +0 -559
- package/coverage/src/utils/index.html +0 -116
- package/docs/SPOKE_GUIDE.md +0 -184
- package/packages/core/src/.aiready/aiready-report-20260314-161145.json +0 -224
- package/packages/core/src/.aiready/aiready-report-20260314-161152.json +0 -235
- package/packages/pattern-detect/src/.aiready/aiready-report-20260314-161139.json +0 -224
- package/src/.aiready/aiready-report-20260312-103623.json +0 -32574
- package/src/.aiready/aiready-report-20260312-110843.json +0 -28740
- package/src/.aiready/aiready-report-20260312-110955.json +0 -28740
- package/src/.aiready/aiready-report-20260314-203209.json +0 -30713
- package/src/.aiready/aiready-report-20260314-203736.json +0 -30713
- package/src/.aiready/aiready-report-20260314-203857.json +0 -30713
- package/src/.aiready/aiready-report-20260314-204047.json +0 -30713
- package/src/.aiready/aiready-report-20260318-002110.json +0 -28782
- package/src/__tests__/cli.test.ts +0 -85
- package/src/__tests__/config-shape.test.ts +0 -105
- package/src/__tests__/unified.test.ts +0 -95
- package/src/cli.ts +0 -333
- package/src/commands/__tests__/agent-grounding.test.ts +0 -24
- package/src/commands/__tests__/ai-signal-clarity.test.ts +0 -32
- package/src/commands/__tests__/consistency.test.ts +0 -100
- package/src/commands/__tests__/deps-health.test.ts +0 -26
- package/src/commands/__tests__/doc-drift.test.ts +0 -26
- package/src/commands/__tests__/extra-commands.test.ts +0 -168
- package/src/commands/__tests__/init.test.ts +0 -51
- package/src/commands/__tests__/scan.test.ts +0 -153
- package/src/commands/__tests__/testability.test.ts +0 -36
- package/src/commands/__tests__/upload.test.ts +0 -50
- package/src/commands/__tests__/visualize.test.ts +0 -78
- package/src/commands/agent-grounding.ts +0 -62
- package/src/commands/ai-signal-clarity.ts +0 -1
- package/src/commands/bug.ts +0 -99
- package/src/commands/change-amplification.ts +0 -3
- package/src/commands/consistency.ts +0 -232
- package/src/commands/context.ts +0 -262
- package/src/commands/deps-health.ts +0 -1
- package/src/commands/doc-drift.ts +0 -1
- package/src/commands/index.ts +0 -20
- package/src/commands/init.ts +0 -199
- package/src/commands/patterns.ts +0 -222
- package/src/commands/report-formatter.ts +0 -267
- package/src/commands/scan.ts +0 -432
- package/src/commands/shared/configured-tool-action.ts +0 -35
- package/src/commands/shared/standard-tool-actions.ts +0 -126
- package/src/commands/testability.ts +0 -73
- package/src/commands/upload.ts +0 -129
- package/src/commands/visualize.ts +0 -321
- package/src/index.ts +0 -465
- package/src/utils/__tests__/helpers.test.ts +0 -35
- package/src/utils/helpers.ts +0 -234
- package/tsconfig.json +0 -11
- package/tsconfig.tsbuildinfo +0 -1
- package/vitest.config.ts +0 -13
package/src/commands/upload.ts
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import { resolve as resolvePath } from 'path';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import { handleCLIError } from '@aiready/core';
|
|
5
|
-
|
|
6
|
-
interface UploadOptions {
|
|
7
|
-
apiKey?: string;
|
|
8
|
-
repoId?: string;
|
|
9
|
-
server?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export async function uploadAction(file: string, options: UploadOptions) {
|
|
13
|
-
const startTime = Date.now();
|
|
14
|
-
const filePath = resolvePath(process.cwd(), file);
|
|
15
|
-
const serverUrl =
|
|
16
|
-
options.server ??
|
|
17
|
-
process.env.AIREADY_SERVER ??
|
|
18
|
-
'https://dev.platform.getaiready.dev';
|
|
19
|
-
const apiKey = options.apiKey ?? process.env.AIREADY_API_KEY;
|
|
20
|
-
|
|
21
|
-
if (!apiKey) {
|
|
22
|
-
console.error(chalk.red('❌ API Key is required for upload.'));
|
|
23
|
-
console.log(
|
|
24
|
-
chalk.dim(
|
|
25
|
-
' Set AIREADY_API_KEY environment variable or use --api-key flag.'
|
|
26
|
-
)
|
|
27
|
-
);
|
|
28
|
-
console.log(
|
|
29
|
-
chalk.dim(
|
|
30
|
-
' Get an API key from https://platform.getaiready.dev/dashboard'
|
|
31
|
-
)
|
|
32
|
-
);
|
|
33
|
-
process.exit(1);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (!fs.existsSync(filePath)) {
|
|
37
|
-
console.error(chalk.red(`❌ File not found: ${filePath}`));
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
try {
|
|
42
|
-
console.log(chalk.blue(`🚀 Uploading report to ${serverUrl}...`));
|
|
43
|
-
|
|
44
|
-
// Read the report file
|
|
45
|
-
console.log(chalk.dim(` Reading report from ${filePath}...`));
|
|
46
|
-
const reportContent = fs.readFileSync(filePath, 'utf-8');
|
|
47
|
-
const reportData = JSON.parse(reportContent);
|
|
48
|
-
console.log(chalk.dim(` Successfully parsed report JSON.`));
|
|
49
|
-
|
|
50
|
-
// Prepare upload payload
|
|
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 ?? reportData.repository?.repoId;
|
|
53
|
-
|
|
54
|
-
const response = await fetch(`${serverUrl}/api/analysis/upload`, {
|
|
55
|
-
method: 'POST',
|
|
56
|
-
headers: {
|
|
57
|
-
'Content-Type': 'application/json',
|
|
58
|
-
Authorization: `Bearer ${apiKey}`,
|
|
59
|
-
},
|
|
60
|
-
body: JSON.stringify({
|
|
61
|
-
data: reportData,
|
|
62
|
-
repoId, // Might be null, server will handle mapping
|
|
63
|
-
}),
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
const contentType = response.headers.get('content-type');
|
|
67
|
-
let uploadResult: any = {};
|
|
68
|
-
|
|
69
|
-
if (contentType?.includes('application/json')) {
|
|
70
|
-
uploadResult = await response.json();
|
|
71
|
-
} else {
|
|
72
|
-
const text = await response.text();
|
|
73
|
-
uploadResult = { error: text ?? response.statusText };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (!response.ok) {
|
|
77
|
-
console.error(
|
|
78
|
-
chalk.red(
|
|
79
|
-
`❌ Upload failed: ${uploadResult.error ?? response.statusText}`
|
|
80
|
-
)
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
// Special case for redirects or HTML error pages
|
|
84
|
-
if (contentType?.includes('text/html')) {
|
|
85
|
-
console.log(
|
|
86
|
-
chalk.yellow(
|
|
87
|
-
' Note: Received an HTML response. This often indicates a redirect (e.g., to a login page) or a server error.'
|
|
88
|
-
)
|
|
89
|
-
);
|
|
90
|
-
if (uploadResult.error?.includes('Redirecting')) {
|
|
91
|
-
console.log(
|
|
92
|
-
chalk.dim(
|
|
93
|
-
' Detected redirect. Check if the API endpoint requires authentication or has changed.'
|
|
94
|
-
)
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (response.status === 401) {
|
|
100
|
-
console.log(
|
|
101
|
-
chalk.dim(' Hint: Your API key may be invalid or expired.')
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
process.exit(1);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const duration = ((Date.now() - startTime) / 1000).toFixed(2);
|
|
108
|
-
console.log(chalk.green(`\n✅ Upload successful! (${duration}s)`));
|
|
109
|
-
console.log(chalk.cyan(` View results: ${serverUrl}/dashboard`));
|
|
110
|
-
|
|
111
|
-
if (uploadResult.analysis) {
|
|
112
|
-
console.log(chalk.dim(` Analysis ID: ${uploadResult.analysis.id}`));
|
|
113
|
-
console.log(chalk.dim(` Score: ${uploadResult.analysis.aiScore}/100`));
|
|
114
|
-
}
|
|
115
|
-
} catch (error) {
|
|
116
|
-
handleCLIError(error, 'Upload');
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export const uploadHelpText = `
|
|
121
|
-
EXAMPLES:
|
|
122
|
-
$ aiready upload report.json --api-key ar_...
|
|
123
|
-
$ aiready upload .aiready/latest.json
|
|
124
|
-
$ AIREADY_API_KEY=ar_... aiready upload report.json
|
|
125
|
-
|
|
126
|
-
ENVIRONMENT VARIABLES:
|
|
127
|
-
AIREADY_API_KEY Your platform API key
|
|
128
|
-
AIREADY_SERVER Custom platform URL (default: https://dev.platform.getaiready.dev)
|
|
129
|
-
`;
|
|
@@ -1,321 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Visualize command - Generate interactive visualization from an AIReady report
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
import { writeFileSync, readFileSync, existsSync, copyFileSync } from 'fs';
|
|
7
|
-
import { resolve as resolvePath } from 'path';
|
|
8
|
-
import { spawn } from 'child_process';
|
|
9
|
-
import { handleCLIError } from '@aiready/core';
|
|
10
|
-
import { generateHTML, findLatestReport } from '@aiready/core';
|
|
11
|
-
|
|
12
|
-
interface VisualizeOptions {
|
|
13
|
-
report?: string;
|
|
14
|
-
output?: string;
|
|
15
|
-
open?: boolean;
|
|
16
|
-
serve?: boolean | number;
|
|
17
|
-
dev?: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* CLI action handler for the "visualize" command.
|
|
22
|
-
* Generates an interactive dependency graph visualization of the project
|
|
23
|
-
* to help understand code structure and AI context usage.
|
|
24
|
-
*
|
|
25
|
-
* @param directory - The directory to analyze and visualize
|
|
26
|
-
* @param options - CLI options from commander
|
|
27
|
-
*/
|
|
28
|
-
export async function visualizeAction(
|
|
29
|
-
directory: string,
|
|
30
|
-
options: VisualizeOptions
|
|
31
|
-
) {
|
|
32
|
-
try {
|
|
33
|
-
const dirPath = resolvePath(process.cwd(), directory ?? '.');
|
|
34
|
-
let reportPath = options.report
|
|
35
|
-
? resolvePath(dirPath, options.report)
|
|
36
|
-
: null;
|
|
37
|
-
|
|
38
|
-
// If report not provided or not found, try to find latest scan report
|
|
39
|
-
if (!reportPath || !existsSync(reportPath)) {
|
|
40
|
-
const latestScan = findLatestReport(dirPath);
|
|
41
|
-
if (latestScan) {
|
|
42
|
-
reportPath = latestScan;
|
|
43
|
-
console.log(
|
|
44
|
-
chalk.dim(`Found latest report: ${latestScan.split('/').pop()}`)
|
|
45
|
-
);
|
|
46
|
-
} else {
|
|
47
|
-
console.error(chalk.red('❌ No AI readiness report found'));
|
|
48
|
-
console.log(
|
|
49
|
-
chalk.dim(
|
|
50
|
-
`\nGenerate a report with:\n aiready scan --output json\n\nOr specify a custom report:\n aiready visualise --report <path-to-report.json>`
|
|
51
|
-
)
|
|
52
|
-
);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const raw = readFileSync(reportPath, 'utf8');
|
|
58
|
-
const report = JSON.parse(raw);
|
|
59
|
-
|
|
60
|
-
// Load config to extract graph caps
|
|
61
|
-
const configPath = resolvePath(dirPath, 'aiready.json');
|
|
62
|
-
let graphConfig = { maxNodes: 400, maxEdges: 600 };
|
|
63
|
-
|
|
64
|
-
if (existsSync(configPath)) {
|
|
65
|
-
try {
|
|
66
|
-
const rawConfig = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
67
|
-
if (rawConfig.visualizer?.graph) {
|
|
68
|
-
graphConfig = {
|
|
69
|
-
maxNodes:
|
|
70
|
-
rawConfig.visualizer.graph.maxNodes ?? graphConfig.maxNodes,
|
|
71
|
-
maxEdges:
|
|
72
|
-
rawConfig.visualizer.graph.maxEdges ?? graphConfig.maxEdges,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
} catch (e) {
|
|
76
|
-
void e;
|
|
77
|
-
// Silently ignore parse errors and use defaults
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Store config in env for vite middleware to pass to client
|
|
82
|
-
const envVisualizerConfig = JSON.stringify(graphConfig);
|
|
83
|
-
process.env.AIREADY_VISUALIZER_CONFIG = envVisualizerConfig;
|
|
84
|
-
|
|
85
|
-
console.log('Building graph from report...');
|
|
86
|
-
const { GraphBuilder } = await import('@aiready/visualizer/graph');
|
|
87
|
-
const graph = GraphBuilder.buildFromReport(report, dirPath);
|
|
88
|
-
|
|
89
|
-
// Check if --dev mode is requested and available
|
|
90
|
-
let useDevMode = options.dev ?? false;
|
|
91
|
-
let devServerStarted = false;
|
|
92
|
-
|
|
93
|
-
if (useDevMode) {
|
|
94
|
-
try {
|
|
95
|
-
const localWebDir = resolvePath(dirPath, 'packages/visualizer');
|
|
96
|
-
let webDir = '';
|
|
97
|
-
let visualizerAvailable = false;
|
|
98
|
-
|
|
99
|
-
if (existsSync(localWebDir)) {
|
|
100
|
-
webDir = localWebDir;
|
|
101
|
-
visualizerAvailable = true;
|
|
102
|
-
} else {
|
|
103
|
-
// Try to resolve installed @aiready/visualizer package from node_modules
|
|
104
|
-
const nodemodulesLocations: string[] = [
|
|
105
|
-
resolvePath(dirPath, 'node_modules', '@aiready', 'visualizer'),
|
|
106
|
-
resolvePath(
|
|
107
|
-
process.cwd(),
|
|
108
|
-
'node_modules',
|
|
109
|
-
'@aiready',
|
|
110
|
-
'visualizer'
|
|
111
|
-
),
|
|
112
|
-
];
|
|
113
|
-
|
|
114
|
-
// Walk up directory tree to find node_modules in parent directories
|
|
115
|
-
let currentDir = dirPath;
|
|
116
|
-
while (currentDir !== '/' && currentDir !== '.') {
|
|
117
|
-
nodemodulesLocations.push(
|
|
118
|
-
resolvePath(currentDir, 'node_modules', '@aiready', 'visualizer')
|
|
119
|
-
);
|
|
120
|
-
const parent = resolvePath(currentDir, '..');
|
|
121
|
-
if (parent === currentDir) break;
|
|
122
|
-
currentDir = parent;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
for (const location of nodemodulesLocations) {
|
|
126
|
-
if (
|
|
127
|
-
existsSync(location) &&
|
|
128
|
-
existsSync(resolvePath(location, 'package.json'))
|
|
129
|
-
) {
|
|
130
|
-
webDir = location;
|
|
131
|
-
visualizerAvailable = true;
|
|
132
|
-
break;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Fallback: try require.resolve
|
|
137
|
-
if (!visualizerAvailable) {
|
|
138
|
-
try {
|
|
139
|
-
const vizPkgPath =
|
|
140
|
-
require.resolve('@aiready/visualizer/package.json');
|
|
141
|
-
webDir = resolvePath(vizPkgPath, '..');
|
|
142
|
-
visualizerAvailable = true;
|
|
143
|
-
} catch (err) {
|
|
144
|
-
void err;
|
|
145
|
-
// Visualizer not found
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Check if web directory with vite config exists (required for dev mode)
|
|
151
|
-
const webViteConfigExists =
|
|
152
|
-
webDir && existsSync(resolvePath(webDir, 'web', 'vite.config.ts'));
|
|
153
|
-
|
|
154
|
-
if (visualizerAvailable && webViteConfigExists) {
|
|
155
|
-
// Dev mode is available - start Vite dev server
|
|
156
|
-
const spawnCwd = webDir!;
|
|
157
|
-
|
|
158
|
-
// Inline report watcher: copy report to web/report-data.json and watch for changes
|
|
159
|
-
const { watch } = await import('fs');
|
|
160
|
-
const copyReportToViz = () => {
|
|
161
|
-
try {
|
|
162
|
-
const destPath = resolvePath(spawnCwd, 'web', 'report-data.json');
|
|
163
|
-
copyFileSync(reportPath!, destPath);
|
|
164
|
-
console.log(`📋 Report synced to ${destPath}`);
|
|
165
|
-
} catch (e) {
|
|
166
|
-
console.error('Failed to sync report:', e);
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
// Initial copy
|
|
171
|
-
copyReportToViz();
|
|
172
|
-
|
|
173
|
-
// Watch source report for changes
|
|
174
|
-
let watchTimeout: NodeJS.Timeout | null = null;
|
|
175
|
-
const reportWatcher = watch(reportPath, () => {
|
|
176
|
-
if (watchTimeout) clearTimeout(watchTimeout);
|
|
177
|
-
watchTimeout = setTimeout(copyReportToViz, 100);
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
const envForSpawn = {
|
|
181
|
-
...process.env,
|
|
182
|
-
AIREADY_REPORT_PATH: reportPath,
|
|
183
|
-
AIREADY_VISUALIZER_CONFIG: envVisualizerConfig,
|
|
184
|
-
};
|
|
185
|
-
const vite = spawn('pnpm', ['run', 'dev:web'], {
|
|
186
|
-
cwd: spawnCwd,
|
|
187
|
-
stdio: 'inherit',
|
|
188
|
-
shell: true,
|
|
189
|
-
env: envForSpawn,
|
|
190
|
-
});
|
|
191
|
-
const onExit = () => {
|
|
192
|
-
try {
|
|
193
|
-
reportWatcher.close();
|
|
194
|
-
} catch (err) {
|
|
195
|
-
void err;
|
|
196
|
-
}
|
|
197
|
-
try {
|
|
198
|
-
vite.kill();
|
|
199
|
-
} catch (err) {
|
|
200
|
-
void err;
|
|
201
|
-
}
|
|
202
|
-
process.exit(0);
|
|
203
|
-
};
|
|
204
|
-
process.on('SIGINT', onExit);
|
|
205
|
-
process.on('SIGTERM', onExit);
|
|
206
|
-
devServerStarted = true;
|
|
207
|
-
void devServerStarted;
|
|
208
|
-
return;
|
|
209
|
-
} else {
|
|
210
|
-
console.log(
|
|
211
|
-
chalk.yellow(
|
|
212
|
-
'⚠️ Dev server not available (requires local @aiready/visualizer with web assets).'
|
|
213
|
-
)
|
|
214
|
-
);
|
|
215
|
-
console.log(
|
|
216
|
-
chalk.cyan(' Falling back to static HTML generation...\n')
|
|
217
|
-
);
|
|
218
|
-
useDevMode = false;
|
|
219
|
-
}
|
|
220
|
-
} catch (err) {
|
|
221
|
-
console.error('Failed to start dev server:', err);
|
|
222
|
-
console.log(
|
|
223
|
-
chalk.cyan(' Falling back to static HTML generation...\n')
|
|
224
|
-
);
|
|
225
|
-
useDevMode = false;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// Generate static HTML (default behavior or fallback from failed --dev)
|
|
230
|
-
console.log('Generating HTML...');
|
|
231
|
-
const html = generateHTML(graph as any);
|
|
232
|
-
const defaultOutput = 'visualization.html';
|
|
233
|
-
const outPath = resolvePath(dirPath, options.output ?? defaultOutput);
|
|
234
|
-
writeFileSync(outPath, html, 'utf8');
|
|
235
|
-
console.log(chalk.green(`✅ Visualization written to: ${outPath}`));
|
|
236
|
-
|
|
237
|
-
if (options.open || options.serve) {
|
|
238
|
-
const opener =
|
|
239
|
-
process.platform === 'darwin'
|
|
240
|
-
? 'open'
|
|
241
|
-
: process.platform === 'win32'
|
|
242
|
-
? 'start'
|
|
243
|
-
: 'xdg-open';
|
|
244
|
-
|
|
245
|
-
if (options.serve) {
|
|
246
|
-
try {
|
|
247
|
-
const port = typeof options.serve === 'number' ? options.serve : 5173;
|
|
248
|
-
const http = await import('http');
|
|
249
|
-
const fsp = await import('fs/promises');
|
|
250
|
-
|
|
251
|
-
const server = http.createServer(async (req, res) => {
|
|
252
|
-
try {
|
|
253
|
-
const urlPath = req.url ?? '/';
|
|
254
|
-
if (urlPath === '/' || urlPath === '/index.html') {
|
|
255
|
-
const content = await fsp.readFile(outPath, 'utf8');
|
|
256
|
-
res.writeHead(200, {
|
|
257
|
-
'Content-Type': 'text/html; charset=utf-8',
|
|
258
|
-
});
|
|
259
|
-
res.end(content);
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
263
|
-
res.end('Not found');
|
|
264
|
-
} catch (e: any) {
|
|
265
|
-
void e;
|
|
266
|
-
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
267
|
-
res.end('Server error');
|
|
268
|
-
}
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
server.listen(port, () => {
|
|
272
|
-
const addr = `http://localhost:${port}/`;
|
|
273
|
-
console.log(
|
|
274
|
-
chalk.cyan(`🌐 Local visualization server running at ${addr}`)
|
|
275
|
-
);
|
|
276
|
-
spawn(opener, [`"${addr}"`], { shell: true });
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
process.on('SIGINT', () => {
|
|
280
|
-
server.close();
|
|
281
|
-
process.exit(0);
|
|
282
|
-
});
|
|
283
|
-
} catch (err) {
|
|
284
|
-
console.error('Failed to start local server:', err);
|
|
285
|
-
}
|
|
286
|
-
} else if (options.open) {
|
|
287
|
-
spawn(opener, [`"${outPath}"`], { shell: true });
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
} catch (err: any) {
|
|
291
|
-
handleCLIError(err, 'Visualization');
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
export const visualizeHelpText = `
|
|
296
|
-
EXAMPLES:
|
|
297
|
-
$ aiready visualize . # Auto-detects latest report, generates HTML
|
|
298
|
-
$ aiready visualize . --report .aiready/aiready-report-20260217-143022.json
|
|
299
|
-
$ aiready visualize . --report report.json -o out/visualization.html --open
|
|
300
|
-
$ aiready visualize . --report report.json --serve
|
|
301
|
-
$ aiready visualize . --report report.json --serve 8080
|
|
302
|
-
$ aiready visualize . --report report.json --dev
|
|
303
|
-
|
|
304
|
-
NOTES:
|
|
305
|
-
- The value passed to --report is interpreted relative to the directory argument (first positional).
|
|
306
|
-
If the report is not found, the CLI will suggest running 'aiready scan' to generate it.
|
|
307
|
-
- Default output path: visualization.html (in the current directory).
|
|
308
|
-
- --serve starts a tiny single-file HTTP server (default port: 5173) and opens your browser.
|
|
309
|
-
- --dev starts a Vite dev server with live reload (requires local @aiready/visualizer installation).
|
|
310
|
-
When --dev is not available, it falls back to static HTML generation.
|
|
311
|
-
`;
|
|
312
|
-
|
|
313
|
-
export const visualiseHelpText = `
|
|
314
|
-
EXAMPLES:
|
|
315
|
-
$ aiready visualise . # Auto-detects latest report
|
|
316
|
-
$ aiready visualise . --report .aiready/aiready-report-20260217-143022.json
|
|
317
|
-
$ aiready visualise . --report report.json --serve 8080
|
|
318
|
-
|
|
319
|
-
NOTES:
|
|
320
|
-
- Same options as 'visualize'. Use --serve to host the static HTML, or --dev for live reload.
|
|
321
|
-
`;
|