@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.
- package/data/providers.json +322 -2
- package/dist/{acp-EDGUWU7N.js → acp-T77EAEDB.js} +469 -465
- package/dist/{auth-SUHKFFO4.js → auth-M6LXZTDA.js} +4 -4
- package/dist/auth-menu/openai-codex-oauth.d.ts +1 -1
- package/dist/auth-menu/panel-provider-edits.d.ts +15 -0
- package/dist/auth-menu/panel-service.d.ts +1 -1
- package/dist/auto-discover-providers-JX346GOM.js +7 -0
- package/dist/boot/governance-evidence-candidate.d.ts +1 -2
- package/dist/boot/system-prompt-builder.d.ts +1 -1
- package/dist/boot/tui-project-spawn.d.ts +0 -1
- package/dist/boot/tui-session-resume-contracts.d.ts +95 -0
- package/dist/boot/tui-session-resume.d.ts +2 -88
- package/dist/boot/tui-settings-read.d.ts +3 -0
- package/dist/{boot-auto-thin-K2DHHYIW.js → boot-auto-thin-YMAZI3QL.js} +2 -2
- package/dist/boot-launch-choices.d.ts +22 -0
- package/dist/boot-provider-gate.d.ts +28 -0
- package/dist/boot-subcommand-dispatch.d.ts +24 -0
- package/dist/boot.d.ts +1 -1
- package/dist/chimera-cascade-evidence.d.ts +1 -1
- package/dist/{chunk-TI7KLHYX.js → chunk-2CMMWRQH.js} +81 -80
- package/dist/{chunk-3LEFXLAW.js → chunk-6SIUTX75.js} +36 -36
- package/dist/{chunk-RQ4UBKYH.js → chunk-6Z6C6ZHH.js} +3 -3
- package/dist/{chunk-5EA6OTLJ.js → chunk-AFOH6CHO.js} +2 -2
- package/dist/{chunk-WHEYHDIE.js → chunk-AKESWZH5.js} +2 -1
- package/dist/{chunk-JHUJUIOH.js → chunk-AT2A7RJZ.js} +4 -16
- package/dist/{chunk-U3SS4NRH.js → chunk-BHXAKTBE.js} +1 -1
- package/dist/{chunk-MPQCHBDJ.js → chunk-CJSHS2K7.js} +5 -1
- package/dist/{chunk-P3GRLV47.js → chunk-GZSKLXYG.js} +208 -141
- package/dist/{chunk-4MDRHMX4.js → chunk-KMU7GF7X.js} +3 -26
- package/dist/{chunk-WXJH4F6K.js → chunk-LDV4ERNV.js} +4 -4
- package/dist/{chunk-LIZXJHZQ.js → chunk-LDXXMPMS.js} +13 -13
- package/dist/{chunk-UQUYBDMG.js → chunk-M4G5FO7F.js} +1 -1
- package/dist/{chunk-CFHWIFXL.js → chunk-PA4VBCXS.js} +25 -33
- package/dist/{chunk-5UZBUV2H.js → chunk-RKU66D2O.js} +6 -4
- package/dist/{chunk-PGNERAZL.js → chunk-RWNI5OWT.js} +2 -2
- package/dist/chunk-TGSPCFBT.js +1 -0
- package/dist/{cli-context-ITHGP2CE.js → cli-context-II57EHD2.js} +1555 -1451
- package/dist/cli-initial-tools.d.ts +54 -0
- package/dist/{cli-main-TQGLKB6D.js → cli-main-YR2WJCPL.js} +38062 -37035
- package/dist/cli-main-boot.d.ts +133 -0
- package/dist/cli-main-orchestration.d.ts +170 -0
- package/dist/cli-main-state.d.ts +19 -0
- package/dist/config-doctor.d.ts +1 -1
- package/dist/{config-transfer-UE37X4B5.js → config-transfer-VOIFY7U4.js} +2 -2
- package/dist/{execution-C2IECWF7.js → execution-IBAZ2EIU.js} +138 -124
- package/dist/fleet/host-director-setup.d.ts +41 -0
- package/dist/fleet/host-spawn-types.d.ts +17 -0
- package/dist/fleet/host.d.ts +2 -1
- package/dist/goal-host-prompts.d.ts +5 -0
- package/dist/goal-host-types.d.ts +94 -0
- package/dist/goal-host.d.ts +2 -91
- package/dist/{hq-KBFDKTDD.js → hq-5OIEKB4V.js} +5 -6
- package/dist/hq-server/handle-types.d.ts +1 -1
- package/dist/hq-server/routes/auth-handlers.d.ts +1 -1
- package/dist/hq-server/routes.d.ts +1 -13
- package/dist/hq-server/utils.d.ts +1 -1
- package/dist/{hq-server-AVNKZ2PV.js → hq-server-DU3ZH3X7.js} +3 -3
- package/dist/{hq-service-FGB7BY2D.js → hq-service-LYZV7EK7.js} +3 -3
- package/dist/index.js +4 -4
- package/dist/live-settings-input.d.ts +2 -0
- package/dist/mailbox-bridge-bootstrap.d.ts +1 -4
- package/dist/{modeldiag-PQILD7TN.js → modeldiag-NEPTLFZW.js} +2 -2
- package/dist/picker-effort.d.ts +32 -0
- package/dist/picker-model-picker.d.ts +13 -2
- package/dist/picker-provider-list.d.ts +66 -0
- package/dist/picker.d.ts +12 -12
- package/dist/{providers-models-W57I3QOA.js → providers-models-37DUV2GW.js} +297 -253
- package/dist/repl-suggestions.d.ts +0 -5
- package/dist/{sdd-runtime-PTOSPYI4.js → sdd-runtime-PF72WHLO.js} +3 -20
- package/dist/services/sdd/task-manager.d.ts +1 -12
- package/dist/services/sdd-runtime.d.ts +3 -4
- package/dist/services/statusline-config.d.ts +0 -2
- package/dist/settings-behavior-sections.d.ts +0 -1
- package/dist/short-circuit-flags-EXJBJ5GT.js +10 -0
- package/dist/{skill-suggest-L2EVWB6R.js → skill-suggest-THANK3LV.js} +1 -1
- package/dist/slash-commands/command-context.d.ts +2 -0
- package/dist/slash-commands/fallback-chain-view.d.ts +3 -0
- package/dist/slash-commands/fallback-ref-validation.d.ts +34 -0
- package/dist/slash-commands/goal-refiner.d.ts +10 -2
- package/dist/slash-commands/goals.d.ts +6 -0
- package/dist/slash-commands/kanban-task-completion.d.ts +17 -0
- package/dist/slash-commands/mcp.d.ts +0 -1
- package/dist/slash-commands/memory-purge-domain-terms.d.ts +5 -0
- package/dist/slash-commands/nextsteps-mode.d.ts +13 -0
- package/dist/slash-commands/session-live-status.d.ts +21 -0
- package/dist/slash-commands/session.d.ts +1 -1
- package/dist/slash-commands/settings-feature-ui-mutations.d.ts +8 -0
- package/dist/slash-commands/settings-hq-autonomy-mutations.d.ts +8 -0
- package/dist/slash-commands/settings-persist-deps.d.ts +10 -0
- package/dist/slash-commands/settings-runtime-mutations.d.ts +12 -0
- package/dist/slash-commands/shadow.d.ts +0 -1
- package/dist/slash-commands/tool-auto-thin-commands.d.ts +15 -0
- package/dist/subcommands/handlers/acp-agents.d.ts +9 -0
- package/dist/subcommands/handlers/acp-server.d.ts +7 -0
- package/dist/subcommands/handlers/hq.d.ts +0 -1
- package/dist/subcommands/handlers/providers-models-custom.d.ts +33 -0
- package/dist/subcommands/handlers/providers-models-visibility.d.ts +29 -0
- package/dist/subcommands/handlers/skill-suggest.d.ts +0 -2
- package/dist/{subcommands-QO7VYTSS.js → subcommands-DTKBXLPU.js} +2 -2
- package/dist/{update-J5WHAFPE.js → update-6OEPAEUV.js} +3 -3
- package/dist/utils/win32-cmd.d.ts +1 -1
- package/dist/{version-help-ATOKGMTK.js → version-help-JQGRPDJW.js} +2 -2
- package/dist/webui-server/host-settings.d.ts +17 -0
- package/dist/webui-server/http-bridge.d.ts +32 -0
- package/dist/webui-server/instance-registration.d.ts +19 -0
- package/dist/webui-server/kanban-services.d.ts +9 -0
- package/dist/webui-server/message-router.d.ts +14 -0
- package/dist/webui-server/prefs-seeding.d.ts +1 -2
- package/dist/webui-server/provider-config.d.ts +0 -1
- package/dist/webui-server/provider-plane.d.ts +14 -0
- package/dist/webui-server/session-agents.d.ts +18 -0
- package/dist/webui-server/session-start-live.d.ts +11 -0
- package/dist/webui-server/stream-coalescer.d.ts +1 -1
- package/dist/webui-server/transport.d.ts +12 -0
- package/dist/{webui-server-GQOVLQS3.js → webui-server-6IC3SLZG.js} +1600 -1435
- package/dist/webui-session-maintenance.d.ts +16 -0
- package/dist/wiring/brain-and-orchestration.d.ts +1 -1
- package/dist/wiring/cli-slash-commands-setup.d.ts +1 -0
- package/dist/wiring/command-host-state.d.ts +11 -2
- package/dist/wiring/dep-watcher-bridge.d.ts +8 -1
- package/dist/wiring/session-command-handlers.d.ts +2 -1
- package/dist/worktree-command-host.d.ts +31 -0
- package/package.json +30 -30
- package/dist/auto-discover-providers-QIL34K3U.js +0 -7
- package/dist/chunk-WHOIR577.js +0 -1
- package/dist/short-circuit-flags-6LB3EGF7.js +0 -10
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
visibleModelIds
|
|
3
|
-
} from "./chunk-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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-
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
342
|
+
color2.bold("Model capabilities") + " " + color2.dim(providerId + "/" + modelId) + "\n"
|
|
478
343
|
);
|
|
479
344
|
deps.renderer.write(
|
|
480
|
-
" context: " + (caps.maxContext ?
|
|
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: " +
|
|
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(", ") :
|
|
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
|
-
|
|
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(
|
|
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(
|
|
509
|
+
deps.renderer.write(color2.dim("No custom models defined.\n"));
|
|
645
510
|
deps.renderer.write(
|
|
646
|
-
|
|
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(
|
|
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 ? ` ${
|
|
654
|
-
deps.renderer.write(` ${
|
|
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(` ${
|
|
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(` ${
|
|
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-
|
|
717
|
+
//# sourceMappingURL=providers-models-37DUV2GW.js.map
|