@aiready/cli 0.3.2 → 0.3.4

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.
@@ -1,6 +1,6 @@
1
1
 
2
2
  
3
- > @aiready/cli@0.3.2 build /Users/pengcao/projects/aiready/packages/cli
3
+ > @aiready/cli@0.3.4 build /Users/pengcao/projects/aiready/packages/cli
4
4
  > tsup src/index.ts src/cli.ts --format cjs,esm --dts
5
5
 
6
6
  CLI Building entry: src/cli.ts, src/index.ts
@@ -9,15 +9,15 @@
9
9
  CLI Target: es2020
10
10
  CJS Build start
11
11
  ESM Build start
12
- ESM dist/chunk-S6JWNLN7.mjs 1.40 KB
12
+ CJS dist/cli.js 9.79 KB
13
+ CJS dist/index.js 2.57 KB
14
+ CJS ⚡️ Build success in 55ms
15
+ ESM dist/chunk-KZKXZKES.mjs 1.45 KB
16
+ ESM dist/cli.mjs 6.94 KB
13
17
  ESM dist/index.mjs 138.00 B
14
- ESM dist/cli.mjs 8.11 KB
15
- ESM ⚡️ Build success in 18ms
16
- CJS dist/index.js 2.51 KB
17
- CJS dist/cli.js 10.97 KB
18
- CJS ⚡️ Build success in 18ms
18
+ ESM ⚡️ Build success in 54ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 492ms
20
+ DTS ⚡️ Build success in 529ms
21
21
  DTS dist/cli.d.ts 20.00 B
22
22
  DTS dist/index.d.ts 731.00 B
23
23
  DTS dist/cli.d.mts 20.00 B
@@ -0,0 +1,54 @@
1
+ // src/index.ts
2
+ import { analyzePatterns } from "@aiready/pattern-detect";
3
+ import { analyzeContext } from "@aiready/context-analyzer";
4
+ async function analyzeUnified(options) {
5
+ const startTime = Date.now();
6
+ const tools = options.tools || ["patterns", "context"];
7
+ const result = {
8
+ summary: {
9
+ totalIssues: 0,
10
+ toolsRun: tools,
11
+ executionTime: 0
12
+ }
13
+ };
14
+ if (tools.includes("patterns")) {
15
+ const patternResult = await analyzePatterns(options);
16
+ result.patterns = patternResult.results;
17
+ result.summary.totalIssues += patternResult.results.length;
18
+ }
19
+ if (tools.includes("context")) {
20
+ result.context = await analyzeContext(options);
21
+ result.summary.totalIssues += result.context?.length || 0;
22
+ }
23
+ result.summary.executionTime = Date.now() - startTime;
24
+ return result;
25
+ }
26
+ function generateUnifiedSummary(result) {
27
+ const { summary } = result;
28
+ let output = `\u{1F680} AIReady Analysis Complete
29
+
30
+ `;
31
+ output += `\u{1F4CA} Summary:
32
+ `;
33
+ output += ` Tools run: ${summary.toolsRun.join(", ")}
34
+ `;
35
+ output += ` Total issues found: ${summary.totalIssues}
36
+ `;
37
+ output += ` Execution time: ${(summary.executionTime / 1e3).toFixed(2)}s
38
+
39
+ `;
40
+ if (result.patterns?.length) {
41
+ output += `\u{1F50D} Pattern Analysis: ${result.patterns.length} issues
42
+ `;
43
+ }
44
+ if (result.context?.length) {
45
+ output += `\u{1F9E0} Context Analysis: ${result.context.length} issues
46
+ `;
47
+ }
48
+ return output;
49
+ }
50
+
51
+ export {
52
+ analyzeUnified,
53
+ generateUnifiedSummary
54
+ };
package/dist/cli.js CHANGED
@@ -40,8 +40,9 @@ async function analyzeUnified(options) {
40
40
  }
41
41
  };
42
42
  if (tools.includes("patterns")) {
43
- result.patterns = await (0, import_pattern_detect.analyzePatterns)(options);
44
- result.summary.totalIssues += result.patterns.length;
43
+ const patternResult = await (0, import_pattern_detect.analyzePatterns)(options);
44
+ result.patterns = patternResult.results;
45
+ result.summary.totalIssues += patternResult.results.length;
45
46
  }
46
47
  if (tools.includes("context")) {
47
48
  result.context = await (0, import_context_analyzer.analyzeContext)(options);
@@ -77,18 +78,16 @@ function generateUnifiedSummary(result) {
77
78
 
78
79
  // src/cli.ts
79
80
  var import_chalk = __toESM(require("chalk"));
80
- var import_fs = require("fs");
81
81
  var import_path = require("path");
82
82
  var import_core = require("@aiready/core");
83
- var import_fs2 = require("fs");
84
- var packageJson = JSON.parse((0, import_fs2.readFileSync)((0, import_path.join)(__dirname, "../package.json"), "utf8"));
83
+ var import_fs = require("fs");
84
+ var packageJson = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(__dirname, "../package.json"), "utf8"));
85
85
  var program = new import_commander.Command();
