free-coding-models 0.1.36 β 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.
- package/bin/free-coding-models.js +103 -24
- package/package.json +1 -1
|
@@ -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'
|
|
@@ -102,6 +102,7 @@ function runUpdate(latestVersion) {
|
|
|
102
102
|
console.log()
|
|
103
103
|
console.log(chalk.bold.cyan(' β¬ Updating free-coding-models to v' + latestVersion + '...'))
|
|
104
104
|
console.log()
|
|
105
|
+
|
|
105
106
|
try {
|
|
106
107
|
// π Force install from npm registry (ignore local cache)
|
|
107
108
|
// π Use --prefer-online to ensure we get the latest published version
|
|
@@ -118,8 +119,37 @@ function runUpdate(latestVersion) {
|
|
|
118
119
|
process.exit(0)
|
|
119
120
|
} catch (err) {
|
|
120
121
|
console.log()
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
// π Check if error is permission-related (EACCES or EPERM)
|
|
123
|
+
const isPermissionError = err.code === 'EACCES' || err.code === 'EPERM' ||
|
|
124
|
+
(err.stderr && (err.stderr.includes('EACCES') || err.stderr.includes('permission') ||
|
|
125
|
+
err.stderr.includes('EACCES'))) ||
|
|
126
|
+
(err.message && (err.message.includes('EACCES') || err.message.includes('permission')))
|
|
127
|
+
|
|
128
|
+
if (isPermissionError) {
|
|
129
|
+
console.log(chalk.yellow(' β οΈ Permission denied. Retrying with sudo...'))
|
|
130
|
+
console.log()
|
|
131
|
+
try {
|
|
132
|
+
execSync(`sudo npm i -g free-coding-models@${latestVersion} --prefer-online`, { stdio: 'inherit' })
|
|
133
|
+
console.log()
|
|
134
|
+
console.log(chalk.green(' β
Update complete with sudo! Version ' + latestVersion + ' installed.'))
|
|
135
|
+
console.log()
|
|
136
|
+
console.log(chalk.dim(' π Restarting with new version...'))
|
|
137
|
+
console.log()
|
|
138
|
+
|
|
139
|
+
// π Relaunch automatically with the same arguments
|
|
140
|
+
const args = process.argv.slice(2)
|
|
141
|
+
execSync(`node bin/free-coding-models.js ${args.join(' ')}`, { stdio: 'inherit' })
|
|
142
|
+
process.exit(0)
|
|
143
|
+
} catch (sudoErr) {
|
|
144
|
+
console.log()
|
|
145
|
+
console.log(chalk.red(' β Update failed even with sudo. Try manually:'))
|
|
146
|
+
console.log(chalk.dim(' sudo npm i -g free-coding-models@' + latestVersion))
|
|
147
|
+
console.log()
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
console.log(chalk.red(' β Update failed. Try manually: npm i -g free-coding-models@' + latestVersion))
|
|
151
|
+
console.log()
|
|
152
|
+
}
|
|
123
153
|
}
|
|
124
154
|
process.exit(1)
|
|
125
155
|
}
|
|
@@ -660,23 +690,44 @@ async function ping(apiKey, modelId) {
|
|
|
660
690
|
}
|
|
661
691
|
|
|
662
692
|
// βββ OpenCode integration ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
663
|
-
|
|
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
|
+
}
|
|
664
713
|
|
|
665
714
|
function loadOpenCodeConfig() {
|
|
666
|
-
|
|
715
|
+
const configPath = getOpenCodeConfigPath()
|
|
716
|
+
if (!existsSync(configPath)) return { provider: {} }
|
|
667
717
|
try {
|
|
668
|
-
return JSON.parse(readFileSync(
|
|
718
|
+
return JSON.parse(readFileSync(configPath, 'utf8'))
|
|
669
719
|
} catch {
|
|
670
720
|
return { provider: {} }
|
|
671
721
|
}
|
|
672
722
|
}
|
|
673
723
|
|
|
674
724
|
function saveOpenCodeConfig(config) {
|
|
675
|
-
const
|
|
725
|
+
const configPath = getOpenCodeConfigPath()
|
|
726
|
+
const dir = dirname(configPath)
|
|
676
727
|
if (!existsSync(dir)) {
|
|
677
728
|
mkdirSync(dir, { recursive: true })
|
|
678
729
|
}
|
|
679
|
-
writeFileSync(
|
|
730
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2))
|
|
680
731
|
}
|
|
681
732
|
|
|
682
733
|
// βββ Check NVIDIA NIM in OpenCode config βββββββββββββββββββββββββββββββββββββββ
|
|
@@ -709,11 +760,11 @@ async function startOpenCode(model) {
|
|
|
709
760
|
console.log()
|
|
710
761
|
|
|
711
762
|
const config = loadOpenCodeConfig()
|
|
712
|
-
const backupPath = `${
|
|
763
|
+
const backupPath = `${getOpenCodeConfigPath()}.backup-${Date.now()}`
|
|
713
764
|
|
|
714
765
|
// π Backup current config
|
|
715
|
-
if (existsSync(
|
|
716
|
-
copyFileSync(
|
|
766
|
+
if (existsSync(getOpenCodeConfigPath())) {
|
|
767
|
+
copyFileSync(getOpenCodeConfigPath(), backupPath)
|
|
717
768
|
console.log(chalk.dim(` πΎ Backup: ${backupPath}`))
|
|
718
769
|
}
|
|
719
770
|
|
|
@@ -741,7 +792,8 @@ async function startOpenCode(model) {
|
|
|
741
792
|
const { spawn } = await import('child_process')
|
|
742
793
|
const child = spawn('opencode', [], {
|
|
743
794
|
stdio: 'inherit',
|
|
744
|
-
shell: true
|
|
795
|
+
shell: true,
|
|
796
|
+
detached: false
|
|
745
797
|
})
|
|
746
798
|
|
|
747
799
|
// π Wait for OpenCode to exit
|
|
@@ -764,7 +816,8 @@ async function startOpenCode(model) {
|
|
|
764
816
|
console.log(chalk.dim(' Starting OpenCode with installation promptβ¦'))
|
|
765
817
|
console.log()
|
|
766
818
|
|
|
767
|
-
const
|
|
819
|
+
const configPath = getOpenCodeConfigPath()
|
|
820
|
+
const installPrompt = `Please install NVIDIA NIM provider in OpenCode by adding this to ${configPath}:
|
|
768
821
|
|
|
769
822
|
{
|
|
770
823
|
"provider": {
|
|
@@ -779,7 +832,7 @@ async function startOpenCode(model) {
|
|
|
779
832
|
}
|
|
780
833
|
}
|
|
781
834
|
|
|
782
|
-
|
|
835
|
+
${isWindows ? 'set NVIDIA_API_KEY=your_key_here' : 'export NVIDIA_API_KEY=your_key_here'}
|
|
783
836
|
|
|
784
837
|
After installation, you can use: opencode --model nvidia/${model.modelId}`
|
|
785
838
|
|
|
@@ -791,7 +844,8 @@ After installation, you can use: opencode --model nvidia/${model.modelId}`
|
|
|
791
844
|
const { spawn } = await import('child_process')
|
|
792
845
|
const child = spawn('opencode', [], {
|
|
793
846
|
stdio: 'inherit',
|
|
794
|
-
shell: true
|
|
847
|
+
shell: true,
|
|
848
|
+
detached: false
|
|
795
849
|
})
|
|
796
850
|
|
|
797
851
|
// π Wait for OpenCode to exit
|
|
@@ -812,7 +866,7 @@ After installation, you can use: opencode --model nvidia/${model.modelId}`
|
|
|
812
866
|
|
|
813
867
|
// βββ Start OpenCode Desktop βββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
814
868
|
// π startOpenCodeDesktop: Same config logic as startOpenCode, but opens the Desktop app.
|
|
815
|
-
// π OpenCode Desktop
|
|
869
|
+
// π OpenCode Desktop shares config at the same location as CLI.
|
|
816
870
|
// π No need to wait for exit β Desktop app stays open independently.
|
|
817
871
|
async function startOpenCodeDesktop(model) {
|
|
818
872
|
const hasNim = checkNvidiaNimConfig()
|
|
@@ -823,10 +877,10 @@ async function startOpenCodeDesktop(model) {
|
|
|
823
877
|
console.log()
|
|
824
878
|
|
|
825
879
|
const config = loadOpenCodeConfig()
|
|
826
|
-
const backupPath = `${
|
|
880
|
+
const backupPath = `${getOpenCodeConfigPath()}.backup-${Date.now()}`
|
|
827
881
|
|
|
828
|
-
if (existsSync(
|
|
829
|
-
copyFileSync(
|
|
882
|
+
if (existsSync(getOpenCodeConfigPath())) {
|
|
883
|
+
copyFileSync(getOpenCodeConfigPath(), backupPath)
|
|
830
884
|
console.log(chalk.dim(` πΎ Backup: ${backupPath}`))
|
|
831
885
|
}
|
|
832
886
|
|
|
@@ -846,18 +900,43 @@ async function startOpenCodeDesktop(model) {
|
|
|
846
900
|
console.log(chalk.dim(' Opening OpenCode Desktopβ¦'))
|
|
847
901
|
console.log()
|
|
848
902
|
|
|
849
|
-
// π Launch Desktop app
|
|
903
|
+
// π Launch Desktop app based on platform
|
|
850
904
|
const { exec } = await import('child_process')
|
|
851
|
-
|
|
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) => {
|
|
852
921
|
if (err) {
|
|
853
|
-
console.error(chalk.red(' β Could not open OpenCode Desktop
|
|
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
|
+
}
|
|
854
931
|
}
|
|
855
932
|
})
|
|
856
933
|
} else {
|
|
857
934
|
console.log(chalk.yellow(' β NVIDIA NIM not configured in OpenCode'))
|
|
858
935
|
console.log(chalk.dim(' Please configure it first. Config is shared between CLI and Desktop.'))
|
|
859
936
|
console.log()
|
|
860
|
-
|
|
937
|
+
|
|
938
|
+
const configPath = getOpenCodeConfigPath()
|
|
939
|
+
const installPrompt = `Add this to ${configPath}:
|
|
861
940
|
|
|
862
941
|
{
|
|
863
942
|
"provider": {
|
|
@@ -872,7 +951,7 @@ async function startOpenCodeDesktop(model) {
|
|
|
872
951
|
}
|
|
873
952
|
}
|
|
874
953
|
|
|
875
|
-
|
|
954
|
+
${isWindows ? 'set NVIDIA_API_KEY=your_key_here' : 'export NVIDIA_API_KEY=your_key_here'}`
|
|
876
955
|
console.log(chalk.cyan(installPrompt))
|
|
877
956
|
console.log()
|
|
878
957
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "free-coding-models",
|
|
3
|
-
"version": "0.1.
|
|
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",
|