118 lines
3.1 KiB
TypeScript
118 lines
3.1 KiB
TypeScript
|
|
import { createAnthropic } from "@ai-sdk/anthropic";
|
||
|
|
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
||
|
|
import { createOpenAI } from "@ai-sdk/openai";
|
||
|
|
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
||
|
|
import { createXai } from "@ai-sdk/xai";
|
||
|
|
import { wrapLanguageModel, type LanguageModel } from "ai";
|
||
|
|
import {
|
||
|
|
assertProviderApiKey,
|
||
|
|
type ProviderApiKeys,
|
||
|
|
type ProviderId,
|
||
|
|
resolveApiKey,
|
||
|
|
} from "./keys";
|
||
|
|
import {
|
||
|
|
getOpenCodeGenerationSettings,
|
||
|
|
OPENCODE_GO_KIMI_MODELS,
|
||
|
|
OPENCODE_GO_MESSAGES_MODELS,
|
||
|
|
} from "./opencode-go-settings";
|
||
|
|
|
||
|
|
export type AIProviderName = ProviderId;
|
||
|
|
|
||
|
|
const OPENCODE_GO_BASE = "https://opencode.ai/zen/go/v1";
|
||
|
|
|
||
|
|
export const PROVIDER_OPTIONS = [
|
||
|
|
{
|
||
|
|
value: "opencode-go" as const,
|
||
|
|
label: "OpenCode Go",
|
||
|
|
models: [
|
||
|
|
"deepseek-v4-flash",
|
||
|
|
"deepseek-v4-pro",
|
||
|
|
"glm-5.1",
|
||
|
|
"glm-5",
|
||
|
|
"kimi-k2.7-code",
|
||
|
|
"kimi-k2.6",
|
||
|
|
"kimi-k2.5",
|
||
|
|
"mimo-v2.5",
|
||
|
|
"mimo-v2.5-pro",
|
||
|
|
"minimax-m3",
|
||
|
|
"minimax-m2.7",
|
||
|
|
"minimax-m2.5",
|
||
|
|
"qwen3.7-max",
|
||
|
|
"qwen3.7-plus",
|
||
|
|
"qwen3.6-plus",
|
||
|
|
"qwen3.5-plus",
|
||
|
|
],
|
||
|
|
},
|
||
|
|
{ value: "xai" as const, label: "Grok (xAI)", models: ["grok-3", "grok-3-fast", "grok-2-1212"] },
|
||
|
|
{ value: "openai" as const, label: "OpenAI", models: ["gpt-4o", "gpt-4o-mini"] },
|
||
|
|
{
|
||
|
|
value: "anthropic" as const,
|
||
|
|
label: "Anthropic",
|
||
|
|
models: ["claude-sonnet-4-20250514", "claude-3-5-haiku-20241022"],
|
||
|
|
},
|
||
|
|
{ value: "google" as const, label: "Google", models: ["gemini-2.0-flash", "gemini-1.5-pro"] },
|
||
|
|
] as const;
|
||
|
|
|
||
|
|
function applyOpenCodeModelDefaults(model: LanguageModel, modelId: string): LanguageModel {
|
||
|
|
if (!OPENCODE_GO_KIMI_MODELS.has(modelId)) return model;
|
||
|
|
|
||
|
|
return wrapLanguageModel({
|
||
|
|
model,
|
||
|
|
modelId,
|
||
|
|
providerId: "opencode-go",
|
||
|
|
middleware: {
|
||
|
|
transformParams: async ({ params }) => ({
|
||
|
|
...params,
|
||
|
|
temperature: 1,
|
||
|
|
}),
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function getOpenCodeGoModel(model: string, apiKey: string): LanguageModel {
|
||
|
|
let resolved: LanguageModel;
|
||
|
|
|
||
|
|
if (OPENCODE_GO_MESSAGES_MODELS.has(model)) {
|
||
|
|
resolved = createAnthropic({
|
||
|
|
apiKey,
|
||
|
|
baseURL: OPENCODE_GO_BASE,
|
||
|
|
})(model);
|
||
|
|
} else {
|
||
|
|
const provider = createOpenAICompatible({
|
||
|
|
name: "opencode-go",
|
||
|
|
baseURL: OPENCODE_GO_BASE,
|
||
|
|
apiKey,
|
||
|
|
});
|
||
|
|
resolved = provider(model);
|
||
|
|
}
|
||
|
|
|
||
|
|
return applyOpenCodeModelDefaults(resolved, model);
|
||
|
|
}
|
||
|
|
|
||
|
|
export function getModel(
|
||
|
|
provider: string,
|
||
|
|
model: string,
|
||
|
|
apiKeys: ProviderApiKeys = {}
|
||
|
|
): LanguageModel {
|
||
|
|
const id = provider as ProviderId;
|
||
|
|
assertProviderApiKey(id, apiKeys);
|
||
|
|
const apiKey = resolveApiKey(id, apiKeys)!;
|
||
|
|
|
||
|
|
switch (id) {
|
||
|
|
case "opencode-go":
|
||
|
|
return getOpenCodeGoModel(model, apiKey);
|
||
|
|
case "openai":
|
||
|
|
return createOpenAI({ apiKey })(model);
|
||
|
|
case "anthropic":
|
||
|
|
return createAnthropic({ apiKey })(model);
|
||
|
|
case "google":
|
||
|
|
return createGoogleGenerativeAI({ apiKey })(model);
|
||
|
|
case "xai":
|
||
|
|
default:
|
||
|
|
return createXai({ apiKey })(model);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export function getModelGenerationSettings(provider: string, model: string) {
|
||
|
|
return getOpenCodeGenerationSettings(provider, model);
|
||
|
|
}
|