86
86
  program.name("aiready").description("AIReady - Unified AI-readiness analysis tools").version(packageJson.version).addHelpText("after", "\nCONFIGURATION:\n Supports config files: aiready.json, aiready.config.json, .aiready.json, .aireadyrc.json, aiready.config.js, .aireadyrc.js\n CLI options override config file settings");
87
87
  program.command("scan").description("Run unified analysis on a codebase").argument("<directory>", "Directory to analyze").option("-t, --tools <tools>", "Tools to run (comma-separated: patterns,context)", "patterns,context").option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").action(async (directory, options) => {
88
88
  console.log(import_chalk.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
89
89
  const startTime = Date.now();
90
90
  try {
91
- const config = (0, import_core.loadConfig)(directory);
92
91
  const defaults = {
93
92
  tools: ["patterns", "context"],
94
93
  include: void 0,
@@ -98,17 +97,15 @@ program.command("scan").description("Run unified analysis on a codebase").argume
98
97
  file: void 0
99
98
  }
100
99
  };
101
- const mergedConfig = (0, import_core.mergeConfigWithDefaults)(config, defaults);
102
- const finalOptions = {
103
- rootDir: directory,
104
- tools: options.tools ? options.tools.split(",").map((t) => t.trim()) : mergedConfig.tools,
105
- include: options.include?.split(",") || mergedConfig.include,
106
- exclude: options.exclude?.split(",") || mergedConfig.exclude
107
- };
100
+ const finalOptions = (0, import_core.loadMergedConfig)(directory, defaults, {
101
+ tools: options.tools ? options.tools.split(",").map((t) => t.trim()) : void 0,
102
+ include: options.include?.split(","),
103
+ exclude: options.exclude?.split(",")
104
+ });
108
105
  const results = await analyzeUnified(finalOptions);
109
- const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
110
- const outputFormat = options.output || mergedConfig.output?.format || "console";
111
- const outputFile = options.outputFile || mergedConfig.output?.file;
106
+ const elapsedTime = (0, import_core.getElapsedTime)(startTime);
107
+ const outputFormat = options.output || finalOptions.output?.format || "console";
108
+ const outputFile = options.outputFile || finalOptions.output?.file;
112
109
  if (outputFormat === "json") {
113
110
  const outputData = {
114
111
  ...results,
@@ -117,25 +114,18 @@ program.command("scan").description("Run unified analysis on a codebase").argume
117
114
  executionTime: parseFloat(elapsedTime)
118
115
  }
119
116
  };
120
- if (outputFile) {
121
- (0, import_fs.writeFileSync)(outputFile, JSON.stringify(outputData, null, 2));
122
- console.log(import_chalk.default.green(`\u2705 Results saved to ${outputFile}`));
123
- } else {
124
- console.log(JSON.stringify(outputData, null, 2));
125
- }
117
+ (0, import_core.handleJSONOutput)(outputData, outputFile, `\u2705 Results saved to ${outputFile}`);
126
118
  } else {
127
119
  console.log(generateUnifiedSummary(results));
128
120
  }
129
121
  } catch (error) {
130
- console.error(import_chalk.default.red("\u274C Analysis failed:"), error);
131
- process.exit(1);
122
+ (0, import_core.handleCLIError)(error, "Analysis");
132
123
  }
133
124
  });
134
125
  program.command("patterns").description("Run pattern detection analysis").argument("<directory>", "Directory to analyze").option("-s, --similarity <number>", "Minimum similarity score (0-1)", "0.40").option("-l, --min-lines <number>", "Minimum lines to consider", "5").option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").action(async (directory, options) => {
135
126
  console.log(import_chalk.default.blue("\u{1F50D} Analyzing patterns...\n"));
136
127
  const startTime = Date.now();
137
128
  try {
138
- const config = (0, import_core.loadConfig)(directory);
139
129
  const defaults = {
140
130
  minSimilarity: 0.4,
141
131
  minLines: 5,
@@ -146,46 +136,37 @@ program.command("patterns").description("Run pattern detection analysis").argume
146
136
  file: void 0
147
137
  }
148
138
  };
