Generate chat, task and learning models from agent-models.json. Use WaterNetwork fast/expert models with 272k context and validate upstream names before readiness. Add an isolated model check command with signal-safe cleanup and plugin, Skill and MCP management docs. Verified in isolation: type checks, 26 focused tests and both model catalog checks; no model inference requests.
60 lines
3.9 KiB
TypeScript
60 lines
3.9 KiB
TypeScript
import type { Plugin } from "@opencode/plugin";
|
|
import { modelCheckInputSchema, type ModelCheckInput, type ModelCheckReport } from "../src/runtime/model-check.js";
|
|
|
|
type Context = Parameters<Plugin.Plugin["setup"]>[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<Context, "model" | "provider">, input: ModelCheckInput, signal: AbortSignal): Promise<ModelCheckReport> {
|
|
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;
|
|
}
|