free-coding-models 0.3.22 → 0.3.24

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.
@@ -19,21 +19,44 @@
19
19
  * → `getToolMeta` — return display metadata for one mode
20
20
  * → `getToolModeOrder` — stable mode cycle order for the `Z` hotkey
21
21
  *
22
- * @exports TOOL_METADATA, TOOL_MODE_ORDER, getToolMeta, getToolModeOrder
22
+ * @exports TOOL_METADATA, TOOL_MODE_ORDER, COMPAT_COLUMN_SLOTS, getToolMeta, getToolModeOrder
23
23
  */
24
+ // 📖 Each tool has a unique `color` RGB tuple used for the "Compatible with" column
25
+ // 📖 and for coloring the tool name in the Z cycle header badge.
26
+ // 📖 `emoji` is the unique icon shown everywhere (header badge, compat column, palette, overlays).
27
+ // 📖 OpenCode CLI and Desktop share 📦 — they are the same platform, split only for launch logic.
24
28
  export const TOOL_METADATA = {
25
- opencode: { label: 'OpenCode CLI', emoji: '💻', flag: '--opencode' },
26
- 'opencode-desktop': { label: 'OpenCode Desktop', emoji: '🖥', flag: '--opencode-desktop' },
27
- openclaw: { label: 'OpenClaw', emoji: '🦞', flag: '--openclaw' },
28
- crush: { label: 'Crush', emoji: '💘', flag: '--crush' },
29
- goose: { label: 'Goose', emoji: '🪿', flag: '--goose' },
30
- pi: { label: 'Pi', emoji: 'π', flag: '--pi' },
31
- aider: { label: 'Aider', emoji: '🛠', flag: '--aider' },
32
- qwen: { label: 'Qwen Code', emoji: '🌊', flag: '--qwen' },
33
- openhands: { label: 'OpenHands', emoji: '🤲', flag: '--openhands' },
34
- amp: { label: 'Amp', emoji: '⚡', flag: '--amp' },
29
+ opencode: { label: 'OpenCode CLI', emoji: '📦', flag: '--opencode', color: [110, 214, 255] },
30
+ 'opencode-desktop': { label: 'OpenCode Desktop', emoji: '📦', flag: '--opencode-desktop', color: [149, 205, 255] },
31
+ openclaw: { label: 'OpenClaw', emoji: '🦞', flag: '--openclaw', color: [255, 129, 129] },
32
+ crush: { label: 'Crush', emoji: '💘', flag: '--crush', color: [255, 168, 209] },
33
+ goose: { label: 'Goose', emoji: '🪿', flag: '--goose', color: [132, 235, 168] },
34
+ pi: { label: 'Pi', emoji: 'π', flag: '--pi', color: [173, 216, 230] },
35
+ aider: { label: 'Aider', emoji: '🛠', flag: '--aider', color: [255, 208, 102] },
36
+ qwen: { label: 'Qwen Code', emoji: '🐉', flag: '--qwen', color: [255, 213, 128] },
37
+ openhands: { label: 'OpenHands', emoji: '🤲', flag: '--openhands', color: [228, 191, 239] },
38
+ amp: { label: 'Amp', emoji: '⚡', flag: '--amp', color: [255, 232, 98] },
39
+ rovo: { label: 'Rovo Dev CLI', emoji: '🦘', flag: '--rovo', color: [148, 163, 184], cliOnly: true },
40
+ gemini: { label: 'Gemini CLI', emoji: '♊', flag: '--gemini', color: [66, 165, 245], cliOnly: true },
35
41
  }
36
42
 