149
- const mergedConfig = (0, import_core.mergeConfigWithDefaults)(config, defaults);
150
- const finalOptions = {
151
- rootDir: directory,
152
- minSimilarity: options.similarity ? parseFloat(options.similarity) : mergedConfig.minSimilarity,
153
- minLines: options.minLines ? parseInt(options.minLines) : mergedConfig.minLines,
154
- include: options.include?.split(",") || mergedConfig.include,
155
- exclude: options.exclude?.split(",") || mergedConfig.exclude
156
- };
139
+ const finalOptions = (0, import_core.loadMergedConfig)(directory, defaults, {
140
+ minSimilarity: options.similarity ? parseFloat(options.similarity) : void 0,
141
+ minLines: options.minLines ? parseInt(options.minLines) : void 0,
142
+ include: options.include?.split(","),
143
+ exclude: options.exclude?.split(",")
144
+ });
157
145
  const { analyzePatterns: analyzePatterns2, generateSummary } = await import("@aiready/pattern-detect");
158
- const results = await analyzePatterns2(finalOptions);
159
- const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
146
+ const { results } = await analyzePatterns2(finalOptions);
147
+ const elapsedTime = (0, import_core.getElapsedTime)(startTime);
160
148
  const summary = generateSummary(results);
161
- const outputFormat = options.output || mergedConfig.output?.format || "console";
162
- const outputFile = options.outputFile || mergedConfig.output?.file;
149
+ const outputFormat = options.output || finalOptions.output?.format || "console";
150
+ const outputFile = options.outputFile || finalOptions.output?.file;
163
151
  if (outputFormat === "json") {
164
152
  const outputData = {
165
153
  results,
166
154
  summary: { ...summary, executionTime: parseFloat(elapsedTime) }
167
155
  };
168
- if (outputFile) {
169
- (0, import_fs.writeFileSync)(outputFile, JSON.stringify(outputData, null, 2));
170
- console.log(import_chalk.default.green(`\u2705 Results saved to ${outputFile}`));
171
- } else {
172
- console.log(JSON.stringify(outputData, null, 2));
173
- }
156
+ (0, import_core.handleJSONOutput)(outputData, outputFile, `\u2705 Results saved to ${outputFile}`);
174
157
  } else {
175
158
  console.log(`Pattern Analysis Complete (${elapsedTime}s)`);
176
159
  console.log(`Found ${summary.totalPatterns} duplicate patterns`);
177
160
  console.log(`Total token cost: ${summary.totalTokenCost} tokens`);
178
161
  }
179
162
  } catch (error) {
180
- console.error(import_chalk.default.red("\u274C Pattern analysis failed:"), error);
181
- process.exit(1);
163
+ (0, import_core.handleCLIError)(error, "Pattern analysis");
182
164
  }
183
165
  });
184
166
  program.command("context").description("Run context window cost analysis").argument("<directory>", "Directory to analyze").option("--max-depth <number>", "Maximum acceptable import depth", "5").option("--max-context <number>", "Maximum acceptable context budget (tokens)", "10000").option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").action(async (directory, options) => {
185
167
  console.log(import_chalk.default.blue("\u{1F9E0} Analyzing context costs...\n"));
186
168
  const startTime = Date.now();
187
169
  try {
188
- const config = (0, import_core.loadConfig)(directory);
189
170
  const defaults = {
190
171
  maxDepth: 5,
191
172
  maxContextBudget: 1e4,
@@ -196,31 +177,24 @@ program.command("context").description("Run context window cost analysis").argum
196
177
  file: void 0
197
178
  }
198
179
  };
199
- const mergedConfig = (0, import_core.mergeConfigWithDefaults)(config, defaults);
200
- const finalOptions = {
201
- rootDir: directory,
202
- maxDepth: options.maxDepth ? parseInt(options.maxDepth) : mergedConfig.maxDepth,
203
- maxContextBudget: options.maxContext ? parseInt(options.maxContext) : mergedConfig.maxContextBudget,
204
- include: options.include?.split(",") || mergedConfig.include,
205
- exclude: options.exclude?.split(",") || mergedConfig.exclude
206
- };
180
+ const finalOptions = (0, import_core.loadMergedConfig)(directory, defaults, {
181
+ maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
182
+ maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
183
+ include: options.include?.split(","),
184
+ exclude: options.exclude?.split(",")
185
+ });
207
186
  const { analyzeContext: analyzeContext2, generateSummary } = await import("@aiready/context-analyzer");
208
187
  const results = await analyzeContext2(finalOptions);
209
- const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
188
+ const elapsedTime = (0, import_core.getElapsedTime)(startTime);
210
189
  const summary = generateSummary(results);
