@vigent/cli 0.0.0-stage → 0.2.0

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.
@@ -0,0 +1,352 @@
1
+ /** Built-in themes. Hand-ported themes are explicit; the rest are built from a palette. */
2
+ import { fromPalette } from "./palette.js";
3
+ // ---------------------------------------------------------------------------
4
+ // Neovim's default dark colorscheme (NvimDark / NvimLight palette, nvim >= 0.10)
5
+ // ---------------------------------------------------------------------------
6
+ const c = {
7
+ darkBlue: "#004c73",
8
+ darkCyan: "#007373",
9
+ darkGreen: "#005523",
10
+ darkGrey1: "#07080d",
11
+ darkGrey2: "#14161b",
12
+ darkGrey3: "#2c2e33",
13
+ darkGrey4: "#4f5258",
14
+ darkMagenta: "#470045",
15
+ darkRed: "#590008",
16
+ darkYellow: "#6b5300",
17
+ lightBlue: "#a6dbff",
18
+ lightCyan: "#8cf8f7",
19
+ lightGreen: "#b3f6c0",
20
+ lightGrey1: "#eef1f8",
21
+ lightGrey2: "#e0e2ea",
22
+ lightGrey3: "#c4c6cd",
23
+ lightGrey4: "#9b9ea4",
24
+ lightMagenta: "#ffcaff",
25
+ lightRed: "#ffc0b9",
26
+ lightYellow: "#fce094",
27
+ };
28
+ export const NVIM_DEFAULT = {
29
+ name: "default",
30
+ background: "dark",
31
+ groups: {
32
+ Normal: { fg: c.lightGrey2, bg: c.darkGrey2 },
33
+ NormalFloat: { fg: c.lightGrey2, bg: c.darkGrey1 },
34
+ WinSeparator: { fg: c.darkGrey4, bg: c.darkGrey2 },
35
+ StatusLine: { fg: c.darkGrey3, bg: c.lightGrey3 },
36
+ StatusLineNC: { fg: c.lightGrey4, bg: c.darkGrey3 },
37
+ CursorLine: { bg: c.darkGrey3 },
38
+ Visual: { bg: c.darkGrey4 },
39
+ LineNr: { fg: c.darkGrey4 },
40
+ CursorLineNr: { fg: c.lightGrey2, bold: true },
41
+ WinBar: { fg: c.lightGrey2, bold: true },
42
+ Comment: { fg: c.lightGrey4, italic: true },
43
+ NonText: { fg: c.darkGrey4 },
44
+ Title: { fg: c.lightGrey2, bold: true },
45
+ Identifier: { fg: c.lightBlue },
46
+ Function: { fg: c.lightCyan },
47
+ String: { fg: c.lightGreen },
48
+ Constant: { fg: c.lightMagenta },
49
+ Keyword: { fg: c.lightGrey2, bold: true },
50
+ Search: { fg: c.lightGrey1, bg: c.darkYellow },
51
+ CurSearch: { fg: c.darkGrey1, bg: c.lightYellow },
52
+ DiffAdd: { fg: c.lightGreen, bg: c.darkGreen },
53
+ DiffDelete: { fg: c.lightRed, bg: c.darkRed },
54
+ DiffChange: { fg: c.lightGrey2, bg: c.darkGrey4 },
55
+ Added: { fg: c.lightGreen },
56
+ Removed: { fg: c.lightRed },
57
+ ErrorMsg: { fg: c.lightRed },
58
+ WarningMsg: { fg: c.lightYellow },
59
+ ModeMsg: { fg: c.lightGreen, bold: true },
60
+ Pmenu: { fg: c.lightGrey2, bg: c.darkGrey3 },
61
+ PmenuSel: { fg: c.darkGrey2, bg: c.lightGrey3 },
62
+ // Vigent mode badges (vim-airline-style blocks)
63
+ VigentSidebar: { fg: c.lightGrey2, bg: c.darkGrey1 },
64
+ VigentModeNormal: { fg: c.darkGrey1, bg: c.lightBlue, bold: true },
65
+ VigentModeInsert: { fg: c.darkGrey1, bg: c.lightGreen, bold: true },
66
+ VigentModeVisual: { fg: c.darkGrey1, bg: c.lightMagenta, bold: true },
67
+ VigentModeCommand: { fg: c.darkGrey1, bg: c.lightYellow, bold: true },
68
+ VigentUser: { fg: c.lightBlue, bold: true },
69
+ VigentTool: { fg: c.lightCyan },
70
+ VigentToolOutput: { fg: c.lightGrey4 },
71
+ VigentSpinner: { fg: c.lightYellow },
72
+ },
73
+ };
74
+ // ---------------------------------------------------------------------------
75
+ // Built-in: gruvbox (dark, medium) — ported from morhetz/gruvbox
76
+ // ---------------------------------------------------------------------------
77
+ const g = {
78
+ bg0h: "#1d2021",
79
+ bg0: "#282828",
80
+ bg1: "#3c3836",
81
+ bg2: "#504945",
82
+ bg3: "#665c54",
83
+ bg4: "#7c6f64",
84
+ fg0: "#fbf1c7",
85
+ fg1: "#ebdbb2",
86
+ fg3: "#bdae93",
87
+ grey: "#928374",
88
+ red: "#fb4934",
89
+ green: "#b8bb26",
90
+ yellow: "#fabd2f",
91
+ blue: "#83a598",
92
+ purple: "#d3869b",
93
+ aqua: "#8ec07c",
94
+ orange: "#fe8019",
95
+ darkRed: "#421e1e",
96
+ darkGreen: "#32361a",
97
+ };
98
+ export const GRUVBOX = {
99
+ name: "gruvbox",
100
+ background: "dark",
101
+ groups: {
102
+ Normal: { fg: g.fg1, bg: g.bg0 },
103
+ WinSeparator: { fg: g.bg3, bg: g.bg0 },
104
+ StatusLine: { fg: g.bg0, bg: g.fg3 },
105
+ StatusLineNC: { fg: g.fg3, bg: g.bg1 },
106
+ CursorLine: { bg: g.bg1 },
107
+ Visual: { bg: g.bg2 },
108
+ LineNr: { fg: g.bg4 },
109
+ CursorLineNr: { fg: g.yellow, bold: true },
110
+ WinBar: { fg: g.fg1, bold: true },
111
+ VigentSidebar: { fg: g.fg1, bg: g.bg0h },
112
+ Comment: { fg: g.grey, italic: true },
113
+ NonText: { fg: g.bg2 },
114
+ Title: { fg: g.green, bold: true },
115
+ Identifier: { fg: g.blue },
116
+ Function: { fg: g.aqua },
117
+ String: { fg: g.green },
118
+ Constant: { fg: g.purple },
119
+ Keyword: { fg: g.red },
120
+ Search: { fg: g.bg0, bg: g.yellow },
121
+ DiffAdd: { fg: g.green, bg: g.darkGreen },
122
+ DiffDelete: { fg: g.red, bg: g.darkRed },
123
+ Added: { fg: g.green },
124
+ Removed: { fg: g.red },
125
+ ErrorMsg: { fg: g.red, bold: true },
126
+ WarningMsg: { fg: g.yellow },
127
+ ModeMsg: { fg: g.fg1, bold: true },
128
+ Pmenu: { fg: g.fg1, bg: g.bg1 },
129
+ PmenuSel: { fg: g.bg0, bg: g.blue },
130
+ VigentModeNormal: { fg: g.bg0, bg: g.blue, bold: true },
131
+ VigentModeInsert: { fg: g.bg0, bg: g.green, bold: true },
132
+ VigentModeVisual: { fg: g.bg0, bg: g.orange, bold: true },
133
+ VigentModeCommand: { fg: g.bg0, bg: g.yellow, bold: true },
134
+ VigentUser: { fg: g.yellow, bold: true },
135
+ VigentTool: { fg: g.aqua },
136
+ VigentToolOutput: { fg: g.grey },
137
+ VigentSpinner: { fg: g.orange },
138
+ },
139
+ };
140
+ // ---------------------------------------------------------------------------
141
+ // Palette themes: each palette expands to the full set of highlight groups
142
+ // ---------------------------------------------------------------------------
143
+ export const TOKYONIGHT = fromPalette("tokyonight", {
144
+ bg: "#1a1b26", bg_dark: "#16161e", bg_alt: "#292e42", selection: "#283457",
145
+ fg: "#c0caf5", muted: "#565f89", subtle: "#3b4261",
146
+ red: "#f7768e", orange: "#ff9e64", yellow: "#e0af68", green: "#9ece6a",
147
+ cyan: "#7dcfff", blue: "#7aa2f7", magenta: "#bb9af7", accent: "#ff9e64",
148
+ });
149
+ // ---------------------------------------------------------------------------
150
+ // tokyonight "moon": the colorscheme LazyVim starts with. `lazyvim` is the same
151
+ // palette drawn on the terminal's own background, LazyVim's transparent look.
152
+ // ---------------------------------------------------------------------------
153
+ const moon = {
154
+ bg: "#222436", bg_dark: "#1e2030", bg_highlight: "#2f334d", visual: "#2d3f76", border: "#589ed7",
155
+ fg: "#c8d3f5", fg_dark: "#828bb8", comment: "#636da6", gutter: "#3b4261", dark5: "#737aa2", black: "#1b1d2b",
156
+ red: "#ff757f", orange: "#ff966c", yellow: "#ffc777", green: "#c3e88d", teal: "#4fd6be",
157
+ cyan: "#86e1fc", blue: "#82aaff", blue0: "#3e68d7", blue1: "#65bcff", magenta: "#c099ff",
158
+ };
159
+ const moonBadge = (bg) => ({ fg: moon.black, bg, bold: true });
160
+ export const TOKYONIGHT_MOON = (() => {
161
+ const t = fromPalette("tokyonight-moon", {
162
+ bg: moon.bg, bg_dark: moon.bg_dark, bg_alt: moon.bg_highlight, selection: moon.visual,
163
+ fg: moon.fg, muted: moon.comment, subtle: moon.gutter,
164
+ red: moon.red, orange: moon.orange, yellow: moon.yellow, green: moon.green,
165
+ cyan: moon.cyan, blue: moon.blue, magenta: moon.magenta, accent: moon.orange,
166
+ });
167
+ Object.assign(t.groups, {
168
+ NormalFloat: { fg: moon.fg, bg: moon.bg_dark },
169
+ FloatBorder: { fg: moon.border, bg: moon.bg_dark },
170
+ FloatTitle: { fg: moon.border, bg: moon.bg_dark, bold: true },
171
+ WinSeparator: { fg: moon.gutter, bold: true },
172
+ StatusLine: { fg: moon.fg_dark, bg: moon.bg_dark },
173
+ StatusLineNC: { fg: moon.gutter, bg: moon.bg_dark },
174
+ CursorLineNr: { fg: moon.orange, bold: true },
175
+ Keyword: { fg: moon.cyan, italic: true },
176
+ Type: { fg: moon.blue1 },
177
+ Special: { fg: moon.blue1 },
178
+ Search: { fg: moon.fg, bg: moon.blue0 },
179
+ CurSearch: { fg: moon.black, bg: moon.orange },
180
+ DiffAdd: { bg: "#273849" },
181
+ DiffDelete: { bg: "#3a273a" },
182
+ DiffChange: { bg: "#252a3f" },
183
+ Added: { fg: "#b8db87" },
184
+ Removed: { fg: "#e26a75" },
185
+ Changed: { fg: "#7ca1f2" },
186
+ Pmenu: { fg: moon.fg, bg: moon.bg_dark },
187
+ PmenuSel: { bg: "#363c58", bold: true },
188
+ NeoTreeNormal: { fg: moon.fg, bg: moon.bg_dark },
189
+ VigentSidebar: { link: "NeoTreeNormal" },
190
+ VigentIndent: { fg: moon.gutter },
191
+ VigentModeNormal: moonBadge(moon.blue),
192
+ VigentModeInsert: moonBadge(moon.green),
193
+ VigentModeVisual: moonBadge(moon.magenta),
194
+ VigentModeCommand: moonBadge(moon.yellow),
195
+ VigentUser: { fg: moon.blue, bold: true },
196
+ VigentTool: { fg: moon.blue1 },
197
+ VigentToolOutput: { fg: moon.dark5 },
198
+ VigentSpinner: { fg: moon.orange },
199
+ });
200
+ return t;
201
+ })();
202
+ export const LAZYVIM = { ...TOKYONIGHT_MOON, name: "lazyvim", transparent: true };
203
+ export const CATPPUCCIN = fromPalette("catppuccin", {
204
+ bg: "#1e1e2e", bg_dark: "#181825", bg_alt: "#313244", selection: "#45475a",
205
+ fg: "#cdd6f4", muted: "#6c7086", subtle: "#585b70",
206
+ red: "#f38ba8", orange: "#fab387", yellow: "#f9e2af", green: "#a6e3a1",
207
+ cyan: "#94e2d5", blue: "#89b4fa", magenta: "#cba6f7", accent: "#b4befe",
208
+ });
209
+ export const CATPPUCCIN_LATTE = fromPalette("catppuccin-latte", {
210
+ bg: "#eff1f5", bg_dark: "#e6e9ef", bg_alt: "#ccd0da", selection: "#bcc0cc",
211
+ fg: "#4c4f69", muted: "#9ca0b0", subtle: "#acb0be",
212
+ red: "#d20f39", orange: "#fe640b", yellow: "#df8e1d", green: "#40a02b",
213
+ cyan: "#179299", blue: "#1e66f5", magenta: "#8839ef", accent: "#7287fd",
214
+ });
215
+ export const NORD = fromPalette("nord", {
216
+ bg: "#2e3440", bg_dark: "#272c36", bg_alt: "#3b4252", selection: "#434c5e",
217
+ fg: "#d8dee9", muted: "#616e88", subtle: "#4c566a",
218
+ red: "#bf616a", orange: "#d08770", yellow: "#ebcb8b", green: "#a3be8c",
219
+ cyan: "#88c0d0", blue: "#81a1c1", magenta: "#b48ead", accent: "#88c0d0",
220
+ });
221
+ export const ROSE_PINE = fromPalette("rose-pine", {
222
+ bg: "#191724", bg_dark: "#1f1d2e", bg_alt: "#26233a", selection: "#403d52",
223
+ fg: "#e0def4", muted: "#6e6a86", subtle: "#524f67",
224
+ red: "#eb6f92", orange: "#ebbcba", yellow: "#f6c177", green: "#f6c177",
225
+ cyan: "#9ccfd8", blue: "#ebbcba", magenta: "#c4a7e7", accent: "#f6c177",
226
+ });
227
+ export const KANAGAWA = fromPalette("kanagawa", {
228
+ bg: "#1f1f28", bg_dark: "#16161d", bg_alt: "#2a2a37", selection: "#223249",
229
+ fg: "#dcd7ba", muted: "#727169", subtle: "#54546d",
230
+ red: "#e46876", orange: "#ffa066", yellow: "#e6c384", green: "#98bb6c",
231
+ cyan: "#7fb4ca", blue: "#7e9cd8", magenta: "#957fb8", accent: "#ffa066",
232
+ });
233
+ // ---------------------------------------------------------------------------
234
+ // More popular colorschemes, from their published palettes
235
+ // ---------------------------------------------------------------------------
236
+ export const CATPPUCCIN_FRAPPE = fromPalette("catppuccin-frappe", {
237
+ bg: "#303446", bg_dark: "#292c3c", bg_alt: "#414559", selection: "#51576d",
238
+ fg: "#c6d0f5", muted: "#737994", subtle: "#626880",
239
+ red: "#e78284", orange: "#ef9f76", yellow: "#e5c890", green: "#a6d189",
240
+ cyan: "#81c8be", blue: "#8caaee", magenta: "#ca9ee6", accent: "#babbf1",
241
+ });
242
+ export const CATPPUCCIN_MACCHIATO = fromPalette("catppuccin-macchiato", {
243
+ bg: "#24273a", bg_dark: "#1e2030", bg_alt: "#363a4f", selection: "#494d64",
244
+ fg: "#cad3f5", muted: "#6e738d", subtle: "#5b6078",
245
+ red: "#ed8796", orange: "#f5a97f", yellow: "#eed49f", green: "#a6da95",
246
+ cyan: "#8bd5ca", blue: "#8aadf4", magenta: "#c6a0f6", accent: "#b7bdf8",
247
+ });
248
+ export const TOKYONIGHT_STORM = fromPalette("tokyonight-storm", {
249
+ bg: "#24283b", bg_dark: "#1f2335", bg_alt: "#292e42", selection: "#2e3c64",
250
+ fg: "#c0caf5", muted: "#565f89", subtle: "#3b4261",
251
+ red: "#f7768e", orange: "#ff9e64", yellow: "#e0af68", green: "#9ece6a",
252
+ cyan: "#7dcfff", blue: "#7aa2f7", magenta: "#bb9af7", accent: "#ff9e64",
253
+ });
254
+ export const ROSE_PINE_MOON = fromPalette("rose-pine-moon", {
255
+ bg: "#232136", bg_dark: "#2a273f", bg_alt: "#393552", selection: "#44415a",
256
+ fg: "#e0def4", muted: "#6e6a86", subtle: "#56526e",
257
+ red: "#eb6f92", orange: "#ea9a97", yellow: "#f6c177", green: "#3e8fb0",
258
+ cyan: "#9ccfd8", blue: "#3e8fb0", magenta: "#c4a7e7", accent: "#f6c177",
259
+ });
260
+ export const ROSE_PINE_DAWN = fromPalette("rose-pine-dawn", {
261
+ bg: "#faf4ed", bg_dark: "#fffaf3", bg_alt: "#f2e9e1", selection: "#dfdad9",
262
+ fg: "#575279", muted: "#9893a5", subtle: "#cecacd",
263
+ red: "#b4637a", orange: "#d7827e", yellow: "#ea9d34", green: "#286983",
264
+ cyan: "#56949f", blue: "#286983", magenta: "#907aa9", accent: "#ea9d34",
265
+ });
266
+ export const DRACULA = fromPalette("dracula", {
267
+ bg: "#282a36", bg_dark: "#21222c", bg_alt: "#44475a", selection: "#44475a",
268
+ fg: "#f8f8f2", muted: "#6272a4", subtle: "#4d5066",
269
+ red: "#ff5555", orange: "#ffb86c", yellow: "#f1fa8c", green: "#50fa7b",
270
+ cyan: "#8be9fd", blue: "#bd93f9", magenta: "#ff79c6", accent: "#ff79c6",
271
+ });
272
+ export const ONEDARK = fromPalette("onedark", {
273
+ bg: "#282c34", bg_dark: "#21252b", bg_alt: "#2c313c", selection: "#3e4452",
274
+ fg: "#abb2bf", muted: "#5c6370", subtle: "#4b5263",
275
+ red: "#e06c75", orange: "#d19a66", yellow: "#e5c07b", green: "#98c379",
276
+ cyan: "#56b6c2", blue: "#61afef", magenta: "#c678dd", accent: "#e5c07b",
277
+ });
278
+ export const EVERFOREST = fromPalette("everforest", {
279
+ bg: "#2d353b", bg_dark: "#232a2e", bg_alt: "#343f44", selection: "#543a48",
280
+ fg: "#d3c6aa", muted: "#859289", subtle: "#4f585e",
281
+ red: "#e67e80", orange: "#e69875", yellow: "#dbbc7f", green: "#a7c080",
282
+ cyan: "#83c092", blue: "#7fbbb3", magenta: "#d699b6", accent: "#a7c080",
283
+ });
284
+ export const NIGHTFOX = fromPalette("nightfox", {
285
+ bg: "#192330", bg_dark: "#131a24", bg_alt: "#29394f", selection: "#2b3b51",
286
+ fg: "#cdcecf", muted: "#738091", subtle: "#39506d",
287
+ red: "#c94f6d", orange: "#f4a261", yellow: "#dbc074", green: "#81b29a",
288
+ cyan: "#63cdcf", blue: "#719cd6", magenta: "#9d79d6", accent: "#f4a261",
289
+ });
290
+ export const SOLARIZED_DARK = fromPalette("solarized-dark", {
291
+ bg: "#002b36", bg_dark: "#00212b", bg_alt: "#073642", selection: "#0b4a5a",
292
+ fg: "#93a1a1", muted: "#586e75", subtle: "#2c4f58",
293
+ red: "#dc322f", orange: "#cb4b16", yellow: "#b58900", green: "#859900",
294
+ cyan: "#2aa198", blue: "#268bd2", magenta: "#d33682", accent: "#b58900",
295
+ });
296
+ export const SOLARIZED_LIGHT = fromPalette("solarized-light", {
297
+ bg: "#fdf6e3", bg_dark: "#f5efdc", bg_alt: "#eee8d5", selection: "#e4ddc8",
298
+ fg: "#586e75", muted: "#93a1a1", subtle: "#c9c3b0",
299
+ red: "#dc322f", orange: "#cb4b16", yellow: "#b58900", green: "#859900",
300
+ cyan: "#2aa198", blue: "#268bd2", magenta: "#d33682", accent: "#cb4b16",
301
+ });
302
+ export const GITHUB_DARK = fromPalette("github-dark", {
303
+ bg: "#0d1117", bg_dark: "#010409", bg_alt: "#161b22", selection: "#1c3a5e",
304
+ fg: "#e6edf3", muted: "#7d8590", subtle: "#30363d",
305
+ red: "#ff7b72", orange: "#ffa657", yellow: "#d29922", green: "#3fb950",
306
+ cyan: "#a5d6ff", blue: "#58a6ff", magenta: "#d2a8ff", accent: "#58a6ff",
307
+ });
308
+ export const GITHUB_LIGHT = fromPalette("github-light", {
309
+ bg: "#ffffff", bg_dark: "#f6f8fa", bg_alt: "#eaeef2", selection: "#cce5ff",
310
+ fg: "#1f2328", muted: "#656d76", subtle: "#d0d7de",
311
+ red: "#cf222e", orange: "#bc4c00", yellow: "#9a6700", green: "#1a7f37",
312
+ cyan: "#0a3069", blue: "#0969da", magenta: "#8250df", accent: "#0969da",
313
+ });
314
+ export const MONOKAI_PRO = fromPalette("monokai-pro", {
315
+ bg: "#2d2a2e", bg_dark: "#221f22", bg_alt: "#403e41", selection: "#5b595c",
316
+ fg: "#fcfcfa", muted: "#727072", subtle: "#5b595c",
317
+ red: "#ff6188", orange: "#fc9867", yellow: "#ffd866", green: "#a9dc76",
318
+ cyan: "#78dce8", blue: "#78dce8", magenta: "#ab9df2", accent: "#ffd866",
319
+ });
320
+ export const AYU_MIRAGE = fromPalette("ayu-mirage", {
321
+ bg: "#1f2430", bg_dark: "#1a1f29", bg_alt: "#242936", selection: "#33415e",
322
+ fg: "#cccac2", muted: "#6c7380", subtle: "#3b4252",
323
+ red: "#f28779", orange: "#ffa659", yellow: "#ffcc66", green: "#d5ff80",
324
+ cyan: "#95e6cb", blue: "#73d0ff", magenta: "#dfbfff", accent: "#ffcc66",
325
+ });
326
+ export const BUILTIN_THEMES = {
327
+ default: NVIM_DEFAULT,
328
+ gruvbox: GRUVBOX,
329
+ tokyonight: TOKYONIGHT,
330
+ "tokyonight-moon": TOKYONIGHT_MOON,
331
+ lazyvim: LAZYVIM,
332
+ catppuccin: CATPPUCCIN,
333
+ "catppuccin-latte": CATPPUCCIN_LATTE,
334
+ nord: NORD,
335
+ "rose-pine": ROSE_PINE,
336
+ kanagawa: KANAGAWA,
337
+ "catppuccin-frappe": CATPPUCCIN_FRAPPE,
338
+ "catppuccin-macchiato": CATPPUCCIN_MACCHIATO,
339
+ "tokyonight-storm": TOKYONIGHT_STORM,
340
+ "rose-pine-moon": ROSE_PINE_MOON,
341
+ "rose-pine-dawn": ROSE_PINE_DAWN,
342
+ dracula: DRACULA,
343
+ onedark: ONEDARK,
344
+ everforest: EVERFOREST,
345
+ nightfox: NIGHTFOX,
346
+ "solarized-dark": SOLARIZED_DARK,
347
+ "solarized-light": SOLARIZED_LIGHT,
348
+ "github-dark": GITHUB_DARK,
349
+ "github-light": GITHUB_LIGHT,
350
+ "monokai-pro": MONOKAI_PRO,
351
+ "ayu-mirage": AYU_MIRAGE,
352
+ };
@@ -0,0 +1,73 @@
1
+ /**
2
+ * What `:model` and `:effort` offer, per engine. Model lists come from the
3
+ * engine itself where it can say (pi-ai's catalog, `opencode models`); any
4
+ * name can still be typed in the picker.
5
+ */
6
+ import { execFile } from "node:child_process";
7
+ /** Reasoning effort / thinking levels each engine accepts. */
8
+ export const EFFORTS = {
9
+ pi: ["off", "minimal", "low", "medium", "high", "xhigh"],
10
+ claude: ["low", "medium", "high", "xhigh", "max"],
11
+ codex: ["minimal", "low", "medium", "high", "xhigh"],
12
+ opencode: ["minimal", "low", "medium", "high", "max"],
13
+ };
14
+ export function effortChoices(engine) {
15
+ return [{ value: "default", note: "what the engine uses" }, ...EFFORTS[engine].map((value) => ({ value }))];
16
+ }
17
+ /** pi providers whose key is in the environment (the ones pi can call now). */
18
+ const PI_KEYS = {
19
+ anthropic: ["ANTHROPIC_API_KEY"],
20
+ openai: ["OPENAI_API_KEY"],
21
+ google: ["GEMINI_API_KEY", "GOOGLE_API_KEY"],
22
+ mistral: ["MISTRAL_API_KEY"],
23
+ groq: ["GROQ_API_KEY"],
24
+ xai: ["XAI_API_KEY"],
25
+ openrouter: ["OPENROUTER_API_KEY"],
26
+ deepseek: ["DEEPSEEK_API_KEY"],
27
+ };
28
+ export async function modelChoices(engine, env = process.env) {
29
+ switch (engine) {
30
+ case "claude":
31
+ return [
32
+ { value: "default", note: "Claude Code's own choice" },
33
+ { value: "fable", note: "latest Fable" },
34
+ { value: "opus", note: "latest Opus" },
35
+ { value: "sonnet", note: "latest Sonnet" },
36
+ { value: "haiku", note: "latest Haiku" },
37
+ ];
38
+ case "codex":
39
+ return [{ value: "default", note: "Codex's own choice (type any model name)" }];
40
+ case "opencode":
41
+ return [{ value: "default", note: "OpenCode's own choice" }, ...(await opencodeModels(env)).map((value) => ({ value }))];
42
+ case "pi": {
43
+ const ai = await import("@mariozechner/pi-ai");
44
+ const providers = Object.keys(PI_KEYS).filter((p) => PI_KEYS[p].some((k) => env[k]));
45
+ const out = [];
46
+ for (const provider of providers.length ? providers : ["anthropic"]) {
47
+ let models = [];
48
+ try {
49
+ models = ai.getModels(provider);
50
+ }
51
+ catch {
52
+ continue;
53
+ }
54
+ for (const m of models)
55
+ out.push({ value: provider === "anthropic" ? m.id : `${provider}/${m.id}`, note: m.name && m.name !== m.id ? m.name : undefined });
56
+ }
57
+ return out;
58
+ }
59
+ }
60
+ }
61
+ function opencodeModels(env) {
62
+ return new Promise((resolve) => {
63
+ execFile("opencode", ["models"], { env, timeout: 20000, maxBuffer: 4 * 1024 * 1024 }, (err, stdout) => {
64
+ if (err)
65
+ return resolve([]);
66
+ resolve(String(stdout)
67
+ .replace(/\x1b\[[0-9;]*m/g, "")
68
+ .split("\n")
69
+ .map((l) => l.trim())
70
+ .filter((l) => /^[\w.-]+\/[\w.:@-]+$/.test(l)));
71
+ });
72
+ });
73
+ }