free-coding-models 0.3.0 → 0.3.2
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/CHANGELOG.md +24 -0
- package/README.md +29 -20
- package/bin/free-coding-models.js +50 -19
- package/package.json +1 -1
- package/src/anthropic-translator.js +78 -8
- package/src/cli-help.js +108 -0
- package/src/config.js +2 -1
- package/src/endpoint-installer.js +5 -4
- package/src/key-handler.js +31 -34
- package/src/opencode.js +17 -12
- package/src/overlays.js +40 -53
- package/src/proxy-server.js +335 -12
- package/src/proxy-sync.js +16 -4
- package/src/render-helpers.js +4 -2
- package/src/render-table.js +34 -36
- package/src/responses-translator.js +423 -0
- package/src/tool-launchers.js +246 -19
- package/src/utils.js +31 -8
package/src/key-handler.js
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*
|
|
11
11
|
* 📖 Key J opens the FCM Proxy V2 overlay directly (with daemon status refresh).
|
|
12
12
|
* 📖 Key I opens the unified "Feedback, bugs & requests" overlay.
|
|
13
|
-
* 📖 The proxy overlay handles
|
|
14
|
-
*
|
|
13
|
+
* 📖 The proxy overlay handles sync toggle and cleanup for the current Z-selected tool,
|
|
14
|
+
* plus all daemon management actions.
|
|
15
15
|
*
|
|
16
16
|
* It also owns the "test key" model selection used by the Settings overlay.
|
|
17
17
|
* Some providers expose models in `/v1/models` that are not actually callable
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
33
|
import { loadChangelog } from './changelog-loader.js'
|
|
34
|
+
import { resolveProxySyncToolMode } from './proxy-sync.js'
|
|
34
35
|
|
|
35
36
|
// 📖 Some providers need an explicit probe model because the first catalog entry
|
|
36
37
|
// 📖 is not guaranteed to be accepted by their chat endpoint.
|
|
@@ -1284,15 +1285,14 @@ export function createKeyHandler(ctx) {
|
|
|
1284
1285
|
if (state.proxyDaemonOpen) {
|
|
1285
1286
|
const proxySettings = getProxySettings(state.config)
|
|
1286
1287
|
const ROW_PROXY_ENABLED = 0
|
|
1287
|
-
const
|
|
1288
|
-
const
|
|
1289
|
-
const
|
|
1290
|
-
const
|
|
1291
|
-
const
|
|
1292
|
-
const
|
|
1293
|
-
const
|
|
1294
|
-
const
|
|
1295
|
-
const ROW_DAEMON_LOGS = 9
|
|
1288
|
+
const ROW_PROXY_SYNC = 1
|
|
1289
|
+
const ROW_PROXY_PORT = 2
|
|
1290
|
+
const ROW_PROXY_CLEANUP = 3
|
|
1291
|
+
const ROW_DAEMON_INSTALL = 4
|
|
1292
|
+
const ROW_DAEMON_RESTART = 5
|
|
1293
|
+
const ROW_DAEMON_STOP = 6
|
|
1294
|
+
const ROW_DAEMON_KILL = 7
|
|
1295
|
+
const ROW_DAEMON_LOGS = 8
|
|
1296
1296
|
|
|
1297
1297
|
const daemonStatus = state.daemonStatus || 'not-installed'
|
|
1298
1298
|
const daemonIsInstalled = daemonStatus === 'running' || daemonStatus === 'stopped' || daemonStatus === 'unhealthy' || daemonStatus === 'stale'
|
|
@@ -1340,8 +1340,9 @@ export function createKeyHandler(ctx) {
|
|
|
1340
1340
|
if (key.name === 'pageup') { state.proxyDaemonCursor = Math.max(0, state.proxyDaemonCursor - 5); return }
|
|
1341
1341
|
if (key.name === 'pagedown') { state.proxyDaemonCursor = Math.min(maxRow, state.proxyDaemonCursor + 5); return }
|
|
1342
1342
|
|
|
1343
|
-
// 📖
|
|
1344
|
-
const
|
|
1343
|
+
// 📖 Proxy sync now follows the current Z-selected tool automatically.
|
|
1344
|
+
const currentToolMode = state.mode || 'opencode'
|
|
1345
|
+
const currentProxyTool = resolveProxySyncToolMode(currentToolMode)
|
|
1345
1346
|
|
|
1346
1347
|
// 📖 Space toggles on proxy rows
|
|
1347
1348
|
if (key.name === 'space') {
|
|
@@ -1352,14 +1353,16 @@ export function createKeyHandler(ctx) {
|
|
|
1352
1353
|
state.proxyDaemonMessage = { type: 'success', msg: `✅ Proxy mode ${state.config.settings.proxy.enabled ? 'enabled' : 'disabled'}`, ts: Date.now() }
|
|
1353
1354
|
return
|
|
1354
1355
|
}
|
|
1355
|
-
if (state.proxyDaemonCursor ===
|
|
1356
|
-
|
|
1357
|
-
|
|
1356
|
+
if (state.proxyDaemonCursor === ROW_PROXY_SYNC) {
|
|
1357
|
+
if (!currentProxyTool) {
|
|
1358
|
+
state.proxyDaemonMessage = { type: 'warning', msg: '⚠ Current tool does not support persisted proxy sync', ts: Date.now() }
|
|
1359
|
+
return
|
|
1360
|
+
}
|
|
1358
1361
|
if (!state.config.settings) state.config.settings = {}
|
|
1359
1362
|
state.config.settings.proxy = { ...proxySettings, syncToOpenCode: !proxySettings.syncToOpenCode }
|
|
1360
1363
|
saveConfig(state.config)
|
|
1361
1364
|
const { getToolMeta } = await import('./tool-metadata.js')
|
|
1362
|
-
const toolLabel = getToolMeta(
|
|
1365
|
+
const toolLabel = getToolMeta(currentProxyTool).label
|
|
1363
1366
|
state.proxyDaemonMessage = { type: 'success', msg: `✅ Auto-sync to ${toolLabel} ${state.config.settings.proxy.syncToOpenCode ? 'enabled' : 'disabled'}`, ts: Date.now() }
|
|
1364
1367
|
return
|
|
1365
1368
|
} else {
|
|
@@ -1367,20 +1370,6 @@ export function createKeyHandler(ctx) {
|
|
|
1367
1370
|
}
|
|
1368
1371
|
}
|
|
1369
1372
|
|
|
1370
|
-
// 📖 Enter or Space on ROW_PROXY_TOOL → cycle active tool
|
|
1371
|
-
if ((key.name === 'return' || key.name === 'space') && state.proxyDaemonCursor === ROW_PROXY_TOOL) {
|
|
1372
|
-
const { PROXY_SYNCABLE_TOOLS } = await import('./proxy-sync.js')
|
|
1373
|
-
const currentIdx = PROXY_SYNCABLE_TOOLS.indexOf(activeProxyTool)
|
|
1374
|
-
const nextIdx = (currentIdx + 1) % PROXY_SYNCABLE_TOOLS.length
|
|
1375
|
-
const nextTool = PROXY_SYNCABLE_TOOLS[nextIdx]
|
|
1376
|
-
if (!state.config.settings) state.config.settings = {}
|
|
1377
|
-
state.config.settings.proxy = { ...proxySettings, activeTool: nextTool }
|
|
1378
|
-
saveConfig(state.config)
|
|
1379
|
-
const { getToolMeta } = await import('./tool-metadata.js')
|
|
1380
|
-
state.proxyDaemonMessage = { type: 'success', msg: `✅ Active tool: ${getToolMeta(nextTool).emoji} ${getToolMeta(nextTool).label}`, ts: Date.now() }
|
|
1381
|
-
return
|
|
1382
|
-
}
|
|
1383
|
-
|
|
1384
1373
|
// 📖 Enter on proxy rows
|
|
1385
1374
|
if (key.name === 'return') {
|
|
1386
1375
|
// 📖 Proxy enabled — toggle
|
|
@@ -1394,11 +1383,15 @@ export function createKeyHandler(ctx) {
|
|
|
1394
1383
|
|
|
1395
1384
|
// 📖 Auto-sync toggle
|
|
1396
1385
|
if (state.proxyDaemonCursor === ROW_PROXY_SYNC) {
|
|
1386
|
+
if (!currentProxyTool) {
|
|
1387
|
+
state.proxyDaemonMessage = { type: 'warning', msg: '⚠ Current tool does not support persisted proxy sync', ts: Date.now() }
|
|
1388
|
+
return
|
|
1389
|
+
}
|
|
1397
1390
|
if (!state.config.settings) state.config.settings = {}
|
|
1398
1391
|
state.config.settings.proxy = { ...proxySettings, syncToOpenCode: !proxySettings.syncToOpenCode }
|
|
1399
1392
|
saveConfig(state.config)
|
|
1400
1393
|
const { getToolMeta } = await import('./tool-metadata.js')
|
|
1401
|
-
const toolLabel = getToolMeta(
|
|
1394
|
+
const toolLabel = getToolMeta(currentProxyTool).label
|
|
1402
1395
|
state.proxyDaemonMessage = { type: 'success', msg: `✅ Auto-sync to ${toolLabel} ${state.config.settings.proxy.syncToOpenCode ? 'enabled' : 'disabled'}`, ts: Date.now() }
|
|
1403
1396
|
return
|
|
1404
1397
|
}
|
|
@@ -1412,9 +1405,13 @@ export function createKeyHandler(ctx) {
|
|
|
1412
1405
|
|
|
1413
1406
|
// 📖 Clean proxy config — generalized for active tool
|
|
1414
1407
|
if (state.proxyDaemonCursor === ROW_PROXY_CLEANUP) {
|
|
1415
|
-
|
|
1408
|
+
if (!currentProxyTool) {
|
|
1409
|
+
state.proxyDaemonMessage = { type: 'warning', msg: '⚠ Current tool has no persisted proxy config to clean', ts: Date.now() }
|
|
1410
|
+
return
|
|
1411
|
+
}
|
|
1412
|
+
const result = cleanupToolConfig(currentProxyTool)
|
|
1416
1413
|
const { getToolMeta } = await import('./tool-metadata.js')
|
|
1417
|
-
const toolLabel = getToolMeta(
|
|
1414
|
+
const toolLabel = getToolMeta(currentProxyTool).label
|
|
1418
1415
|
if (result.success) {
|
|
1419
1416
|
state.proxyDaemonMessage = { type: 'success', msg: `✅ ${toolLabel} proxy config cleaned — all fcm-* entries removed`, ts: Date.now() }
|
|
1420
1417
|
} else {
|
package/src/opencode.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - Launch OpenCode CLI or Desktop
|
|
9
9
|
* - Manage ZAI proxy bridge for non-standard API paths
|
|
10
10
|
* - Start/stop the multi-account proxy server (fcm-proxy)
|
|
11
|
-
* - Auto-start proxy when
|
|
11
|
+
* - Auto-start proxy when the current tool is configured for proxy auto-sync
|
|
12
12
|
*
|
|
13
13
|
* 🎯 Key features:
|
|
14
14
|
* - Provider-aware config setup for OpenCode (NIM, Groq, Cerebras, etc.)
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* - `startOpenCode` — Launch OpenCode CLI with selected model
|
|
22
22
|
* - `startOpenCodeDesktop` — Set model and open Desktop app
|
|
23
23
|
* - `startProxyAndLaunch` — Start fcm-proxy then launch OpenCode
|
|
24
|
-
* - `autoStartProxyIfSynced` — Auto-start proxy
|
|
24
|
+
* - `autoStartProxyIfSynced` — Auto-start proxy and sync the current tool when enabled
|
|
25
25
|
* - `ensureProxyRunning` — Ensure proxy is running (start or reuse)
|
|
26
26
|
* - `isProxyEnabledForConfig` — Check whether proxy mode is opted in
|
|
27
27
|
*
|
|
@@ -40,12 +40,14 @@ import { copyFileSync, existsSync } from 'fs'
|
|
|
40
40
|
import { sources } from '../sources.js'
|
|
41
41
|
import { PROVIDER_COLOR } from './render-table.js'
|
|
42
42
|
import { ProxyServer } from './proxy-server.js'
|
|
43
|
-
import { loadOpenCodeConfig, saveOpenCodeConfig
|
|
43
|
+
import { loadOpenCodeConfig, saveOpenCodeConfig } from './opencode-sync.js'
|
|
44
44
|
import { getApiKey, getProxySettings } from './config.js'
|
|
45
45
|
import { ENV_VAR_NAMES, OPENCODE_MODEL_MAP, isWindows, isMac, isLinux } from './provider-metadata.js'
|
|
46
46
|
import { setActiveProxy } from './render-table.js'
|
|
47
47
|
import { buildProxyTopologyFromConfig as _buildTopology } from './proxy-topology.js'
|
|
48
48
|
import { isDaemonRunning, getDaemonInfo } from './daemon-manager.js'
|
|
49
|
+
import { syncProxyToTool, resolveProxySyncToolMode } from './proxy-sync.js'
|
|
50
|
+
import { getToolMeta } from './tool-metadata.js'
|
|
49
51
|
|
|
50
52
|
// 📖 OpenCode config location: ~/.config/opencode/opencode.json on ALL platforms.
|
|
51
53
|
// 📖 OpenCode uses xdg-basedir which resolves to %USERPROFILE%\.config on Windows.
|
|
@@ -633,24 +635,27 @@ export async function autoStartProxyIfSynced(fcmConfig, state) {
|
|
|
633
635
|
try {
|
|
634
636
|
const proxySettings = getProxySettings(fcmConfig)
|
|
635
637
|
if (!proxySettings.enabled || !proxySettings.syncToOpenCode) return
|
|
636
|
-
|
|
637
|
-
const
|
|
638
|
-
if (!
|
|
638
|
+
const currentToolMode = state?.mode || 'opencode'
|
|
639
|
+
const syncTarget = resolveProxySyncToolMode(currentToolMode)
|
|
640
|
+
if (!syncTarget) return
|
|
639
641
|
|
|
640
642
|
state.proxyStartupStatus = { phase: 'starting' }
|
|
641
643
|
|
|
642
644
|
const started = await ensureProxyRunning(fcmConfig)
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
645
|
+
const syncResult = syncProxyToTool(syncTarget, {
|
|
646
|
+
baseUrl: `http://127.0.0.1:${started.port}/v1`,
|
|
647
|
+
token: started.proxyToken,
|
|
648
|
+
}, mergedModelsRef)
|
|
649
|
+
if (!syncResult.success) {
|
|
650
|
+
throw new Error(syncResult.error || `Proxy sync failed for ${syncTarget}`)
|
|
651
|
+
}
|
|
649
652
|
|
|
650
653
|
state.proxyStartupStatus = {
|
|
651
654
|
phase: 'running',
|
|
652
655
|
port: started.port,
|
|
653
656
|
accountCount: started.accountCount,
|
|
657
|
+
tool: getToolMeta(syncTarget).label,
|
|
658
|
+
path: syncResult.path || null,
|
|
654
659
|
}
|
|
655
660
|
} catch (err) {
|
|
656
661
|
state.proxyStartupStatus = {
|
package/src/overlays.js
CHANGED
|
@@ -5,27 +5,27 @@
|
|
|
5
5
|
* @details
|
|
6
6
|
* This module centralizes all overlay rendering in one place:
|
|
7
7
|
* - Settings, Install Endpoints, Help, Log, Smart Recommend, Feedback, Changelog
|
|
8
|
-
* - FCM Proxy V2 overlay with tool
|
|
8
|
+
* - FCM Proxy V2 overlay with current-tool auto-sync toggle and cleanup
|
|
9
9
|
* - Settings diagnostics for provider key tests, including wrapped retry/error details
|
|
10
10
|
* - Recommend analysis timer orchestration and progress updates
|
|
11
11
|
*
|
|
12
12
|
* The factory pattern keeps stateful UI logic isolated while still
|
|
13
13
|
* allowing the main CLI to control shared state and dependencies.
|
|
14
14
|
*
|
|
15
|
-
* 📖 The proxy overlay rows are: Enable →
|
|
16
|
-
* 📖 Tool selector cycles through PROXY_SYNCABLE_TOOLS (12 tools from proxy-sync.js)
|
|
15
|
+
* 📖 The proxy overlay rows are: Enable → Auto-sync current tool → Port → Cleanup → Install/Restart/Stop/Kill/Logs
|
|
17
16
|
* 📖 Feedback overlay (I key) combines feature requests + bug reports in one left-aligned input
|
|
18
17
|
*
|
|
19
18
|
* → Functions:
|
|
20
19
|
* - `createOverlayRenderers` — returns renderer + analysis helpers
|
|
21
20
|
*
|
|
22
21
|
* @exports { createOverlayRenderers }
|
|
23
|
-
* @see ./proxy-sync.js —
|
|
22
|
+
* @see ./proxy-sync.js — resolveProxySyncToolMode powers current-tool proxy sync hints
|
|
24
23
|
* @see ./key-handler.js — handles keypresses for all overlay interactions
|
|
25
24
|
*/
|
|
26
25
|
|
|
27
26
|
import { loadChangelog } from './changelog-loader.js'
|
|
28
|
-
import {
|
|
27
|
+
import { buildCliHelpLines } from './cli-help.js'
|
|
28
|
+
import { resolveProxySyncToolMode } from './proxy-sync.js'
|
|
29
29
|
|
|
30
30
|
export function createOverlayRenderers(state, deps) {
|
|
31
31
|
const {
|
|
@@ -627,7 +627,7 @@ export function createOverlayRenderers(state, deps) {
|
|
|
627
627
|
lines.push(` ${chalk.yellow('X')} Toggle token log page ${chalk.dim('(shows recent request usage from request-log.jsonl)')}`)
|
|
628
628
|
lines.push(` ${chalk.yellow('Z')} Cycle tool mode ${chalk.dim('(OpenCode → Desktop → OpenClaw → Crush → Goose → Pi → Aider → Claude Code → Codex → Gemini → Qwen → OpenHands → Amp)')}`)
|
|
629
629
|
lines.push(` ${chalk.yellow('F')} Toggle favorite on selected row ${chalk.dim('(⭐ pinned at top, persisted)')}`)
|
|
630
|
-
lines.push(` ${chalk.yellow('Y')} Install endpoints ${chalk.dim('(provider catalog →
|
|
630
|
+
lines.push(` ${chalk.yellow('Y')} Install endpoints ${chalk.dim('(provider catalog → compatible tools, Direct or FCM Proxy V2)')}`)
|
|
631
631
|
lines.push(` ${chalk.yellow('Q')} Smart Recommend ${chalk.dim('(🎯 find the best model for your task — questionnaire + live analysis)')}`)
|
|
632
632
|
lines.push(` ${chalk.rgb(255, 87, 51).bold('I')} Feedback, bugs & requests ${chalk.dim('(📝 send anonymous feedback, bug reports, or feature requests)')}`)
|
|
633
633
|
lines.push(` ${chalk.yellow('J')} FCM Proxy V2 settings ${chalk.dim('(📡 open proxy configuration and background service management)')}`)
|
|
@@ -651,29 +651,7 @@ export function createOverlayRenderers(state, deps) {
|
|
|
651
651
|
lines.push(` ${chalk.yellow('U')} Check updates manually`)
|
|
652
652
|
lines.push(` ${chalk.yellow('Esc')} Close settings`)
|
|
653
653
|
lines.push('')
|
|
654
|
-
lines.push(
|
|
655
|
-
lines.push(` ${chalk.dim('Usage: free-coding-models [options]')}`)
|
|
656
|
-
lines.push(` ${chalk.cyan('free-coding-models --opencode')} ${chalk.dim('OpenCode CLI mode')}`)
|
|
657
|
-
lines.push(` ${chalk.cyan('free-coding-models --opencode-desktop')} ${chalk.dim('OpenCode Desktop mode')}`)
|
|
658
|
-
lines.push(` ${chalk.cyan('free-coding-models --openclaw')} ${chalk.dim('OpenClaw mode')}`)
|
|
659
|
-
lines.push(` ${chalk.cyan('free-coding-models --crush')} ${chalk.dim('Crush mode')}`)
|
|
660
|
-
lines.push(` ${chalk.cyan('free-coding-models --goose')} ${chalk.dim('Goose mode')}`)
|
|
661
|
-
lines.push(` ${chalk.cyan('free-coding-models --pi')} ${chalk.dim('Pi mode')}`)
|
|
662
|
-
lines.push(` ${chalk.cyan('free-coding-models --aider')} ${chalk.dim('Aider mode')}`)
|
|
663
|
-
lines.push(` ${chalk.cyan('free-coding-models --claude-code')} ${chalk.dim('Claude Code mode')}`)
|
|
664
|
-
lines.push(` ${chalk.cyan('free-coding-models --codex')} ${chalk.dim('Codex CLI mode')}`)
|
|
665
|
-
lines.push(` ${chalk.cyan('free-coding-models --gemini')} ${chalk.dim('Gemini CLI mode')}`)
|
|
666
|
-
lines.push(` ${chalk.cyan('free-coding-models --qwen')} ${chalk.dim('Qwen Code mode')}`)
|
|
667
|
-
lines.push(` ${chalk.cyan('free-coding-models --openhands')} ${chalk.dim('OpenHands mode')}`)
|
|
668
|
-
lines.push(` ${chalk.cyan('free-coding-models --amp')} ${chalk.dim('Amp mode')}`)
|
|
669
|
-
lines.push(` ${chalk.cyan('free-coding-models --best')} ${chalk.dim('Only top tiers (A+, S, S+)')}`)
|
|
670
|
-
lines.push(` ${chalk.cyan('free-coding-models --fiable')} ${chalk.dim('10s reliability analysis')}`)
|
|
671
|
-
lines.push(` ${chalk.cyan('free-coding-models --tier S|A|B|C')} ${chalk.dim('Filter by tier letter')}`)
|
|
672
|
-
lines.push(` ${chalk.cyan('free-coding-models --no-telemetry')} ${chalk.dim('Disable telemetry for this run')}`)
|
|
673
|
-
lines.push(` ${chalk.cyan('free-coding-models --recommend')} ${chalk.dim('Auto-open Smart Recommend on start')}`)
|
|
674
|
-
lines.push(` ${chalk.cyan('free-coding-models --profile <name>')} ${chalk.dim('Load a saved config profile')}`)
|
|
675
|
-
lines.push(` ${chalk.cyan('free-coding-models --clean-proxy')} ${chalk.dim('Remove persisted fcm-proxy config from OpenCode')}`)
|
|
676
|
-
lines.push(` ${chalk.dim('Flags can be combined: --openclaw --tier S')}`)
|
|
654
|
+
lines.push(...buildCliHelpLines({ chalk, indent: ' ', title: 'CLI Flags' }))
|
|
677
655
|
lines.push('')
|
|
678
656
|
// 📖 Help overlay can be longer than viewport, so keep a dedicated scroll offset.
|
|
679
657
|
const { visible, offset } = sliceOverlayLines(lines, state.helpScrollOffset, state.terminalRows)
|
|
@@ -1273,15 +1251,14 @@ export function createOverlayRenderers(state, deps) {
|
|
|
1273
1251
|
|
|
1274
1252
|
// 📖 Row indices — these control cursor navigation
|
|
1275
1253
|
const ROW_PROXY_ENABLED = 0
|
|
1276
|
-
const
|
|
1277
|
-
const
|
|
1278
|
-
const
|
|
1279
|
-
const
|
|
1280
|
-
const
|
|
1281
|
-
const
|
|
1282
|
-
const
|
|
1283
|
-
const
|
|
1284
|
-
const ROW_DAEMON_LOGS = 9
|
|
1254
|
+
const ROW_PROXY_SYNC = 1
|
|
1255
|
+
const ROW_PROXY_PORT = 2
|
|
1256
|
+
const ROW_PROXY_CLEANUP = 3
|
|
1257
|
+
const ROW_DAEMON_INSTALL = 4
|
|
1258
|
+
const ROW_DAEMON_RESTART = 5
|
|
1259
|
+
const ROW_DAEMON_STOP = 6
|
|
1260
|
+
const ROW_DAEMON_KILL = 7
|
|
1261
|
+
const ROW_DAEMON_LOGS = 8
|
|
1285
1262
|
|
|
1286
1263
|
const daemonStatus = state.daemonStatus || 'not-installed'
|
|
1287
1264
|
const daemonInfo = state.daemonInfo
|
|
@@ -1318,10 +1295,16 @@ export function createOverlayRenderers(state, deps) {
|
|
|
1318
1295
|
lines.push(` ${chalk.dim(' to this proxy which handles key rotation, rate limiting, and failover.')}`)
|
|
1319
1296
|
lines.push('')
|
|
1320
1297
|
|
|
1321
|
-
// 📖
|
|
1322
|
-
const
|
|
1323
|
-
const
|
|
1324
|
-
const
|
|
1298
|
+
// 📖 Proxy sync now always follows the currently selected Z-mode when supported.
|
|
1299
|
+
const currentToolMode = state.mode || 'opencode'
|
|
1300
|
+
const currentToolMeta = getToolMeta(currentToolMode)
|
|
1301
|
+
const currentToolLabel = `${currentToolMeta.emoji} ${currentToolMeta.label}`
|
|
1302
|
+
const proxySyncTool = resolveProxySyncToolMode(currentToolMode)
|
|
1303
|
+
const proxySyncHint = proxySyncTool
|
|
1304
|
+
? chalk.dim(` Current tool: ${currentToolLabel}`)
|
|
1305
|
+
: chalk.yellow(` Current tool: ${currentToolLabel} (launcher-only, no persisted proxy config)`)
|
|
1306
|
+
lines.push(proxySyncHint)
|
|
1307
|
+
lines.push('')
|
|
1325
1308
|
|
|
1326
1309
|
// 📖 Row 0: Proxy enabled toggle
|
|
1327
1310
|
const r0b = state.proxyDaemonCursor === ROW_PROXY_ENABLED ? chalk.bold.cyan(' ❯ ') : chalk.dim(' ')
|
|
@@ -1330,20 +1313,18 @@ export function createOverlayRenderers(state, deps) {
|
|
|
1330
1313
|
cursorLineByRow[ROW_PROXY_ENABLED] = lines.length
|
|
1331
1314
|
lines.push(state.proxyDaemonCursor === ROW_PROXY_ENABLED ? chalk.bgRgb(20, 45, 60)(r0) : r0)
|
|
1332
1315
|
|
|
1333
|
-
// 📖 Row 1:
|
|
1334
|
-
const r1b = state.proxyDaemonCursor === ROW_PROXY_TOOL ? chalk.bold.cyan(' ❯ ') : chalk.dim(' ')
|
|
1335
|
-
const r1 = `${r1b}${chalk.bold('Active tool').padEnd(44)} ${chalk.cyanBright(activeToolLabel)} ${chalk.dim('← Enter to cycle')}`
|
|
1336
|
-
cursorLineByRow[ROW_PROXY_TOOL] = lines.length
|
|
1337
|
-
lines.push(state.proxyDaemonCursor === ROW_PROXY_TOOL ? chalk.bgRgb(20, 45, 60)(r1) : r1)
|
|
1338
|
-
|
|
1339
|
-
// 📖 Row 2: Auto-sync proxy config to active tool
|
|
1316
|
+
// 📖 Row 1: Auto-sync proxy config to the current tool when that tool supports persisted sync.
|
|
1340
1317
|
const r2b = state.proxyDaemonCursor === ROW_PROXY_SYNC ? chalk.bold.cyan(' ❯ ') : chalk.dim(' ')
|
|
1341
1318
|
const r2val = proxySettings.syncToOpenCode ? chalk.greenBright('Enabled') : chalk.dim('Disabled')
|
|
1342
|
-
const
|
|
1319
|
+
const r2label = proxySyncTool
|
|
1320
|
+
? `Auto-sync proxy to ${currentToolMeta.label}`
|
|
1321
|
+
: 'Auto-sync proxy to current tool'
|
|
1322
|
+
const r2note = proxySyncTool ? '' : ` ${chalk.dim('(unavailable for this mode)')}`
|
|
1323
|
+
const r2 = `${r2b}${chalk.bold(r2label).padEnd(44)} ${r2val}${r2note}`
|
|
1343
1324
|
cursorLineByRow[ROW_PROXY_SYNC] = lines.length
|
|
1344
1325
|
lines.push(state.proxyDaemonCursor === ROW_PROXY_SYNC ? chalk.bgRgb(20, 45, 60)(r2) : r2)
|
|
1345
1326
|
|
|
1346
|
-
// 📖 Row
|
|
1327
|
+
// 📖 Row 2: Preferred port
|
|
1347
1328
|
const r3b = state.proxyDaemonCursor === ROW_PROXY_PORT ? chalk.bold.cyan(' ❯ ') : chalk.dim(' ')
|
|
1348
1329
|
const r3val = state.settingsProxyPortEditMode && state.proxyDaemonCursor === ROW_PROXY_PORT
|
|
1349
1330
|
? chalk.cyanBright(`${state.settingsProxyPortBuffer}▏`)
|
|
@@ -1352,9 +1333,15 @@ export function createOverlayRenderers(state, deps) {
|
|
|
1352
1333
|
cursorLineByRow[ROW_PROXY_PORT] = lines.length
|
|
1353
1334
|
lines.push(state.proxyDaemonCursor === ROW_PROXY_PORT ? chalk.bgRgb(20, 45, 60)(r3) : r3)
|
|
1354
1335
|
|
|
1355
|
-
// 📖 Row
|
|
1336
|
+
// 📖 Row 3: Clean current tool proxy config
|
|
1356
1337
|
const r4b = state.proxyDaemonCursor === ROW_PROXY_CLEANUP ? chalk.bold.cyan(' ❯ ') : chalk.dim(' ')
|
|
1357
|
-
const
|
|
1338
|
+
const r4title = proxySyncTool
|
|
1339
|
+
? `Clean ${currentToolMeta.label} proxy config`
|
|
1340
|
+
: `Clean ${currentToolMeta.label} proxy config`
|
|
1341
|
+
const r4hint = proxySyncTool
|
|
1342
|
+
? chalk.dim('Enter → removes all fcm-* entries')
|
|
1343
|
+
: chalk.dim('Unavailable for this mode')
|
|
1344
|
+
const r4 = `${r4b}${chalk.bold(r4title).padEnd(44)} ${r4hint}`
|
|
1358
1345
|
cursorLineByRow[ROW_PROXY_CLEANUP] = lines.length
|
|
1359
1346
|
lines.push(state.proxyDaemonCursor === ROW_PROXY_CLEANUP ? chalk.bgRgb(45, 30, 30)(r4) : r4)
|
|
1360
1347
|
|