211
- const outputFormat = options.output || mergedConfig.output?.format || "console";
212
- const outputFile = options.outputFile || mergedConfig.output?.file;
190
+ const outputFormat = options.output || finalOptions.output?.format || "console";
191
+ const outputFile = options.outputFile || finalOptions.output?.file;
213
192
  if (outputFormat === "json") {
214
193
  const outputData = {
215
194
  results,
216
195
  summary: { ...summary, executionTime: parseFloat(elapsedTime) }
217
196
  };
218
- if (outputFile) {
219
- (0, import_fs.writeFileSync)(outputFile, JSON.stringify(outputData, null, 2));
220
- console.log(import_chalk.default.green(`\u2705 Results saved to ${outputFile}`));
221
- } else {
222
- console.log(JSON.stringify(outputData, null, 2));
223
- }
197
+ (0, import_core.handleJSONOutput)(outputData, outputFile, `\u2705 Results saved to ${outputFile}`);
224
198
  } else {
225
199
  console.log(`Context Analysis Complete (${elapsedTime}s)`);
226
200
  console.log(`Files analyzed: ${summary.totalFiles}`);
@@ -229,8 +203,7 @@ program.command("context").description("Run context window cost analysis").argum
229
203
  console.log(`Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(1)}%`);
230
204
  }
231
205
  } catch (error) {
232
- console.error(import_chalk.default.red("\u274C Context analysis failed:"), error);
233
- process.exit(1);
206
+ (0, import_core.handleCLIError)(error, "Context analysis");
234
207
  }
235
208
  });
236
209
  program.parse();
package/dist/cli.mjs CHANGED
@@ -2,14 +2,13 @@
2
2
  import {
3
3
  analyzeUnified,
4
4
  generateUnifiedSummary
5
- } from "./chunk-S6JWNLN7.mjs";
5
+ } from "./chunk-KZKXZKES.mjs";
6
6
 
7
7
  // src/cli.ts
8
8
  import { Command } from "commander";
9
9
  import chalk from "chalk";
10
- import { writeFileSync } from "fs";
11
10
  import { join } from "path";
12
- import { loadConfig, mergeConfigWithDefaults } from "@aiready/core";
11
+ import { loadMergedConfig, handleJSONOutput, handleCLIError, getElapsedTime } from "@aiready/core";
13
12
  import { readFileSync } from "fs";
14
13
  var packageJson = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf8"));
15
14
  var program = new Command();
@@ -18,7 +17,6 @@ program.command("scan").description("Run unified analysis on a codebase").argume
18
17
  console.log(chalk.blue("\u{1F680} Starting AIReady unified analysis...\n"));
19
18
  const startTime = Date.now();
20
19
  try {
21
- const config = loadConfig(directory);
22
20
  const defaults = {
23
21
  tools: ["patterns", "context"],
24
22
  include: void 0,
@@ -28,17 +26,15 @@ program.command("scan").description("Run unified analysis on a codebase").argume
28
26
  file: void 0
29
27
  }
30
28
  };
31
- const mergedConfig = mergeConfigWithDefaults(config, defaults);
32
- const finalOptions = {
33
- rootDir: directory,
34
- tools: options.tools ? options.tools.split(",").map((t) => t.trim()) : mergedConfig.tools,
35
- include: options.include?.split(",") || mergedConfig.include,
36
- exclude: options.exclude?.split(",") || mergedConfig.exclude
37
- };
29
+ const finalOptions = loadMergedConfig(directory, defaults, {
30
+ tools: options.tools ? options.tools.split(",").map((t) => t.trim()) : void 0,
31
+ include: options.include?.split(","),
32
+ exclude: options.exclude?.split(",")
33
+ });
38
34
  const results = await analyzeUnified(finalOptions);
39
- const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
40
- const outputFormat = options.output || mergedConfig.output?.format || "console";
41
- const outputFile = options.outputFile || mergedConfig.output?.file;
35
+ const elapsedTime = getElapsedTime(startTime);
36
+ const outputFormat = options.output || finalOptions.output?.format || "console";
37
+ const outputFile = options.outputFile || finalOptions.output?.file;
42
38
  if (outputFormat === "json") {
43
39
  const outputData = {
44
40
  ...results,
@@ -47,25 +43,18 @@ program.command("scan").description("Run unified analysis on a codebase").argume
47
43
  executionTime: parseFloat(elapsedTime)
48
44
  }
49
45
  };
50
- if (outputFile) {
51
- writeFileSync(outputFile, JSON.stringify(outputData, null, 2));
52
- console.log(chalk.green(`\u2705 Results saved to ${outputFile}`));
53
- } else {
54
- console.log(JSON.stringify(outputData, null, 2));
55
- }
46
+ handleJSONOutput(outputData, outputFile, `\u2705 Results saved to ${outputFile}`);
56
47
  } else {
57
48
  console.log(generateUnifiedSummary(results));
58
49
  }
