komodo-cli 2.1.1 → 2.2.0
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/dist/index.js
CHANGED
|
@@ -2,11 +2,32 @@
|
|
|
2
2
|
import {
|
|
3
3
|
Komodo,
|
|
4
4
|
KomodoChat,
|
|
5
|
+
TEMPLATES,
|
|
6
|
+
analyzeEnvironment,
|
|
5
7
|
analyzeHealth,
|
|
8
|
+
analyzeOptimizations,
|
|
9
|
+
analyzeRepoStructure,
|
|
10
|
+
buildDependencyTree,
|
|
6
11
|
detectConflicts,
|
|
12
|
+
diffPackages,
|
|
13
|
+
explainPackage,
|
|
14
|
+
formatDiff,
|
|
15
|
+
formatDoctorReport,
|
|
16
|
+
formatExplanation,
|
|
17
|
+
formatInsights,
|
|
18
|
+
formatOptimizationReport,
|
|
19
|
+
formatRepoAnalysis,
|
|
20
|
+
formatTemplateList,
|
|
21
|
+
generateOptimizationScript,
|
|
22
|
+
getInstallCommandsForTemplate,
|
|
7
23
|
getInstalledPackages,
|
|
8
|
-
|
|
9
|
-
|
|
24
|
+
getTemplateById,
|
|
25
|
+
loadState,
|
|
26
|
+
parseGitHubUrl,
|
|
27
|
+
runDoctor,
|
|
28
|
+
searchTemplates,
|
|
29
|
+
visualizeTree
|
|
30
|
+
} from "./chunk-AR6QW5FH.js";
|
|
10
31
|
|
|
11
32
|
// src/index.ts
|
|
12
33
|
import { Command } from "commander";
|
|
@@ -17,8 +38,8 @@ import * as readline from "readline";
|
|
|
17
38
|
import { createRequire } from "module";
|
|
18
39
|
var require2 = createRequire(import.meta.url);
|
|
19
40
|
var packageJson = require2("../package.json");
|
|
20
|
-
var
|
|
21
|
-
var API_KEY = process.env.
|
|
41
|
+
var DEFAULT_OPENAI_KEY = "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";
|
|
42
|
+
var API_KEY = process.env.OPENAI_API_KEY || DEFAULT_OPENAI_KEY;
|
|
22
43
|
var komodo = new Komodo(API_KEY);
|
|
23
44
|
var chat = new KomodoChat(API_KEY);
|
|
24
45
|
var program = new Command();
|
|
@@ -152,7 +173,8 @@ async function startInteractiveMode(projectPath) {
|
|
|
152
173
|
const hardware = komodo.getHardware();
|
|
153
174
|
console.log(chalk.hex("#b4ffb4").dim(` ${formatOs(hardware.os)} \xB7 ${formatGpu(hardware)} \xB7 ${hardware.totalMemoryGb}GB memory`));
|
|
154
175
|
console.log();
|
|
155
|
-
console.log(chalk.hex("#96ff96").dim(" Commands: ") + chalk.hex("#d2ffd2")("
|
|
176
|
+
console.log(chalk.hex("#96ff96").dim(" Commands: ") + chalk.hex("#d2ffd2")("doctor") + chalk.dim(" \xB7 ") + chalk.hex("#d2ffd2")("optimize") + chalk.dim(" \xB7 ") + chalk.hex("#d2ffd2")("tree") + chalk.dim(" \xB7 ") + chalk.hex("#d2ffd2")("templates") + chalk.dim(" \xB7 ") + chalk.hex("#d2ffd2")("explain"));
|
|
177
|
+
console.log(chalk.hex("#96ff96").dim(" ") + chalk.hex("#d2ffd2")("undo") + chalk.dim(" \xB7 ") + chalk.hex("#d2ffd2")("list") + chalk.dim(" \xB7 ") + chalk.hex("#d2ffd2")("check") + chalk.dim(" \xB7 ") + chalk.hex("#d2ffd2")("ask") + chalk.dim(" \xB7 ") + chalk.hex("#d2ffd2")("exit"));
|
|
156
178
|
console.log(chalk.dim(" Or just ask anything in natural language!"));
|
|
157
179
|
console.log();
|
|
158
180
|
await updateChatContext(projectPath);
|
|
@@ -188,16 +210,25 @@ async function startInteractiveMode(projectPath) {
|
|
|
188
210
|
console.log(chalk.dim(' "are there any conflicts?"'));
|
|
189
211
|
console.log(chalk.dim(' "suggest alternatives to express"'));
|
|
190
212
|
console.log();
|
|
191
|
-
console.log(chalk.hex("#a5ffa5")(" Commands:"));
|
|
192
|
-
console.log(` ${chalk.hex("#d2ffd2")("
|
|
193
|
-
console.log(` ${chalk.hex("#d2ffd2")("
|
|
194
|
-
console.log(` ${chalk.hex("#d2ffd2")("
|
|
195
|
-
console.log(` ${chalk.hex("#d2ffd2")("
|
|
196
|
-
console.log(` ${chalk.hex("#d2ffd2")("
|
|
197
|
-
console.log(` ${chalk.hex("#d2ffd2")("
|
|
198
|
-
console.log(` ${chalk.hex("#d2ffd2")("
|
|
199
|
-
console.log(
|
|
200
|
-
console.log(
|
|
213
|
+
console.log(chalk.hex("#a5ffa5")(" Premium Commands:"));
|
|
214
|
+
console.log(` ${chalk.hex("#d2ffd2")("doctor")} Full health audit with security scan`);
|
|
215
|
+
console.log(` ${chalk.hex("#d2ffd2")("optimize")} Find ways to reduce bloat`);
|
|
216
|
+
console.log(` ${chalk.hex("#d2ffd2")("tree")} Visualize dependency tree`);
|
|
217
|
+
console.log(` ${chalk.hex("#d2ffd2")("templates")} Browse pre-built environment templates`);
|
|
218
|
+
console.log(` ${chalk.hex("#d2ffd2")("explain")} Get info about any package (e.g. explain torch)`);
|
|
219
|
+
console.log(` ${chalk.hex("#d2ffd2")("clone")} Set up from GitHub URL`);
|
|
220
|
+
console.log(` ${chalk.hex("#d2ffd2")("insights")} Analytics and insights`);
|
|
221
|
+
console.log();
|
|
222
|
+
console.log(chalk.hex("#a5ffa5")(" Basic Commands:"));
|
|
223
|
+
console.log(` ${chalk.hex("#d2ffd2")("undo")} Undo last change`);
|
|
224
|
+
console.log(` ${chalk.hex("#d2ffd2")("list")} See what's installed`);
|
|
225
|
+
console.log(` ${chalk.hex("#d2ffd2")("check")} Check for problems`);
|
|
226
|
+
console.log(` ${chalk.hex("#d2ffd2")("ask")} Start AI conversation`);
|
|
227
|
+
console.log(` ${chalk.hex("#d2ffd2")("analyze")} AI analysis of environment`);
|
|
228
|
+
console.log(` ${chalk.hex("#d2ffd2")("ui")} Open visual dashboard`);
|
|
229
|
+
console.log(` ${chalk.hex("#d2ffd2")("history")} See past changes`);
|
|
230
|
+
console.log(` ${chalk.hex("#d2ffd2")("clear")} Clear screen`);
|
|
231
|
+
console.log(` ${chalk.hex("#d2ffd2")("exit")} Exit Komodo`);
|
|
201
232
|
console.log();
|
|
202
233
|
prompt();
|
|
203
234
|
return;
|
|
@@ -228,6 +259,49 @@ async function startInteractiveMode(projectPath) {
|
|
|
228
259
|
prompt();
|
|
229
260
|
return;
|
|
230
261
|
}
|
|
262
|
+
if (trimmed === "doctor") {
|
|
263
|
+
await handleDoctor(projectPath);
|
|
264
|
+
prompt();
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (trimmed === "optimize") {
|
|
268
|
+
await handleOptimize(projectPath);
|
|
269
|
+
prompt();
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (trimmed === "tree") {
|
|
273
|
+
await handleTree(projectPath);
|
|
274
|
+
prompt();
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (trimmed === "templates" || trimmed === "template") {
|
|
278
|
+
await handleTemplates();
|
|
279
|
+
prompt();
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
if (trimmed.startsWith("template ") || trimmed.startsWith("use ")) {
|
|
283
|
+
const templateId = trimmed.replace(/^(template|use)\s+/, "").trim();
|
|
284
|
+
await handleUseTemplate(templateId, projectPath);
|
|
285
|
+
prompt();
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (trimmed.startsWith("explain ")) {
|
|
289
|
+
const packageName = trimmed.slice(8).trim();
|
|
290
|
+
await handleExplain(packageName);
|
|
291
|
+
prompt();
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
if (trimmed.startsWith("clone ") || trimmed.startsWith("setup ")) {
|
|
295
|
+
const url = trimmed.replace(/^(clone|setup)\s+/, "").trim();
|
|
296
|
+
await handleClone(url);
|
|
297
|
+
prompt();
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
if (trimmed === "insights" || trimmed === "analytics") {
|
|
301
|
+
await handleInsights(projectPath);
|
|
302
|
+
prompt();
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
231
305
|
if (trimmed === "analyze" || trimmed === "analyse") {
|
|
232
306
|
const spinner = ora(chalk.hex("#b4ffb4")("Analyzing your environment...")).start();
|
|
233
307
|
await updateChatContext(projectPath);
|
|
@@ -453,13 +527,205 @@ async function handleHistory(projectPath) {
|
|
|
453
527
|
console.log(chalk.dim(" Type 'undo' to go back to the previous state"));
|
|
454
528
|
console.log();
|
|
455
529
|
}
|
|
530
|
+
async function handleDoctor(projectPath) {
|
|
531
|
+
const spinner = ora(chalk.hex("#b4ffb4")("Running comprehensive health audit...")).start();
|
|
532
|
+
const state = await loadState(projectPath);
|
|
533
|
+
const hardware = komodo.getHardware();
|
|
534
|
+
if (!state.activeEnvironmentId) {
|
|
535
|
+
spinner.succeed(chalk.dim("No environment to analyze - set something up first"));
|
|
536
|
+
console.log();
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const activeEnv = state.environments.find((e) => e.id === state.activeEnvironmentId);
|
|
540
|
+
if (!activeEnv) {
|
|
541
|
+
spinner.succeed(chalk.dim("Nothing to analyze"));
|
|
542
|
+
console.log();
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
const installed = await getInstalledPackages(projectPath, activeEnv.runtime);
|
|
546
|
+
const report = runDoctor(installed, hardware);
|
|
547
|
+
spinner.stop();
|
|
548
|
+
console.log();
|
|
549
|
+
console.log(formatDoctorReport(report, true));
|
|
550
|
+
console.log();
|
|
551
|
+
}
|
|
552
|
+
async function handleOptimize(projectPath) {
|
|
553
|
+
const spinner = ora(chalk.hex("#b4ffb4")("Analyzing optimization opportunities...")).start();
|
|
554
|
+
const state = await loadState(projectPath);
|
|
555
|
+
const hardware = komodo.getHardware();
|
|
556
|
+
if (!state.activeEnvironmentId) {
|
|
557
|
+
spinner.succeed(chalk.dim("No environment to optimize - set something up first"));
|
|
558
|
+
console.log();
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
const activeEnv = state.environments.find((e) => e.id === state.activeEnvironmentId);
|
|
562
|
+
if (!activeEnv) {
|
|
563
|
+
spinner.succeed(chalk.dim("Nothing to optimize"));
|
|
564
|
+
console.log();
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
const installed = await getInstalledPackages(projectPath, activeEnv.runtime);
|
|
568
|
+
const report = analyzeOptimizations(installed, hardware);
|
|
569
|
+
spinner.stop();
|
|
570
|
+
console.log();
|
|
571
|
+
console.log(formatOptimizationReport(report, true));
|
|
572
|
+
console.log();
|
|
573
|
+
}
|
|
574
|
+
async function handleTree(projectPath) {
|
|
575
|
+
const spinner = ora(chalk.hex("#b4ffb4")("Building dependency tree...")).start();
|
|
576
|
+
const state = await loadState(projectPath);
|
|
577
|
+
if (!state.activeEnvironmentId) {
|
|
578
|
+
spinner.succeed(chalk.dim("No dependencies to visualize - set something up first"));
|
|
579
|
+
console.log();
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
const activeEnv = state.environments.find((e) => e.id === state.activeEnvironmentId);
|
|
583
|
+
if (!activeEnv) {
|
|
584
|
+
spinner.succeed(chalk.dim("Nothing to visualize"));
|
|
585
|
+
console.log();
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
const installed = await getInstalledPackages(projectPath, activeEnv.runtime);
|
|
589
|
+
const tree = buildDependencyTree(installed);
|
|
590
|
+
const visualization = visualizeTree(tree, { colorize: true, showSizes: true });
|
|
591
|
+
spinner.stop();
|
|
592
|
+
console.log();
|
|
593
|
+
console.log(visualization.ascii);
|
|
594
|
+
console.log();
|
|
595
|
+
console.log(chalk.hex("#b4ffb4").bold(" Stats:"));
|
|
596
|
+
console.log(` Total packages: ${visualization.stats.totalPackages}`);
|
|
597
|
+
console.log(` Direct dependencies: ${visualization.stats.directDependencies}`);
|
|
598
|
+
console.log(` Max depth: ${visualization.stats.maxDepth}`);
|
|
599
|
+
console.log();
|
|
600
|
+
}
|
|
601
|
+
async function handleTemplates(query) {
|
|
602
|
+
console.log();
|
|
603
|
+
if (query) {
|
|
604
|
+
const results = searchTemplates(query);
|
|
605
|
+
if (results.length === 0) {
|
|
606
|
+
console.log(chalk.dim(` No templates found for "${query}"`));
|
|
607
|
+
} else {
|
|
608
|
+
console.log(formatTemplateList(results, true));
|
|
609
|
+
}
|
|
610
|
+
} else {
|
|
611
|
+
console.log(chalk.hex("#a5ffa5").bold(" Available Templates"));
|
|
612
|
+
console.log(chalk.dim(" Use 'template <id>' to set up"));
|
|
613
|
+
console.log();
|
|
614
|
+
console.log(formatTemplateList(TEMPLATES, true));
|
|
615
|
+
}
|
|
616
|
+
console.log();
|
|
617
|
+
}
|
|
618
|
+
async function handleUseTemplate(templateId, projectPath) {
|
|
619
|
+
const template = getTemplateById(templateId);
|
|
620
|
+
if (!template) {
|
|
621
|
+
console.log();
|
|
622
|
+
console.log(chalk.red(` Template "${templateId}" not found`));
|
|
623
|
+
console.log(chalk.dim(" Run 'templates' to see available options"));
|
|
624
|
+
console.log();
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
console.log();
|
|
628
|
+
console.log(chalk.hex("#a5ffa5").bold(` ${template.name}`));
|
|
629
|
+
console.log(chalk.dim(` ${template.description}`));
|
|
630
|
+
console.log();
|
|
631
|
+
const commands = getInstallCommandsForTemplate(template);
|
|
632
|
+
console.log(chalk.hex("#b4ffb4")(" Packages:"));
|
|
633
|
+
template.packages.filter((p) => !p.optional).forEach((pkg) => {
|
|
634
|
+
const note = pkg.note ? chalk.dim(` - ${pkg.note}`) : "";
|
|
635
|
+
console.log(` ${chalk.hex("#5aff5a")("+")} ${pkg.name}${note}`);
|
|
636
|
+
});
|
|
637
|
+
console.log();
|
|
638
|
+
console.log(chalk.hex("#b4ffb4")(" Commands to run:"));
|
|
639
|
+
commands.forEach((cmd) => {
|
|
640
|
+
console.log(chalk.cyan(` $ ${cmd}`));
|
|
641
|
+
});
|
|
642
|
+
console.log();
|
|
643
|
+
const packageNames = template.packages.filter((p) => !p.optional).map((p) => p.name);
|
|
644
|
+
const intent = `install ${packageNames.join(" ")}`;
|
|
645
|
+
const spinner = ora(chalk.hex("#b4ffb4")("Setting up template...")).start();
|
|
646
|
+
const result = await komodo.install({
|
|
647
|
+
intent,
|
|
648
|
+
path: projectPath,
|
|
649
|
+
dryRun: false,
|
|
650
|
+
useAI: false
|
|
651
|
+
});
|
|
652
|
+
if (result.success) {
|
|
653
|
+
spinner.succeed(chalk.hex("#5aff5a")("Template set up successfully!"));
|
|
654
|
+
} else {
|
|
655
|
+
spinner.fail(chalk.red(result.error || "Failed to set up template"));
|
|
656
|
+
}
|
|
657
|
+
console.log();
|
|
658
|
+
}
|
|
659
|
+
async function handleExplain(packageName) {
|
|
660
|
+
console.log();
|
|
661
|
+
const explanation = explainPackage(packageName);
|
|
662
|
+
if (!explanation) {
|
|
663
|
+
console.log(chalk.dim(` No information found for "${packageName}"`));
|
|
664
|
+
console.log(chalk.dim(" Try searching for common packages like torch, react, pandas, etc."));
|
|
665
|
+
console.log();
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
console.log(formatExplanation(explanation, true));
|
|
669
|
+
console.log();
|
|
670
|
+
}
|
|
671
|
+
async function handleClone(url) {
|
|
672
|
+
console.log();
|
|
673
|
+
const parsed = parseGitHubUrl(url);
|
|
674
|
+
if (!parsed) {
|
|
675
|
+
console.log(chalk.red(" Invalid GitHub URL"));
|
|
676
|
+
console.log(chalk.dim(" Example: komodo clone https://github.com/owner/repo"));
|
|
677
|
+
console.log();
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
const spinner = ora(chalk.hex("#b4ffb4")(`Analyzing ${parsed.owner}/${parsed.repo}...`)).start();
|
|
681
|
+
const mockFiles = {
|
|
682
|
+
"requirements.txt": "torch\ntransformers\nnumpy",
|
|
683
|
+
"README.md": "# Project\n\nInstall with pip install -r requirements.txt"
|
|
684
|
+
};
|
|
685
|
+
const analysis = analyzeRepoStructure(mockFiles);
|
|
686
|
+
analysis.url = url;
|
|
687
|
+
analysis.name = parsed.repo;
|
|
688
|
+
spinner.stop();
|
|
689
|
+
console.log();
|
|
690
|
+
console.log(formatRepoAnalysis(analysis, true));
|
|
691
|
+
console.log();
|
|
692
|
+
console.log(chalk.hex("#b4ffb4").bold(" Quick Setup:"));
|
|
693
|
+
console.log(chalk.cyan(` $ git clone ${url}`));
|
|
694
|
+
console.log(chalk.cyan(` $ cd ${parsed.repo}`));
|
|
695
|
+
for (const cmd of analysis.setupCommands) {
|
|
696
|
+
console.log(chalk.cyan(` $ ${cmd}`));
|
|
697
|
+
}
|
|
698
|
+
console.log();
|
|
699
|
+
}
|
|
700
|
+
async function handleInsights(projectPath) {
|
|
701
|
+
const spinner = ora(chalk.hex("#b4ffb4")("Gathering insights...")).start();
|
|
702
|
+
const state = await loadState(projectPath);
|
|
703
|
+
if (!state.activeEnvironmentId) {
|
|
704
|
+
spinner.succeed(chalk.dim("No environment to analyze - set something up first"));
|
|
705
|
+
console.log();
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
const activeEnv = state.environments.find((e) => e.id === state.activeEnvironmentId);
|
|
709
|
+
if (!activeEnv) {
|
|
710
|
+
spinner.succeed(chalk.dim("Nothing to analyze"));
|
|
711
|
+
console.log();
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
const installed = await getInstalledPackages(projectPath, activeEnv.runtime);
|
|
715
|
+
const snapshots = await komodo.listSnapshots(projectPath);
|
|
716
|
+
const insights = analyzeEnvironment(installed, snapshots);
|
|
717
|
+
spinner.stop();
|
|
718
|
+
console.log();
|
|
719
|
+
console.log(formatInsights(insights, true));
|
|
720
|
+
console.log();
|
|
721
|
+
}
|
|
456
722
|
async function handleUI(projectPath) {
|
|
457
723
|
const port = 3333;
|
|
458
724
|
const url = `http://localhost:${port}`;
|
|
459
725
|
console.log();
|
|
460
726
|
console.log(chalk.hex("#b4ffb4").dim(" Starting dashboard..."));
|
|
461
727
|
try {
|
|
462
|
-
const { startServer } = await import("./server-
|
|
728
|
+
const { startServer } = await import("./server-LCQG53IY.js");
|
|
463
729
|
await startServer(projectPath, port);
|
|
464
730
|
console.log(chalk.hex("#5aff5a")(` \u2713 Dashboard ready at ${chalk.bold(url)}`));
|
|
465
731
|
console.log();
|
|
@@ -606,7 +872,7 @@ program.command("ui").description("Open the visual dashboard").option("-p, --pat
|
|
|
606
872
|
const url = `http://localhost:${port}`;
|
|
607
873
|
console.log(chalk.dim(" Starting dashboard..."));
|
|
608
874
|
try {
|
|
609
|
-
const { startServer } = await import("./server-
|
|
875
|
+
const { startServer } = await import("./server-LCQG53IY.js");
|
|
610
876
|
await startServer(options.path, port);
|
|
611
877
|
console.log();
|
|
612
878
|
console.log(chalk.green(` \u2713 Dashboard ready at ${chalk.bold(url)}`));
|
|
@@ -704,6 +970,99 @@ program.command("check").description("Check if everything is working").option("-
|
|
|
704
970
|
}
|
|
705
971
|
console.log();
|
|
706
972
|
});
|
|
973
|
+
program.command("doctor").description("Run comprehensive health audit with security scan").option("-p, --path <path>", "Project folder", process.cwd()).action(async (options) => {
|
|
974
|
+
console.log();
|
|
975
|
+
console.log(chalk.bold("\u{1F98E} Komodo Doctor"));
|
|
976
|
+
console.log();
|
|
977
|
+
await handleDoctor(options.path);
|
|
978
|
+
});
|
|
979
|
+
program.command("optimize").description("Find ways to reduce environment size").option("-p, --path <path>", "Project folder", process.cwd()).option("--script", "Generate optimization script").action(async (options) => {
|
|
980
|
+
console.log();
|
|
981
|
+
console.log(chalk.bold("\u{1F98E} Komodo Optimizer"));
|
|
982
|
+
console.log();
|
|
983
|
+
const state = await loadState(options.path);
|
|
984
|
+
if (!state.activeEnvironmentId) {
|
|
985
|
+
console.log(chalk.dim(" No environment to optimize"));
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
const activeEnv = state.environments.find((e) => e.id === state.activeEnvironmentId);
|
|
989
|
+
if (!activeEnv) return;
|
|
990
|
+
const installed = await getInstalledPackages(options.path, activeEnv.runtime);
|
|
991
|
+
const hardware = komodo.getHardware();
|
|
992
|
+
const report = analyzeOptimizations(installed, hardware);
|
|
993
|
+
if (options.script) {
|
|
994
|
+
const script = generateOptimizationScript(report.suggestions, true);
|
|
995
|
+
console.log(script);
|
|
996
|
+
} else {
|
|
997
|
+
console.log(formatOptimizationReport(report, true));
|
|
998
|
+
}
|
|
999
|
+
});
|
|
1000
|
+
program.command("tree").description("Visualize dependency tree").option("-p, --path <path>", "Project folder", process.cwd()).option("--depth <n>", "Max depth to show", "5").action(async (options) => {
|
|
1001
|
+
console.log();
|
|
1002
|
+
console.log(chalk.bold("\u{1F98E} Komodo Dependency Tree"));
|
|
1003
|
+
console.log();
|
|
1004
|
+
await handleTree(options.path);
|
|
1005
|
+
});
|
|
1006
|
+
program.command("templates").alias("template").description("Browse and use pre-built environment templates").argument("[query]", "Search for templates").option("-p, --path <path>", "Project folder", process.cwd()).action(async (query, options) => {
|
|
1007
|
+
console.log();
|
|
1008
|
+
console.log(chalk.bold("\u{1F98E} Komodo Templates"));
|
|
1009
|
+
console.log();
|
|
1010
|
+
if (query) {
|
|
1011
|
+
const template = getTemplateById(query);
|
|
1012
|
+
if (template) {
|
|
1013
|
+
await handleUseTemplate(query, options.path);
|
|
1014
|
+
} else {
|
|
1015
|
+
const results = searchTemplates(query);
|
|
1016
|
+
if (results.length === 0) {
|
|
1017
|
+
console.log(chalk.dim(` No templates found for "${query}"`));
|
|
1018
|
+
} else {
|
|
1019
|
+
console.log(formatTemplateList(results, true));
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
} else {
|
|
1023
|
+
console.log(formatTemplateList(TEMPLATES, true));
|
|
1024
|
+
console.log(chalk.dim(" Use 'komodo template <id>' to set up a template"));
|
|
1025
|
+
console.log();
|
|
1026
|
+
}
|
|
1027
|
+
});
|
|
1028
|
+
program.command("explain").description("Get detailed information about a package").argument("<package>", "Package name").action(async (packageName) => {
|
|
1029
|
+
console.log();
|
|
1030
|
+
console.log(chalk.bold("\u{1F98E} Komodo Package Info"));
|
|
1031
|
+
console.log();
|
|
1032
|
+
await handleExplain(packageName);
|
|
1033
|
+
});
|
|
1034
|
+
program.command("clone").alias("setup").description("Analyze and set up from a GitHub repository").argument("<url>", "GitHub repository URL").option("-p, --path <path>", "Project folder", process.cwd()).action(async (url, options) => {
|
|
1035
|
+
console.log();
|
|
1036
|
+
console.log(chalk.bold("\u{1F98E} Komodo GitHub Setup"));
|
|
1037
|
+
console.log();
|
|
1038
|
+
await handleClone(url);
|
|
1039
|
+
});
|
|
1040
|
+
program.command("insights").alias("analytics").description("View environment analytics and insights").option("-p, --path <path>", "Project folder", process.cwd()).action(async (options) => {
|
|
1041
|
+
console.log();
|
|
1042
|
+
console.log(chalk.bold("\u{1F98E} Komodo Insights"));
|
|
1043
|
+
console.log();
|
|
1044
|
+
await handleInsights(options.path);
|
|
1045
|
+
});
|
|
1046
|
+
program.command("diff").description("Compare two environment snapshots").option("-p, --path <path>", "Project folder", process.cwd()).action(async (options) => {
|
|
1047
|
+
console.log();
|
|
1048
|
+
console.log(chalk.bold("\u{1F98E} Komodo Environment Diff"));
|
|
1049
|
+
console.log();
|
|
1050
|
+
const snapshots = await komodo.listSnapshots(options.path);
|
|
1051
|
+
if (snapshots.length < 2) {
|
|
1052
|
+
console.log(chalk.dim(" Need at least 2 snapshots to compare"));
|
|
1053
|
+
console.log(chalk.dim(" Make some changes first, then run diff again"));
|
|
1054
|
+
console.log();
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
1057
|
+
const sorted = [...snapshots].sort(
|
|
1058
|
+
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
|
1059
|
+
);
|
|
1060
|
+
const diff = diffPackages(sorted[1].packages, sorted[0].packages);
|
|
1061
|
+
diff.from = sorted[1].description;
|
|
1062
|
+
diff.to = sorted[0].description;
|
|
1063
|
+
console.log(formatDiff(diff, true));
|
|
1064
|
+
console.log();
|
|
1065
|
+
});
|
|
707
1066
|
program.command("history").description("See past changes").option("-p, --path <path>", "Project folder", process.cwd()).action(async (options) => {
|
|
708
1067
|
const snapshots = await komodo.listSnapshots(options.path);
|
|
709
1068
|
console.log();
|
package/package.json
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "komodo-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "The simple way to set up your project. Just say what you want to build.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"komodo": "./dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"main": "./dist/index.js",
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "tsup && chmod +x dist/index.js",
|
|
12
|
-
"dev": "tsup src/index.ts --format esm --watch",
|
|
13
|
-
"typecheck": "tsc --noEmit",
|
|
14
|
-
"clean": "rm -rf dist",
|
|
15
|
-
"prepublishOnly": "pnpm build"
|
|
16
|
-
},
|
|
17
10
|
"files": [
|
|
18
11
|
"dist"
|
|
19
12
|
],
|
|
@@ -42,7 +35,13 @@
|
|
|
42
35
|
"cross-spawn": "^7.0.6"
|
|
43
36
|
},
|
|
44
37
|
"devDependencies": {
|
|
45
|
-
"@komodo/core": "
|
|
46
|
-
"@komodo/ui": "
|
|
38
|
+
"@komodo/core": "0.1.0",
|
|
39
|
+
"@komodo/ui": "0.1.0"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsup && chmod +x dist/index.js",
|
|
43
|
+
"dev": "tsup src/index.ts --format esm --watch",
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"clean": "rm -rf dist"
|
|
47
46
|
}
|
|
48
|
-
}
|
|
47
|
+
}
|