free-coding-models 0.1.37 → 0.1.38

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.
@@ -75,7 +75,7 @@ import chalk from 'chalk'
75
75
  import { createRequire } from 'module'
76
76
  import { readFileSync, writeFileSync, existsSync, copyFileSync, mkdirSync } from 'fs'
77
77
  import { homedir } from 'os'
78
- import { join } from 'path'
78
+ import { join, dirname } from 'path'
79
79
  import { MODELS } from '../sources.js'
80
80
  import { patchOpenClawModelsJson } from '../patch-openclaw-models.js'
81
81
  import { getAvg, getVerdict, getUptime, sortResults, filterByTier, findBestModel, parseArgs, TIER_ORDER, VERDICT_ORDER, TIER_LETTER_MAP } from '../lib/utils.js'
@@ -690,23 +690,44 @@ async function ping(apiKey, modelId) {
690
690
  }
691
691
 
692
692
  // ─── OpenCode integration ──────────────────────────────────────────────────────
693
- const OPENCODE_CONFIG = join(homedir(), '.config/opencode/opencode.json')
693
+ // 📖 Platform-specific config path
694
+ const isWindows = process.platform === 'win32'
695
+ const isMac = process.platform === 'darwin'
696
+ const isLinux = process.platform === 'linux'
697
+
698
+ // 📖 OpenCode config location varies by platform
699
+ // 📖 Windows: %APPDATA%\opencode\opencode.json (or sometimes ~/.config/opencode)
700
+ // 📖 macOS/Linux: ~/.config/opencode/opencode.json
701
+ const OPENCODE_CONFIG = isWindows
702
+ ? join(homedir(), 'AppData', 'Roaming', 'opencode', 'opencode.json')
703
+ : join(homedir(), '.config', 'opencode', 'opencode.json')
704
+
705
+ // 📖 Fallback to .config on Windows if AppData doesn't exist
706
+ const OPENCODE_CONFIG_FALLBACK = join(homedir(), '.config', 'opencode', 'opencode.json')
707
+
708
+ function getOpenCodeConfigPath() {
709
+ if (existsSync(OPENCODE_CONFIG)) return OPENCODE_CONFIG
710
+ if (isWindows && existsSync(OPENCODE_CONFIG_FALLBACK)) return OPENCODE_CONFIG_FALLBACK
711
+ return OPENCODE_CONFIG
712
+ }
694
713
 
695
714
  function loadOpenCodeConfig() {
696
- if (!existsSync(OPENCODE_CONFIG)) return { provider: {} }
715
+ const configPath = getOpenCodeConfigPath()
716
+ if (!existsSync(configPath)) return { provider: {} }
697
717
  try {
698
- return JSON.parse(readFileSync(OPENCODE_CONFIG, 'utf8'))
718
+ return JSON.parse(readFileSync(configPath, 'utf8'))
699
719
  } catch {
700
720
  return { provider: {} }
701
721
  }
702
722
  }
703
723
 
704
724
  function saveOpenCodeConfig(config) {
705
- const dir = join(homedir(), '.config/opencode')
725
+ const configPath = getOpenCodeConfigPath()
726
+ const dir = dirname(configPath)
706
727
  if (!existsSync(dir)) {
707
728
  mkdirSync(dir, { recursive: true })
708
729
  }
709
- writeFileSync(OPENCODE_CONFIG, JSON.stringify(config, null, 2))
730
+ writeFileSync(configPath, JSON.stringify(config, null, 2))
710
731
  }
711
732
 
712
733
  // ─── Check NVIDIA NIM in OpenCode config ───────────────────────────────────────