59
50
  } catch (error) {
60
- console.error(chalk.red("\u274C Analysis failed:"), error);
61
- process.exit(1);
51
+ handleCLIError(error, "Analysis");
62
52
  }
63
53
  });
64
54
  program.command("patterns").description("Run pattern detection analysis").argument("<directory>", "Directory to analyze").option("-s, --similarity <number>", "Minimum similarity score (0-1)", "0.40").option("-l, --min-lines <number>", "Minimum lines to consider", "5").option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").action(async (directory, options) => {
65
55
  console.log(chalk.blue("\u{1F50D} Analyzing patterns...\n"));
66
56
  const startTime = Date.now();
67
57
  try {
68
- const config = loadConfig(directory);
69
58
  const defaults = {
70
59
  minSimilarity: 0.4,
71
60
  minLines: 5,
@@ -76,46 +65,37 @@ program.command("patterns").description("Run pattern detection analysis").argume
76
65
  file: void 0
77
66
  }
78
67
  };
79
- const mergedConfig = mergeConfigWithDefaults(config, defaults);
80
- const finalOptions = {
81
- rootDir: directory,
82
- minSimilarity: options.similarity ? parseFloat(options.similarity) : mergedConfig.minSimilarity,
83
- minLines: options.minLines ? parseInt(options.minLines) : mergedConfig.minLines,
84
- include: options.include?.split(",") || mergedConfig.include,
85
- exclude: options.exclude?.split(",") || mergedConfig.exclude
86
- };
68
+ const finalOptions = loadMergedConfig(directory, defaults, {
69
+ minSimilarity: options.similarity ? parseFloat(options.similarity) : void 0,
70
+ minLines: options.minLines ? parseInt(options.minLines) : void 0,
71
+ include: options.include?.split(","),
72
+ exclude: options.exclude?.split(",")
73
+ });
87
74
  const { analyzePatterns, generateSummary } = await import("@aiready/pattern-detect");
88
- const results = await analyzePatterns(finalOptions);
89
- const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
75
+ const { results } = await analyzePatterns(finalOptions);
76
+ const elapsedTime = getElapsedTime(startTime);
90
77
  const summary = generateSummary(results);
91
- const outputFormat = options.output || mergedConfig.output?.format || "console";
92
- const outputFile = options.outputFile || mergedConfig.output?.file;
78
+ const outputFormat = options.output || finalOptions.output?.format || "console";
79
+ const outputFile = options.outputFile || finalOptions.output?.file;
93
80
  if (outputFormat === "json") {
94
81
  const outputData = {
95
82
  results,
96
83
  summary: { ...summary, executionTime: parseFloat(elapsedTime) }
97
84
  };
98
- if (outputFile) {
99
- writeFileSync(outputFile, JSON.stringify(outputData, null, 2));
100
- console.log(chalk.green(`\u2705 Results saved to ${outputFile}`));
101
- } else {
102
- console.log(JSON.stringify(outputData, null, 2));
103
- }
85
+ handleJSONOutput(outputData, outputFile, `\u2705 Results saved to ${outputFile}`);
104
86
  } else {
105
87
  console.log(`Pattern Analysis Complete (${elapsedTime}s)`);
106
88
  console.log(`Found ${summary.totalPatterns} duplicate patterns`);
107
89
  console.log(`Total token cost: ${summary.totalTokenCost} tokens`);
108
90
  }
109
91
  } catch (error) {
110
- console.error(chalk.red("\u274C Pattern analysis failed:"), error);
111
- process.exit(1);
92
+ handleCLIError(error, "Pattern analysis");
112
93
  }
113
94
  });
114
95
  program.command("context").description("Run context window cost analysis").argument("<directory>", "Directory to analyze").option("--max-depth <number>", "Maximum acceptable import depth", "5").option("--max-context <number>", "Maximum acceptable context budget (tokens)", "10000").option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").action(async (directory, options) => {
115
96
  console.log(chalk.blue("\u{1F9E0} Analyzing context costs...\n"));
116
97
  const startTime = Date.now();
117
98
  try {
118
- const config = loadConfig(directory);
119
99
  const defaults = {
120
100
  maxDepth: 5,
121
101
  maxContextBudget: 1e4,
@@ -126,31 +106,24 @@ program.command("context").description("Run context window cost analysis").argum
126
106
  file: void 0
127
107
  }
128
108
  };
129
- const mergedConfig = mergeConfigWithDefaults(config, defaults);
130
- const finalOptions = {
131
- rootDir: directory,
132
- maxDepth: options.maxDepth ? parseInt(options.maxDepth) : mergedConfig.maxDepth,
133
- maxContextBudget: options.maxContext ? parseInt(options.maxContext) : mergedConfig.maxContextBudget,
134
- include: options.include?.split(",") || mergedConfig.include,
135
- exclude: options.exclude?.split(",") || mergedConfig.exclude
136
- };
109
+ const finalOptions = loadMergedConfig(directory, defaults, {
110
+ maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
111
+ maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
112
+ include: options.include?.split(","),
113
+ exclude: options.exclude?.split(",")
114
+ });
137
115
  const { analyzeContext, generateSummary } = await import("@aiready/context-analyzer");
