mirror of
https://github.com/Routstr/routstrd.git
synced 2026-10-05 20:38:22 +00:00
142 lines
4.3 KiB
TypeScript
142 lines
4.3 KiB
TypeScript
import { existsSync, mkdirSync } from "fs";
|
|
import { readFile, writeFile } from "fs/promises";
|
|
import { dirname } from "path";
|
|
import type { RoutstrdConfig } from "../utils/config";
|
|
import type { IntegrationConfig, RoutstrModel } from "./registry";
|
|
import { callDaemon, getDaemonBaseUrl } from "../utils/daemon-client";
|
|
|
|
const OPENCLAW_PROVIDER_ID = "routstr";
|
|
const OPENCLAW_DEFAULT_PRIMARY_MODEL = "routstr/minimax-m2.5";
|
|
const OPENCLAW_DEFAULT_FALLBACK_MODEL = "routstr/kimi-k2.5";
|
|
|
|
type OpenClawModelEntry = {
|
|
id: string;
|
|
name: string;
|
|
reasoning: boolean;
|
|
};
|
|
|
|
type OpenClawConfig = {
|
|
models?: {
|
|
providers?: Record<string, {
|
|
baseUrl?: string;
|
|
apiKey?: string;
|
|
api?: string;
|
|
models?: OpenClawModelEntry[];
|
|
}>;
|
|
};
|
|
agents?: {
|
|
defaults?: {
|
|
model?: {
|
|
primary?: string;
|
|
fallbacks?: string[];
|
|
};
|
|
models?: Record<string, {
|
|
alias?: string;
|
|
}>;
|
|
};
|
|
};
|
|
};
|
|
|
|
function toAlias(modelId: string): string {
|
|
if (modelId === "claude-sonnet-4.5") return "sonnet-4.5";
|
|
if (modelId === "claude-opus-4.5") return "opus-4.5";
|
|
if (modelId === "gemini-3-pro-preview") return "gemini-3-pro";
|
|
if (modelId === "gemini-3-flash-preview") return "gemini-3-flash";
|
|
if (modelId === "kimi-k2-thinking") return "kimi-k2";
|
|
if (modelId === "deepseek-v3.2-speciale") return "deepseek-special";
|
|
if (modelId === "grok-code-fast-1") return "grok-code";
|
|
return modelId;
|
|
}
|
|
|
|
export async function installOpenClawIntegration(
|
|
config: RoutstrdConfig,
|
|
apiKey: string,
|
|
integrationConfig: IntegrationConfig,
|
|
): Promise<void> {
|
|
const { name, configPath } = integrationConfig;
|
|
|
|
console.log("\nInstalling routstr models in openclaw.json...");
|
|
console.log(`Using API key for ${name}`);
|
|
|
|
const baseUrl = getDaemonBaseUrl(config);
|
|
|
|
let openclawConfig: OpenClawConfig = {};
|
|
|
|
try {
|
|
if (existsSync(configPath)) {
|
|
const content = await readFile(configPath, "utf-8");
|
|
openclawConfig = JSON.parse(content) as OpenClawConfig;
|
|
}
|
|
} catch (error) {
|
|
console.error(`Failed to read or parse ${configPath}; leaving it unchanged:`, error);
|
|
return;
|
|
}
|
|
|
|
if (!openclawConfig.models) {
|
|
openclawConfig.models = {};
|
|
}
|
|
if (!openclawConfig.models.providers) {
|
|
openclawConfig.models.providers = {};
|
|
}
|
|
if (!openclawConfig.agents) {
|
|
openclawConfig.agents = {};
|
|
}
|
|
if (!openclawConfig.agents.defaults) {
|
|
openclawConfig.agents.defaults = {};
|
|
}
|
|
|
|
try {
|
|
mkdirSync(dirname(configPath), { recursive: true });
|
|
|
|
const data = await callDaemon("/models");
|
|
const models = (data.output as { models: RoutstrModel[] } | undefined)?.models || [];
|
|
|
|
if (models.length === 0) {
|
|
console.log("No models found from routstr daemon.");
|
|
return;
|
|
}
|
|
|
|
const providerModels: OpenClawModelEntry[] = models.map((model) => ({
|
|
id: model.id,
|
|
name: model.name || model.id,
|
|
reasoning: true,
|
|
}));
|
|
|
|
openclawConfig.models.providers[OPENCLAW_PROVIDER_ID] = {
|
|
baseUrl: `${baseUrl}/v1`,
|
|
apiKey,
|
|
api: "openai-completions",
|
|
models: providerModels,
|
|
};
|
|
|
|
const availableModelIds = new Set(providerModels.map((model) => model.id));
|
|
const primaryId = availableModelIds.has("gpt-5.3-codex") ? "gpt-5.3-codex" : providerModels[0]?.id;
|
|
const fallbackId = availableModelIds.has("minimax-m2.5")
|
|
? "minimax-m2.5"
|
|
: providerModels.find((model) => model.id !== primaryId)?.id;
|
|
|
|
if (primaryId) {
|
|
openclawConfig.agents.defaults.model = {
|
|
primary: `${OPENCLAW_PROVIDER_ID}/${primaryId}`,
|
|
fallbacks: fallbackId ? [`${OPENCLAW_PROVIDER_ID}/${fallbackId}`] : [],
|
|
};
|
|
} else {
|
|
openclawConfig.agents.defaults.model = {
|
|
primary: OPENCLAW_DEFAULT_PRIMARY_MODEL,
|
|
fallbacks: [OPENCLAW_DEFAULT_FALLBACK_MODEL],
|
|
};
|
|
}
|
|
|
|
// const aliasMap: Record<string, { alias?: string }> = {};
|
|
// for (const model of providerModels) {
|
|
// aliasMap[`${OPENCLAW_PROVIDER_ID}/${model.id}`] = { alias: toAlias(model.id) };
|
|
// }
|
|
// openclawConfig.agents.defaults.models = aliasMap;
|
|
|
|
await writeFile(configPath, JSON.stringify(openclawConfig, null, 2));
|
|
console.log(`Added "${OPENCLAW_PROVIDER_ID}" provider with ${models.length} models to openclaw.json`);
|
|
} catch (error) {
|
|
console.error("Failed to install models in openclaw.json:", error);
|
|
}
|
|
}
|