Files
openclaw/extensions/opencode-go/opencode-go.live.test.ts

76 lines
3.2 KiB
TypeScript

import { completeSimple, type Model } from "openclaw/plugin-sdk/llm";
import { extractNonEmptyAssistantText, isLiveTestEnabled } from "openclaw/plugin-sdk/test-live";
import { describe, expect, it } from "vitest";
import {
buildOpencodeGoLiveProviderConfig,
listOpencodeGoModelCatalogEntries,
} from "./provider-catalog.js";
const OPENCODE_GO_MODELS_URL = "https://opencode.ai/zen/go/v1/models";
const OPENCODE_API_KEY =
process.env.OPENCODE_API_KEY?.trim() || process.env.OPENCODE_ZEN_API_KEY?.trim() || "";
const LIVE = isLiveTestEnabled(["OPENCODE_GO_LIVE_TEST"]) && OPENCODE_API_KEY.length > 0;
const describeLive = LIVE ? describe : describe.skip;
type ModelsResponse = { data?: Array<{ id?: unknown; object?: unknown }> };
describeLive("OpenCode Go live dynamic catalog", () => {
it("discovers the active advertised models with trusted upstream metadata", async () => {
const response = await fetch(OPENCODE_GO_MODELS_URL, {
headers: {
accept: "application/json",
authorization: `Bearer ${OPENCODE_API_KEY}`,
"accept-encoding": "identity",
},
});
expect(response.ok).toBe(true);
const body = (await response.json()) as ModelsResponse;
const liveIds = (body.data ?? [])
.filter((row) => row.object === undefined || row.object === "model")
.map((row) => row.id)
.filter((id): id is string => typeof id === "string" && id.trim().length > 0)
.map((id) => id.trim().toLowerCase())
.toSorted();
const live = await buildOpencodeGoLiveProviderConfig({
apiKey: OPENCODE_API_KEY,
discoveryApiKey: OPENCODE_API_KEY,
});
const discoveredIds = live.models.map((model) => model.id).toSorted();
const trustedRows = listOpencodeGoModelCatalogEntries();
const activeIds = new Set(
trustedRows.filter((row) => !row.status).map((row) => row.id.toLowerCase()),
);
expect(discoveredIds.length).toBeGreaterThan(0);
expect(new Set(discoveredIds).size).toBe(discoveredIds.length);
expect(discoveredIds).toEqual([...new Set(liveIds)].filter((id) => activeIds.has(id)));
}, 30_000);
it("runs a discovered Go model with the account credential", async () => {
const provider = await buildOpencodeGoLiveProviderConfig({ apiKey: OPENCODE_API_KEY });
const row = provider.models.find((model) => model.id === "gpt-5.6-luna");
if (!row || row.api !== "openai-responses" || !row.contextWindow) {
throw new Error("OpenCode Go catalog lacks the GPT 5.6 Luna Responses route");
}
const input = row.input.filter((kind) => kind === "text" || kind === "image");
expect(input).toEqual(row.input);
const model: Model<"openai-responses"> = {
...row,
api: row.api,
contextWindow: row.contextWindow,
provider: "opencode-go",
baseUrl: row.baseUrl ?? provider.baseUrl,
input,
};
const result = await completeSimple(
model,
{ messages: [{ role: "user", content: "Reply with exactly: ok", timestamp: Date.now() }] },
{ apiKey: OPENCODE_API_KEY, maxTokens: 128 },
);
if (result.stopReason === "error") {
throw new Error(result.errorMessage || "OpenCode Go inference returned an error");
}
expect(extractNonEmptyAssistantText(result.content)).toMatch(/^ok[.!]?$/i);
}, 120_000);
});