138
116
  const results = await analyzeContext(finalOptions);
139
- const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
117
+ const elapsedTime = getElapsedTime(startTime);
140
118
  const summary = generateSummary(results);
141
- const outputFormat = options.output || mergedConfig.output?.format || "console";
142
- const outputFile = options.outputFile || mergedConfig.output?.file;
119
+ const outputFormat = options.output || finalOptions.output?.format || "console";
120
+ const outputFile = options.outputFile || finalOptions.output?.file;
143
121
  if (outputFormat === "json") {
144
122
  const outputData = {
145
123
  results,
146
124
  summary: { ...summary, executionTime: parseFloat(elapsedTime) }
147
125
  };
148
- if (outputFile) {
149
- writeFileSync(outputFile, JSON.stringify(outputData, null, 2));
150
- console.log(chalk.green(`\u2705 Results saved to ${outputFile}`));
151
- } else {
152
- console.log(JSON.stringify(outputData, null, 2));
153
- }
126
+ handleJSONOutput(outputData, outputFile, `\u2705 Results saved to ${outputFile}`);
154
127
  } else {
155
128
  console.log(`Context Analysis Complete (${elapsedTime}s)`);
156
129
  console.log(`Files analyzed: ${summary.totalFiles}`);
@@ -159,8 +132,7 @@ program.command("context").description("Run context window cost analysis").argum
159
132
  console.log(`Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(1)}%`);
160
133
  }
161
134
  } catch (error) {
162
- console.error(chalk.red("\u274C Context analysis failed:"), error);
163
- process.exit(1);
135
+ handleCLIError(error, "Context analysis");
164
136
  }
165
137
  });
166
138
  program.parse();
package/dist/index.js CHANGED
@@ -37,8 +37,9 @@ async function analyzeUnified(options) {
37
37
  }
38
38
  };
39
39
  if (tools.includes("patterns")) {
40
- result.patterns = await (0, import_pattern_detect.analyzePatterns)(options);
41
- result.summary.totalIssues += result.patterns.length;
40
+ const patternResult = await (0, import_pattern_detect.analyzePatterns)(options);
41
+ result.patterns = patternResult.results;
42
+ result.summary.totalIssues += patternResult.results.length;
42
43
  }
