@gguf/claw
Version:
WhatsApp gateway CLI (Baileys web) with Pi RPC agent
1,444 lines (1,434 loc) • 115 kB
JavaScript
import { C as buildAllowedModelSet, K as VENICE_DEFAULT_MODEL_REF, M as resolveAllowlistModelKey, N as resolveConfiguredModelRef, O as modelKey, S as resolveOpenClawAgentDir, T as buildModelAliasIndex, X as SYNTHETIC_DEFAULT_MODEL_REF, _ as ensureAuthProfileStore, _t as DEFAULT_PROVIDER, c as CHUTES_AUTHORIZE_ENDPOINT, d as parseOAuthCallbackInput, et as getCustomProviderApiKey, ft as CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, g as upsertAuthProfile, gt as DEFAULT_MODEL, it as resolveEnvApiKey, k as normalizeProviderId, l as exchangeChutesCodeForTokens, n as resolveAuthProfileOrder, p as listProfilesForProvider, u as generateChutesPkce } from "./auth-profiles-CYBuGiBb.js";
import { t as formatCliCommand } from "./command-format-ayFsmwwz.js";
import { d as resolveConfigDir, m as resolveUserPath, o as ensureDir, t as CONFIG_DIR } from "./utils-DX85MiPR.js";
import { t as runCommandWithTimeout } from "./exec-B8JKbXKW.js";
import { a as resolveAgentModelPrimary, c as resolveDefaultAgentId, r as resolveAgentDir, s as resolveAgentWorkspaceDir, w as resolveDefaultAgentWorkspaceDir } from "./agent-scope-C9VjJXEK.js";
import { t as resolveBrewExecutable } from "./brew-CcZV0dSS.js";
import { Kt as loadModelCatalog, m as openUrl, o as detectBinary, y as resolveNodeManagerOptions } from "./loader-_Pj-TZS2.js";
import { a as enablePluginInConfig } from "./onboard-channels-D-ZQTy5V.js";
import { t as scanDirectoryWithSummary } from "./skill-scanner-Bp1D9gra.js";
import { R as fetchWithSsrFGuard } from "./deliver-Cau4HL7W.js";
import { _ as resolveSkillKey, d as hasBinary, i as loadWorkspaceSkillEntries, t as resolveSkillsInstallPreferences } from "./skills-CmU0Q92f.js";
import { n as resolveWideAreaDiscoveryDomain } from "./widearea-dns-CsSylzXH.js";
import { $ as setVeniceApiKey, A as applySyntheticProviderConfig, B as OPENROUTER_DEFAULT_MODEL_REF, C as applyMoonshotConfig, D as applyOpenrouterConfig, E as applyMoonshotProviderConfigCn, F as applyXaiConfig, G as setCloudflareAiGatewayConfig, H as XIAOMI_DEFAULT_MODEL_REF, I as applyXaiProviderConfig, J as setMinimaxApiKey, K as setGeminiApiKey, L as applyXiaomiConfig, M as applyVeniceProviderConfig, N as applyVercelAiGatewayConfig, O as applyOpenrouterProviderConfig, P as applyVercelAiGatewayProviderConfig, Q as setSyntheticApiKey, R as applyXiaomiProviderConfig, S as applyKimiCodeProviderConfig, T as applyMoonshotProviderConfig, U as ZAI_DEFAULT_MODEL_REF, V as VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, W as setAnthropicApiKey, X as setOpencodeZenApiKey, Y as setMoonshotApiKey, Z as setOpenrouterApiKey, _ as applyMinimaxProviderConfig, at as KIMI_CODING_MODEL_REF, b as applyCloudflareAiGatewayProviderConfig, ct as buildTokenProfileId, d as resolvePluginProviders, et as setVercelAiGatewayApiKey, f as applyOpencodeZenConfig, g as applyMinimaxConfig, h as applyMinimaxApiProviderConfig, i as formatTokenK, it as writeOAuthCredentials, j as applyVeniceConfig, k as applySyntheticConfig, l as createVpsAwareOAuthHandlers, lt as validateAnthropicSetupToken, m as applyMinimaxApiConfig, nt as setXiaomiApiKey, ot as MOONSHOT_DEFAULT_MODEL_REF, p as applyOpencodeZenProviderConfig, q as setKimiCodingApiKey, rt as setZaiApiKey, st as XAI_DEFAULT_MODEL_REF, t as githubCopilotLoginCommand, tt as setXaiApiKey, u as isRemoteEnvironment, v as applyAuthProfileConfig, w as applyMoonshotConfigCn, x as applyKimiCodeConfig, y as applyCloudflareAiGatewayConfig, z as applyZaiConfig } from "./github-copilot-auth-B_lK1g__.js";
import { t as buildWorkspaceSkillStatus } from "./skills-status-DtXrj3fy.js";
import path from "node:path";
import fs from "node:fs";
import { loginOpenAICodex } from "@mariozechner/pi-ai";
import { randomBytes } from "node:crypto";
import { createServer } from "node:http";
import { Readable } from "node:stream";
import { pipeline } from "node:stream/promises";
//#region src/infra/bonjour-discovery.ts
const DEFAULT_TIMEOUT_MS = 2e3;
const GATEWAY_SERVICE_TYPE = "_openclaw-gw._tcp";
function decodeDnsSdEscapes(value) {
let decoded = false;
const bytes = [];
let pending = "";
const flush = () => {
if (!pending) return;
bytes.push(...Buffer.from(pending, "utf8"));
pending = "";
};
for (let i = 0; i < value.length; i += 1) {
const ch = value[i] ?? "";
if (ch === "\\" && i + 3 < value.length) {
const escaped = value.slice(i + 1, i + 4);
if (/^[0-9]{3}$/.test(escaped)) {
const byte = Number.parseInt(escaped, 10);
if (!Number.isFinite(byte) || byte < 0 || byte > 255) {
pending += ch;
continue;
}
flush();
bytes.push(byte);
decoded = true;
i += 3;
continue;
}
}
pending += ch;
}
if (!decoded) return value;
flush();
return Buffer.from(bytes).toString("utf8");
}
function isTailnetIPv4(address) {
const parts = address.split(".");
if (parts.length !== 4) return false;
const octets = parts.map((p) => Number.parseInt(p, 10));
if (octets.some((n) => !Number.isFinite(n) || n < 0 || n > 255)) return false;
const [a, b] = octets;
return a === 100 && b >= 64 && b <= 127;
}
function parseDigShortLines(stdout) {
return stdout.split("\n").map((l) => l.trim()).filter(Boolean);
}
function parseDigTxt(stdout) {
const tokens = [];
for (const raw of stdout.split("\n")) {
const line = raw.trim();
if (!line) continue;
const matches = Array.from(line.matchAll(/"([^"]*)"/g), (m) => m[1] ?? "");
for (const m of matches) {
const unescaped = m.replaceAll("\\\\", "\\").replaceAll("\\\"", "\"").replaceAll("\\n", "\n");
tokens.push(unescaped);
}
}
return tokens;
}
function parseDigSrv(stdout) {
const line = stdout.split("\n").map((l) => l.trim()).find(Boolean);
if (!line) return null;
const parts = line.split(/\s+/).filter(Boolean);
if (parts.length < 4) return null;
const port = Number.parseInt(parts[2] ?? "", 10);
const hostRaw = parts[3] ?? "";
if (!Number.isFinite(port) || port <= 0) return null;
const host = hostRaw.replace(/\.$/, "");
if (!host) return null;
return {
host,
port
};
}
function parseTailscaleStatusIPv4s(stdout) {
const parsed = stdout ? JSON.parse(stdout) : {};
const out = [];
const addIps = (value) => {
if (!value || typeof value !== "object") return;
const ips = value.TailscaleIPs;
if (!Array.isArray(ips)) return;
for (const ip of ips) {
if (typeof ip !== "string") continue;
const trimmed = ip.trim();
if (trimmed && isTailnetIPv4(trimmed)) out.push(trimmed);
}
};
addIps(parsed.Self);
const peerObj = parsed.Peer;
if (peerObj && typeof peerObj === "object") for (const peer of Object.values(peerObj)) addIps(peer);
return [...new Set(out)];
}
function parseIntOrNull(value) {
if (!value) return;
const parsed = Number.parseInt(value, 10);
return Number.isFinite(parsed) ? parsed : void 0;
}
function parseTxtTokens(tokens) {
const txt = {};
for (const token of tokens) {
const idx = token.indexOf("=");
if (idx <= 0) continue;
const key = token.slice(0, idx).trim();
const value = decodeDnsSdEscapes(token.slice(idx + 1).trim());
if (!key) continue;
txt[key] = value;
}
return txt;
}
function parseDnsSdBrowse(stdout) {
const instances = /* @__PURE__ */ new Set();
for (const raw of stdout.split("\n")) {
const line = raw.trim();
if (!line || !line.includes(GATEWAY_SERVICE_TYPE)) continue;
if (!line.includes("Add")) continue;
const match = line.match(/_openclaw-gw\._tcp\.?\s+(.+)$/);
if (match?.[1]) instances.add(decodeDnsSdEscapes(match[1].trim()));
}
return Array.from(instances.values());
}
function parseDnsSdResolve(stdout, instanceName) {
const decodedInstanceName = decodeDnsSdEscapes(instanceName);
const beacon = { instanceName: decodedInstanceName };
let txt = {};
for (const raw of stdout.split("\n")) {
const line = raw.trim();
if (!line) continue;
if (line.includes("can be reached at")) {
const match = line.match(/can be reached at\s+([^\s:]+):(\d+)/i);
if (match?.[1]) beacon.host = match[1].replace(/\.$/, "");
if (match?.[2]) beacon.port = parseIntOrNull(match[2]);
continue;
}
if (line.startsWith("txt") || line.includes("txtvers=")) txt = parseTxtTokens(line.split(/\s+/).filter(Boolean));
}
beacon.txt = Object.keys(txt).length ? txt : void 0;
if (txt.displayName) beacon.displayName = decodeDnsSdEscapes(txt.displayName);
if (txt.lanHost) beacon.lanHost = txt.lanHost;
if (txt.tailnetDns) beacon.tailnetDns = txt.tailnetDns;
if (txt.cliPath) beacon.cliPath = txt.cliPath;
beacon.gatewayPort = parseIntOrNull(txt.gatewayPort);
beacon.sshPort = parseIntOrNull(txt.sshPort);
if (txt.gatewayTls) {
const raw = txt.gatewayTls.trim().toLowerCase();
beacon.gatewayTls = raw === "1" || raw === "true" || raw === "yes";
}
if (txt.gatewayTlsSha256) beacon.gatewayTlsFingerprintSha256 = txt.gatewayTlsSha256;
if (txt.role) beacon.role = txt.role;
if (txt.transport) beacon.transport = txt.transport;
if (!beacon.displayName) beacon.displayName = decodedInstanceName;
return beacon;
}
async function discoverViaDnsSd(domain, timeoutMs, run) {
const instances = parseDnsSdBrowse((await run([
"dns-sd",
"-B",
GATEWAY_SERVICE_TYPE,
domain
], { timeoutMs })).stdout);
const results = [];
for (const instance of instances) {
const parsed = parseDnsSdResolve((await run([
"dns-sd",
"-L",
instance,
GATEWAY_SERVICE_TYPE,
domain
], { timeoutMs })).stdout, instance);
if (parsed) results.push({
...parsed,
domain
});
}
return results;
}
async function discoverWideAreaViaTailnetDns(domain, timeoutMs, run) {
if (!domain || domain === "local.") return [];
const startedAt = Date.now();
const remainingMs = () => timeoutMs - (Date.now() - startedAt);
const tailscaleCandidates = ["tailscale", "/Applications/Tailscale.app/Contents/MacOS/Tailscale"];
let ips = [];
for (const candidate of tailscaleCandidates) try {
ips = parseTailscaleStatusIPv4s((await run([
candidate,
"status",
"--json"
], { timeoutMs: Math.max(1, Math.min(700, remainingMs())) })).stdout);
if (ips.length > 0) break;
} catch {}
if (ips.length === 0) return [];
if (remainingMs() <= 0) return [];
ips = ips.slice(0, 40);
const probeName = `${GATEWAY_SERVICE_TYPE}.${domain.replace(/\.$/, "")}`;
const concurrency = 6;
let nextIndex = 0;
let nameserver = null;
let ptrs = [];
const worker = async () => {
while (nameserver === null) {
const budget = remainingMs();
if (budget <= 0) return;
const i = nextIndex;
nextIndex += 1;
if (i >= ips.length) return;
const ip = ips[i] ?? "";
if (!ip) continue;
try {
const lines = parseDigShortLines((await run([
"dig",
"+short",
"+time=1",
"+tries=1",
`@${ip}`,
probeName,
"PTR"
], { timeoutMs: Math.max(1, Math.min(250, budget)) })).stdout);
if (lines.length === 0) continue;
nameserver = ip;
ptrs = lines;
return;
} catch {}
}
};
await Promise.all(Array.from({ length: Math.min(concurrency, ips.length) }, () => worker()));
if (!nameserver || ptrs.length === 0) return [];
if (remainingMs() <= 0) return [];
const nameserverArg = `@${String(nameserver)}`;
const results = [];
for (const ptr of ptrs) {
const budget = remainingMs();
if (budget <= 0) break;
const ptrName = ptr.trim().replace(/\.$/, "");
if (!ptrName) continue;
const instanceName = ptrName.replace(/\.?_openclaw-gw\._tcp\..*$/, "");
const srv = await run([
"dig",
"+short",
"+time=1",
"+tries=1",
nameserverArg,
ptrName,
"SRV"
], { timeoutMs: Math.max(1, Math.min(350, budget)) }).catch(() => null);
const srvParsed = srv ? parseDigSrv(srv.stdout) : null;
if (!srvParsed) continue;
const txtBudget = remainingMs();
if (txtBudget <= 0) {
results.push({
instanceName: instanceName || ptrName,
displayName: instanceName || ptrName,
domain,
host: srvParsed.host,
port: srvParsed.port
});
continue;
}
const txt = await run([
"dig",
"+short",
"+time=1",
"+tries=1",
nameserverArg,
ptrName,
"TXT"
], { timeoutMs: Math.max(1, Math.min(350, txtBudget)) }).catch(() => null);
const txtTokens = txt ? parseDigTxt(txt.stdout) : [];
const txtMap = txtTokens.length > 0 ? parseTxtTokens(txtTokens) : {};
const beacon = {
instanceName: instanceName || ptrName,
displayName: txtMap.displayName || instanceName || ptrName,
domain,
host: srvParsed.host,
port: srvParsed.port,
txt: Object.keys(txtMap).length ? txtMap : void 0,
gatewayPort: parseIntOrNull(txtMap.gatewayPort),
sshPort: parseIntOrNull(txtMap.sshPort),
tailnetDns: txtMap.tailnetDns || void 0,
cliPath: txtMap.cliPath || void 0
};
if (txtMap.gatewayTls) {
const raw = txtMap.gatewayTls.trim().toLowerCase();
beacon.gatewayTls = raw === "1" || raw === "true" || raw === "yes";
}
if (txtMap.gatewayTlsSha256) beacon.gatewayTlsFingerprintSha256 = txtMap.gatewayTlsSha256;
if (txtMap.role) beacon.role = txtMap.role;
if (txtMap.transport) beacon.transport = txtMap.transport;
results.push(beacon);
}
return results;
}
function parseAvahiBrowse(stdout) {
const results = [];
let current = null;
for (const raw of stdout.split("\n")) {
const line = raw.trimEnd();
if (!line) continue;
if (line.startsWith("=") && line.includes(GATEWAY_SERVICE_TYPE)) {
if (current) results.push(current);
const marker = ` ${GATEWAY_SERVICE_TYPE}`;
const idx = line.indexOf(marker);
const left = idx >= 0 ? line.slice(0, idx).trim() : line;
const parts = left.split(/\s+/);
const instanceName = parts.length > 3 ? parts.slice(3).join(" ") : left;
current = {
instanceName,
displayName: instanceName
};
continue;
}
if (!current) continue;
const trimmed = line.trim();
if (trimmed.startsWith("hostname =")) {
const match = trimmed.match(/hostname\s*=\s*\[([^\]]+)\]/);
if (match?.[1]) current.host = match[1];
continue;
}
if (trimmed.startsWith("port =")) {
const match = trimmed.match(/port\s*=\s*\[(\d+)\]/);
if (match?.[1]) current.port = parseIntOrNull(match[1]);
continue;
}
if (trimmed.startsWith("txt =")) {
const txt = parseTxtTokens(Array.from(trimmed.matchAll(/"([^"]*)"/g), (m) => m[1]));
current.txt = Object.keys(txt).length ? txt : void 0;
if (txt.displayName) current.displayName = txt.displayName;
if (txt.lanHost) current.lanHost = txt.lanHost;
if (txt.tailnetDns) current.tailnetDns = txt.tailnetDns;
if (txt.cliPath) current.cliPath = txt.cliPath;
current.gatewayPort = parseIntOrNull(txt.gatewayPort);
current.sshPort = parseIntOrNull(txt.sshPort);
if (txt.gatewayTls) {
const raw = txt.gatewayTls.trim().toLowerCase();
current.gatewayTls = raw === "1" || raw === "true" || raw === "yes";
}
if (txt.gatewayTlsSha256) current.gatewayTlsFingerprintSha256 = txt.gatewayTlsSha256;
if (txt.role) current.role = txt.role;
if (txt.transport) current.transport = txt.transport;
}
}
if (current) results.push(current);
return results;
}
async function discoverViaAvahi(domain, timeoutMs, run) {
const args = [
"avahi-browse",
"-rt",
GATEWAY_SERVICE_TYPE
];
if (domain && domain !== "local.") args.push("-d", domain.replace(/\.$/, ""));
return parseAvahiBrowse((await run(args, { timeoutMs })).stdout).map((beacon) => ({
...beacon,
domain
}));
}
async function discoverGatewayBeacons(opts = {}) {
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
const platform = opts.platform ?? process.platform;
const run = opts.run ?? runCommandWithTimeout;
const wideAreaDomain = resolveWideAreaDiscoveryDomain({ configDomain: opts.wideAreaDomain });
const domainsRaw = Array.isArray(opts.domains) ? opts.domains : [];
const defaultDomains = ["local.", ...wideAreaDomain ? [wideAreaDomain] : []];
const domains = (domainsRaw.length > 0 ? domainsRaw : defaultDomains).map((d) => String(d).trim()).filter(Boolean).map((d) => d.endsWith(".") ? d : `${d}.`);
try {
if (platform === "darwin") {
const discovered = (await Promise.allSettled(domains.map(async (domain) => await discoverViaDnsSd(domain, timeoutMs, run)))).flatMap((r) => r.status === "fulfilled" ? r.value : []);
const wantsWideArea = wideAreaDomain ? domains.includes(wideAreaDomain) : false;
const hasWideArea = wideAreaDomain ? discovered.some((b) => b.domain === wideAreaDomain) : false;
if (wantsWideArea && !hasWideArea && wideAreaDomain) {
const fallback = await discoverWideAreaViaTailnetDns(wideAreaDomain, timeoutMs, run).catch(() => []);
return [...discovered, ...fallback];
}
return discovered;
}
if (platform === "linux") return (await Promise.allSettled(domains.map(async (domain) => await discoverViaAvahi(domain, timeoutMs, run)))).flatMap((r) => r.status === "fulfilled" ? r.value : []);
} catch {
return [];
}
return [];
}
//#endregion
//#region src/commands/auth-choice-options.ts
const AUTH_CHOICE_GROUP_DEFS = [
{
value: "xai",
label: "xAI (Grok)",
hint: "API key",
choices: ["xai-api-key"]
},
{
value: "openai",
label: "OpenAI",
hint: "Codex OAuth + API key",
choices: ["openai-codex", "openai-api-key"]
},
{
value: "anthropic",
label: "Anthropic",
hint: "setup-token + API key",
choices: ["token", "apiKey"]
},
{
value: "minimax",
label: "MiniMax",
hint: "M2.1 (recommended)",
choices: [
"minimax-portal",
"minimax-api",
"minimax-api-lightning"
]
},
{
value: "moonshot",
label: "Moonshot AI (Kimi K2.5)",
hint: "Kimi K2.5 + Kimi Coding",
choices: [
"moonshot-api-key",
"moonshot-api-key-cn",
"kimi-code-api-key"
]
},
{
value: "google",
label: "Google",
hint: "Gemini API key + OAuth",
choices: [
"gemini-api-key",
"google-antigravity",
"google-gemini-cli"
]
},
{
value: "openrouter",
label: "OpenRouter",
hint: "API key",
choices: ["openrouter-api-key"]
},
{
value: "qwen",
label: "Qwen",
hint: "OAuth",
choices: ["qwen-portal"]
},
{
value: "zai",
label: "Z.AI (GLM 4.7)",
hint: "API key",
choices: ["zai-api-key"]
},
{
value: "copilot",
label: "Copilot",
hint: "GitHub + local proxy",
choices: ["github-copilot", "copilot-proxy"]
},
{
value: "ai-gateway",
label: "Vercel AI Gateway",
hint: "API key",
choices: ["ai-gateway-api-key"]
},
{
value: "opencode-zen",
label: "OpenCode Zen",
hint: "API key",
choices: ["opencode-zen"]
},
{
value: "xiaomi",
label: "Xiaomi",
hint: "API key",
choices: ["xiaomi-api-key"]
},
{
value: "synthetic",
label: "Synthetic",
hint: "Anthropic-compatible (multi-model)",
choices: ["synthetic-api-key"]
},
{
value: "venice",
label: "Venice AI",
hint: "Privacy-focused (uncensored models)",
choices: ["venice-api-key"]
},
{
value: "cloudflare-ai-gateway",
label: "Cloudflare AI Gateway",
hint: "Account ID + Gateway ID + API key",
choices: ["cloudflare-ai-gateway-api-key"]
}
];
function buildAuthChoiceOptions(params) {
params.store;
const options = [];
options.push({
value: "token",
label: "Anthropic token (paste setup-token)",
hint: "run `claude setup-token` elsewhere, then paste the token here"
});
options.push({
value: "openai-codex",
label: "OpenAI Codex (ChatGPT OAuth)"
});
options.push({
value: "chutes",
label: "Chutes (OAuth)"
});
options.push({
value: "openai-api-key",
label: "OpenAI API key"
});
options.push({
value: "openrouter-api-key",
label: "OpenRouter API key"
});
options.push({
value: "xai-api-key",
label: "xAI (Grok) API key"
});
options.push({
value: "ai-gateway-api-key",
label: "Vercel AI Gateway API key"
});
options.push({
value: "cloudflare-ai-gateway-api-key",
label: "Cloudflare AI Gateway",
hint: "Account ID + Gateway ID + API key"
});
options.push({
value: "moonshot-api-key",
label: "Kimi API key (.ai)"
});
options.push({
value: "moonshot-api-key-cn",
label: "Kimi API key (.cn)"
});
options.push({
value: "kimi-code-api-key",
label: "Kimi Code API key (subscription)"
});
options.push({
value: "synthetic-api-key",
label: "Synthetic API key"
});
options.push({
value: "venice-api-key",
label: "Venice AI API key",
hint: "Privacy-focused inference (uncensored models)"
});
options.push({
value: "github-copilot",
label: "GitHub Copilot (GitHub device login)",
hint: "Uses GitHub device flow"
});
options.push({
value: "gemini-api-key",
label: "Google Gemini API key"
});
options.push({
value: "google-antigravity",
label: "Google Antigravity OAuth",
hint: "Uses the bundled Antigravity auth plugin"
});
options.push({
value: "google-gemini-cli",
label: "Google Gemini CLI OAuth",
hint: "Uses the bundled Gemini CLI auth plugin"
});
options.push({
value: "zai-api-key",
label: "Z.AI (GLM 4.7) API key"
});
options.push({
value: "xiaomi-api-key",
label: "Xiaomi API key"
});
options.push({
value: "minimax-portal",
label: "MiniMax OAuth",
hint: "Oauth plugin for MiniMax"
});
options.push({
value: "qwen-portal",
label: "Qwen OAuth"
});
options.push({
value: "copilot-proxy",
label: "Copilot Proxy (local)",
hint: "Local proxy for VS Code Copilot models"
});
options.push({
value: "apiKey",
label: "Anthropic API key"
});
options.push({
value: "opencode-zen",
label: "OpenCode Zen (multi-model proxy)",
hint: "Claude, GPT, Gemini via opencode.ai/zen"
});
options.push({
value: "minimax-api",
label: "MiniMax M2.1"
});
options.push({
value: "minimax-api-lightning",
label: "MiniMax M2.1 Lightning",
hint: "Faster, higher output cost"
});
if (params.includeSkip) options.push({
value: "skip",
label: "Skip for now"
});
return options;
}
function buildAuthChoiceGroups(params) {
const options = buildAuthChoiceOptions({
...params,
includeSkip: false
});
const optionByValue = new Map(options.map((opt) => [opt.value, opt]));
return {
groups: AUTH_CHOICE_GROUP_DEFS.map((group) => ({
...group,
options: group.choices.map((choice) => optionByValue.get(choice)).filter((opt) => Boolean(opt))
})),
skipOption: params.includeSkip ? {
value: "skip",
label: "Skip for now"
} : void 0
};
}
//#endregion
//#region src/commands/auth-choice-prompt.ts
const BACK_VALUE = "__back";
async function promptAuthChoiceGrouped(params) {
const { groups, skipOption } = buildAuthChoiceGroups(params);
const availableGroups = groups.filter((group) => group.options.length > 0);
while (true) {
const providerOptions = [...availableGroups.map((group) => ({
value: group.value,
label: group.label,
hint: group.hint
})), ...skipOption ? [skipOption] : []];
const providerSelection = await params.prompter.select({
message: "Model/auth provider",
options: providerOptions
});
if (providerSelection === "skip") return "skip";
const group = availableGroups.find((candidate) => candidate.value === providerSelection);
if (!group || group.options.length === 0) {
await params.prompter.note("No auth methods available for that provider.", "Model/auth choice");
continue;
}
const methodSelection = await params.prompter.select({
message: `${group.label} auth method`,
options: [...group.options, {
value: BACK_VALUE,
label: "Back"
}]
});
if (methodSelection === BACK_VALUE) continue;
return methodSelection;
}
}
//#endregion
//#region src/commands/auth-choice.api-key.ts
const DEFAULT_KEY_PREVIEW = {
head: 4,
tail: 4
};
function normalizeApiKeyInput(raw) {
const trimmed = String(raw ?? "").trim();
if (!trimmed) return "";
const assignmentMatch = trimmed.match(/^(?:export\s+)?[A-Za-z_][A-Za-z0-9_]*\s*=\s*(.+)$/);
const valuePart = assignmentMatch ? assignmentMatch[1].trim() : trimmed;
const unquoted = valuePart.length >= 2 && (valuePart.startsWith("\"") && valuePart.endsWith("\"") || valuePart.startsWith("'") && valuePart.endsWith("'") || valuePart.startsWith("`") && valuePart.endsWith("`")) ? valuePart.slice(1, -1) : valuePart;
return (unquoted.endsWith(";") ? unquoted.slice(0, -1) : unquoted).trim();
}
const validateApiKeyInput = (value) => normalizeApiKeyInput(value).length > 0 ? void 0 : "Required";
function formatApiKeyPreview(raw, opts = {}) {
const trimmed = raw.trim();
if (!trimmed) return "…";
const head = opts.head ?? DEFAULT_KEY_PREVIEW.head;
const tail = opts.tail ?? DEFAULT_KEY_PREVIEW.tail;
if (trimmed.length <= head + tail) {
const shortHead = Math.min(2, trimmed.length);
const shortTail = Math.min(2, trimmed.length - shortHead);
if (shortTail <= 0) return `${trimmed.slice(0, shortHead)}…`;
return `${trimmed.slice(0, shortHead)}…${trimmed.slice(-shortTail)}`;
}
return `${trimmed.slice(0, head)}…${trimmed.slice(-tail)}`;
}
//#endregion
//#region src/commands/auth-choice.apply.anthropic.ts
async function applyAuthChoiceAnthropic(params) {
if (params.authChoice === "setup-token" || params.authChoice === "oauth" || params.authChoice === "token") {
let nextConfig = params.config;
await params.prompter.note(["Run `claude setup-token` in your terminal.", "Then paste the generated token below."].join("\n"), "Anthropic setup-token");
const tokenRaw = await params.prompter.text({
message: "Paste Anthropic setup-token",
validate: (value) => validateAnthropicSetupToken(String(value ?? ""))
});
const token = String(tokenRaw).trim();
const profileNameRaw = await params.prompter.text({
message: "Token name (blank = default)",
placeholder: "default"
});
const provider = "anthropic";
const namedProfileId = buildTokenProfileId({
provider,
name: String(profileNameRaw ?? "")
});
upsertAuthProfile({
profileId: namedProfileId,
agentDir: params.agentDir,
credential: {
type: "token",
provider,
token
}
});
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: namedProfileId,
provider,
mode: "token"
});
return { config: nextConfig };
}
if (params.authChoice === "apiKey") {
if (params.opts?.tokenProvider && params.opts.tokenProvider !== "anthropic") return null;
let nextConfig = params.config;
let hasCredential = false;
const envKey = process.env.ANTHROPIC_API_KEY?.trim();
if (params.opts?.token) {
await setAnthropicApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
if (!hasCredential && envKey) {
if (await params.prompter.confirm({
message: `Use existing ANTHROPIC_API_KEY (env, ${formatApiKeyPreview(envKey)})?`,
initialValue: true
})) {
await setAnthropicApiKey(envKey, params.agentDir);
hasCredential = true;
}
}
if (!hasCredential) {
const key = await params.prompter.text({
message: "Enter Anthropic API key",
validate: validateApiKeyInput
});
await setAnthropicApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "anthropic:default",
provider: "anthropic",
mode: "api_key"
});
return { config: nextConfig };
}
return null;
}
//#endregion
//#region src/commands/model-allowlist.ts
function ensureModelAllowlistEntry(params) {
const rawModelRef = params.modelRef.trim();
if (!rawModelRef) return params.cfg;
const models = { ...params.cfg.agents?.defaults?.models };
const keySet = new Set([rawModelRef]);
const canonicalKey = resolveAllowlistModelKey(rawModelRef, params.defaultProvider ?? DEFAULT_PROVIDER);
if (canonicalKey) keySet.add(canonicalKey);
for (const key of keySet) models[key] = { ...models[key] };
return {
...params.cfg,
agents: {
...params.cfg.agents,
defaults: {
...params.cfg.agents?.defaults,
models
}
}
};
}
//#endregion
//#region src/commands/auth-choice.default-model.ts
async function applyDefaultModelChoice(params) {
if (params.setDefaultModel) {
const next = params.applyDefaultConfig(params.config);
if (params.noteDefault) await params.prompter.note(`Default model set to ${params.noteDefault}`, "Model configured");
return { config: next };
}
const nextWithModel = ensureModelAllowlistEntry({
cfg: params.applyProviderConfig(params.config),
modelRef: params.defaultModel
});
await params.noteAgentModel(params.defaultModel);
return {
config: nextWithModel,
agentModelOverride: params.defaultModel
};
}
//#endregion
//#region src/commands/google-gemini-model-default.ts
const GOOGLE_GEMINI_DEFAULT_MODEL = "google/gemini-3-pro-preview";
function resolvePrimaryModel$1(model) {
if (typeof model === "string") return model;
if (model && typeof model === "object" && typeof model.primary === "string") return model.primary;
}
function applyGoogleGeminiModelDefault(cfg) {
if (resolvePrimaryModel$1(cfg.agents?.defaults?.model)?.trim() === GOOGLE_GEMINI_DEFAULT_MODEL) return {
next: cfg,
changed: false
};
return {
next: {
...cfg,
agents: {
...cfg.agents,
defaults: {
...cfg.agents?.defaults,
model: cfg.agents?.defaults?.model && typeof cfg.agents.defaults.model === "object" ? {
...cfg.agents.defaults.model,
primary: GOOGLE_GEMINI_DEFAULT_MODEL
} : { primary: GOOGLE_GEMINI_DEFAULT_MODEL }
}
}
},
changed: true
};
}
//#endregion
//#region src/commands/opencode-zen-model-default.ts
const OPENCODE_ZEN_DEFAULT_MODEL = "opencode/claude-opus-4-6";
//#endregion
//#region src/commands/auth-choice.apply.api-providers.ts
async function applyAuthChoiceApiProviders(params) {
let nextConfig = params.config;
let agentModelOverride;
const noteAgentModel = async (model) => {
if (!params.agentId) return;
await params.prompter.note(`Default model set to ${model} for agent "${params.agentId}".`, "Model configured");
};
let authChoice = params.authChoice;
if (authChoice === "apiKey" && params.opts?.tokenProvider && params.opts.tokenProvider !== "anthropic" && params.opts.tokenProvider !== "openai") {
if (params.opts.tokenProvider === "openrouter") authChoice = "openrouter-api-key";
else if (params.opts.tokenProvider === "vercel-ai-gateway") authChoice = "ai-gateway-api-key";
else if (params.opts.tokenProvider === "cloudflare-ai-gateway") authChoice = "cloudflare-ai-gateway-api-key";
else if (params.opts.tokenProvider === "moonshot") authChoice = "moonshot-api-key";
else if (params.opts.tokenProvider === "kimi-code" || params.opts.tokenProvider === "kimi-coding") authChoice = "kimi-code-api-key";
else if (params.opts.tokenProvider === "google") authChoice = "gemini-api-key";
else if (params.opts.tokenProvider === "zai") authChoice = "zai-api-key";
else if (params.opts.tokenProvider === "xiaomi") authChoice = "xiaomi-api-key";
else if (params.opts.tokenProvider === "synthetic") authChoice = "synthetic-api-key";
else if (params.opts.tokenProvider === "venice") authChoice = "venice-api-key";
else if (params.opts.tokenProvider === "opencode") authChoice = "opencode-zen";
}
if (authChoice === "openrouter-api-key") {
const store = ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false });
const existingProfileId = resolveAuthProfileOrder({
cfg: nextConfig,
store,
provider: "openrouter"
}).find((profileId) => Boolean(store.profiles[profileId]));
const existingCred = existingProfileId ? store.profiles[existingProfileId] : void 0;
let profileId = "openrouter:default";
let mode = "api_key";
let hasCredential = false;
if (existingProfileId && existingCred?.type) {
profileId = existingProfileId;
mode = existingCred.type === "oauth" ? "oauth" : existingCred.type === "token" ? "token" : "api_key";
hasCredential = true;
}
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "openrouter") {
await setOpenrouterApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
if (!hasCredential) {
const envKey = resolveEnvApiKey("openrouter");
if (envKey) {
if (await params.prompter.confirm({
message: `Use existing OPENROUTER_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true
})) {
await setOpenrouterApiKey(envKey.apiKey, params.agentDir);
hasCredential = true;
}
}
}
if (!hasCredential) {
const key = await params.prompter.text({
message: "Enter OpenRouter API key",
validate: validateApiKeyInput
});
await setOpenrouterApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
hasCredential = true;
}
if (hasCredential) nextConfig = applyAuthProfileConfig(nextConfig, {
profileId,
provider: "openrouter",
mode
});
{
const applied = await applyDefaultModelChoice({
config: nextConfig,
setDefaultModel: params.setDefaultModel,
defaultModel: OPENROUTER_DEFAULT_MODEL_REF,
applyDefaultConfig: applyOpenrouterConfig,
applyProviderConfig: applyOpenrouterProviderConfig,
noteDefault: OPENROUTER_DEFAULT_MODEL_REF,
noteAgentModel,
prompter: params.prompter
});
nextConfig = applied.config;
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
}
return {
config: nextConfig,
agentModelOverride
};
}
if (authChoice === "ai-gateway-api-key") {
let hasCredential = false;
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "vercel-ai-gateway") {
await setVercelAiGatewayApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
const envKey = resolveEnvApiKey("vercel-ai-gateway");
if (envKey) {
if (await params.prompter.confirm({
message: `Use existing AI_GATEWAY_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true
})) {
await setVercelAiGatewayApiKey(envKey.apiKey, params.agentDir);
hasCredential = true;
}
}
if (!hasCredential) {
const key = await params.prompter.text({
message: "Enter Vercel AI Gateway API key",
validate: validateApiKeyInput
});
await setVercelAiGatewayApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "vercel-ai-gateway:default",
provider: "vercel-ai-gateway",
mode: "api_key"
});
{
const applied = await applyDefaultModelChoice({
config: nextConfig,
setDefaultModel: params.setDefaultModel,
defaultModel: VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF,
applyDefaultConfig: applyVercelAiGatewayConfig,
applyProviderConfig: applyVercelAiGatewayProviderConfig,
noteDefault: VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF,
noteAgentModel,
prompter: params.prompter
});
nextConfig = applied.config;
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
}
return {
config: nextConfig,
agentModelOverride
};
}
if (authChoice === "cloudflare-ai-gateway-api-key") {
let hasCredential = false;
let accountId = params.opts?.cloudflareAiGatewayAccountId?.trim() ?? "";
let gatewayId = params.opts?.cloudflareAiGatewayGatewayId?.trim() ?? "";
const ensureAccountGateway = async () => {
if (!accountId) {
const value = await params.prompter.text({
message: "Enter Cloudflare Account ID",
validate: (val) => String(val).trim() ? void 0 : "Account ID is required"
});
accountId = String(value).trim();
}
if (!gatewayId) {
const value = await params.prompter.text({
message: "Enter Cloudflare AI Gateway ID",
validate: (val) => String(val).trim() ? void 0 : "Gateway ID is required"
});
gatewayId = String(value).trim();
}
};
const optsApiKey = normalizeApiKeyInput(params.opts?.cloudflareAiGatewayApiKey ?? "");
if (!hasCredential && accountId && gatewayId && optsApiKey) {
await setCloudflareAiGatewayConfig(accountId, gatewayId, optsApiKey, params.agentDir);
hasCredential = true;
}
const envKey = resolveEnvApiKey("cloudflare-ai-gateway");
if (!hasCredential && envKey) {
if (await params.prompter.confirm({
message: `Use existing CLOUDFLARE_AI_GATEWAY_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true
})) {
await ensureAccountGateway();
await setCloudflareAiGatewayConfig(accountId, gatewayId, normalizeApiKeyInput(envKey.apiKey), params.agentDir);
hasCredential = true;
}
}
if (!hasCredential && optsApiKey) {
await ensureAccountGateway();
await setCloudflareAiGatewayConfig(accountId, gatewayId, optsApiKey, params.agentDir);
hasCredential = true;
}
if (!hasCredential) {
await ensureAccountGateway();
const key = await params.prompter.text({
message: "Enter Cloudflare AI Gateway API key",
validate: validateApiKeyInput
});
await setCloudflareAiGatewayConfig(accountId, gatewayId, normalizeApiKeyInput(String(key)), params.agentDir);
hasCredential = true;
}
if (hasCredential) nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "cloudflare-ai-gateway:default",
provider: "cloudflare-ai-gateway",
mode: "api_key"
});
{
const applied = await applyDefaultModelChoice({
config: nextConfig,
setDefaultModel: params.setDefaultModel,
defaultModel: CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF,
applyDefaultConfig: (cfg) => applyCloudflareAiGatewayConfig(cfg, {
accountId: accountId || params.opts?.cloudflareAiGatewayAccountId,
gatewayId: gatewayId || params.opts?.cloudflareAiGatewayGatewayId
}),
applyProviderConfig: (cfg) => applyCloudflareAiGatewayProviderConfig(cfg, {
accountId: accountId || params.opts?.cloudflareAiGatewayAccountId,
gatewayId: gatewayId || params.opts?.cloudflareAiGatewayGatewayId
}),
noteDefault: CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF,
noteAgentModel,
prompter: params.prompter
});
nextConfig = applied.config;
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
}
return {
config: nextConfig,
agentModelOverride
};
}
if (authChoice === "moonshot-api-key") {
let hasCredential = false;
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "moonshot") {
await setMoonshotApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
const envKey = resolveEnvApiKey("moonshot");
if (envKey) {
if (await params.prompter.confirm({
message: `Use existing MOONSHOT_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true
})) {
await setMoonshotApiKey(envKey.apiKey, params.agentDir);
hasCredential = true;
}
}
if (!hasCredential) {
const key = await params.prompter.text({
message: "Enter Moonshot API key",
validate: validateApiKeyInput
});
await setMoonshotApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "moonshot:default",
provider: "moonshot",
mode: "api_key"
});
{
const applied = await applyDefaultModelChoice({
config: nextConfig,
setDefaultModel: params.setDefaultModel,
defaultModel: MOONSHOT_DEFAULT_MODEL_REF,
applyDefaultConfig: applyMoonshotConfig,
applyProviderConfig: applyMoonshotProviderConfig,
noteAgentModel,
prompter: params.prompter
});
nextConfig = applied.config;
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
}
return {
config: nextConfig,
agentModelOverride
};
}
if (authChoice === "moonshot-api-key-cn") {
let hasCredential = false;
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "moonshot") {
await setMoonshotApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
const envKey = resolveEnvApiKey("moonshot");
if (envKey) {
if (await params.prompter.confirm({
message: `Use existing MOONSHOT_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true
})) {
await setMoonshotApiKey(envKey.apiKey, params.agentDir);
hasCredential = true;
}
}
if (!hasCredential) {
const key = await params.prompter.text({
message: "Enter Moonshot API key (.cn)",
validate: validateApiKeyInput
});
await setMoonshotApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "moonshot:default",
provider: "moonshot",
mode: "api_key"
});
{
const applied = await applyDefaultModelChoice({
config: nextConfig,
setDefaultModel: params.setDefaultModel,
defaultModel: MOONSHOT_DEFAULT_MODEL_REF,
applyDefaultConfig: applyMoonshotConfigCn,
applyProviderConfig: applyMoonshotProviderConfigCn,
noteAgentModel,
prompter: params.prompter
});
nextConfig = applied.config;
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
}
return {
config: nextConfig,
agentModelOverride
};
}
if (authChoice === "kimi-code-api-key") {
let hasCredential = false;
const tokenProvider = params.opts?.tokenProvider?.trim().toLowerCase();
if (!hasCredential && params.opts?.token && (tokenProvider === "kimi-code" || tokenProvider === "kimi-coding")) {
await setKimiCodingApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
if (!hasCredential) await params.prompter.note(["Kimi Coding uses a dedicated endpoint and API key.", "Get your API key at: https://www.kimi.com/code/en"].join("\n"), "Kimi Coding");
const envKey = resolveEnvApiKey("kimi-coding");
if (envKey) {
if (await params.prompter.confirm({
message: `Use existing KIMI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true
})) {
await setKimiCodingApiKey(envKey.apiKey, params.agentDir);
hasCredential = true;
}
}
if (!hasCredential) {
const key = await params.prompter.text({
message: "Enter Kimi Coding API key",
validate: validateApiKeyInput
});
await setKimiCodingApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "kimi-coding:default",
provider: "kimi-coding",
mode: "api_key"
});
{
const applied = await applyDefaultModelChoice({
config: nextConfig,
setDefaultModel: params.setDefaultModel,
defaultModel: KIMI_CODING_MODEL_REF,
applyDefaultConfig: applyKimiCodeConfig,
applyProviderConfig: applyKimiCodeProviderConfig,
noteDefault: KIMI_CODING_MODEL_REF,
noteAgentModel,
prompter: params.prompter
});
nextConfig = applied.config;
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
}
return {
config: nextConfig,
agentModelOverride
};
}
if (authChoice === "gemini-api-key") {
let hasCredential = false;
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "google") {
await setGeminiApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
const envKey = resolveEnvApiKey("google");
if (envKey) {
if (await params.prompter.confirm({
message: `Use existing GEMINI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true
})) {
await setGeminiApiKey(envKey.apiKey, params.agentDir);
hasCredential = true;
}
}
if (!hasCredential) {
const key = await params.prompter.text({
message: "Enter Gemini API key",
validate: validateApiKeyInput
});
await setGeminiApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "google:default",
provider: "google",
mode: "api_key"
});
if (params.setDefaultModel) {
const applied = applyGoogleGeminiModelDefault(nextConfig);
nextConfig = applied.next;
if (applied.changed) await params.prompter.note(`Default model set to ${GOOGLE_GEMINI_DEFAULT_MODEL}`, "Model configured");
} else {
agentModelOverride = GOOGLE_GEMINI_DEFAULT_MODEL;
await noteAgentModel(GOOGLE_GEMINI_DEFAULT_MODEL);
}
return {
config: nextConfig,
agentModelOverride
};
}
if (authChoice === "zai-api-key") {
let hasCredential = false;
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "zai") {
await setZaiApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
const envKey = resolveEnvApiKey("zai");
if (envKey) {
if (await params.prompter.confirm({
message: `Use existing ZAI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true
})) {
await setZaiApiKey(envKey.apiKey, params.agentDir);
hasCredential = true;
}
}
if (!hasCredential) {
const key = await params.prompter.text({
message: "Enter Z.AI API key",
validate: validateApiKeyInput
});
await setZaiApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "zai:default",
provider: "zai",
mode: "api_key"
});
{
const applied = await applyDefaultModelChoice({
config: nextConfig,
setDefaultModel: params.setDefaultModel,
defaultModel: ZAI_DEFAULT_MODEL_REF,
applyDefaultConfig: applyZaiConfig,
applyProviderConfig: (config) => ({
...config,
agents: {
...config.agents,
defaults: {
...config.agents?.defaults,
models: {
...config.agents?.defaults?.models,
[ZAI_DEFAULT_MODEL_REF]: {
...config.agents?.defaults?.models?.[ZAI_DEFAULT_MODEL_REF],
alias: config.agents?.defaults?.models?.[ZAI_DEFAULT_MODEL_REF]?.alias ?? "GLM"
}
}
}
}
}),
noteDefault: ZAI_DEFAULT_MODEL_REF,
noteAgentModel,
prompter: params.prompter
});
nextConfig = applied.config;
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
}
return {
config: nextConfig,
agentModelOverride
};
}
if (authChoice === "xiaomi-api-key") {
let hasCredential = false;
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "xiaomi") {
await setXiaomiApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
const envKey = resolveEnvApiKey("xiaomi");
if (envKey) {
if (await params.prompter.confirm({
message: `Use existing XIAOMI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true
})) {
await setXiaomiApiKey(envKey.apiKey, params.agentDir);
hasCredential = true;
}
}
if (!hasCredential) {
const key = await params.prompter.text({
message: "Enter Xiaomi API key",
validate: validateApiKeyInput
});
await setXiaomiApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "xiaomi:default",
provider: "xiaomi",
mode: "api_key"
});
{
const applied = await applyDefaultModelChoice({
config: nextConfig,
setDefaultModel: params.setDefaultModel,
defaultModel: XIAOMI_DEFAULT_MODEL_REF,
applyDefaultConfig: applyXiaomiConfig,
applyProviderConfig: applyXiaomiProviderConfig,
noteDefault: XIAOMI_DEFAULT_MODEL_REF,
noteAgentModel,
prompter: params.prompter
});
nextConfig = applied.config;
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
}
return {
config: nextConfig,
agentModelOverride
};
}
if (authChoice === "synthetic-api-key") {
if (params.opts?.token && params.opts?.tokenProvider === "synthetic") await setSyntheticApiKey(String(params.opts.token).trim(), params.agentDir);
else {
const key = await params.prompter.text({
message: "Enter Synthetic API key",
validate: (value) => value?.trim() ? void 0 : "Required"
});
await setSyntheticApiKey(String(key).trim(), params.agentDir);
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "synthetic:default",
provider: "synthetic",
mode: "api_key"
});
{
const applied = await applyDefaultModelChoice({
config: nextConfig,
setDefaultModel: params.setDefaultModel,
defaultModel: SYNTHETIC_DEFAULT_MODEL_REF,
applyDefaultConfig: applySyntheticConfig,
applyProviderConfig: applySyntheticProviderConfig,
noteDefault: SYNTHETIC_DEFAULT_MODEL_REF,
noteAgentModel,
prompter: params.prompter
});
nextConfig = applied.config;
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
}
return {
config: nextConfig,
agentModelOverride
};
}
if (authChoice === "venice-api-key") {
let hasCredential = false;
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "venice") {
await setVeniceApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
if (!hasCredential) await params.prompter.note([
"Venice AI provides privacy-focused inference with uncensored models.",
"Get your API key at: https://venice.ai/settings/api",
"Supports 'private' (fully private) and 'anonymized' (proxy) modes."
].join("\n"), "Venice AI");
const envKey = resolveEnvApiKey("venice");
if (envKey) {
if (await params.prompter.confirm({
message: `Use existing VENICE_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true
})) {
await setVeniceApiKey(envKey.apiKey, params.agentDir);
hasCredential = true;
}
}
if (!hasCredential) {
const key = await params.prompter.text({
message: "Enter Venice AI API key",
validate: validateApiKeyInput
});
await setVeniceApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "venice:default",
provider: "venice",
mode: "api_key"
});
{
const applied = await applyDefaultModelChoice({
config: nextConfig,
setDefaultModel: params.setDefaultModel,
defaultModel: VENICE_DEFAULT_MODEL_REF,
applyDefaultConfig: applyVeniceConfig,
applyProviderConfig: applyVeniceProviderConfig,
noteDefault: VENICE_DEFAULT_MODEL_REF,
noteAgentM