fix: add OpenCode Go DeepSeek V4 models

This commit is contained in:
Peter Steinberger
2026-04-25 18:11:54 +01:00
parent 0d274ef6c2
commit 390be8138f
7 changed files with 169 additions and 17 deletions

View File

@@ -43,7 +43,7 @@ describe("opencode-go provider plugin", () => {
});
});
it("leaves OpenCode Go models to Pi's built-in registry", async () => {
it("keeps OpenCode Go catalog coverage aligned with upstream", async () => {
const provider = await registerSingleProviderPlugin(plugin);
expect(provider.catalog).toBeUndefined();
@@ -62,6 +62,27 @@ describe("opencode-go provider plugin", () => {
"qwen3.5-plus",
"qwen3.6-plus",
]);
const supplemental = await provider.augmentModelCatalog?.({
entries: [...models.values()].map((model) => ({
provider: model.provider,
id: model.id,
name: model.name,
})),
} as never);
expect(supplemental).toEqual(
expect.arrayContaining([
expect.objectContaining({
provider: "opencode-go",
id: "deepseek-v4-pro",
name: "DeepSeek V4 Pro",
}),
expect.objectContaining({
provider: "opencode-go",
id: "deepseek-v4-flash",
name: "DeepSeek V4 Flash",
}),
]),
);
expect(models.get("kimi-k2.6")).toMatchObject({
api: "openai-completions",
@@ -92,6 +113,19 @@ describe("opencode-go provider plugin", () => {
contextWindow: 262_144,
maxTokens: 128_000,
});
expect(
provider.resolveDynamicModel?.({
modelId: "deepseek-v4-pro",
} as never),
).toMatchObject({
id: "deepseek-v4-pro",
api: "anthropic-messages",
provider: "opencode-go",
baseUrl: "https://opencode.ai/zen/go",
reasoning: true,
contextWindow: 1_000_000,
maxTokens: 384_000,
});
});
it("canonicalizes stale OpenCode Go base URLs", async () => {

View File

@@ -3,7 +3,11 @@ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
import { PASSTHROUGH_GEMINI_REPLAY_HOOKS } from "openclaw/plugin-sdk/provider-model-shared";
import { applyOpencodeGoConfig, OPENCODE_GO_DEFAULT_MODEL_REF } from "./api.js";
import { opencodeGoMediaUnderstandingProvider } from "./media-understanding-provider.js";
import { normalizeOpencodeGoBaseUrl } from "./provider-catalog.js";
import {
listOpencodeGoSupplementalModelCatalogEntries,
normalizeOpencodeGoBaseUrl,
resolveOpencodeGoSupplementalModel,
} from "./provider-catalog.js";
const PROVIDER_ID = "opencode-go";
export default definePluginEntry({
@@ -60,6 +64,8 @@ export default definePluginEntry({
}
: undefined;
},
resolveDynamicModel: ({ modelId }) => resolveOpencodeGoSupplementalModel(modelId),
augmentModelCatalog: () => listOpencodeGoSupplementalModelCatalogEntries(),
...PASSTHROUGH_GEMINI_REPLAY_HOOKS,
isModernModelRef: () => true,
});

View File

@@ -1,6 +1,69 @@
import type { ModelCatalogEntry } from "openclaw/plugin-sdk/agent-runtime";
import type { ProviderRuntimeModel } from "openclaw/plugin-sdk/plugin-entry";
import { normalizeModelCompat } from "openclaw/plugin-sdk/provider-model-shared";
const PROVIDER_ID = "opencode-go";
export const OPENCODE_GO_OPENAI_BASE_URL = "https://opencode.ai/zen/go/v1";
export const OPENCODE_GO_ANTHROPIC_BASE_URL = "https://opencode.ai/zen/go";
const OPENCODE_GO_SUPPLEMENTAL_MODELS = (
[
{
id: "deepseek-v4-pro",
name: "DeepSeek V4 Pro",
api: "anthropic-messages",
provider: PROVIDER_ID,
baseUrl: OPENCODE_GO_ANTHROPIC_BASE_URL,
reasoning: true,
input: ["text"],
cost: {
input: 1.74,
output: 3.48,
cacheRead: 0.145,
cacheWrite: 0,
},
contextWindow: 1_000_000,
maxTokens: 384_000,
},
{
id: "deepseek-v4-flash",
name: "DeepSeek V4 Flash",
api: "anthropic-messages",
provider: PROVIDER_ID,
baseUrl: OPENCODE_GO_ANTHROPIC_BASE_URL,
reasoning: true,
input: ["text"],
cost: {
input: 0.14,
output: 0.28,
cacheRead: 0.028,
cacheWrite: 0,
},
contextWindow: 1_000_000,
maxTokens: 384_000,
},
] satisfies ProviderRuntimeModel[]
).map((model) => normalizeModelCompat(model));
export function listOpencodeGoSupplementalModelCatalogEntries(): ModelCatalogEntry[] {
return OPENCODE_GO_SUPPLEMENTAL_MODELS.map((model) => ({
provider: model.provider,
id: model.id,
name: model.name,
reasoning: model.reasoning,
input: model.input,
contextWindow: model.contextWindow,
}));
}
export function resolveOpencodeGoSupplementalModel(
modelId: string,
): ProviderRuntimeModel | undefined {
const normalizedModelId = modelId.trim().toLowerCase();
return OPENCODE_GO_SUPPLEMENTAL_MODELS.find((model) => model.id === normalizedModelId);
}
function normalizeBaseUrl(baseUrl: string | undefined): string {
return (baseUrl ?? "").trim().replace(/\/+$/, "");
}