43
+ // 📖 Deduplicated emoji order for the "Compatible with" column.
44
+ // 📖 OpenCode CLI + Desktop are merged into a single 📦 slot since they share compatibility.
45
+ // 📖 Each slot maps to one or more toolKeys for compatibility checking.
46
+ export const COMPAT_COLUMN_SLOTS = [
47
+ { emoji: '📦', toolKeys: ['opencode', 'opencode-desktop'], color: [110, 214, 255] },
48
+ { emoji: '🦞', toolKeys: ['openclaw'], color: [255, 129, 129] },
49
+ { emoji: '💘', toolKeys: ['crush'], color: [255, 168, 209] },
50
+ { emoji: '🪿', toolKeys: ['goose'], color: [132, 235, 168] },
51
+ { emoji: 'π', toolKeys: ['pi'], color: [173, 216, 230] },
52
+ { emoji: '🛠', toolKeys: ['aider'], color: [255, 208, 102] },
53
+ { emoji: '🐉', toolKeys: ['qwen'], color: [255, 213, 128] },
54
+ { emoji: '🤲', toolKeys: ['openhands'], color: [228, 191, 239] },
55
+ { emoji: '⚡', toolKeys: ['amp'], color: [255, 232, 98] },
56
+ { emoji: '🦘', toolKeys: ['rovo'], color: [148, 163, 184] },
57
+ { emoji: '♊', toolKeys: ['gemini'], color: [66, 165, 245] },
58
+ ]
59
+
37
60
  export const TOOL_MODE_ORDER = [
38
61
  'opencode',
39
62
  'opencode-desktop',
@@ -45,6 +68,8 @@ export const TOOL_MODE_ORDER = [
45
68
  'qwen',
46
69
  'openhands',
47
70
  'amp',
71
+ 'rovo',
72
+ 'gemini',
48
73
  ]
49
74
 
50
75
  export function getToolMeta(mode) {
@@ -54,3 +79,61 @@ export function getToolMeta(mode) {
54
79
  export function getToolModeOrder() {
55
80
  return [...TOOL_MODE_ORDER]
56
81
  }
82
+
83
+ // 📖 Regular tools: all tools EXCEPT rovo, gemini (which are CLI-only exclusives).
84
+ // 📖 Used as the default compatible set for normal provider models.
85
+ const REGULAR_TOOLS = Object.keys(TOOL_METADATA).filter(k => !TOOL_METADATA[k].cliOnly)
86
+
87
+ // 📖 Zen-only tools: OpenCode Zen models can ONLY run on OpenCode CLI / OpenCode Desktop.
88
+ const ZEN_COMPATIBLE_TOOLS = ['opencode', 'opencode-desktop']
89
+
90
+ /**
91
+ * 📖 Returns the list of tool keys a model is compatible with.
92
+ * - Rovo models → only 'rovo'
93
+ * - Gemini models → only 'gemini'
94
+ * - OpenCode Zen models → only 'opencode', 'opencode-desktop'
95
+ * - Regular models → all non-cliOnly tools
96
+ * @param {string} providerKey — the source key from sources.js (e.g. 'nvidia', 'rovo', 'opencode-zen')
97
+ * @returns {string[]} — array of compatible tool keys
98
+ */
99
+ export function getCompatibleTools(providerKey) {
100
+ if (providerKey === 'rovo') return ['rovo']
101
+ if (providerKey === 'gemini') return ['gemini']
102
+ if (providerKey === 'opencode-zen') return ZEN_COMPATIBLE_TOOLS
103
+ return REGULAR_TOOLS
104
+ }
105
+
106
+ /**
107
+ * 📖 Checks whether a model from the given provider can run on the specified tool mode.
108
+ * @param {string} providerKey — source key
109
+ * @param {string} toolMode — active tool mode
110
+ * @returns {boolean}
111
+ */
112
+ export function isModelCompatibleWithTool(providerKey, toolMode) {
113
+ return getCompatibleTools(providerKey).includes(toolMode)
114
+ }
115
+
116
+ /**
117
+ * 📖 Finds compatible models with a similar SWE score to the selected one.
118
+ * 📖 Used by the incompatibility fallback overlay to suggest alternatives.
119
+ * @param {string} selectedSwe — SWE score string like '72.0%' or '-'
120
+ * @param {string} toolMode — current active tool mode
121
+ * @param {Array} allResults — the state.results array (each has .providerKey, .modelId, .label, .tier, .sweScore)
122
+ * @param {number} [maxResults=3] — max suggestions to return
123
+ * @returns {{ modelId: string, label: string, tier: string, sweScore: string, providerKey: string, sweDelta: number }[]}
124
+ */
125
+ export function findSimilarCompatibleModels(selectedSwe, toolMode, allResults, maxResults = 3) {
126
+ const targetSwe = parseFloat(selectedSwe) || 0
127
+ return allResults
128
+ .filter(r => !r.hidden && isModelCompatibleWithTool(r.providerKey, toolMode))
129
+ .map(r => ({
130
+ modelId: r.modelId,
131
+ label: r.label,
132
+ tier: r.tier,
133
+ sweScore: r.sweScore || '-',
134
+ providerKey: r.providerKey,
135
+ sweDelta: Math.abs((parseFloat(r.sweScore) || 0) - targetSwe),
136
+ }))
137
+ .sort((a, b) => a.sweDelta - b.sweDelta)
138
+ .slice(0, maxResults)
139
+ }
package/src/utils.js CHANGED
@@ -220,7 +220,7 @@ export const getStabilityScore = (r) => {
220
220
  //
221
221
  // 📖 Supported columns in the sorter.
222
222
  // 📖 Most map directly to visible TUI sort hotkeys; `tier` remains available internally
223
- // 📖 even though the live TUI now reserves `Y` for the install-endpoints flow.
223
+ // 📖 while `Y` is used by the live UI for favorites display mode.
224
224
  // - 'rank' (R key) — original index from sources.js
225
225
  // - 'tier' (internal) — tier hierarchy (S+ first, C last)
226
226
  // - 'origin' (O key) — provider name (all NIM for now, future-proofed)
@@ -454,6 +454,8 @@ export function parseArgs(argv) {
454
454
  const openHandsMode = flags.includes('--openhands')
455
455
  const ampMode = flags.includes('--amp')
456
456
  const piMode = flags.includes('--pi')
457
+ const rovoMode = flags.includes('--rovo')
458
+ const geminiMode = flags.includes('--gemini')
457
459
  const noTelemetry = flags.includes('--no-telemetry')
458
460
  const jsonMode = flags.includes('--json')
459
461
  const helpMode = flags.includes('--help') || flags.includes('-h')
@@ -490,6 +492,8 @@ export function parseArgs(argv) {
490
492
  openHandsMode,
491
493
  ampMode,
492
494
  piMode,
495
+ rovoMode,
496
+ geminiMode,
493
497
  noTelemetry,
494
498
  jsonMode,
495
499
  helpMode,