@wrongstack/cli 1.0.32 → 1.0.35

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.
Files changed (126) hide show
  1. package/data/providers.json +322 -2
  2. package/dist/{acp-EDGUWU7N.js → acp-T77EAEDB.js} +469 -465
  3. package/dist/{auth-SUHKFFO4.js → auth-M6LXZTDA.js} +4 -4
  4. package/dist/auth-menu/openai-codex-oauth.d.ts +1 -1
  5. package/dist/auth-menu/panel-provider-edits.d.ts +15 -0
  6. package/dist/auth-menu/panel-service.d.ts +1 -1
  7. package/dist/auto-discover-providers-JX346GOM.js +7 -0
  8. package/dist/boot/governance-evidence-candidate.d.ts +1 -2
  9. package/dist/boot/system-prompt-builder.d.ts +1 -1
  10. package/dist/boot/tui-project-spawn.d.ts +0 -1
  11. package/dist/boot/tui-session-resume-contracts.d.ts +95 -0
  12. package/dist/boot/tui-session-resume.d.ts +2 -88
  13. package/dist/boot/tui-settings-read.d.ts +3 -0
  14. package/dist/{boot-auto-thin-K2DHHYIW.js → boot-auto-thin-YMAZI3QL.js} +2 -2
  15. package/dist/boot-launch-choices.d.ts +22 -0
  16. package/dist/boot-provider-gate.d.ts +28 -0
  17. package/dist/boot-subcommand-dispatch.d.ts +24 -0
  18. package/dist/boot.d.ts +1 -1
  19. package/dist/chimera-cascade-evidence.d.ts +1 -1
  20. package/dist/{chunk-TI7KLHYX.js → chunk-2CMMWRQH.js} +81 -80
  21. package/dist/{chunk-3LEFXLAW.js → chunk-6SIUTX75.js} +36 -36
  22. package/dist/{chunk-RQ4UBKYH.js → chunk-6Z6C6ZHH.js} +3 -3
  23. package/dist/{chunk-5EA6OTLJ.js → chunk-AFOH6CHO.js} +2 -2
  24. package/dist/{chunk-WHEYHDIE.js → chunk-AKESWZH5.js} +2 -1
  25. package/dist/{chunk-JHUJUIOH.js → chunk-AT2A7RJZ.js} +4 -16
  26. package/dist/{chunk-U3SS4NRH.js → chunk-BHXAKTBE.js} +1 -1
  27. package/dist/{chunk-MPQCHBDJ.js → chunk-CJSHS2K7.js} +5 -1
  28. package/dist/{chunk-P3GRLV47.js → chunk-GZSKLXYG.js} +208 -141
  29. package/dist/{chunk-4MDRHMX4.js → chunk-KMU7GF7X.js} +3 -26
  30. package/dist/{chunk-WXJH4F6K.js → chunk-LDV4ERNV.js} +4 -4
  31. package/dist/{chunk-LIZXJHZQ.js → chunk-LDXXMPMS.js} +13 -13
  32. package/dist/{chunk-UQUYBDMG.js → chunk-M4G5FO7F.js} +1 -1
  33. package/dist/{chunk-CFHWIFXL.js → chunk-PA4VBCXS.js} +25 -33
  34. package/dist/{chunk-5UZBUV2H.js → chunk-RKU66D2O.js} +6 -4
  35. package/dist/{chunk-PGNERAZL.js → chunk-RWNI5OWT.js} +2 -2
  36. package/dist/chunk-TGSPCFBT.js +1 -0
  37. package/dist/{cli-context-ITHGP2CE.js → cli-context-II57EHD2.js} +1555 -1451
  38. package/dist/cli-initial-tools.d.ts +54 -0
  39. package/dist/{cli-main-TQGLKB6D.js → cli-main-YR2WJCPL.js} +38062 -37035
  40. package/dist/cli-main-boot.d.ts +133 -0
  41. package/dist/cli-main-orchestration.d.ts +170 -0
  42. package/dist/cli-main-state.d.ts +19 -0
  43. package/dist/config-doctor.d.ts +1 -1
  44. package/dist/{config-transfer-UE37X4B5.js → config-transfer-VOIFY7U4.js} +2 -2
  45. package/dist/{execution-C2IECWF7.js → execution-IBAZ2EIU.js} +138 -124
  46. package/dist/fleet/host-director-setup.d.ts +41 -0
  47. package/dist/fleet/host-spawn-types.d.ts +17 -0
  48. package/dist/fleet/host.d.ts +2 -1
  49. package/dist/goal-host-prompts.d.ts +5 -0
  50. package/dist/goal-host-types.d.ts +94 -0
  51. package/dist/goal-host.d.ts +2 -91
  52. package/dist/{hq-KBFDKTDD.js → hq-5OIEKB4V.js} +5 -6
  53. package/dist/hq-server/handle-types.d.ts +1 -1
  54. package/dist/hq-server/routes/auth-handlers.d.ts +1 -1
  55. package/dist/hq-server/routes.d.ts +1 -13
  56. package/dist/hq-server/utils.d.ts +1 -1
  57. package/dist/{hq-server-AVNKZ2PV.js → hq-server-DU3ZH3X7.js} +3 -3
  58. package/dist/{hq-service-FGB7BY2D.js → hq-service-LYZV7EK7.js} +3 -3
  59. package/dist/index.js +4 -4
  60. package/dist/live-settings-input.d.ts +2 -0
  61. package/dist/mailbox-bridge-bootstrap.d.ts +1 -4
  62. package/dist/{modeldiag-PQILD7TN.js → modeldiag-NEPTLFZW.js} +2 -2
  63. package/dist/picker-effort.d.ts +32 -0
  64. package/dist/picker-model-picker.d.ts +13 -2
  65. package/dist/picker-provider-list.d.ts +66 -0
  66. package/dist/picker.d.ts +12 -12
  67. package/dist/{providers-models-W57I3QOA.js → providers-models-37DUV2GW.js} +297 -253
  68. package/dist/repl-suggestions.d.ts +0 -5
  69. package/dist/{sdd-runtime-PTOSPYI4.js → sdd-runtime-PF72WHLO.js} +3 -20
  70. package/dist/services/sdd/task-manager.d.ts +1 -12
  71. package/dist/services/sdd-runtime.d.ts +3 -4
  72. package/dist/services/statusline-config.d.ts +0 -2
  73. package/dist/settings-behavior-sections.d.ts +0 -1
  74. package/dist/short-circuit-flags-EXJBJ5GT.js +10 -0
  75. package/dist/{skill-suggest-L2EVWB6R.js → skill-suggest-THANK3LV.js} +1 -1
  76. package/dist/slash-commands/command-context.d.ts +2 -0
  77. package/dist/slash-commands/fallback-chain-view.d.ts +3 -0
  78. package/dist/slash-commands/fallback-ref-validation.d.ts +34 -0
  79. package/dist/slash-commands/goal-refiner.d.ts +10 -2
  80. package/dist/slash-commands/goals.d.ts +6 -0
  81. package/dist/slash-commands/kanban-task-completion.d.ts +17 -0
  82. package/dist/slash-commands/mcp.d.ts +0 -1
  83. package/dist/slash-commands/memory-purge-domain-terms.d.ts +5 -0
  84. package/dist/slash-commands/nextsteps-mode.d.ts +13 -0
  85. package/dist/slash-commands/session-live-status.d.ts +21 -0
  86. package/dist/slash-commands/session.d.ts +1 -1
  87. package/dist/slash-commands/settings-feature-ui-mutations.d.ts +8 -0
  88. package/dist/slash-commands/settings-hq-autonomy-mutations.d.ts +8 -0
  89. package/dist/slash-commands/settings-persist-deps.d.ts +10 -0
  90. package/dist/slash-commands/settings-runtime-mutations.d.ts +12 -0
  91. package/dist/slash-commands/shadow.d.ts +0 -1
  92. package/dist/slash-commands/tool-auto-thin-commands.d.ts +15 -0
  93. package/dist/subcommands/handlers/acp-agents.d.ts +9 -0
  94. package/dist/subcommands/handlers/acp-server.d.ts +7 -0
  95. package/dist/subcommands/handlers/hq.d.ts +0 -1
  96. package/dist/subcommands/handlers/providers-models-custom.d.ts +33 -0
  97. package/dist/subcommands/handlers/providers-models-visibility.d.ts +29 -0
  98. package/dist/subcommands/handlers/skill-suggest.d.ts +0 -2
  99. package/dist/{subcommands-QO7VYTSS.js → subcommands-DTKBXLPU.js} +2 -2
  100. package/dist/{update-J5WHAFPE.js → update-6OEPAEUV.js} +3 -3
  101. package/dist/utils/win32-cmd.d.ts +1 -1
  102. package/dist/{version-help-ATOKGMTK.js → version-help-JQGRPDJW.js} +2 -2
  103. package/dist/webui-server/host-settings.d.ts +17 -0
  104. package/dist/webui-server/http-bridge.d.ts +32 -0
  105. package/dist/webui-server/instance-registration.d.ts +19 -0
  106. package/dist/webui-server/kanban-services.d.ts +9 -0
  107. package/dist/webui-server/message-router.d.ts +14 -0
  108. package/dist/webui-server/prefs-seeding.d.ts +1 -2
  109. package/dist/webui-server/provider-config.d.ts +0 -1
  110. package/dist/webui-server/provider-plane.d.ts +14 -0
  111. package/dist/webui-server/session-agents.d.ts +18 -0
  112. package/dist/webui-server/session-start-live.d.ts +11 -0
  113. package/dist/webui-server/stream-coalescer.d.ts +1 -1
  114. package/dist/webui-server/transport.d.ts +12 -0
  115. package/dist/{webui-server-GQOVLQS3.js → webui-server-6IC3SLZG.js} +1600 -1435
  116. package/dist/webui-session-maintenance.d.ts +16 -0
  117. package/dist/wiring/brain-and-orchestration.d.ts +1 -1
  118. package/dist/wiring/cli-slash-commands-setup.d.ts +1 -0
  119. package/dist/wiring/command-host-state.d.ts +11 -2
  120. package/dist/wiring/dep-watcher-bridge.d.ts +8 -1
  121. package/dist/wiring/session-command-handlers.d.ts +2 -1
  122. package/dist/worktree-command-host.d.ts +31 -0
  123. package/package.json +30 -30
  124. package/dist/auto-discover-providers-QIL34K3U.js +0 -7
  125. package/dist/chunk-WHOIR577.js +0 -1
  126. package/dist/short-circuit-flags-6LB3EGF7.js +0 -10
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  visibleModelIds
3
- } from "./chunk-5UZBUV2H.js";
3
+ } from "./chunk-RKU66D2O.js";
4
4
  import {
5
5
  mutateConfigProviders
6
6
  } from "./chunk-ZYACRPLN.js";