43
44
  if (tools.includes("context")) {
44
45
  result.context = await (0, import_context_analyzer.analyzeContext)(options);
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  analyzeUnified,
3
3
  generateUnifiedSummary
4
- } from "./chunk-S6JWNLN7.mjs";
4
+ } from "./chunk-KZKXZKES.mjs";
5
5
  export {
6
6
  analyzeUnified,
7
7
  generateUnifiedSummary
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/cli",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "Unified CLI for AIReady analysis tools",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -11,9 +11,9 @@
11
11
  "dependencies": {
12
12
  "commander": "^12.1.0",
13
13
  "chalk": "^5.3.0",
14
- "@aiready/core": "0.3.0",
15
- "@aiready/pattern-detect": "0.7.0",
16
- "@aiready/context-analyzer": "0.3.0"
14
+ "@aiready/core": "0.3.2",
15
+ "@aiready/pattern-detect": "0.7.6",
16
+ "@aiready/context-analyzer": "0.3.4"
17
17
  },
18
18
  "devDependencies": {
19
19
  "tsup": "^8.3.5",
package/src/cli.ts CHANGED
@@ -5,7 +5,7 @@ import { analyzeUnified, generateUnifiedSummary } from './index';
5
5
  import chalk from 'chalk';
6
6
  import { writeFileSync } from 'fs';
7
7
  import { join } from 'path';
8
- import { loadConfig, mergeConfigWithDefaults } from '@aiready/core';
8
+ import { loadMergedConfig, handleJSONOutput, handleCLIError, getElapsedTime } from '@aiready/core';
9
9
  import { readFileSync } from 'fs';
10
10
 
11
11
  const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf8'));
@@ -33,9 +33,6 @@ program
33
33
  const startTime = Date.now();
34
34
 
35
35
  try {
36
- // Load config file if it exists
37
- const config = loadConfig(directory);
38
-
39
36
  // Define defaults
40
37
  const defaults = {
41
38
  tools: ['patterns', 'context'],
@@ -47,23 +44,19 @@ program
47
44
  },
48
45
  };
49
46
 
50
- // Merge config with defaults
51
- const mergedConfig = mergeConfigWithDefaults(config, defaults);
52
-
53
- // Override with CLI options (CLI takes precedence)
54
- const finalOptions = {
55
- rootDir: directory,
56
- tools: options.tools ? options.tools.split(',').map((t: string) => t.trim()) as ('patterns' | 'context')[] : mergedConfig.tools,
57
- include: options.include?.split(',') || mergedConfig.include,
58
- exclude: options.exclude?.split(',') || mergedConfig.exclude,
59
- };
47
+ // Load and merge config with CLI options
48
+ const finalOptions = loadMergedConfig(directory, defaults, {
49
+ tools: options.tools ? options.tools.split(',').map((t: string) => t.trim()) as ('patterns' | 'context')[] : undefined,
50
+ include: options.include?.split(','),
51
+ exclude: options.exclude?.split(','),
52
+ }) as any;
60
53
 
61
54
  const results = await analyzeUnified(finalOptions);
62
55
 
63
- const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(2);
56
+ const elapsedTime = getElapsedTime(startTime);
64
57
 
65
- const outputFormat = options.output || mergedConfig.output?.format || 'console';
66
- const outputFile = options.outputFile || mergedConfig.output?.file;
58
+ const outputFormat = options.output || finalOptions.output?.format || 'console';
59
+ const outputFile = options.outputFile || finalOptions.output?.file;
67
60
 
68
61
  if (outputFormat === 'json') {
69
62
  const outputData = {
@@ -74,19 +67,13 @@ program
74
67
  },
75
68
  };
76
69
 
77
- if (outputFile) {
78
- writeFileSync(outputFile, JSON.stringify(outputData, null, 2));
79
- console.log(chalk.green(`✅ Results saved to ${outputFile}`));
80
- } else {
81
- console.log(JSON.stringify(outputData, null, 2));
82
- }
70
+ handleJSONOutput(outputData, outputFile, `✅ Results saved to ${outputFile}`);
83
71
  } else {
84
72
  // Console output
85
73
  console.log(generateUnifiedSummary(results));
86
74
  }
87
75
  } catch (error) {
88
- console.error(chalk.red('Analysis failed:'), error);
89
- process.exit(1);
76
+ handleCLIError(error, 'Analysis');
90
77
  }
91
78
  });
92
79
 
@@ -107,9 +94,6 @@ program
107
94
  const startTime = Date.now();
108
95
 
109
96
  try {
110
- // Load config file if it exists
111
- const config = loadConfig(directory);
112
-
113
97
  // Define defaults
114
98
  const defaults = {
115
99
  minSimilarity: 0.4,
@@ -122,27 +106,23 @@ program
122
106
  },
123
107
  };
124
108
 
125
- // Merge config with defaults
126
- const mergedConfig = mergeConfigWithDefaults(config, defaults);
127
-
128
- // Override with CLI options (CLI takes precedence)
129
- const finalOptions = {
130
- rootDir: directory,
131
- minSimilarity: options.similarity ? parseFloat(options.similarity) : mergedConfig.minSimilarity,
132
- minLines: options.minLines ? parseInt(options.minLines) : mergedConfig.minLines,
133
- include: options.include?.split(',') || mergedConfig.include,
134
- exclude: options.exclude?.split(',') || mergedConfig.exclude,
135
- };
109
+ // Load and merge config with CLI options
110
+ const finalOptions = loadMergedConfig(directory, defaults, {
111
+ minSimilarity: options.similarity ? parseFloat(options.similarity) : undefined,
112
+ minLines: options.minLines ? parseInt(options.minLines) : undefined,
113
+ include: options.include?.split(','),
114
+ exclude: options.exclude?.split(','),
115
+ });
136
116
 
137
117
  const { analyzePatterns, generateSummary } = await import('@aiready/pattern-detect');
138
118
 
139
- const results = await analyzePatterns(finalOptions);
119
+ const { results } = await analyzePatterns(finalOptions);
140
120
 
141
- const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(2);
121
+ const elapsedTime = getElapsedTime(startTime);
142
122
  const summary = generateSummary(results);
143
123
 
144
- const outputFormat = options.output || mergedConfig.output?.format || 'console';
145
- const outputFile = options.outputFile || mergedConfig.output?.file;
124
+ const outputFormat = options.output || finalOptions.output?.format || 'console';
125
+ const outputFile = options.outputFile || finalOptions.output?.file;
146
126
 
