komodo-cli 2.2.0 → 2.4.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.
@@ -35,9 +35,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
35
35
  ));
36
36
 
37
37
  // ../core/dist/index.js
38
- import { randomUUID as randomUUID2 } from "crypto";
38
+ import { randomUUID as randomUUID3 } from "crypto";
39
39
  import { mkdir as mkdir3 } from "fs/promises";
40
- import { existsSync as existsSync3 } from "fs";
40
+ import { existsSync as existsSync4 } from "fs";
41
41
  import { resolve } from "path";
42
42
  import { execSync } from "child_process";
43
43
  import os from "os";
@@ -52,6 +52,11 @@ import { randomUUID } from "crypto";
52
52
  import { mkdir as mkdir2, writeFile as writeFile3, readFile as readFile3 } from "fs/promises";
53
53
  import { existsSync as existsSync2 } from "fs";
54
54
  import { join as join3 } from "path";
55
+ import { execa as execa3 } from "execa";
56
+ import { existsSync as existsSync3 } from "fs";
57
+ import { readFile as readFile4 } from "fs/promises";
58
+ import { join as join4 } from "path";
59
+ import { randomUUID as randomUUID2 } from "crypto";
55
60
 
56
61
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
57
62
  var external_exports = {};
@@ -4095,10 +4100,12 @@ var coerce = {
4095
4100
  var NEVER = INVALID;
4096
4101
 
4097
4102
  // ../core/dist/index.js
4098
- import { execa as execa3 } from "execa";
4099
- import { existsSync as existsSync4 } from "fs";
4100
- import { readFile as readFile4 } from "fs/promises";
4101
- import { join as join5 } from "path";
4103
+ import { execa as execa4 } from "execa";
4104
+ import { existsSync as existsSync5 } from "fs";
4105
+ import { join as join6 } from "path";
4106
+ import { randomUUID as randomUUID4 } from "crypto";
4107
+ import { execa as execa5 } from "execa";
4108
+ import { execa as execa6 } from "execa";
4102
4109
  function detectOs() {
4103
4110
  const platform = os.platform();
4104
4111
  if (platform === "darwin") return "darwin";
@@ -4938,9 +4945,19 @@ async function listSnapshots(basePath, environmentId) {
4938
4945
  }
4939
4946
  return state.snapshots;
4940
4947
  }
4941
- var DEFAULT_MODEL = "llama-3.3-70b";
4942
- var DEFAULT_MAX_TOKENS = 2048;
4943
- var DEFAULT_TEMPERATURE = 0.2;
4948
+ async function getLatestSnapshot(basePath, environmentId) {
4949
+ const snapshots = await listSnapshots(basePath, environmentId);
4950
+ if (snapshots.length === 0) {
4951
+ return void 0;
4952
+ }
4953
+ snapshots.sort(
4954
+ (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
4955
+ );
4956
+ return snapshots[0];
4957
+ }
4958
+ var DEFAULT_MODEL = "zai-glm-4.7";
4959
+ var DEFAULT_MAX_TOKENS = 4096;
4960
+ var DEFAULT_TEMPERATURE = 0.7;
4944
4961
  var CerebrasAI = class {
4945
4962
  apiKey;
4946
4963
  model;
@@ -5146,7 +5163,7 @@ var KomodoChat = class {
5146
5163
  baseUrl = "https://api.cerebras.ai/v1";
5147
5164
  conversationHistory = [];
5148
5165
  context = null;
5149
- constructor(apiKey, model = "llama-3.3-70b") {
5166
+ constructor(apiKey, model = "zai-glm-4.7") {
5150
5167
  this.apiKey = apiKey;
5151
5168
  this.model = model;
5152
5169
  }
@@ -5273,13 +5290,14 @@ Only include the JSON block if you're recommending specific package changes.`;
5273
5290
  body: JSON.stringify({
5274
5291
  model: this.model,
5275
5292
  messages,
5276
- max_tokens: 2048,
5277
- temperature: 0.3,
5293
+ max_tokens: 4096,
5294
+ temperature: 0.7,
5278
5295
  top_p: 1
5279
5296
  })
5280
5297
  });
5281
5298
  if (!response.ok) {
5282
- throw new Error(`API error: ${response.status}`);
5299
+ const error = await response.text();
5300
+ throw new Error(`API error: ${response.status} - ${error}`);
5283
5301
  }
5284
5302
  const data = await response.json();
5285
5303
  return data.choices[0]?.message?.content ?? "";
@@ -5320,6 +5338,450 @@ Only include the JSON block if you're recommending specific package changes.`;
5320
5338
  return result;
5321
5339
  }
5322
5340
  };
5341
+ var KNOWN_CONFLICTS = [
5342
+ {
5343
+ packages: ["tensorflow", "torch"],
5344
+ reason: "Both use significant GPU memory and may conflict",
5345
+ suggestion: "Use separate environments for TensorFlow and PyTorch projects"
5346
+ },
5347
+ {
5348
+ packages: ["numpy", "jax"],
5349
+ reason: "JAX includes its own numpy-like API that may conflict",
5350
+ suggestion: "Use jax.numpy instead of importing both"
5351
+ },
5352
+ {
5353
+ packages: ["PIL", "pillow"],
5354
+ reason: "PIL and Pillow are the same library, cannot coexist",
5355
+ suggestion: "Remove PIL and use Pillow instead"
5356
+ },
5357
+ {
5358
+ packages: ["opencv-python", "opencv-contrib-python"],
5359
+ reason: "These packages overlap and can cause import conflicts",
5360
+ suggestion: "Use opencv-contrib-python only (includes all opencv-python features)"
5361
+ },
5362
+ {
5363
+ packages: ["tensorflow", "tensorflow-gpu"],
5364
+ reason: "TensorFlow 2.x already includes GPU support",
5365
+ suggestion: "Remove tensorflow-gpu and use tensorflow only"
5366
+ },
5367
+ {
5368
+ packages: ["requests", "urllib3"],
5369
+ reason: "Requests includes urllib3, may cause version conflicts",
5370
+ suggestion: "Let requests manage its own urllib3 dependency"
5371
+ },
5372
+ {
5373
+ packages: ["pandas", "numpy"],
5374
+ reason: "Version mismatch between pandas and numpy can cause errors",
5375
+ suggestion: "Ensure compatible versions or let pandas manage numpy version"
5376
+ },
5377
+ {
5378
+ packages: ["jupyter", "ipython"],
5379
+ reason: "Conflicting IPython versions",
5380
+ suggestion: "Use jupyter only, which includes IPython"
5381
+ },
5382
+ {
5383
+ packages: ["scikit-learn", "sklearn"],
5384
+ reason: "sklearn is deprecated, scikit-learn is the correct package",
5385
+ suggestion: "Remove sklearn and use scikit-learn only"
5386
+ },
5387
+ {
5388
+ packages: ["pyyaml", "yaml"],
5389
+ reason: "Different YAML parsers can conflict",
5390
+ suggestion: "Use pyyaml only"
5391
+ },
5392
+ // Node.js conflicts
5393
+ {
5394
+ packages: ["moment", "dayjs"],
5395
+ reason: "Both date libraries serve same purpose, adds bundle bloat",
5396
+ suggestion: "Choose one date library (dayjs is lighter)"
5397
+ },
5398
+ {
5399
+ packages: ["axios", "node-fetch"],
5400
+ reason: "Both HTTP clients serve same purpose",
5401
+ suggestion: "Choose one HTTP client"
5402
+ },
5403
+ {
5404
+ packages: ["lodash", "underscore"],
5405
+ reason: "Both utility libraries serve same purpose",
5406
+ suggestion: "Choose one utility library (lodash is more feature-complete)"
5407
+ },
5408
+ {
5409
+ packages: ["express", "koa"],
5410
+ reason: "Both web frameworks, cannot be used together",
5411
+ suggestion: "Choose one web framework"
5412
+ },
5413
+ {
5414
+ packages: ["react", "vue"],
5415
+ reason: "Cannot use multiple frontend frameworks simultaneously",
5416
+ suggestion: "Choose one frontend framework"
5417
+ },
5418
+ {
5419
+ packages: ["webpack", "vite"],
5420
+ reason: "Both bundlers serve same purpose",
5421
+ suggestion: "Choose one bundler (vite is faster for development)"
5422
+ },
5423
+ {
5424
+ packages: ["eslint", "tslint"],
5425
+ reason: "TSLint is deprecated in favor of ESLint",
5426
+ suggestion: "Remove tslint and use eslint with @typescript-eslint"
5427
+ },
5428
+ {
5429
+ packages: ["node-sass", "sass"],
5430
+ reason: "node-sass is deprecated, sass is the new implementation",
5431
+ suggestion: "Remove node-sass and use sass (dart-sass)"
5432
+ }
5433
+ ];
5434
+ async function getInstalledPackages(path, runtime) {
5435
+ if (runtime === "python") {
5436
+ return getPythonPackages(path);
5437
+ } else {
5438
+ return getNodePackages(path);
5439
+ }
5440
+ }
5441
+ async function getPythonPackages(path) {
5442
+ const venvPath = join4(path, ".venv");
5443
+ if (!existsSync3(venvPath)) {
5444
+ return [];
5445
+ }
5446
+ try {
5447
+ const pipPath = join4(venvPath, "bin", "pip");
5448
+ const result = await execa3(pipPath, ["list", "--format=json"], { cwd: path });
5449
+ const packages = JSON.parse(result.stdout);
5450
+ return packages.map((pkg) => ({
5451
+ name: pkg.name,
5452
+ version: pkg.version
5453
+ }));
5454
+ } catch {
5455
+ try {
5456
+ const result = await execa3(
5457
+ "uv",
5458
+ ["pip", "list", "--format=json", "--python", join4(venvPath, "bin", "python")],
5459
+ { cwd: path }
5460
+ );
5461
+ const packages = JSON.parse(result.stdout);
5462
+ return packages.map((pkg) => ({
5463
+ name: pkg.name,
5464
+ version: pkg.version
5465
+ }));
5466
+ } catch {
5467
+ return [];
5468
+ }
5469
+ }
5470
+ }
5471
+ async function getNodePackages(path) {
5472
+ const packageJsonPath = join4(path, "package.json");
5473
+ if (!existsSync3(packageJsonPath)) {
5474
+ return [];
5475
+ }
5476
+ try {
5477
+ const content = await readFile4(packageJsonPath, "utf-8");
5478
+ const packageJson = JSON.parse(content);
5479
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
5480
+ const packages = [];
5481
+ for (const [name, version] of Object.entries(deps)) {
5482
+ packages.push({
5483
+ name,
5484
+ version: String(version).replace(/^[\^~]/, "")
5485
+ });
5486
+ }
5487
+ return packages;
5488
+ } catch {
5489
+ return [];
5490
+ }
5491
+ }
5492
+ function detectConflicts(packages) {
5493
+ const conflicts = [];
5494
+ const packageNames = packages.map((p) => p.name.toLowerCase());
5495
+ for (const known of KNOWN_CONFLICTS) {
5496
+ const [pkg1, pkg2] = known.packages;
5497
+ if (packageNames.includes(pkg1) && packageNames.includes(pkg2)) {
5498
+ conflicts.push({
5499
+ package1: pkg1,
5500
+ package2: pkg2,
5501
+ reason: known.reason,
5502
+ severity: "warning",
5503
+ suggestion: known.suggestion
5504
+ });
5505
+ }
5506
+ }
5507
+ return conflicts;
5508
+ }
5509
+ function analyzeHealth(packages, conflicts) {
5510
+ const issues = [];
5511
+ let score = 100;
5512
+ for (const conflict of conflicts) {
5513
+ issues.push({
5514
+ type: "conflict",
5515
+ severity: conflict.severity,
5516
+ title: `${conflict.package1} and ${conflict.package2} may conflict`,
5517
+ description: conflict.reason,
5518
+ fix: conflict.suggestion,
5519
+ autoFixable: false
5520
+ });
5521
+ score -= conflict.severity === "error" ? 20 : 10;
5522
+ }
5523
+ const commonOutdated = ["requests", "axios", "lodash"];
5524
+ for (const pkg of packages) {
5525
+ if (commonOutdated.includes(pkg.name.toLowerCase())) {
5526
+ }
5527
+ }
5528
+ return {
5529
+ healthy: issues.filter((i) => i.severity === "error").length === 0,
5530
+ issues,
5531
+ score: Math.max(0, score)
5532
+ };
5533
+ }
5534
+ async function detectRealConflicts(path, runtime) {
5535
+ const conflicts = [];
5536
+ if (runtime === "python") {
5537
+ const venvPath = join4(path, ".venv");
5538
+ if (!existsSync3(venvPath)) {
5539
+ return conflicts;
5540
+ }
5541
+ try {
5542
+ const pipPath = join4(venvPath, "bin", "pip");
5543
+ const result = await execa3(pipPath, ["check"], { cwd: path, reject: false });
5544
+ if (result.exitCode !== 0 && result.stdout) {
5545
+ const lines = result.stdout.split("\n");
5546
+ for (const line of lines) {
5547
+ const match = line.match(/(\S+)\s+[\d.]+\s+requires\s+(\S+)\s*([>=<]+[\d.]+)?.*but.*you.*have\s+(\S+)\s+([\d.]+)/);
5548
+ if (match) {
5549
+ const [, pkg1, pkg2, requiredVersion, , actualVersion] = match;
5550
+ if (pkg1 && pkg2) {
5551
+ conflicts.push({
5552
+ package1: pkg1,
5553
+ package2: pkg2,
5554
+ reason: `${pkg1} requires ${pkg2}${requiredVersion || ""}, but ${actualVersion || "unknown version"} is installed`,
5555
+ severity: "error",
5556
+ suggestion: `Upgrade ${pkg2} to meet ${pkg1}'s requirements`
5557
+ });
5558
+ }
5559
+ }
5560
+ }
5561
+ }
5562
+ } catch {
5563
+ }
5564
+ } else {
5565
+ try {
5566
+ const result = await execa3("npm", ["ls", "--json"], {
5567
+ cwd: path,
5568
+ reject: false
5569
+ });
5570
+ if (result.stdout) {
5571
+ try {
5572
+ const output = JSON.parse(result.stdout);
5573
+ if (output.problems && Array.isArray(output.problems)) {
5574
+ for (const problem of output.problems) {
5575
+ const problemStr = String(problem);
5576
+ const match = problemStr.match(/(\S+)@[\d.]+\s+requires\s+(\S+)@([^\s]+)/);
5577
+ if (match) {
5578
+ const [, pkg1, pkg2, version] = match;
5579
+ if (pkg1 && pkg2) {
5580
+ conflicts.push({
5581
+ package1: pkg1,
5582
+ package2: pkg2,
5583
+ reason: `${pkg1} requires ${pkg2}@${version || "unknown"}`,
5584
+ severity: "warning",
5585
+ suggestion: `Install compatible version of ${pkg2}`
5586
+ });
5587
+ }
5588
+ } else {
5589
+ conflicts.push({
5590
+ package1: "unknown",
5591
+ package2: "unknown",
5592
+ reason: problemStr,
5593
+ severity: "warning"
5594
+ });
5595
+ }
5596
+ }
5597
+ }
5598
+ } catch {
5599
+ }
5600
+ }
5601
+ } catch {
5602
+ }
5603
+ }
5604
+ return conflicts;
5605
+ }
5606
+ async function checkPreInstallConflicts(path, runtime, newPackages) {
5607
+ const conflicts = [];
5608
+ const suggestions = [];
5609
+ const installed = await getInstalledPackages(path, runtime);
5610
+ const installedNames = installed.map((p) => p.name.toLowerCase());
5611
+ for (const newPkg of newPackages) {
5612
+ for (const known of KNOWN_CONFLICTS) {
5613
+ const [pkg1, pkg2] = known.packages;
5614
+ const newPkgName = newPkg.name.toLowerCase();
5615
+ if (newPkgName === pkg1 && installedNames.includes(pkg2)) {
5616
+ conflicts.push({
5617
+ package1: pkg1,
5618
+ package2: pkg2,
5619
+ reason: known.reason,
5620
+ severity: "warning",
5621
+ suggestion: known.suggestion
5622
+ });
5623
+ } else if (newPkgName === pkg2 && installedNames.includes(pkg1)) {
5624
+ conflicts.push({
5625
+ package1: pkg1,
5626
+ package2: pkg2,
5627
+ reason: known.reason,
5628
+ severity: "warning",
5629
+ suggestion: known.suggestion
5630
+ });
5631
+ }
5632
+ }
5633
+ }
5634
+ const newPackageNames = newPackages.map((p) => p.name.toLowerCase());
5635
+ for (const known of KNOWN_CONFLICTS) {
5636
+ const [pkg1, pkg2] = known.packages;
5637
+ if (newPackageNames.includes(pkg1) && newPackageNames.includes(pkg2)) {
5638
+ conflicts.push({
5639
+ package1: pkg1,
5640
+ package2: pkg2,
5641
+ reason: known.reason,
5642
+ severity: "warning",
5643
+ suggestion: known.suggestion
5644
+ });
5645
+ }
5646
+ }
5647
+ if (runtime === "python") {
5648
+ const venvPath = join4(path, ".venv");
5649
+ if (existsSync3(venvPath)) {
5650
+ try {
5651
+ const pipPath = join4(venvPath, "bin", "pip");
5652
+ const packageSpecs = newPackages.map(
5653
+ (p) => p.version ? `${p.name}==${p.version}` : p.name
5654
+ );
5655
+ const result = await execa3(
5656
+ pipPath,
5657
+ ["install", "--dry-run", ...packageSpecs],
5658
+ { cwd: path, reject: false }
5659
+ );
5660
+ if (result.exitCode !== 0 && result.stderr) {
5661
+ if (result.stderr.includes("ResolutionImpossible") || result.stderr.includes("incompatible")) {
5662
+ conflicts.push({
5663
+ package1: "new packages",
5664
+ package2: "existing packages",
5665
+ reason: "Package versions are incompatible",
5666
+ severity: "error",
5667
+ suggestion: "Review package version requirements"
5668
+ });
5669
+ }
5670
+ }
5671
+ } catch {
5672
+ }
5673
+ }
5674
+ } else {
5675
+ try {
5676
+ const packageSpecs = newPackages.map(
5677
+ (p) => p.version ? `${p.name}@${p.version}` : p.name
5678
+ );
5679
+ const result = await execa3(
5680
+ "npm",
5681
+ ["install", "--dry-run", ...packageSpecs],
5682
+ { cwd: path, reject: false }
5683
+ );
5684
+ if (result.exitCode !== 0 && result.stderr) {
5685
+ if (result.stderr.includes("ERESOLVE") || result.stderr.includes("conflict")) {
5686
+ conflicts.push({
5687
+ package1: "new packages",
5688
+ package2: "existing packages",
5689
+ reason: "Dependency resolution conflict",
5690
+ severity: "error",
5691
+ suggestion: "Review peer dependencies"
5692
+ });
5693
+ }
5694
+ }
5695
+ } catch {
5696
+ }
5697
+ }
5698
+ for (const conflict of conflicts) {
5699
+ if (conflict.package1 !== "unknown" && conflict.package2 !== "unknown") {
5700
+ suggestions.push({
5701
+ conflictId: randomUUID2(),
5702
+ strategy: "separate-env",
5703
+ packages: [],
5704
+ description: `Create separate environment for ${conflict.package1} and ${conflict.package2}`,
5705
+ friendlyDescription: "Use different projects for these packages",
5706
+ automated: false,
5707
+ risk: "safe"
5708
+ });
5709
+ }
5710
+ }
5711
+ return {
5712
+ willConflict: conflicts.length > 0,
5713
+ conflicts,
5714
+ suggestions
5715
+ };
5716
+ }
5717
+ async function resolveConflicts(path, runtime, conflicts, onProgress) {
5718
+ const resolved = [];
5719
+ const remaining = [];
5720
+ onProgress?.("Analyzing conflicts...");
5721
+ for (const conflict of conflicts) {
5722
+ if (conflict.package1 === "PIL" && conflict.package2 === "pillow") {
5723
+ onProgress?.("Removing deprecated PIL package...");
5724
+ try {
5725
+ if (runtime === "python") {
5726
+ const pipPath = join4(path, ".venv", "bin", "pip");
5727
+ await execa3(pipPath, ["uninstall", "-y", "PIL"], { cwd: path });
5728
+ resolved.push(`Removed ${conflict.package1}`);
5729
+ }
5730
+ } catch {
5731
+ remaining.push(conflict);
5732
+ }
5733
+ } else if (conflict.package1 === "tensorflow" && conflict.package2 === "tensorflow-gpu") {
5734
+ onProgress?.("Removing deprecated tensorflow-gpu...");
5735
+ try {
5736
+ if (runtime === "python") {
5737
+ const pipPath = join4(path, ".venv", "bin", "pip");
5738
+ await execa3(pipPath, ["uninstall", "-y", "tensorflow-gpu"], { cwd: path });
5739
+ resolved.push(`Removed ${conflict.package2}`);
5740
+ }
5741
+ } catch {
5742
+ remaining.push(conflict);
5743
+ }
5744
+ } else if (conflict.package1 === "sklearn" && conflict.package2 === "scikit-learn") {
5745
+ onProgress?.("Removing deprecated sklearn...");
5746
+ try {
5747
+ if (runtime === "python") {
5748
+ const pipPath = join4(path, ".venv", "bin", "pip");
5749
+ await execa3(pipPath, ["uninstall", "-y", "sklearn"], { cwd: path });
5750
+ resolved.push(`Removed ${conflict.package1}`);
5751
+ }
5752
+ } catch {
5753
+ remaining.push(conflict);
5754
+ }
5755
+ } else if (conflict.package1 === "tslint" && conflict.package2 === "eslint") {
5756
+ onProgress?.("Removing deprecated tslint...");
5757
+ try {
5758
+ if (runtime === "node") {
5759
+ await execa3("npm", ["uninstall", "tslint"], { cwd: path });
5760
+ resolved.push(`Removed ${conflict.package1}`);
5761
+ }
5762
+ } catch {
5763
+ remaining.push(conflict);
5764
+ }
5765
+ } else if (conflict.package1 === "node-sass" && conflict.package2 === "sass") {
5766
+ onProgress?.("Removing deprecated node-sass...");
5767
+ try {
5768
+ if (runtime === "node") {
5769
+ await execa3("npm", ["uninstall", "node-sass"], { cwd: path });
5770
+ resolved.push(`Removed ${conflict.package1}`);
5771
+ }
5772
+ } catch {
5773
+ remaining.push(conflict);
5774
+ }
5775
+ } else {
5776
+ remaining.push(conflict);
5777
+ }
5778
+ }
5779
+ return {
5780
+ success: remaining.length === 0,
5781
+ resolved,
5782
+ remaining
5783
+ };
5784
+ }
5323
5785
  var Komodo = class {
5324
5786
  hardware;
5325
5787
  ai = null;
@@ -5417,6 +5879,31 @@ var Komodo = class {
5417
5879
  aiAnalysis
5418
5880
  };
5419
5881
  }
5882
+ if (resolution.packages.length > 0 && existsSync4(targetPath)) {
5883
+ onProgress?.("Checking for potential conflicts...");
5884
+ try {
5885
+ const preCheck = await checkPreInstallConflicts(
5886
+ targetPath,
5887
+ resolution.runtime,
5888
+ resolution.packages
5889
+ );
5890
+ if (preCheck.willConflict) {
5891
+ for (const conflict of preCheck.conflicts) {
5892
+ const warningMsg = `Warning: ${conflict.package1} and ${conflict.package2} may conflict - ${conflict.reason}`;
5893
+ onWarning?.(warningMsg);
5894
+ resolution.warnings.push(warningMsg);
5895
+ }
5896
+ const criticalConflicts = preCheck.conflicts.filter((c) => c.severity === "error");
5897
+ if (criticalConflicts.length > 0) {
5898
+ resolution.explanations.push(
5899
+ `Found ${criticalConflicts.length} potential conflict(s). Installation may fail or cause issues.`
5900
+ );
5901
+ }
5902
+ }
5903
+ } catch (error) {
5904
+ onWarning?.("Could not check for conflicts, proceeding anyway");
5905
+ }
5906
+ }
5420
5907
  if (dryRun) {
5421
5908
  return {
5422
5909
  success: true,
@@ -5425,10 +5912,10 @@ var Komodo = class {
5425
5912
  aiAnalysis
5426
5913
  };
5427
5914
  }
5428
- if (!existsSync3(targetPath)) {
5915
+ if (!existsSync4(targetPath)) {
5429
5916
  await mkdir3(targetPath, { recursive: true });
5430
5917
  }
5431
- const environmentId = randomUUID2();
5918
+ const environmentId = randomUUID3();
5432
5919
  const environmentName = aiAnalysis?.goal ?? intent.slice(0, 50);
5433
5920
  const environment = {
5434
5921
  id: environmentId,
@@ -5591,118 +6078,6 @@ var GpuTypeSchema = external_exports.enum(["nvidia", "amd", "apple-silicon", "in
5591
6078
  var OsSchema = external_exports.enum(["darwin", "linux", "windows"]);
5592
6079
  var ArchSchema = external_exports.enum(["x64", "arm64"]);
5593
6080
  var RuntimeSchema = external_exports.enum(["python", "node"]);
5594
- var KNOWN_CONFLICTS = [
5595
- {
5596
- packages: ["tensorflow", "torch"],
5597
- reason: "Both use significant GPU memory and may conflict",
5598
- suggestion: "Use separate environments for TensorFlow and PyTorch projects"
5599
- },
5600
- {
5601
- packages: ["numpy", "jax"],
5602
- reason: "JAX includes its own numpy-like API that may conflict",
5603
- suggestion: "Use jax.numpy instead of importing both"
5604
- }
5605
- ];
5606
- async function getInstalledPackages(path, runtime) {
5607
- if (runtime === "python") {
5608
- return getPythonPackages(path);
5609
- } else {
5610
- return getNodePackages(path);
5611
- }
5612
- }
5613
- async function getPythonPackages(path) {
5614
- const venvPath = join5(path, ".venv");
5615
- if (!existsSync4(venvPath)) {
5616
- return [];
5617
- }
5618
- try {
5619
- const pipPath = join5(venvPath, "bin", "pip");
5620
- const result = await execa3(pipPath, ["list", "--format=json"], { cwd: path });
5621
- const packages = JSON.parse(result.stdout);
5622
- return packages.map((pkg) => ({
5623
- name: pkg.name,
5624
- version: pkg.version
5625
- }));
5626
- } catch {
5627
- try {
5628
- const result = await execa3(
5629
- "uv",
5630
- ["pip", "list", "--format=json", "--python", join5(venvPath, "bin", "python")],
5631
- { cwd: path }
5632
- );
5633
- const packages = JSON.parse(result.stdout);
5634
- return packages.map((pkg) => ({
5635
- name: pkg.name,
5636
- version: pkg.version
5637
- }));
5638
- } catch {
5639
- return [];
5640
- }
5641
- }
5642
- }
5643
- async function getNodePackages(path) {
5644
- const packageJsonPath = join5(path, "package.json");
5645
- if (!existsSync4(packageJsonPath)) {
5646
- return [];
5647
- }
5648
- try {
5649
- const content = await readFile4(packageJsonPath, "utf-8");
5650
- const packageJson = JSON.parse(content);
5651
- const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
5652
- const packages = [];
5653
- for (const [name, version] of Object.entries(deps)) {
5654
- packages.push({
5655
- name,
5656
- version: String(version).replace(/^[\^~]/, "")
5657
- });
5658
- }
5659
- return packages;
5660
- } catch {
5661
- return [];
5662
- }
5663
- }
5664
- function detectConflicts(packages) {
5665
- const conflicts = [];
5666
- const packageNames = packages.map((p) => p.name.toLowerCase());
5667
- for (const known of KNOWN_CONFLICTS) {
5668
- const [pkg1, pkg2] = known.packages;
5669
- if (packageNames.includes(pkg1) && packageNames.includes(pkg2)) {
5670
- conflicts.push({
5671
- package1: pkg1,
5672
- package2: pkg2,
5673
- reason: known.reason,
5674
- severity: "warning",
5675
- suggestion: known.suggestion
5676
- });
5677
- }
5678
- }
5679
- return conflicts;
5680
- }
5681
- function analyzeHealth(packages, conflicts) {
5682
- const issues = [];
5683
- let score = 100;
5684
- for (const conflict of conflicts) {
5685
- issues.push({
5686
- type: "conflict",
5687
- severity: conflict.severity,
5688
- title: `${conflict.package1} and ${conflict.package2} may conflict`,
5689
- description: conflict.reason,
5690
- fix: conflict.suggestion,
5691
- autoFixable: false
5692
- });
5693
- score -= conflict.severity === "error" ? 20 : 10;
5694
- }
5695
- const commonOutdated = ["requests", "axios", "lodash"];
5696
- for (const pkg of packages) {
5697
- if (commonOutdated.includes(pkg.name.toLowerCase())) {
5698
- }
5699
- }
5700
- return {
5701
- healthy: issues.filter((i) => i.severity === "error").length === 0,
5702
- issues,
5703
- score: Math.max(0, score)
5704
- };
5705
- }
5706
6081
  var KNOWN_VULNERABILITIES = {
5707
6082
  "torch": [
5708
6083
  { versions: "<1.13.0", severity: "high", description: "Arbitrary code execution via pickle deserialization", fix: ">=2.0.0" }
@@ -7818,6 +8193,469 @@ function formatInsights(insights, colorize = true) {
7818
8193
  }
7819
8194
  return lines.join("\n");
7820
8195
  }
8196
+ async function diagnoseEnvironment(path, runtime, onProgress) {
8197
+ const id = randomUUID4();
8198
+ const problems = [];
8199
+ let detectedRuntime = null;
8200
+ onProgress?.("Scanning environment...");
8201
+ if (!runtime) {
8202
+ if (existsSync5(join6(path, ".venv")) || existsSync5(join6(path, "requirements.txt"))) {
8203
+ detectedRuntime = "python";
8204
+ } else if (existsSync5(join6(path, "node_modules")) || existsSync5(join6(path, "package.json"))) {
8205
+ detectedRuntime = "node";
8206
+ }
8207
+ } else {
8208
+ detectedRuntime = runtime;
8209
+ }
8210
+ if (!detectedRuntime) {
8211
+ problems.push({
8212
+ id: randomUUID4(),
8213
+ severity: "critical",
8214
+ category: "missing-env",
8215
+ title: "No environment detected",
8216
+ friendlyTitle: "No project setup found",
8217
+ description: "Could not detect a Python or Node.js environment",
8218
+ technicalDetail: "No .venv, node_modules, requirements.txt, or package.json found"
8219
+ });
8220
+ return {
8221
+ id,
8222
+ timestamp: /* @__PURE__ */ new Date(),
8223
+ runtime: "python",
8224
+ // default fallback
8225
+ status: "missing",
8226
+ problems,
8227
+ repairPlan: [],
8228
+ estimatedTime: "Unknown",
8229
+ confidence: 0
8230
+ };
8231
+ }
8232
+ onProgress?.(`Checking ${detectedRuntime} environment...`);
8233
+ const envExists = await checkEnvironmentExists(path, detectedRuntime, problems);
8234
+ if (envExists) {
8235
+ await checkRuntimeFunctional(path, detectedRuntime, problems, onProgress);
8236
+ }
8237
+ if (envExists) {
8238
+ await checkDependencyConflicts(path, detectedRuntime, problems, onProgress);
8239
+ }
8240
+ if (envExists) {
8241
+ await checkLockfileDrift(path, detectedRuntime, problems, onProgress);
8242
+ }
8243
+ if (envExists) {
8244
+ await checkKnownConflicts(path, detectedRuntime, problems, onProgress);
8245
+ }
8246
+ const hasSnapshot = await checkSnapshotAvailable(path, onProgress);
8247
+ const criticalCount = problems.filter((p) => p.severity === "critical").length;
8248
+ const warningCount = problems.filter((p) => p.severity === "warning").length;
8249
+ let status;
8250
+ if (criticalCount > 0) {
8251
+ status = "broken";
8252
+ } else if (warningCount > 0) {
8253
+ status = "degraded";
8254
+ } else if (problems.length === 0) {
8255
+ status = "healthy";
8256
+ } else {
8257
+ status = "degraded";
8258
+ }
8259
+ const repairPlan = createRepairPlan({
8260
+ id,
8261
+ timestamp: /* @__PURE__ */ new Date(),
8262
+ runtime: detectedRuntime,
8263
+ status,
8264
+ problems,
8265
+ repairPlan: [],
8266
+ estimatedTime: "",
8267
+ confidence: 0
8268
+ });
8269
+ const estimatedTime = estimateRepairTime(repairPlan);
8270
+ const confidence = calculateConfidence(problems, hasSnapshot);
8271
+ return {
8272
+ id,
8273
+ timestamp: /* @__PURE__ */ new Date(),
8274
+ runtime: detectedRuntime,
8275
+ status,
8276
+ problems,
8277
+ repairPlan,
8278
+ estimatedTime,
8279
+ confidence
8280
+ };
8281
+ }
8282
+ function createRepairPlan(diagnosis) {
8283
+ const steps = [];
8284
+ let order = 1;
8285
+ const missingEnv = diagnosis.problems.find((p) => p.category === "missing-env");
8286
+ if (missingEnv) {
8287
+ steps.push({
8288
+ id: randomUUID4(),
8289
+ order: order++,
8290
+ action: "recreate-venv",
8291
+ description: `Create new ${diagnosis.runtime} virtual environment`,
8292
+ friendlyDescription: "Setting up your project from scratch...",
8293
+ automated: true,
8294
+ risk: "safe"
8295
+ });
8296
+ return steps;
8297
+ }
8298
+ const corruptVenv = diagnosis.problems.find((p) => p.category === "corrupt-venv");
8299
+ if (corruptVenv) {
8300
+ steps.push({
8301
+ id: randomUUID4(),
8302
+ order: order++,
8303
+ action: "recreate-venv",
8304
+ description: `Recreate corrupted ${diagnosis.runtime} environment`,
8305
+ friendlyDescription: "Rebuilding your project setup...",
8306
+ automated: true,
8307
+ risk: "moderate"
8308
+ });
8309
+ return steps;
8310
+ }
8311
+ const hasSnapshotProblem = diagnosis.problems.some(
8312
+ (p) => p.category === "broken-deps" || p.category === "version-conflict"
8313
+ );
8314
+ if (hasSnapshotProblem) {
8315
+ steps.push({
8316
+ id: randomUUID4(),
8317
+ order: order++,
8318
+ action: "restore-snapshot",
8319
+ description: "Restore from last known working state",
8320
+ friendlyDescription: "Going back to when things were working...",
8321
+ automated: true,
8322
+ risk: "safe"
8323
+ });
8324
+ }
8325
+ const versionConflicts = diagnosis.problems.filter(
8326
+ (p) => p.category === "version-conflict"
8327
+ );
8328
+ for (const conflict of versionConflicts) {
8329
+ steps.push({
8330
+ id: randomUUID4(),
8331
+ order: order++,
8332
+ action: "resolve-conflicts",
8333
+ description: conflict.description,
8334
+ friendlyDescription: "Fixing incompatible package versions...",
8335
+ automated: true,
8336
+ risk: "moderate"
8337
+ });
8338
+ }
8339
+ const staleLockfile = diagnosis.problems.find((p) => p.category === "stale-lockfile");
8340
+ if (staleLockfile) {
8341
+ steps.push({
8342
+ id: randomUUID4(),
8343
+ order: order++,
8344
+ action: "reinstall-deps",
8345
+ description: "Reinstall packages from lockfile",
8346
+ friendlyDescription: "Updating your packages...",
8347
+ automated: true,
8348
+ risk: "safe"
8349
+ });
8350
+ }
8351
+ return steps;
8352
+ }
8353
+ async function executeRepair(path, diagnosis, options) {
8354
+ const { autoBackup = true, dryRun = false, onProgress } = options || {};
8355
+ const { repairPlan, runtime } = diagnosis;
8356
+ if (repairPlan.length === 0) {
8357
+ return {
8358
+ success: true,
8359
+ stepsCompleted: 0,
8360
+ stepsTotal: 0,
8361
+ problemsFixed: [],
8362
+ problemsRemaining: []
8363
+ };
8364
+ }
8365
+ let snapshotId;
8366
+ const problemsFixed = [];
8367
+ const problemsRemaining = [];
8368
+ let stepsCompleted = 0;
8369
+ if (autoBackup && !dryRun) {
8370
+ try {
8371
+ const state = await loadState(path);
8372
+ if (state.activeEnvironmentId) {
8373
+ const env = state.environments.find((e) => e.id === state.activeEnvironmentId);
8374
+ if (env) {
8375
+ const snapshot = await createSnapshot(
8376
+ path,
8377
+ env,
8378
+ "Pre-repair backup"
8379
+ );
8380
+ snapshotId = snapshot.id;
8381
+ }
8382
+ }
8383
+ } catch {
8384
+ }
8385
+ }
8386
+ for (const step of repairPlan) {
8387
+ if (dryRun) {
8388
+ onProgress?.(step, "starting");
8389
+ onProgress?.(step, "complete");
8390
+ stepsCompleted++;
8391
+ continue;
8392
+ }
8393
+ try {
8394
+ onProgress?.(step, "starting");
8395
+ switch (step.action) {
8396
+ case "recreate-venv":
8397
+ await recreateEnvironment(path, runtime);
8398
+ problemsFixed.push("Recreated environment");
8399
+ break;
8400
+ case "restore-snapshot":
8401
+ await restoreFromSnapshot(path, runtime);
8402
+ problemsFixed.push("Restored from backup");
8403
+ break;
8404
+ case "reinstall-deps":
8405
+ await reinstallDependencies(path, runtime);
8406
+ problemsFixed.push("Reinstalled dependencies");
8407
+ break;
8408
+ case "resolve-conflicts":
8409
+ await resolveConflicts2(path, runtime);
8410
+ problemsFixed.push("Resolved conflicts");
8411
+ break;
8412
+ default:
8413
+ break;
8414
+ }
8415
+ onProgress?.(step, "complete");
8416
+ stepsCompleted++;
8417
+ } catch (error) {
8418
+ onProgress?.(step, "failed");
8419
+ problemsRemaining.push(
8420
+ error instanceof Error ? error.message : "Unknown error"
8421
+ );
8422
+ }
8423
+ }
8424
+ return {
8425
+ success: stepsCompleted === repairPlan.length,
8426
+ stepsCompleted,
8427
+ stepsTotal: repairPlan.length,
8428
+ snapshotId,
8429
+ problemsFixed,
8430
+ problemsRemaining
8431
+ };
8432
+ }
8433
+ async function checkEnvironmentExists(path, runtime, problems) {
8434
+ if (runtime === "python") {
8435
+ const venvPath = join6(path, ".venv");
8436
+ if (!existsSync5(venvPath)) {
8437
+ problems.push({
8438
+ id: randomUUID4(),
8439
+ severity: "critical",
8440
+ category: "missing-env",
8441
+ title: "Virtual environment missing",
8442
+ friendlyTitle: "Project setup is missing",
8443
+ description: "No .venv directory found",
8444
+ technicalDetail: `Expected ${venvPath} to exist`
8445
+ });
8446
+ return false;
8447
+ }
8448
+ } else {
8449
+ const nodeModulesPath = join6(path, "node_modules");
8450
+ if (!existsSync5(nodeModulesPath)) {
8451
+ problems.push({
8452
+ id: randomUUID4(),
8453
+ severity: "critical",
8454
+ category: "missing-env",
8455
+ title: "node_modules missing",
8456
+ friendlyTitle: "Dependencies not installed",
8457
+ description: "No node_modules directory found",
8458
+ technicalDetail: `Expected ${nodeModulesPath} to exist`
8459
+ });
8460
+ return false;
8461
+ }
8462
+ }
8463
+ return true;
8464
+ }
8465
+ async function checkRuntimeFunctional(path, runtime, problems, onProgress) {
8466
+ onProgress?.("Checking if runtime is functional...");
8467
+ try {
8468
+ if (runtime === "python") {
8469
+ const pythonPath = join6(path, ".venv", "bin", "python");
8470
+ await execa4(pythonPath, ["--version"], { cwd: path });
8471
+ } else {
8472
+ await execa4("node", ["--version"], { cwd: path });
8473
+ }
8474
+ } catch {
8475
+ problems.push({
8476
+ id: randomUUID4(),
8477
+ severity: "critical",
8478
+ category: "corrupt-venv",
8479
+ title: `${runtime} runtime not functional`,
8480
+ friendlyTitle: "Something is broken",
8481
+ description: `Cannot invoke ${runtime} from environment`,
8482
+ technicalDetail: runtime === "python" ? "Python executable in .venv/bin/python is not working" : "Node.js is not accessible"
8483
+ });
8484
+ }
8485
+ }
8486
+ async function checkDependencyConflicts(path, runtime, problems, onProgress) {
8487
+ onProgress?.("Checking for dependency conflicts...");
8488
+ try {
8489
+ if (runtime === "python") {
8490
+ const pipPath = join6(path, ".venv", "bin", "pip");
8491
+ const result = await execa4(pipPath, ["check"], { cwd: path, reject: false });
8492
+ if (result.exitCode !== 0 && result.stdout) {
8493
+ const lines = result.stdout.split("\n").filter((l) => l.trim());
8494
+ for (const line of lines) {
8495
+ if (line.includes("requires") || line.includes("incompatible")) {
8496
+ problems.push({
8497
+ id: randomUUID4(),
8498
+ severity: "critical",
8499
+ category: "broken-deps",
8500
+ title: "Dependency conflict detected",
8501
+ friendlyTitle: "Packages don't work together",
8502
+ description: line,
8503
+ technicalDetail: "pip check failed"
8504
+ });
8505
+ }
8506
+ }
8507
+ }
8508
+ } else {
8509
+ const result = await execa4("npm", ["ls", "--json"], {
8510
+ cwd: path,
8511
+ reject: false
8512
+ });
8513
+ if (result.stdout) {
8514
+ try {
8515
+ const output = JSON.parse(result.stdout);
8516
+ if (output.problems && output.problems.length > 0) {
8517
+ for (const problem of output.problems) {
8518
+ problems.push({
8519
+ id: randomUUID4(),
8520
+ severity: "warning",
8521
+ category: "broken-deps",
8522
+ title: "Dependency issue detected",
8523
+ friendlyTitle: "Package issue found",
8524
+ description: String(problem),
8525
+ technicalDetail: "npm ls reported issues"
8526
+ });
8527
+ }
8528
+ }
8529
+ } catch {
8530
+ }
8531
+ }
8532
+ }
8533
+ } catch {
8534
+ }
8535
+ }
8536
+ async function checkLockfileDrift(path, runtime, problems, onProgress) {
8537
+ onProgress?.("Checking lockfile consistency...");
8538
+ try {
8539
+ if (runtime === "python") {
8540
+ const lockfilePath = join6(path, "requirements.lock");
8541
+ if (existsSync5(lockfilePath)) {
8542
+ const installed = await getInstalledPackages(path, runtime);
8543
+ if (installed.length === 0) {
8544
+ problems.push({
8545
+ id: randomUUID4(),
8546
+ severity: "warning",
8547
+ category: "stale-lockfile",
8548
+ title: "Lockfile exists but no packages installed",
8549
+ friendlyTitle: "Packages need to be installed",
8550
+ description: "requirements.lock exists but environment is empty"
8551
+ });
8552
+ }
8553
+ }
8554
+ } else {
8555
+ const lockfilePath = join6(path, "package-lock.json");
8556
+ if (existsSync5(lockfilePath)) {
8557
+ const nodeModulesPath = join6(path, "node_modules");
8558
+ if (!existsSync5(nodeModulesPath)) {
8559
+ problems.push({
8560
+ id: randomUUID4(),
8561
+ severity: "warning",
8562
+ category: "stale-lockfile",
8563
+ title: "Lockfile exists but node_modules missing",
8564
+ friendlyTitle: "Dependencies need installation",
8565
+ description: "package-lock.json exists but node_modules is missing"
8566
+ });
8567
+ }
8568
+ }
8569
+ }
8570
+ } catch {
8571
+ }
8572
+ }
8573
+ async function checkKnownConflicts(path, runtime, problems, onProgress) {
8574
+ onProgress?.("Checking for known conflicts...");
8575
+ try {
8576
+ const installed = await getInstalledPackages(path, runtime);
8577
+ const conflicts = detectConflicts(installed);
8578
+ for (const conflict of conflicts) {
8579
+ const severity = conflict.severity === "error" ? "critical" : conflict.severity;
8580
+ problems.push({
8581
+ id: randomUUID4(),
8582
+ severity,
8583
+ category: "version-conflict",
8584
+ title: `${conflict.package1} conflicts with ${conflict.package2}`,
8585
+ friendlyTitle: "Incompatible packages detected",
8586
+ description: conflict.reason,
8587
+ technicalDetail: conflict.suggestion
8588
+ });
8589
+ }
8590
+ } catch {
8591
+ }
8592
+ }
8593
+ async function checkSnapshotAvailable(path, onProgress) {
8594
+ onProgress?.("Checking for backups...");
8595
+ try {
8596
+ const state = await loadState(path);
8597
+ if (state.activeEnvironmentId) {
8598
+ const snapshot = await getLatestSnapshot(path, state.activeEnvironmentId);
8599
+ return snapshot !== null;
8600
+ }
8601
+ return false;
8602
+ } catch {
8603
+ return false;
8604
+ }
8605
+ }
8606
+ async function recreateEnvironment(path, runtime) {
8607
+ if (runtime === "python") {
8608
+ const venvPath = join6(path, ".venv");
8609
+ if (existsSync5(venvPath)) {
8610
+ await execa4("rm", ["-rf", venvPath], { cwd: path });
8611
+ }
8612
+ await execa4("python3", ["-m", "venv", ".venv"], { cwd: path });
8613
+ } else {
8614
+ await execa4("npm", ["install"], { cwd: path });
8615
+ }
8616
+ }
8617
+ async function restoreFromSnapshot(path, runtime) {
8618
+ const state = await loadState(path);
8619
+ if (!state.activeEnvironmentId) {
8620
+ throw new Error("No active environment found");
8621
+ }
8622
+ const snapshot = await getLatestSnapshot(path, state.activeEnvironmentId);
8623
+ if (!snapshot) {
8624
+ throw new Error("No snapshot available");
8625
+ }
8626
+ if (runtime === "python") {
8627
+ await restorePythonEnvironment(path, snapshot.lockfileContent);
8628
+ } else {
8629
+ await restoreNodeEnvironment(path, snapshot.lockfileContent);
8630
+ }
8631
+ }
8632
+ async function reinstallDependencies(path, runtime) {
8633
+ if (runtime === "python") {
8634
+ const lockfilePath = join6(path, "requirements.lock");
8635
+ if (existsSync5(lockfilePath)) {
8636
+ const pipPath = join6(path, ".venv", "bin", "pip");
8637
+ await execa4(pipPath, ["install", "-r", "requirements.lock"], { cwd: path });
8638
+ }
8639
+ } else {
8640
+ await execa4("npm", ["ci"], { cwd: path });
8641
+ }
8642
+ }
8643
+ async function resolveConflicts2(path, runtime) {
8644
+ await reinstallDependencies(path, runtime);
8645
+ }
8646
+ function estimateRepairTime(steps) {
8647
+ if (steps.length === 0) return "None needed";
8648
+ if (steps.length === 1) return "~1 minute";
8649
+ if (steps.length <= 3) return "~2 minutes";
8650
+ return "~5 minutes";
8651
+ }
8652
+ function calculateConfidence(problems, hasSnapshot) {
8653
+ if (problems.length === 0) return 1;
8654
+ const criticalCount = problems.filter((p) => p.severity === "critical").length;
8655
+ if (criticalCount > 2) return hasSnapshot ? 0.7 : 0.5;
8656
+ if (criticalCount > 0) return hasSnapshot ? 0.85 : 0.7;
8657
+ return 0.9;
8658
+ }
7821
8659
 
7822
8660
  export {
7823
8661
  __require,
@@ -7825,10 +8663,12 @@ export {
7825
8663
  __toESM,
7826
8664
  loadState,
7827
8665
  KomodoChat,
7828
- Komodo,
7829
8666
  getInstalledPackages,
7830
8667
  detectConflicts,
7831
8668
  analyzeHealth,
8669
+ detectRealConflicts,
8670
+ resolveConflicts,
8671
+ Komodo,
7832
8672
  runDoctor,
7833
8673
  formatDoctorReport,
7834
8674
  buildDependencyTree,
@@ -7849,5 +8689,7 @@ export {
7849
8689
  analyzeRepoStructure,
7850
8690
  formatRepoAnalysis,
7851
8691
  analyzeEnvironment,
7852
- formatInsights
8692
+ formatInsights,
8693
+ diagnoseEnvironment,
8694
+ executeRepair
7853
8695
  };