function quoteToml(value) { return `"${String(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`; } function json(value) { return JSON.stringify(value, null, 2); } function safeContextWindow(modelData) { return ( modelData?.gguf?.context_length ?? modelData?.config?.max_position_embeddings ?? modelData?.transformersInfo?.max_position_embeddings ?? 128000 ); } function safeMaxTokens(modelData) { const contextWindow = safeContextWindow(modelData); return Math.min(Math.max(4096, Math.floor(contextWindow / 8)), 32768); } function agentDisplayName(modelData) { return modelData.repoId.split("/").pop() ?? modelData.repoId; } export const AGENTS = { pi: { apiFormats: ["openai-completions"] }, openclaw: { apiFormats: ["openai-completions", "openai-responses", "anthropic-messages"] }, opencode: { apiFormats: ["openai-completions"] }, codex: { apiFormats: ["openai-responses"] }, claude: { apiFormats: ["anthropic-messages"] } }; export function assertAgentCompatibility(agent, runtime) { const descriptor = AGENTS[agent]; if (!descriptor) { throw new Error(`Unknown agent "${agent}".`); } if (!descriptor.apiFormats.includes(runtime.apiFormat)) { throw new Error( [ `Agent "${agent}" is incompatible with runtime "${runtime.key}".`, `Agent "${agent}" needs one of: ${descriptor.apiFormats.join(", ")}.`, `Runtime "${runtime.key}" exposes: ${runtime.apiFormat}.` ].join(" ") ); } } function renderPiArtifacts({ baseUrl, servedModelId, modelData }) { const content = { providers: { "hf-local": { baseUrl, api: "openai-completions", apiKey: "none", models: [ { id: servedModelId, contextWindow: safeContextWindow(modelData) } ] } } }; return { files: [ { name: "pi.models.json", targetPath: "~/.pi/agent/models.json", content: json(content) } ], cliCommands: [] }; } function renderOpenClawArtifacts({ baseUrl, servedModelId, modelData, runtime }) { const primaryRef = `hf-local/${servedModelId}`; const configFragment = { agents: { defaults: { model: { primary: primaryRef }, models: { [primaryRef]: { alias: agentDisplayName(modelData) } } } }, models: { mode: "merge", providers: { "hf-local": { baseUrl, apiKey: "none", api: runtime.apiFormat, models: [ { id: servedModelId, name: agentDisplayName(modelData), reasoning: false, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: safeContextWindow(modelData), maxTokens: safeMaxTokens(modelData) } ] } } } }; const cliCommands = []; if (runtime.apiFormat === "openai-completions") { const onboardCommand = [ "openclaw onboard --non-interactive \\", " --auth-choice custom-api-key \\", ` --custom-base-url "${baseUrl}" \\`, ` --custom-model-id "${servedModelId}" \\`, ' --custom-api-key "hf-local" \\', ' --secret-input-mode plaintext \\', ' --custom-compatibility openai \\', " --accept-risk" ].join("\n"); cliCommands.push({ title: "openclaw onboard", content: onboardCommand }); } return { files: [ { name: "openclaw.config.json", targetPath: "merge into your OpenClaw config or agent models.json", content: json(configFragment) } ], cliCommands }; } function renderOpenCodeArtifacts({ baseUrl, servedModelId, modelData }) { const contextWindow = safeContextWindow(modelData); const outputTokens = safeMaxTokens(modelData); const content = { $schema: "https://opencode.ai/config.json", provider: { "hf-local": { npm: "@ai-sdk/openai-compatible", name: "HF Local", options: { baseURL: baseUrl, apiKey: "none" }, models: { [servedModelId]: { name: agentDisplayName(modelData), limit: { context: contextWindow, output: outputTokens } } } } }, model: `hf-local/${servedModelId}` }; return { files: [ { name: "opencode.json", targetPath: "~/.config/opencode/opencode.json", content: json(content) } ], cliCommands: [] }; } function renderCodexArtifacts({ baseUrl, servedModelId }) { const content = [ 'model_provider = "hf_local"', `model = ${quoteToml(servedModelId)}`, "", "[model_providers.hf_local]", 'name = "HF Local Responses"', `base_url = ${quoteToml(baseUrl)}`, 'wire_api = "responses"', "requires_openai_auth = false", "supports_websockets = false" ].join("\n"); return { files: [ { name: "codex.config.toml", targetPath: "~/.codex/config.toml", content } ], cliCommands: [] }; } function renderClaudeArtifacts({ baseUrl, servedModelId }) { const content = { model: servedModelId, env: { ANTHROPIC_BASE_URL: baseUrl, ANTHROPIC_MODEL: servedModelId, ANTHROPIC_CUSTOM_MODEL_OPTION: servedModelId, ANTHROPIC_CUSTOM_MODEL_OPTION_NAME: "HF Local", ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION: "Gateway-routed Hugging Face local model" } }; return { files: [ { name: "claude.settings.json", targetPath: "~/.claude/settings.json", content: json(content) } ], cliCommands: [] }; } export function buildAgentArtifacts({ agent, runtime, baseUrl, servedModelId, modelData }) { assertAgentCompatibility(agent, runtime); if (!baseUrl) { throw new Error(`Agent "${agent}" requires a base URL, but runtime "${runtime.key}" does not define one. Pass --base-url.`); } if (agent === "pi") { return renderPiArtifacts({ baseUrl, servedModelId, modelData }); } if (agent === "openclaw") { return renderOpenClawArtifacts({ baseUrl, servedModelId, modelData, runtime }); } if (agent === "opencode") { return renderOpenCodeArtifacts({ baseUrl, servedModelId, modelData }); } if (agent === "codex") { return renderCodexArtifacts({ baseUrl, servedModelId }); } if (agent === "claude") { return renderClaudeArtifacts({ baseUrl, servedModelId }); } throw new Error(`Unknown agent "${agent}".`); }