@@ -739,11 +760,11 @@ async function startOpenCode(model) {
739
760
  console.log()
740
761
 
741
762
  const config = loadOpenCodeConfig()
742
- const backupPath = `${OPENCODE_CONFIG}.backup-${Date.now()}`
763
+ const backupPath = `${getOpenCodeConfigPath()}.backup-${Date.now()}`
743
764
 
744
765
  // 📖 Backup current config
745
- if (existsSync(OPENCODE_CONFIG)) {
746
- copyFileSync(OPENCODE_CONFIG, backupPath)
766
+ if (existsSync(getOpenCodeConfigPath())) {
767
+ copyFileSync(getOpenCodeConfigPath(), backupPath)
747
768
  console.log(chalk.dim(` 💾 Backup: ${backupPath}`))
748
769
  }
749
770
 
@@ -771,7 +792,8 @@ async function startOpenCode(model) {
771
792
  const { spawn } = await import('child_process')
772
793
  const child = spawn('opencode', [], {
773
794
  stdio: 'inherit',
774
- shell: true
795
+ shell: true,
796
+ detached: false
775
797
  })
776
798
 
777
799
  // 📖 Wait for OpenCode to exit
@@ -794,7 +816,8 @@ async function startOpenCode(model) {
794
816
  console.log(chalk.dim(' Starting OpenCode with installation prompt…'))
795
817
  console.log()
796
818
 
797
- const installPrompt = `Please install NVIDIA NIM provider in OpenCode by adding this to ~/.config/opencode/opencode.json:
819
+ const configPath = getOpenCodeConfigPath()
820
+ const installPrompt = `Please install NVIDIA NIM provider in OpenCode by adding this to ${configPath}:
798
821
 
799
822
  {
800
823
  "provider": {
@@ -809,7 +832,7 @@ async function startOpenCode(model) {
809
832
  }
810
833
  }
811
834
 
812
- Then set env var: export NVIDIA_API_KEY=your_key_here
835
+ ${isWindows ? 'set NVIDIA_API_KEY=your_key_here' : 'export NVIDIA_API_KEY=your_key_here'}
813
836
 
814
837
  After installation, you can use: opencode --model nvidia/${model.modelId}`
815
838
 
@@ -821,7 +844,8 @@ After installation, you can use: opencode --model nvidia/${model.modelId}`
821
844
  const { spawn } = await import('child_process')
822
845
  const child = spawn('opencode', [], {
823
846
  stdio: 'inherit',
824
- shell: true
847
+ shell: true,
848
+ detached: false
825
849
  })
826
850
 
827
851
  // 📖 Wait for OpenCode to exit
@@ -842,7 +866,7 @@ After installation, you can use: opencode --model nvidia/${model.modelId}`
842
866
 
843
867
  // ─── Start OpenCode Desktop ─────────────────────────────────────────────────────
844
868
  // 📖 startOpenCodeDesktop: Same config logic as startOpenCode, but opens the Desktop app.
845
- // 📖 OpenCode Desktop (/Applications/OpenCode.app) shares config at ~/.config/opencode/opencode.json.
869
+ // 📖 OpenCode Desktop shares config at the same location as CLI.
846
870
  // 📖 No need to wait for exit — Desktop app stays open independently.
847
871
  async function startOpenCodeDesktop(model) {
848
872
  const hasNim = checkNvidiaNimConfig()
@@ -853,10 +877,10 @@ async function startOpenCodeDesktop(model) {
853
877
  console.log()
854
878
 
855
879
  const config = loadOpenCodeConfig()
856
- const backupPath = `${OPENCODE_CONFIG}.backup-${Date.now()}`
880
+ const backupPath = `${getOpenCodeConfigPath()}.backup-${Date.now()}`
857
881
 
858
- if (existsSync(OPENCODE_CONFIG)) {
859
- copyFileSync(OPENCODE_CONFIG, backupPath)
882
+ if (existsSync(getOpenCodeConfigPath())) {
883
+ copyFileSync(getOpenCodeConfigPath(), backupPath)
860
884
  console.log(chalk.dim(` 💾 Backup: ${backupPath}`))
861
885
  }
862
886
 
@@ -876,18 +900,43 @@ async function startOpenCodeDesktop(model) {
876
900
  console.log(chalk.dim(' Opening OpenCode Desktop…'))
877
901
  console.log()
878
902
 
879
- // 📖 Launch Desktop app no need to wait, it stays open independently
903
+ // 📖 Launch Desktop app based on platform
880
904
  const { exec } = await import('child_process')
881
- exec('open -a OpenCode', (err) => {
905
+
906
+ let command
907
+ if (isMac) {
908
+ command = 'open -a OpenCode'
909
+ } else if (isWindows) {
910
+ // 📖 On Windows, try common installation paths
911
+ // 📖 User installation: %LOCALAPPDATA%\Programs\OpenCode\OpenCode.exe
912
+ // 📖 System installation: C:\Program Files\OpenCode\OpenCode.exe
913
+ command = 'start "" "%LOCALAPPDATA%\\Programs\\OpenCode\\OpenCode.exe" 2>nul || start "" "%PROGRAMFILES%\\OpenCode\\OpenCode.exe" 2>nul || start OpenCode'
914
+ } else if (isLinux) {
915
+ // 📖 On Linux, try different methods
916
+ // 📖 Check if opencode-desktop exists, otherwise try xdg-open
917
+ command = 'opencode-desktop 2>/dev/null || xdg-open /usr/share/applications/opencode.desktop 2>/dev/null || flatpak run ai.opencode.OpenCode 2>/dev/null || snap run opencode 2>/dev/null || echo "OpenCode not found"'
918
+ }
919
+
920
+ exec(command, (err, stdout, stderr) => {
882
921
  if (err) {
883
- console.error(chalk.red(' ✗ Could not open OpenCode Desktop — is it installed at /Applications/OpenCode.app?'))
922
+ console.error(chalk.red(' ✗ Could not open OpenCode Desktop'))
923
+ if (isWindows) {
924
+ console.error(chalk.dim(' Make sure OpenCode is installed from https://opencode.ai'))
925
+ } else if (isLinux) {
926
+ console.error(chalk.dim(' Install via: snap install opencode OR flatpak install ai.opencode.OpenCode'))
927
+ console.error(chalk.dim(' Or download from https://opencode.ai'))
928
+ } else {
929
+ console.error(chalk.dim(' Is it installed at /Applications/OpenCode.app?'))
930
+ }
884
931
  }
885
932
  })
886
933
  } else {
887
934
  console.log(chalk.yellow(' ⚠ NVIDIA NIM not configured in OpenCode'))
888
935
  console.log(chalk.dim(' Please configure it first. Config is shared between CLI and Desktop.'))
889
936
  console.log()
890
- const installPrompt = `Add this to ~/.config/opencode/opencode.json:
937
+
938
+ const configPath = getOpenCodeConfigPath()
939
+ const installPrompt = `Add this to ${configPath}:
891
940
 
892
941
  {
893
942
  "provider": {
@@ -902,7 +951,7 @@ async function startOpenCodeDesktop(model) {
902
951
  }
903
952
  }
904
953
 
905
- Then set env var: export NVIDIA_API_KEY=your_key_here`
954
+ ${isWindows ? 'set NVIDIA_API_KEY=your_key_here' : 'export NVIDIA_API_KEY=your_key_here'}`
906
955
  console.log(chalk.cyan(installPrompt))
907
956
  console.log()
908
957
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "free-coding-models",
3
- "version": "0.1.37",
3
+ "version": "0.1.38",
4
4
  "description": "Find the fastest coding LLM models in seconds — ping free models from multiple providers, pick the best one for OpenCode, Cursor, or any AI coding assistant.",
5
5
  "keywords": [
6
6
  "nvidia",