import type { Plugin } from "@opencode/plugin"; import { modelCheckInputSchema, type ModelCheckInput, type ModelCheckReport } from "../src/runtime/model-check.js"; type Context = Parameters[0]; const catalogPackage = /^(?:@opencode\/ai\/providers\/(?:openai(?:\/chat|\/responses)?|openai-compatible(?:\/responses)?|openrouter|xai))$/; // Runs inside OpenCode and uses its effective provider and model definitions. // A manually registered model ID is only valid after upstream advertisement. export async function checkOpencodeModels(ctx: Pick, input: ModelCheckInput, signal: AbortSignal): Promise { const targets = modelCheckInputSchema.parse(input).models; const nativeModels = (await ctx.model.list({}, { signal })).data; const report: ModelCheckReport = { providers: [], models: targets.map((target) => { const model = nativeModels.find((model) => model.providerID === target.provider_id && model.id === target.model_id); return { id: target.id, model_id: target.wire_id, status: !model ? "not_registered" : !model.enabled ? "not_enabled" : target.requires_tools && !model.capabilities.tools ? "no_tools" : model.modelID !== target.wire_id ? "wire_id_mismatch" : "unchecked" }; }), }; await Promise.all([...new Set(targets.map((target) => target.provider_id))].map(async (providerID) => { const providerReport: ModelCheckReport["providers"][number] = { id: providerID, status: "not_registered" }; report.providers.push(providerReport); let provider; try { provider = (await ctx.provider.get({ providerID }, { signal })).data; } catch { return; } if (!catalogPackage.test(provider.package)) { providerReport.status = "unsupported_catalog"; return; } const baseURL = provider.settings?.baseURL; if (typeof baseURL !== "string") { providerReport.status = "catalog_unavailable"; return; } let endpoint: URL; try { endpoint = new URL(`${baseURL.replace(/\/+$/, "")}/models`); if (!["http:", "https:"].includes(endpoint.protocol) || endpoint.username || endpoint.password || endpoint.search || endpoint.hash) throw new Error(); } catch { providerReport.status = "catalog_unavailable"; return; } let headers: Headers; try { headers = new Headers(provider.headers); headers.set("Accept", "application/json"); const apiKey = provider.settings?.apiKey; if (!headers.has("Authorization") && typeof apiKey === "string" && apiKey.trim()) headers.set("Authorization", `Bearer ${apiKey}`); // An explicit header can also carry a service-owned credential. if (!headers.has("Authorization")) throw new Error(); } catch { providerReport.status = "credentials_unavailable"; return; } try { const response = await fetch(endpoint, { headers, redirect: "error", signal: AbortSignal.any([signal, AbortSignal.timeout(10_000)]) }); if (!response.ok) { providerReport.status = "catalog_unavailable"; providerReport.http_status = response.status; return; } const payload: unknown = await response.json(); const data = payload && typeof payload === "object" && "data" in payload ? payload.data : undefined; if (!Array.isArray(data) || data.some((model) => !model || typeof model.id !== "string")) { providerReport.status = "catalog_invalid"; return; } const advertised = new Set(data.map((model) => model.id as string)); providerReport.status = "checked"; for (const target of targets.filter((target) => target.provider_id === providerID)) { const model = report.models.find((model) => model.id === target.id)!; if (model.status === "unchecked") model.status = advertised.has(target.wire_id) ? "valid" : "not_advertised"; } } catch { providerReport.status = "catalog_unavailable"; } })); report.providers.sort((a, b) => a.id.localeCompare(b.id)); return report; }