147
127
  if (outputFormat === 'json') {
148
128
  const outputData = {
@@ -150,20 +130,14 @@ program
150
130
  summary: { ...summary, executionTime: parseFloat(elapsedTime) },
151
131
  };
152
132
 
153
- if (outputFile) {
154
- writeFileSync(outputFile, JSON.stringify(outputData, null, 2));
155
- console.log(chalk.green(`✅ Results saved to ${outputFile}`));
156
- } else {
157
- console.log(JSON.stringify(outputData, null, 2));
158
- }
133
+ handleJSONOutput(outputData, outputFile, `✅ Results saved to ${outputFile}`);
159
134
  } else {
160
135
  console.log(`Pattern Analysis Complete (${elapsedTime}s)`);
161
136
  console.log(`Found ${summary.totalPatterns} duplicate patterns`);
162
137
  console.log(`Total token cost: ${summary.totalTokenCost} tokens`);
163
138
  }
164
139
  } catch (error) {
165
- console.error(chalk.red('Pattern analysis failed:'), error);
166
- process.exit(1);
140
+ handleCLIError(error, 'Pattern analysis');
167
141
  }
168
142
  });
169
143
 
@@ -183,9 +157,6 @@ program
183
157
  const startTime = Date.now();
184
158
 
185
159
  try {
186
- // Load config file if it exists
187
- const config = loadConfig(directory);
188
-
189
160
  // Define defaults
190
161
  const defaults = {
191
162
  maxDepth: 5,
@@ -198,27 +169,23 @@ program
198
169
  },
199
170
  };
200
171
 
201
- // Merge config with defaults
202
- const mergedConfig = mergeConfigWithDefaults(config, defaults);
203
-
204
- // Override with CLI options (CLI takes precedence)
205
- const finalOptions = {
206
- rootDir: directory,
207
- maxDepth: options.maxDepth ? parseInt(options.maxDepth) : mergedConfig.maxDepth,
208
- maxContextBudget: options.maxContext ? parseInt(options.maxContext) : mergedConfig.maxContextBudget,
209
- include: options.include?.split(',') || mergedConfig.include,
210
- exclude: options.exclude?.split(',') || mergedConfig.exclude,
211
- };
172
+ // Load and merge config with CLI options
173
+ const finalOptions = loadMergedConfig(directory, defaults, {
174
+ maxDepth: options.maxDepth ? parseInt(options.maxDepth) : undefined,
175
+ maxContextBudget: options.maxContext ? parseInt(options.maxContext) : undefined,
176
+ include: options.include?.split(','),
177
+ exclude: options.exclude?.split(','),
178
+ });
212
179
 
213
180
  const { analyzeContext, generateSummary } = await import('@aiready/context-analyzer');
214
181
 
215
182
  const results = await analyzeContext(finalOptions);
216
183
 
217
- const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(2);
184
+ const elapsedTime = getElapsedTime(startTime);
218
185
  const summary = generateSummary(results);
219
186
 
220
- const outputFormat = options.output || mergedConfig.output?.format || 'console';
221
- const outputFile = options.outputFile || mergedConfig.output?.file;
187
+ const outputFormat = options.output || finalOptions.output?.format || 'console';
188
+ const outputFile = options.outputFile || finalOptions.output?.file;
222
189
 
223
190
  if (outputFormat === 'json') {
224
191
  const outputData = {
@@ -226,12 +193,7 @@ program
226
193
  summary: { ...summary, executionTime: parseFloat(elapsedTime) },
227
194
  };
228
195
 
229
- if (outputFile) {
230
- writeFileSync(outputFile, JSON.stringify(outputData, null, 2));
231
- console.log(chalk.green(`✅ Results saved to ${outputFile}`));
232
- } else {
233
- console.log(JSON.stringify(outputData, null, 2));
234
- }
196
+ handleJSONOutput(outputData, outputFile, `✅ Results saved to ${outputFile}`);
235
197
  } else {
236
198
  console.log(`Context Analysis Complete (${elapsedTime}s)`);
237
199
  console.log(`Files analyzed: ${summary.totalFiles}`);
@@ -240,8 +202,7 @@ program
240
202
  console.log(`Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(1)}%`);
241
203
  }
242
204
  } catch (error) {
243
- console.error(chalk.red('Context analysis failed:'), error);
244
- process.exit(1);
205
+ handleCLIError(error, 'Context analysis');
245
206
  }
246
207
  });
247
208
 
package/src/index.ts CHANGED
@@ -32,8 +32,9 @@ export async function analyzeUnified(
32
32
 
33
33
  // Run pattern detection
34
34
  if (tools.includes('patterns')) {
35
- result.patterns = await analyzePatterns(options);
36
- result.summary.totalIssues += result.patterns.length;
35
+ const patternResult = await analyzePatterns(options);
36
+ result.patterns = patternResult.results;
37
+ result.summary.totalIssues += patternResult.results.length;
37
38
  }
38
39
 
39
40
  // Run context analysis