@@ -9,6 +9,9 @@ import {
9
9
  } from "./chunk-YMXXOOFN.js";
10
10
 
11
11
  // src/subcommands/handlers/providers-models.ts
12
+ import { color as color3 } from "@wrongstack/core/utils";
13
+
14
+ // src/subcommands/handlers/providers-models-custom.ts
12
15
  import * as fs from "node:fs/promises";
13
16
  import { decryptConfigSecretsForRewrite, encryptConfigSecrets } from "@wrongstack/core/security";
14
17
  import {
@@ -17,238 +20,23 @@ import {
17
20
  import {
18
21
  atomicWrite,
19
22
  backupConfigFile,
20
- color,
23
+ color as color2,
21
24
  expectDefined,
22
25
  withFileLock
23
26
  } from "@wrongstack/core/utils";
24
- var providersCmd = async (args, deps) => {
25
- const providerFlags = subcommandFlags(args, deps);
26
- const showAll = providerFlags["all"] === true || providerFlags["all"] === "true";
27
- const showUnsupported = providerFlags["unsupported"] === true || providerFlags["unsupported"] === "true";
28
- try {
29
- const all = await deps.modelsRegistry.listProviders();
30
- const byFamily = {
31
- anthropic: [],
32
- "anthropic-oauth": [],
33
- openai: [],
34
- "openai-compatible": [],
35
- "openai-codex": [],
36
- "github-copilot": [],
37
- google: [],
38
- "google-antigravity": [],
39
- unsupported: []
40
- };
41
- for (const p of all) byFamily[p.family].push(p);
42
- const families = showUnsupported ? ["unsupported"] : showAll ? ["anthropic", "openai", "google", "openai-compatible", "unsupported"] : ["anthropic", "openai", "google", "openai-compatible"];
43
- for (const family of families) {
44
- const list = byFamily[family];
45
- if (list.length === 0) continue;
46
- deps.renderer.write(`
47
- ${color.bold(family)} (${list.length}):
48
- `);
49
- for (const p of list) {
50
- const envFound = p.envVars.some((v) => process.env[v]);
51
- const marker = envFound ? color.green("\u25CF") : color.dim("\u25CB");
52
- const envHint = p.envVars[0] ? color.dim(`[${p.envVars[0]}]`) : "";
53
- const note = family === "unsupported" ? color.dim("(needs plugin)") : "";
54
- deps.renderer.write(
55
- ` ${marker} ${p.id.padEnd(20)} ${p.name.padEnd(28)} ${envHint} ${note}
56
- `
57
- );
58
- }
59
- }
60
- deps.renderer.write(
61
- `
62
- ${color.dim(`Current: ${deps.config.provider ?? "<unset>"} / ${deps.config.model ?? "<unset>"}. Use --all to include unsupported families.`)}
63
- `
64
- );
65
- return 0;
66
- } catch (err) {
67
- deps.renderer.writeError(
68
- `Failed to list providers: ${err instanceof Error ? err.message : err}`
69
- );
70
- return 1;
71
- }
72
- };
73
- function parseFlags(args) {
74
- const flags = {};
75
- for (let i = 0; i < args.length; i++) {
76
- const a = expectDefined(args[i]);
77
- if (a.startsWith("--")) {
78
- const eq = a.indexOf("=");
79
- if (eq !== -1) {
80
- flags[a.slice(2, eq)] = a.slice(eq + 1);
81
- } else {
82
- const name = a.slice(2);
83
- if (i + 1 < args.length && !args[i + 1]?.startsWith("--")) {
84
- flags[name] = args[++i] ?? "";
85
- } else {
86
- flags[name] = true;
87
- }
88
- }
89
- }
90
- }
91
- return flags;
92
- }
93
- function positionals(args) {
94
- const out = [];
95
- for (let i = 0; i < args.length; i++) {
96
- const a = expectDefined(args[i]);
97
- if (a.startsWith("--")) {
98
- const eq = a.indexOf("=");
99
- if (eq === -1) {
100
- if (i + 1 < args.length && !args[i + 1]?.startsWith("--")) {
101
- i++;
102
- }
103
- }
104
- continue;
105
- }
106
- out.push(a);
107
- }
108
- return out;
109
- }
110
- var DEFAULT_PER_PAGE = 15;
111
- function fmtPrice(usdPer1M) {
112
- if (usdPer1M === void 0) return color.dim("?");
113
- const value = usdPer1M >= 10 ? usdPer1M.toFixed(1) : usdPer1M.toFixed(2);
114
- return "$" + value;
115
- }
116
- var modelsCmd = async (args, deps) => {
117
- const sub = args[0];
118
- if (sub === "hide") return modelsHide(args.slice(1), deps);
119
- if (sub === "show") return modelsShow(args.slice(1), deps);
120
- if (sub === "hidden") return modelsHidden(args.slice(1), deps);
121
- if (sub === "reset") return modelsReset(args.slice(1), deps);
122
- if (sub === "add") return modelsAdd(args.slice(1), deps);
123
- if (sub === "remove") return modelsRemove(args.slice(1), deps);
124
- if (sub === "list") return modelsList(args.slice(1), deps);
125
- if (sub === "caps" || sub === "capabilities") return modelsCaps(args.slice(1), deps);
126
- if (sub === "refresh") {
127
- deps.renderer.writeInfo("Refreshing models.dev cache\u2026");
128
- try {
129
- const payload = await deps.modelsRegistry.refresh();
130
- deps.renderer.writeInfo(
131
- `Cached ${Object.keys(payload).length} providers to ${deps.paths.modelsCache}`
132
- );
133
- return 0;
134
- } catch (err) {
135
- deps.renderer.writeError(`Refresh failed: ${err instanceof Error ? err.message : err}`);
136
- return 1;
137
- }
138
- }
139
- const flags = subcommandFlags(args, deps);
140
- const search = typeof flags["search"] === "string" ? flags["search"].toLowerCase() : "";
141
- const perPage = Number(flags["per-page"]) > 0 ? Number(flags["per-page"]) : DEFAULT_PER_PAGE;
142
- const page = Math.max(1, Number(flags["page"]) || 1);
143
- const providerId = sub ?? deps.config.provider ?? "";
144
- if (!providerId) {
145
- deps.renderer.writeError(
146
- "Usage: wstack models <provider> [--search <term>] [--page N] [--per-page N]"
147
- );
148
- return 1;
149
- }
150
- const { providerId: lookupId, provider } = await getCatalogProviderForConfigProvider(
151
- providerId,
152
- deps
153
- );
154
- if (!provider) {
155
- deps.renderer.writeError(
156
- lookupId !== providerId ? `Alias "${providerId}" points at catalog id "${lookupId}" which is not in the cache.` : `Provider "${providerId}" not in catalog.`
157
- );
158
- return 1;
159
- }
160
- if (lookupId !== providerId)
161
- deps.renderer.write(
162
- color.dim(`(showing catalog models for "${lookupId}" via alias "${providerId}")
163
- `)
164
- );
165
- deps.renderer.write(`${color.bold(provider.name)} ${color.dim(`(${provider.id})`)}
166
- `);
167
- if (provider.doc) deps.renderer.write(color.dim(`Docs: ${provider.doc}
168
- `));
169
- const savedProvider = deps.config.providers?.[providerId];
170
- const userModels = savedProvider?.models;
171
- const catalogById = new Map(provider.models.map((m) => [m.id, m]));
172
- const allKnownSorted = [...provider.models].sort(
173
- (a, b) => (b.release_date ?? "").localeCompare(a.release_date ?? "")
174
- );
175
- const visibleIds = visibleModelIds(
176
- providerId,
177
- deps.config,
178
- allKnownSorted.map((m) => m.id),
179
- savedProvider
180
- );
181
- const allSorted = visibleIds.map((id) => catalogById.get(id) ?? { id, name: id });
182
- if (userModels !== void 0) {
183
- const hiddenCount = Math.max(0, allKnownSorted.length - visibleIds.length);
184
- const restoredCount = Math.max(0, visibleIds.length - userModels.length);
185
- deps.renderer.write(
186
- color.dim(
187
- `(${visibleIds.length} visible model(s)${restoredCount > 0 ? `, ${restoredCount} from providers.json/catalog fallback` : " from your saved config"}${hiddenCount > 0 ? `, ${hiddenCount} hidden` : ""})
188
- `
189
- )
190
- );
191
- }
192
- const filtered = search ? allSorted.filter((m) => m.id.toLowerCase().includes(search)) : allSorted;
193
- const total = filtered.length;
194
- const totalPages = Math.max(1, Math.ceil(total / perPage));
195
- const actualPage = Math.min(page, totalPages);
196
- const start = (actualPage - 1) * perPage;
197
- const pageItems = filtered.slice(start, start + perPage);
198
- const end = Math.min(start + pageItems.length, total);
199
- const pageHint = totalPages > 1 ? color.cyan(`[page ${actualPage}/${totalPages}]`) : "";
200
- const searchHint = search ? color.yellow(` (filtered: "${search}" \u2014 ${total} match${total === 1 ? "" : "es"})`) : color.dim(` (${total} model${total === 1 ? "" : "s"})`);
201
- deps.renderer.write(`${pageHint}${searchHint}
202
- `);
203
- if (pageItems.length === 0) {
204
- deps.renderer.write(color.dim("(no models match)\n"));
205
- } else {
206
- if (start > 0)
207
- deps.renderer.write(color.dim(` ${String.fromCharCode(8593)} ${start} above
208
- `));
209
- for (const m of pageItems) {
210
- const caps = [];
211
- if ("tool_call" in m && m.tool_call) caps.push("tools");
212
- if ("reasoning" in m && m.reasoning) caps.push("reasoning");
213
- if ("modalities" in m && m.modalities?.input?.includes("image")) caps.push("vision");
214
- const ctx = "limit" in m && m.limit?.context ? `${(m.limit.context / 1e3).toFixed(0)}k` : "?";
215
- const cost = "cost" in m && m.cost?.input !== void 0 ? `${m.cost.input}/${m.cost.output ?? "?"}` : "";
216
- deps.renderer.write(
217
- ` ${m.id.padEnd(40)} ${color.dim(ctx.padStart(6))} ${color.dim(cost.padEnd(14))} ${color.dim(caps.join(","))}
218
- `
219
- );
220
- }
221
- if (end < total)
222
- deps.renderer.write(color.dim(` ${String.fromCharCode(8595)} ${total - end} below
223
- `));
224
- }
225
- const navLines = [];
226
- if (totalPages > 1) {
227
- if (actualPage > 1) navLines.push(`--page ${actualPage - 1} (prev)`);
228
- if (actualPage < totalPages) navLines.push(`--page ${actualPage + 1} (next)`);
229
- }
230
- navLines.push("--search <term> (filter)");
231
- deps.renderer.write(color.dim(`
232
- ${navLines.join(" \xB7 ")}
233
- `));
234
- const age = await deps.modelsRegistry.ageSeconds();
235
- deps.renderer.write(
236
- color.dim(
237
- `Cache age: ${isFinite(age) ? `${Math.round(age / 60)}m` : "never fetched"}. Run \`wstack models refresh\` to update.
238
- `
239
- )
240
- );
241
- return 0;
242
- };
27
+
28
+ // src/subcommands/handlers/providers-models-visibility.ts
29
+ import { color } from "@wrongstack/core/utils";
243
30
  function aliasProviderId(configProviderId, cfg) {
244
31
  return cfg?.type && cfg.type !== configProviderId ? cfg.type : configProviderId;
245
32
  }
246
- async function discoverProviderModels(deps, ids) {
33
+ async function discoverProviderModels(deps, ids, onlyProviderId) {
247
34
  if (!("mergeOverlay" in deps.modelsRegistry)) return void 0;
248
35
  try {
249
- const { discoverAndMergeProviders } = await import("./auto-discover-providers-QIL34K3U.js");
36
+ const { discoverAndMergeProviders } = await import("./auto-discover-providers-JX346GOM.js");
37
+ const only = onlyProviderId ? deps.config.providers?.[onlyProviderId] : void 0;
250
38
  await discoverAndMergeProviders({
251
- config: deps.config,
39
+ config: only ? { ...deps.config, providers: { [onlyProviderId]: only } } : deps.config,
252
40
  registry: deps.modelsRegistry,
253
41
  cacheDir: deps.paths.cacheDir
254
42
  });
@@ -263,6 +51,10 @@ async function discoverProviderModels(deps, ids) {
263
51
  }
264
52
  async function getCatalogProviderForConfigProvider(providerId, deps) {
265
53
  const cfg = deps.config.providers?.[providerId];
54
+ if (usesAccountCatalog(cfg)) {
55
+ const found = await discoverProviderModels(deps, [providerId], providerId);
56
+ if (found) return { providerId, provider: found };
57
+ }
266
58
  const lookupId = aliasProviderId(providerId, cfg);
267
59
  const provider = await deps.modelsRegistry.getProvider(lookupId);
268
60
  if (provider) return { providerId: lookupId, provider };
@@ -271,6 +63,10 @@ async function getCatalogProviderForConfigProvider(providerId, deps) {
271
63
  provider: await discoverProviderModels(deps, [lookupId, providerId])
272
64
  };
273
65
  }
66
+ function usesAccountCatalog(cfg) {
67
+ const active = cfg?.apiKeys?.find((key) => key.label === cfg.activeKey) ?? cfg?.apiKeys?.[0];
68
+ return active?.authMethod === "oauth";
69
+ }
274
70
  function uniqueStrings(values) {
275
71
  return [...new Set(values.map((v) => v.trim()).filter(Boolean))];
276
72
  }
@@ -312,10 +108,7 @@ async function modelsHide(args, deps) {
312
108
  p.models = nextVisible;
313
109
  }
314
110
  );
315
- deps.config.providers = {
316
- ...deps.config.providers ?? {},
317
- [providerId]: { ...saved, models: nextVisible }
318
- };
111
+ publishProviderConfig(deps, providerId, { ...saved, models: nextVisible });
319
112
  deps.renderer.writeInfo(
320
113
  `Hidden ${providerId}/${modelId}. Visible: ${nextVisible.length}, hidden: ${Math.max(0, knownIds.length - nextVisible.length)}.`
321
114
  );
@@ -365,10 +158,7 @@ async function modelsShow(args, deps) {
365
158
  p.models = nextVisible;
366
159
  }
367
160
  );
368
- deps.config.providers = {
369
- ...deps.config.providers ?? {},
370
- [providerId]: { ...saved, models: nextVisible }
371
- };
161
+ publishProviderConfig(deps, providerId, { ...saved, models: nextVisible });
372
162
  const isKnown = knownIds.includes(modelId);
373
163
  deps.renderer.writeInfo(
374
164
  `Visible ${providerId}/${modelId}${isKnown ? "" : " (not in current catalog)"}. Visible: ${nextVisible.length}.`
@@ -414,10 +204,84 @@ Restore: wstack models show ${providerId} <model> \xB7 reset ${providerId}
414
204
  );
415
205
  return 0;
416
206
  }
207
+ function publishProviderConfig(deps, providerId, next) {
208
+ deps.config = {
209
+ ...deps.config,
210
+ providers: { ...deps.config.providers ?? {}, [providerId]: next }
211
+ };
212
+ }
213
+
214
+ // src/subcommands/handlers/providers-models-custom.ts
215
+ function parseFlags(args) {
216
+ const flags = {};
217
+ for (let i = 0; i < args.length; i++) {
218
+ const a = expectDefined(args[i]);
219
+ if (a.startsWith("--")) {
220
+ const eq = a.indexOf("=");
221
+ if (eq !== -1) {
222
+ flags[a.slice(2, eq)] = a.slice(eq + 1);
223
+ } else {
224
+ const name = a.slice(2);
225
+ if (i + 1 < args.length && !args[i + 1]?.startsWith("--")) {
226
+ flags[name] = args[++i] ?? "";
227
+ } else {
228
+ flags[name] = true;
229
+ }
230
+ }
231
+ }
232
+ }
233
+ return flags;
234
+ }
235
+ function positionals(args) {
236
+ const out = [];
237
+ for (let i = 0; i < args.length; i++) {
238
+ const a = expectDefined(args[i]);
239
+ if (a.startsWith("--")) {
240
+ const eq = a.indexOf("=");
241
+ if (eq === -1) {
242
+ if (i + 1 < args.length && !args[i + 1]?.startsWith("--")) {
243
+ i++;
244
+ }
245
+ }
246
+ continue;
247
+ }
248
+ out.push(a);
249
+ }
250
+ return out;
251
+ }
252
+ function fmtPrice(usdPer1M) {
253
+ if (usdPer1M === void 0) return color2.dim("?");
254
+ const value = usdPer1M >= 10 ? usdPer1M.toFixed(1) : usdPer1M.toFixed(2);
255
+ return "$" + value;
256
+ }
257
+ async function modelsResetCustomModel(providerId, modelId, saved, deps) {
258
+ if (!saved.customModels || !Object.hasOwn(saved.customModels, modelId)) {
259
+ deps.renderer.writeInfo(`${providerId}/${modelId} has no custom definition; nothing to reset.`);
260
+ return 0;
261
+ }
262
+ await mutateConfigProviders(
263
+ activeProfileConfigPath(deps.paths, deps.config),
264
+ deps.vault,
265
+ (providers) => {
266
+ const p = providers[providerId];
267
+ if (!p?.customModels) return;
268
+ delete p.customModels[modelId];
269
+ if (Object.keys(p.customModels).length === 0) delete p.customModels;
270
+ }
271
+ );
272
+ const { [modelId]: _dropped, ...rest } = saved.customModels;
273
+ const next = { ...saved };
274
+ if (Object.keys(rest).length > 0) next.customModels = rest;
275
+ else delete next.customModels;
276
+ publishProviderConfig(deps, providerId, next);
277
+ deps.renderer.writeInfo(`Reset ${providerId}/${modelId} to the catalog definition.`);
278
+ return 0;
279
+ }
417
280
  async function modelsReset(args, deps) {
418
281
  const providerId = args[0];
282
+ const modelId = args[1];
419
283
  if (!providerId) {
420
- deps.renderer.writeError("Usage: wstack models reset <provider>");
284
+ deps.renderer.writeError("Usage: wstack models reset <provider> [model]");
421
285
  return 1;
422
286
  }
423
287
  const saved = deps.config.providers?.[providerId];
@@ -425,6 +289,7 @@ async function modelsReset(args, deps) {
425
289
  deps.renderer.writeError(`Provider "${providerId}" is not configured.`);
426
290
  return 1;
427
291
  }
292
+ if (modelId) return modelsResetCustomModel(providerId, modelId, saved, deps);
428
293
  if (saved.models === void 0) {
429
294
  deps.renderer.writeInfo(`${providerId} already shows the full catalog model list.`);
430
295
  return 0;
@@ -440,10 +305,7 @@ async function modelsReset(args, deps) {
440
305
  );
441
306
  const nextProvider = { ...saved };
442
307
  delete nextProvider.models;
443
- deps.config.providers = {
444
- ...deps.config.providers ?? {},
445
- [providerId]: nextProvider
446
- };
308
+ publishProviderConfig(deps, providerId, nextProvider);
447
309
  deps.renderer.writeInfo(
448
310
  `Reset visible model list for ${providerId} to the full catalog default.`
449
311
  );
@@ -454,14 +316,17 @@ async function modelsCaps(args, deps) {
454
316
  const modelId = args[1] ?? deps.config.model;
455
317
  if (!providerId || !modelId) {
456
318
  deps.renderer.writeError("Usage: wstack models caps [provider] [model]");
457
- deps.renderer.write(color.dim("Defaults to current configured provider/model when omitted.\n"));
319
+ deps.renderer.write(color2.dim("Defaults to current configured provider/model when omitted.\n"));
458
320
  return 1;
459
321
  }
322
+ if (usesAccountCatalog(deps.config.providers?.[providerId])) {
323
+ await discoverProviderModels(deps, [providerId], providerId);
324
+ }
460
325
  const resolved = await deps.modelsRegistry.getModel(providerId, modelId);
461
326
  if (!resolved) {
462
327
  deps.renderer.writeError("Model not found in catalog: " + providerId + "/" + modelId);
463
328
  deps.renderer.write(
464
- color.dim("Run `wstack models refresh` or add a custom model if this is expected.\n")
329
+ color2.dim("Run `wstack models refresh` or add a custom model if this is expected.\n")
465
330
  );
466
331
  return 1;
467
332
  }
@@ -474,17 +339,17 @@ async function modelsCaps(args, deps) {
474
339
  const rc = caps.reasoningConfig;
475
340
  const cost = resolved.cost;
476
341
  deps.renderer.write(
477
- color.bold("Model capabilities") + " " + color.dim(providerId + "/" + modelId) + "\n"
342
+ color2.bold("Model capabilities") + " " + color2.dim(providerId + "/" + modelId) + "\n"
478
343
  );
479
344
  deps.renderer.write(
480
- " context: " + (caps.maxContext ? color.yellow(String(caps.maxContext)) : color.dim("?")) + "\n"
345
+ " context: " + (caps.maxContext ? color2.yellow(String(caps.maxContext)) : color2.dim("?")) + "\n"
481
346
  );
482
347
  if (caps.maxOutput !== void 0) {
483
- deps.renderer.write(" max output: " + color.yellow(String(caps.maxOutput)) + "\n");
348
+ deps.renderer.write(" max output: " + color2.yellow(String(caps.maxOutput)) + "\n");
484
349
  }
485
350
  if (caps.knowledge) deps.renderer.write(" knowledge: " + caps.knowledge + "\n");
486
351
  deps.renderer.write(
487
- " flags: " + (flags.length > 0 ? flags.join(", ") : color.dim("(none)")) + "\n"
352
+ " flags: " + (flags.length > 0 ? flags.join(", ") : color2.dim("(none)")) + "\n"
488
353
  );
489
354
  deps.renderer.write(
490
355
  " pricing/1M: input " + fmtPrice(cost?.input) + " output " + fmtPrice(cost?.output) + " cacheR " + fmtPrice(cost?.cache_read) + "\n"
@@ -507,7 +372,7 @@ async function modelsCaps(args, deps) {
507
372
  deps.renderer.write(" preserve: " + rc.preserveThinking + "\n");
508
373
  } else if (caps.reasoning) {
509
374
  deps.renderer.write(
510
- color.dim(" reasoning: supported, but no detailed config in catalog\n")
375
+ color2.dim(" reasoning: supported, but no detailed config in catalog\n")
511
376
  );
512
377
  }
513
378
  return 0;
@@ -616,7 +481,7 @@ async function modelsAdd(args, deps) {
616
481
  }
617
482
  if (def.maxOutput !== void 0) capLines.push(` maxOutput: ${def.maxOutput}`);
618
483
  if (capLines.length > 0) {
619
- deps.renderer.write(color.dim(capLines.join("\n") + "\n"));
484
+ deps.renderer.write(color2.dim(capLines.join("\n") + "\n"));
620
485
  }
621
486
  return 0;
622
487
  }
@@ -641,33 +506,212 @@ async function modelsList(_args, deps) {
641
506
  const models = deps.config.models ?? {};
642
507
  const entries = Object.entries(models);
643
508
  if (entries.length === 0) {
644
- deps.renderer.write(color.dim("No custom models defined.\n"));
509
+ deps.renderer.write(color2.dim("No custom models defined.\n"));
645
510
  deps.renderer.write(
646
- color.dim("Use `wstack models add <modelId> --max-context 128k --tools`\n")
511
+ color2.dim("Use `wstack models add <modelId> --max-context 128k --tools`\n")
647
512
  );
648
513
  return 0;
649
514
  }
650
- deps.renderer.write(color.bold("Custom models\n"));
515
+ deps.renderer.write(color2.bold("Custom models\n"));
651
516
  for (const [id, def] of entries.sort(([a], [b]) => a.localeCompare(b))) {
652
517
  const label = def.name ?? id;
653
- const provider = def.provider ? ` ${color.dim(`(${def.provider})`)}` : "";
654
- deps.renderer.write(` ${color.bold(label)}${provider}
518
+ const provider = def.provider ? ` ${color2.dim(`(${def.provider})`)}` : "";
519
+ deps.renderer.write(` ${color2.bold(label)}${provider}
655
520
  `);
656
521
  if (def.capabilities) {
657
522
  for (const [k, v] of Object.entries(def.capabilities)) {
658
- deps.renderer.write(` ${color.dim(`${k}:`)} ${v}
523
+ deps.renderer.write(` ${color2.dim(`${k}:`)} ${v}
659
524
  `);
660
525
  }
661
526
  }
662
527
  if (def.maxOutput !== void 0) {
663
- deps.renderer.write(` ${color.dim("maxOutput:")} ${def.maxOutput}
528
+ deps.renderer.write(` ${color2.dim("maxOutput:")} ${def.maxOutput}
664
529
  `);
665
530
  }
666
531
  }
667
532
  return 0;
668
533
  }
534
+
535
+ // src/subcommands/handlers/providers-models.ts
536
+ var providersCmd = async (args, deps) => {
537
+ const providerFlags = subcommandFlags(args, deps);
538
+ const showAll = providerFlags["all"] === true || providerFlags["all"] === "true";
539
+ const showUnsupported = providerFlags["unsupported"] === true || providerFlags["unsupported"] === "true";
540
+ try {
541
+ const all = await deps.modelsRegistry.listProviders();
542
+ const byFamily = {
543
+ anthropic: [],
544
+ "anthropic-oauth": [],
545
+ openai: [],
546
+ "openai-compatible": [],
547
+ "openai-codex": [],
548
+ "github-copilot": [],
549
+ google: [],
550
+ "google-antigravity": [],
551
+ unsupported: []
552
+ };
553
+ for (const p of all) byFamily[p.family].push(p);
554
+ const families = showUnsupported ? ["unsupported"] : showAll ? ["anthropic", "openai", "google", "openai-compatible", "unsupported"] : ["anthropic", "openai", "google", "openai-compatible"];
555
+ for (const family of families) {
556
+ const list = byFamily[family];
557
+ if (list.length === 0) continue;
558
+ deps.renderer.write(`
559
+ ${color3.bold(family)} (${list.length}):
560
+ `);
561
+ for (const p of list) {
562
+ const envFound = p.envVars.some((v) => process.env[v]);
563
+ const marker = envFound ? color3.green("\u25CF") : color3.dim("\u25CB");
564
+ const envHint = p.envVars[0] ? color3.dim(`[${p.envVars[0]}]`) : "";
565
+ const note = family === "unsupported" ? color3.dim("(needs plugin)") : "";
566
+ deps.renderer.write(
567
+ ` ${marker} ${p.id.padEnd(20)} ${p.name.padEnd(28)} ${envHint} ${note}
568
+ `
569
+ );
570
+ }
571
+ }
572
+ deps.renderer.write(
573
+ `
574
+ ${color3.dim(`Current: ${deps.config.provider ?? "<unset>"} / ${deps.config.model ?? "<unset>"}. Use --all to include unsupported families.`)}
575
+ `
576
+ );
577
+ return 0;
578
+ } catch (err) {
579
+ deps.renderer.writeError(
580
+ `Failed to list providers: ${err instanceof Error ? err.message : err}`
581
+ );
582
+ return 1;
583
+ }
584
+ };
585
+ var DEFAULT_PER_PAGE = 15;
586
+ var modelsCmd = async (args, deps) => {
587
+ const sub = args[0];
588
+ if (sub === "hide") return modelsHide(args.slice(1), deps);
589
+ if (sub === "show") return modelsShow(args.slice(1), deps);
590
+ if (sub === "hidden") return modelsHidden(args.slice(1), deps);
591
+ if (sub === "reset") return modelsReset(args.slice(1), deps);
592
+ if (sub === "add") return modelsAdd(args.slice(1), deps);
593
+ if (sub === "remove") return modelsRemove(args.slice(1), deps);
594
+ if (sub === "list") return modelsList(args.slice(1), deps);
595
+ if (sub === "caps" || sub === "capabilities") return modelsCaps(args.slice(1), deps);
596
+ if (sub === "refresh") {
597
+ deps.renderer.writeInfo("Refreshing models.dev cache\u2026");
598
+ try {
599
+ const payload = await deps.modelsRegistry.refresh();
600
+ deps.renderer.writeInfo(
601
+ `Cached ${Object.keys(payload).length} providers to ${deps.paths.modelsCache}`
602
+ );
603
+ return 0;
604
+ } catch (err) {
605
+ deps.renderer.writeError(`Refresh failed: ${err instanceof Error ? err.message : err}`);
606
+ return 1;
607
+ }
608
+ }
609
+ const flags = subcommandFlags(args, deps);
610
+ const search = typeof flags["search"] === "string" ? flags["search"].toLowerCase() : "";
611
+ const perPage = Number(flags["per-page"]) > 0 ? Number(flags["per-page"]) : DEFAULT_PER_PAGE;
612
+ const page = Math.max(1, Number(flags["page"]) || 1);
613
+ const providerId = sub ?? deps.config.provider ?? "";
614
+ if (!providerId) {
615
+ deps.renderer.writeError(
616
+ "Usage: wstack models <provider> [--search <term>] [--page N] [--per-page N]"
617
+ );
618
+ return 1;
619
+ }
620
+ const { providerId: lookupId, provider } = await getCatalogProviderForConfigProvider(
621
+ providerId,
622
+ deps
623
+ );
624
+ if (!provider) {
625
+ deps.renderer.writeError(
626
+ lookupId !== providerId ? `Alias "${providerId}" points at catalog id "${lookupId}" which is not in the cache.` : `Provider "${providerId}" not in catalog.`
627
+ );
628
+ return 1;
629
+ }
630
+ if (lookupId !== providerId)
631
+ deps.renderer.write(
632
+ color3.dim(`(showing catalog models for "${lookupId}" via alias "${providerId}")
633
+ `)
634
+ );
635
+ deps.renderer.write(`${color3.bold(provider.name)} ${color3.dim(`(${provider.id})`)}
636
+ `);
637
+ if (provider.doc) deps.renderer.write(color3.dim(`Docs: ${provider.doc}
638
+ `));
639
+ const savedProvider = deps.config.providers?.[providerId];
640
+ const userModels = savedProvider?.models;
641
+ const catalogById = new Map(provider.models.map((m) => [m.id, m]));
642
+ const allKnownSorted = [...provider.models].sort(
643
+ (a, b) => (b.release_date ?? "").localeCompare(a.release_date ?? "")
644
+ );
645
+ const visibleIds = visibleModelIds(
646
+ providerId,
647
+ deps.config,
648
+ allKnownSorted.map((m) => m.id),
649
+ savedProvider
650
+ );
651
+ const allSorted = visibleIds.map((id) => catalogById.get(id) ?? { id, name: id });
652
+ if (userModels !== void 0) {
653
+ const hiddenCount = Math.max(0, allKnownSorted.length - visibleIds.length);
654
+ const restoredCount = Math.max(0, visibleIds.length - userModels.length);
655
+ deps.renderer.write(
656
+ color3.dim(
657
+ `(${visibleIds.length} visible model(s)${restoredCount > 0 ? `, ${restoredCount} from providers.json/catalog fallback` : " from your saved config"}${hiddenCount > 0 ? `, ${hiddenCount} hidden` : ""})
658
+ `
659
+ )
660
+ );
661
+ }
662
+ const filtered = search ? allSorted.filter((m) => m.id.toLowerCase().includes(search)) : allSorted;
663
+ const total = filtered.length;
664
+ const totalPages = Math.max(1, Math.ceil(total / perPage));
665
+ const actualPage = Math.min(page, totalPages);
666
+ const start = (actualPage - 1) * perPage;
667
+ const pageItems = filtered.slice(start, start + perPage);
668
+ const end = Math.min(start + pageItems.length, total);
669
+ const pageHint = totalPages > 1 ? color3.cyan(`[page ${actualPage}/${totalPages}]`) : "";
670
+ const searchHint = search ? color3.yellow(` (filtered: "${search}" \u2014 ${total} match${total === 1 ? "" : "es"})`) : color3.dim(` (${total} model${total === 1 ? "" : "s"})`);
671
+ deps.renderer.write(`${pageHint}${searchHint}
672
+ `);
673
+ if (pageItems.length === 0) {
674
+ deps.renderer.write(color3.dim("(no models match)\n"));
675
+ } else {
676
+ if (start > 0)
677
+ deps.renderer.write(color3.dim(` ${String.fromCharCode(8593)} ${start} above
678
+ `));
679
+ for (const m of pageItems) {
680
+ const caps = [];
681
+ if ("tool_call" in m && m.tool_call) caps.push("tools");
682
+ if ("reasoning" in m && m.reasoning) caps.push("reasoning");
683
+ if ("modalities" in m && m.modalities?.input?.includes("image")) caps.push("vision");
684
+ const ctx = "limit" in m && m.limit?.context ? `${(m.limit.context / 1e3).toFixed(0)}k` : "?";
685
+ const cost = "cost" in m && m.cost?.input !== void 0 ? `${m.cost.input}/${m.cost.output ?? "?"}` : "";
686
+ deps.renderer.write(
687
+ ` ${m.id.padEnd(40)} ${color3.dim(ctx.padStart(6))} ${color3.dim(cost.padEnd(14))} ${color3.dim(caps.join(","))}
688
+ `
689
+ );
690
+ }
691
+ if (end < total)
692
+ deps.renderer.write(color3.dim(` ${String.fromCharCode(8595)} ${total - end} below
693
+ `));
694
+ }
695
+ const navLines = [];
696
+ if (totalPages > 1) {
697
+ if (actualPage > 1) navLines.push(`--page ${actualPage - 1} (prev)`);
698
+ if (actualPage < totalPages) navLines.push(`--page ${actualPage + 1} (next)`);
699
+ }
700
+ navLines.push("--search <term> (filter)");
701
+ deps.renderer.write(color3.dim(`
702
+ ${navLines.join(" \xB7 ")}
703
+ `));
704
+ const age = await deps.modelsRegistry.ageSeconds();
705
+ deps.renderer.write(
706
+ color3.dim(
707
+ `Cache age: ${isFinite(age) ? `${Math.round(age / 60)}m` : "never fetched"}. Run \`wstack models refresh\` to update.
708
+ `
709
+ )
710
+ );
711
+ return 0;
712
+ };
669
713
  export {
670
714
  modelsCmd,
671
715
  providersCmd
672
716
  };
673
- //# sourceMappingURL=providers-models-W57I3QOA.js.map
717
+ //# sourceMappingURL=providers-models-37DUV2GW.js.map