1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: MIT
4
5import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
6
7export type SetModelResult =
8 | { ok: true }
9 | { ok: false; reason: "invalid-format" | "unknown-model" | "set-failed"; detail: string };
10
11/**
12 * Parse a "provider/modelId" string, look it up in the model registry, and
13 * set it as the active model. Returns a result describing what happened.
14 */
15export async function parseAndSetModel(spec: string, ctx: ExtensionContext, pi: ExtensionAPI): Promise<SetModelResult> {
16 const slashIdx = spec.indexOf("/");
17 if (slashIdx <= 0 || slashIdx === spec.length - 1) {
18 return { ok: false, reason: "invalid-format", detail: `Invalid model format "${spec}", expected provider/modelId` };
19 }
20
21 const provider = spec.slice(0, slashIdx);
22 const modelId = spec.slice(slashIdx + 1);
23 const model = ctx.modelRegistry.find(provider, modelId);
24
25 if (!model) {
26 return { ok: false, reason: "unknown-model", detail: `Unknown model: ${spec}` };
27 }
28
29 try {
30 await pi.setModel(model);
31 } catch (err) {
32 const msg = err instanceof Error ? err.message : String(err);
33 return { ok: false, reason: "set-failed", detail: `Failed to set model ${spec}: ${msg}` };
34 }
35
36 return { ok: true };
37}
38
39/**
40 * Convenience wrapper: parse and set the model, notifying the user on failure.
41 */
42export async function parseAndSetModelWithNotify(
43 spec: string,
44 ctx: ExtensionContext,
45 pi: ExtensionAPI,
46): Promise<SetModelResult> {
47 const result = await parseAndSetModel(spec, ctx, pi);
48 if (!result.ok) {
49 ctx.ui.notify(result.detail, "warning");
50 }
51 return result;
52}