free-coding-models 0.3.17 → 0.3.19

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/src/openclaw.js CHANGED
@@ -3,10 +3,12 @@
3
3
  * @description OpenClaw config helpers for persisting the selected provider/model as the default.
4
4
  *
5
5
  * @details
6
- * 📖 OpenClaw is config-driven: FCM does not launch a separate foreground CLI here.
6
+ * 📖 OpenClaw is primarily config-driven, but FCM can now optionally launch the
7
+ * 📖 installed CLI right after persisting the selected default model.
7
8
  * 📖 Pressing Enter in `OpenClaw` mode must therefore do two things reliably:
8
9
  * - install the selected provider/model into `~/.openclaw/openclaw.json`
9
10
  * - set that exact model as the default primary model for the next OpenClaw session
11
+ * - optionally start `openclaw` immediately when the caller asks for it
10
12
  *
11
13
  * 📖 The old implementation was hard-coded to `nvidia/*`, which meant selecting
12
14
  * 📖 a Groq/Cerebras/etc. row silently wrote the wrong provider/model into the
@@ -30,6 +32,7 @@ import { dirname, join } from 'path'
30
32
  import { installProviderEndpoints } from './endpoint-installer.js'
31
33
  import { ENV_VAR_NAMES } from './provider-metadata.js'
32
34
  import { PROVIDER_COLOR } from './render-table.js'
35
+ import { resolveToolBinaryPath } from './tool-bootstrap.js'
33
36
 
34
37
  const OPENCLAW_CONFIG = join(homedir(), '.openclaw', 'openclaw.json')
35
38
 
@@ -53,13 +56,38 @@ export function saveOpenClawConfig(config, options = {}) {
53
56
  writeFileSync(filePath, JSON.stringify(config, null, 2))
54
57
  }
55
58
 
59
+ function spawnOpenClawCli() {
60
+ return new Promise(async (resolve, reject) => {
61
+ const { spawn } = await import('child_process')
62
+ const command = resolveToolBinaryPath('openclaw') || 'openclaw'
63
+ const child = spawn(command, [], {
64
+ stdio: 'inherit',
65
+ shell: false,
66
+ detached: false,
67
+ env: process.env,
68
+ })
69
+
70
+ child.on('exit', (code) => resolve(typeof code === 'number' ? code : 0))
71
+ child.on('error', (error) => {
72
+ if (error?.code === 'ENOENT') {
73
+ console.log(chalk.red(' X Could not find "openclaw" in PATH.'))
74
+ console.log(chalk.dim(' Install: npm install -g openclaw@latest or see https://docs.openclaw.ai/install'))
75
+ console.log()
76
+ resolve(1)
77
+ return
78
+ }
79
+ reject(error)
80
+ })
81
+ })
82
+ }
83
+
56
84
  /**
57
85
  * 📖 startOpenClaw installs the selected provider/model into OpenClaw and sets
58
86
  * 📖 it as the primary default model. OpenClaw itself is not launched here.
59
87
  *
60
88
  * @param {{ providerKey: string, modelId: string, label: string }} model
61
89
  * @param {Record<string, unknown>} config
62
- * @param {{ paths?: { openclawConfigPath?: string } }} [options]
90
+ * @param {{ paths?: { openclawConfigPath?: string }, launchCli?: boolean }} [options]
63
91
  * @returns {Promise<ReturnType<typeof installProviderEndpoints> | null>}
64
92
  */
65
93
  export async function startOpenClaw(model, config, options = {}) {
@@ -85,9 +113,15 @@ export async function startOpenClaw(model, config, options = {}) {
85
113
  if (result.backupPath) console.log(chalk.dim(` 💾 Backup: ${result.backupPath}`))
86
114
  if (providerEnvName) console.log(chalk.dim(` 🔑 API key synced under config env.${providerEnvName}`))
87
115
  console.log()
88
- console.log(chalk.dim(' 💡 OpenClaw will reload config automatically when it notices the file change.'))
89
- console.log(chalk.dim(` To apply manually: openclaw models set ${result.primaryModelRef || `${result.providerId}/${model.modelId}`}`))
90
- console.log()
116
+ if (options.launchCli) {
117
+ console.log(chalk.dim(' Starting OpenClaw...'))
118
+ console.log()
119
+ await spawnOpenClawCli()
120
+ } else {
121
+ console.log(chalk.dim(' 💡 OpenClaw will reload config automatically when it notices the file change.'))
122
+ console.log(chalk.dim(` To apply manually: openclaw models set ${result.primaryModelRef || `${result.providerId}/${model.modelId}`}`))
123
+ console.log()
124
+ }
91
125
  return result
92
126
  } catch (error) {
93
127
  console.log(chalk.red(` X Could not configure OpenClaw: ${error instanceof Error ? error.message : String(error)}`))
package/src/opencode.js CHANGED
@@ -32,6 +32,7 @@ import { PROVIDER_COLOR } from './render-table.js'
32
32
  import { loadOpenCodeConfig, saveOpenCodeConfig } from './opencode-config.js'
33
33
  import { getApiKey } from './config.js'
34
34
  import { ENV_VAR_NAMES, OPENCODE_MODEL_MAP, isWindows, isMac, isLinux } from './provider-metadata.js'
35
+ import { resolveToolBinaryPath } from './tool-bootstrap.js'
35
36
 
36
37
  // 📖 OpenCode config location: ~/.config/opencode/opencode.json on ALL platforms.
37
38
  // 📖 OpenCode uses xdg-basedir which resolves to %USERPROFILE%\.config on Windows.
@@ -177,7 +178,7 @@ async function spawnOpenCode(args, providerKey, fcmConfig, existingZaiProxy = nu
177
178
  }
178
179
 
179
180
  const { spawn } = await import('child_process')
180
- const child = spawn('opencode', finalArgs, {
181
+ const child = spawn(resolveToolBinaryPath('opencode') || 'opencode', finalArgs, {
181
182
  stdio: 'inherit',
182
183
  shell: true,
183
184
  detached: false,