import { createOpencodeCatalogApiKeyAuthMethod } from "openclaw/plugin-sdk/opencode"; import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry"; import { matchesExactOrPrefix, PASSTHROUGH_GEMINI_REPLAY_HOOKS, } from "openclaw/plugin-sdk/provider-model-shared"; import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime"; import { applyOpencodeZenConfig, OPENCODE_ZEN_DEFAULT_MODEL } from "./api.js"; const PROVIDER_ID = "opencode"; const MINIMAX_MODERN_MODEL_MATCHERS = ["minimax-m2.7"] as const; function isModernOpencodeModel(modelId: string): boolean { const lower = normalizeLowercaseStringOrEmpty(modelId); if (lower.endsWith("-free") || lower === "alpha-glm-4.7") { return false; } return !matchesExactOrPrefix(lower, MINIMAX_MODERN_MODEL_MATCHERS); } export default definePluginEntry({ id: PROVIDER_ID, name: "OpenCode Zen Provider", description: "Bundled OpenCode Zen provider plugin", register(api) { api.registerProvider({ id: PROVIDER_ID, label: "OpenCode Zen", docsPath: "/providers/models", envVars: ["OPENCODE_API_KEY", "OPENCODE_ZEN_API_KEY"], auth: [ createOpencodeCatalogApiKeyAuthMethod({ providerId: PROVIDER_ID, label: "OpenCode Zen catalog", optionKey: "opencodeZenApiKey", flagName: "--opencode-zen-api-key", defaultModel: OPENCODE_ZEN_DEFAULT_MODEL, applyConfig: (cfg) => applyOpencodeZenConfig(cfg), noteMessage: [ "OpenCode uses one API key across the Zen and Go catalogs.", "Zen provides access to Claude, GPT, Gemini, and more models.", "Get your API key at: https://opencode.ai/auth", "Choose the Zen catalog when you want the curated multi-model proxy.", ].join("\n"), choiceId: "opencode-zen", choiceLabel: "OpenCode Zen catalog", }), ], ...PASSTHROUGH_GEMINI_REPLAY_HOOKS, isModernModelRef: ({ modelId }) => isModernOpencodeModel(modelId), }); }, });