// SPDX-FileCopyrightText: Amolith // // SPDX-License-Identifier: MIT import { type ExtensionAPI, type ExtensionContext, ModelSelectorComponent, SettingsManager, } from "@earendil-works/pi-coding-agent"; export type SetModelResult = | { ok: true } | { ok: false; reason: "invalid-format" | "unknown-model" | "set-failed"; detail: string }; /** * Parse a "provider/modelId" string, look it up in the model registry, and * set it as the active model. Returns a result describing what happened. */ export async function parseAndSetModel(spec: string, ctx: ExtensionContext, pi: ExtensionAPI): Promise { const slashIdx = spec.indexOf("/"); if (slashIdx <= 0 || slashIdx === spec.length - 1) { return { ok: false, reason: "invalid-format", detail: `Invalid model format "${spec}", expected provider/modelId` }; } const provider = spec.slice(0, slashIdx); const modelId = spec.slice(slashIdx + 1); const model = ctx.modelRegistry.find(provider, modelId); if (!model) { return { ok: false, reason: "unknown-model", detail: `Unknown model: ${spec}` }; } try { await pi.setModel(model); } catch (err) { const msg = err instanceof Error ? err.message : String(err); return { ok: false, reason: "set-failed", detail: `Failed to set model ${spec}: ${msg}` }; } return { ok: true }; } /** * Convenience wrapper: parse and set the model, notifying the user on failure. */ export async function parseAndSetModelWithNotify( spec: string, ctx: ExtensionContext, pi: ExtensionAPI, ): Promise { const result = await parseAndSetModel(spec, ctx, pi); if (!result.ok) { ctx.ui.notify(result.detail, "warning"); } return result; } /** * Show Pi's built-in model picker and return the user's selection without * changing Pi's active model or default model setting. */ export async function pickModel( ctx: ExtensionContext, currentModel: ExtensionContext["model"] = ctx.model, initialSearchInput?: string, ): Promise { return ctx.ui.custom((tui, _theme, _keybindings, done) => { const selector = new ModelSelectorComponent( tui, currentModel, SettingsManager.inMemory(), ctx.modelRegistry, [], (model) => done(model), () => done(undefined), initialSearchInput, ); return selector; }); }