refactor(auth): drop provider auth storage switchboard

This commit is contained in:
Vincent Koc
2026-04-06 13:01:21 +01:00
parent 58409cd5c5
commit a5d2e89d3d
4 changed files with 75 additions and 226 deletions

View File

@@ -1,12 +1,5 @@
import { afterEach, describe, expect, it } from "vitest";
import {
setByteplusApiKey,
setCloudflareAiGatewayConfig,
setMoonshotApiKey,
setOpencodeZenApiKey,
setOpenaiApiKey,
setVolcengineApiKey,
} from "../plugins/provider-auth-storage.js";
import { upsertApiKeyProfile } from "../plugins/provider-auth-helpers.js";
import {
createAuthTestLifecycle,
readAuthProfilesForAgent,
@@ -80,7 +73,7 @@ describe("onboard auth credentials secret refs", () => {
envValue: "sk-moonshot-env",
profileId: "moonshot:default",
apply: async () => {
await setMoonshotApiKey("sk-moonshot-env");
upsertApiKeyProfile({ provider: "moonshot", input: "sk-moonshot-env" });
},
expected: {
key: "sk-moonshot-env",
@@ -96,7 +89,12 @@ describe("onboard auth credentials secret refs", () => {
envValue: "sk-moonshot-env",
profileId: "moonshot:default",
apply: async (agentDir) => {
await setMoonshotApiKey("sk-moonshot-env", agentDir, { secretInputMode: "ref" }); // pragma: allowlist secret
upsertApiKeyProfile({
provider: "moonshot",
input: "sk-moonshot-env",
agentDir,
options: { secretInputMode: "ref" }, // pragma: allowlist secret
});
},
expected: {
keyRef: { source: "env", provider: "default", id: "MOONSHOT_API_KEY" },
@@ -110,7 +108,7 @@ describe("onboard auth credentials secret refs", () => {
prefix: "openclaw-onboard-auth-credentials-inline-ref-",
profileId: "moonshot:default",
apply: async () => {
await setMoonshotApiKey("${MOONSHOT_API_KEY}");
upsertApiKeyProfile({ provider: "moonshot", input: "${MOONSHOT_API_KEY}" });
},
expected: {
keyRef: { source: "env", provider: "default", id: "MOONSHOT_API_KEY" },
@@ -126,7 +124,7 @@ describe("onboard auth credentials secret refs", () => {
envValue: "sk-moonshot-other",
profileId: "moonshot:default",
apply: async () => {
await setMoonshotApiKey("sk-moonshot-plaintext");
upsertApiKeyProfile({ provider: "moonshot", input: "sk-moonshot-plaintext" });
},
expected: {
key: "sk-moonshot-plaintext",
@@ -140,8 +138,15 @@ describe("onboard auth credentials secret refs", () => {
lifecycle.setStateDir(env.stateDir);
process.env.CLOUDFLARE_AI_GATEWAY_API_KEY = "cf-secret"; // pragma: allowlist secret
await setCloudflareAiGatewayConfig("account-1", "gateway-1", "cf-secret", env.agentDir, {
secretInputMode: "ref", // pragma: allowlist secret
upsertApiKeyProfile({
provider: "cloudflare-ai-gateway",
input: "cf-secret",
agentDir: env.agentDir,
options: { secretInputMode: "ref" }, // pragma: allowlist secret
metadata: {
accountId: "account-1",
gatewayId: "gateway-1",
},
});
const parsed = await readAuthProfilesForAgent<{
@@ -161,7 +166,7 @@ describe("onboard auth credentials secret refs", () => {
envValue: "sk-openai-env",
profileId: "openai:default",
apply: async () => {
await setOpenaiApiKey("sk-openai-env");
upsertApiKeyProfile({ provider: "openai", input: "sk-openai-env" });
},
expected: {
key: "sk-openai-env",
@@ -177,7 +182,12 @@ describe("onboard auth credentials secret refs", () => {
envValue: "sk-openai-env",
profileId: "openai:default",
apply: async (agentDir) => {
await setOpenaiApiKey("sk-openai-env", agentDir, { secretInputMode: "ref" }); // pragma: allowlist secret
upsertApiKeyProfile({
provider: "openai",
input: "sk-openai-env",
agentDir,
options: { secretInputMode: "ref" }, // pragma: allowlist secret
});
},
expected: {
keyRef: { source: "env", provider: "default", id: "OPENAI_API_KEY" },
@@ -192,8 +202,18 @@ describe("onboard auth credentials secret refs", () => {
process.env.VOLCANO_ENGINE_API_KEY = "volcengine-secret"; // pragma: allowlist secret
process.env.BYTEPLUS_API_KEY = "byteplus-secret"; // pragma: allowlist secret
await setVolcengineApiKey("volcengine-secret", env.agentDir, { secretInputMode: "ref" }); // pragma: allowlist secret
await setByteplusApiKey("byteplus-secret", env.agentDir, { secretInputMode: "ref" }); // pragma: allowlist secret
upsertApiKeyProfile({
provider: "volcengine",
input: "volcengine-secret",
agentDir: env.agentDir,
options: { secretInputMode: "ref" }, // pragma: allowlist secret
});
upsertApiKeyProfile({
provider: "byteplus",
input: "byteplus-secret",
agentDir: env.agentDir,
options: { secretInputMode: "ref" }, // pragma: allowlist secret
});
const parsed = await readAuthProfilesForAgent<{
profiles?: Record<string, { key?: string; keyRef?: unknown }>;
@@ -215,9 +235,14 @@ describe("onboard auth credentials secret refs", () => {
lifecycle.setStateDir(env.stateDir);
process.env.OPENCODE_API_KEY = "sk-opencode-env"; // pragma: allowlist secret
await setOpencodeZenApiKey("sk-opencode-env", env.agentDir, {
secretInputMode: "ref", // pragma: allowlist secret
});
for (const provider of ["opencode", "opencode-go"] as const) {
upsertApiKeyProfile({
provider,
input: "sk-opencode-env",
agentDir: env.agentDir,
options: { secretInputMode: "ref" }, // pragma: allowlist secret
});
}
const parsed = await readAuthProfilesForAgent<{
profiles?: Record<string, { key?: string; keyRef?: unknown }>;

View File

@@ -3,8 +3,11 @@ import os from "node:os";
import path from "node:path";
import type { OAuthCredentials } from "@mariozechner/pi-ai";
import { afterEach, describe, expect, it } from "vitest";
import { applyAuthProfileConfig } from "../plugins/provider-auth-helpers.js";
import { setMinimaxApiKey, writeOAuthCredentials } from "../plugins/provider-auth-storage.js";
import {
applyAuthProfileConfig,
upsertApiKeyProfile,
writeOAuthCredentials,
} from "../plugins/provider-auth-helpers.js";
import {
createAuthTestLifecycle,
readAuthProfilesForAgent,
@@ -163,7 +166,7 @@ describe("writeOAuthCredentials", () => {
});
});
describe("setMinimaxApiKey", () => {
describe("upsertApiKeyProfile", () => {
const lifecycle = createAuthTestLifecycle([
"OPENCLAW_STATE_DIR",
"OPENCLAW_AGENT_DIR",
@@ -178,7 +181,7 @@ describe("setMinimaxApiKey", () => {
const env = await setupAuthTestEnv("openclaw-minimax-", { agentSubdir: "custom-agent" });
lifecycle.setStateDir(env.stateDir);
await setMinimaxApiKey("sk-minimax-test");
upsertApiKeyProfile({ provider: "minimax", input: "sk-minimax-test" });
const parsed = await readAuthProfilesForAgent<{
profiles?: Record<string, { type?: string; provider?: string; key?: string }>;

View File

@@ -103,6 +103,28 @@ export function buildApiKeyCredential(
};
}
export function upsertApiKeyProfile(params: {
provider: string;
input: SecretInput;
agentDir?: string;
options?: ApiKeyStorageOptions;
profileId?: string;
metadata?: Record<string, string>;
}): string {
const profileId = params.profileId ?? buildAuthProfileId({ providerId: params.provider });
upsertAuthProfile({
profileId,
credential: buildApiKeyCredential(
params.provider,
params.input,
params.metadata,
params.options,
),
agentDir: resolveAuthAgentDir(params.agentDir),
});
return profileId;
}
export function applyAuthProfileConfig(
cfg: OpenClawConfig,
params: {

View File

@@ -1,201 +0,0 @@
import { resolveOpenClawAgentDir } from "../agents/agent-paths.js";
import { upsertAuthProfile } from "../agents/auth-profiles.js";
import type { SecretInput } from "../config/types.secrets.js";
import {
buildApiKeyCredential,
type ApiKeyStorageOptions,
writeOAuthCredentials,
type WriteOAuthCredentialsOptions,
} from "./provider-auth-helpers.js";
const resolveAuthAgentDir = (agentDir?: string) => agentDir ?? resolveOpenClawAgentDir();
type ProviderApiKeySetter = (
key: SecretInput,
agentDir?: string,
options?: ApiKeyStorageOptions,
) => Promise<void> | void;
function upsertProviderApiKeyProfile(params: {
provider: string;
key: SecretInput;
agentDir?: string;
options?: ApiKeyStorageOptions;
profileId?: string;
metadata?: Record<string, string>;
}) {
upsertAuthProfile({
profileId: params.profileId ?? `${params.provider}:default`,
credential: buildApiKeyCredential(params.provider, params.key, params.metadata, params.options),
agentDir: resolveAuthAgentDir(params.agentDir),
});
}
function createProviderApiKeySetter(
provider: string,
resolveKey: (key: SecretInput) => SecretInput = (key) => key,
): ProviderApiKeySetter {
return async (key, agentDir, options) => {
upsertProviderApiKeyProfile({
provider,
key: resolveKey(key),
agentDir,
options,
});
};
}
type ProviderApiKeySetterSpec = {
provider: string;
resolveKey?: (key: SecretInput) => SecretInput;
};
function createProviderApiKeySetters<const T extends Record<string, ProviderApiKeySetterSpec>>(
specs: T,
): { [K in keyof T]: ProviderApiKeySetter } {
const entries = Object.entries(specs).map(([name, spec]) => [
name,
createProviderApiKeySetter(spec.provider, spec.resolveKey),
]);
return Object.fromEntries(entries) as { [K in keyof T]: ProviderApiKeySetter };
}
export {
buildApiKeyCredential,
type ApiKeyStorageOptions,
writeOAuthCredentials,
type WriteOAuthCredentialsOptions,
};
const {
setAnthropicApiKey,
setOpenaiApiKey,
setGeminiApiKey,
setMoonshotApiKey,
setKimiCodingApiKey,
setVolcengineApiKey,
setByteplusApiKey,
setSyntheticApiKey,
setVeniceApiKey,
setZaiApiKey,
setXiaomiApiKey,
setOpenrouterApiKey,
setLitellmApiKey,
setVercelAiGatewayApiKey,
setTogetherApiKey,
setHuggingfaceApiKey,
setQianfanApiKey,
setQwenApiKey,
setModelStudioApiKey,
setXaiApiKey,
setMistralApiKey,
setKilocodeApiKey,
} = createProviderApiKeySetters({
setAnthropicApiKey: { provider: "anthropic" },
setOpenaiApiKey: { provider: "openai" },
setGeminiApiKey: { provider: "google" },
setMoonshotApiKey: { provider: "moonshot" },
setKimiCodingApiKey: { provider: "kimi" },
setVolcengineApiKey: { provider: "volcengine" },
setByteplusApiKey: { provider: "byteplus" },
setSyntheticApiKey: { provider: "synthetic" },
setVeniceApiKey: { provider: "venice" },
setZaiApiKey: { provider: "zai" },
setXiaomiApiKey: { provider: "xiaomi" },
setOpenrouterApiKey: {
provider: "openrouter",
resolveKey: (key) => (typeof key === "string" && key === "undefined" ? "" : key),
},
setLitellmApiKey: { provider: "litellm" },
setVercelAiGatewayApiKey: { provider: "vercel-ai-gateway" },
setTogetherApiKey: { provider: "together" },
setHuggingfaceApiKey: { provider: "huggingface" },
setQianfanApiKey: { provider: "qianfan" },
setQwenApiKey: { provider: "qwen" },
setModelStudioApiKey: { provider: "qwen" },
setXaiApiKey: { provider: "xai" },
setMistralApiKey: { provider: "mistral" },
setKilocodeApiKey: { provider: "kilocode" },
});
export {
setAnthropicApiKey,
setOpenaiApiKey,
setGeminiApiKey,
setMoonshotApiKey,
setKimiCodingApiKey,
setVolcengineApiKey,
setByteplusApiKey,
setSyntheticApiKey,
setVeniceApiKey,
setZaiApiKey,
setXiaomiApiKey,
setOpenrouterApiKey,
setLitellmApiKey,
setVercelAiGatewayApiKey,
setTogetherApiKey,
setHuggingfaceApiKey,
setQianfanApiKey,
setQwenApiKey,
setModelStudioApiKey,
setXaiApiKey,
setMistralApiKey,
setKilocodeApiKey,
};
export async function setMinimaxApiKey(
key: SecretInput,
agentDir?: string,
profileId: string = "minimax:default",
options?: ApiKeyStorageOptions,
) {
const provider = profileId.split(":")[0] ?? "minimax";
upsertProviderApiKeyProfile({ provider, key, agentDir, options, profileId });
}
export async function setCloudflareAiGatewayConfig(
accountId: string,
gatewayId: string,
apiKey: SecretInput,
agentDir?: string,
options?: ApiKeyStorageOptions,
) {
const normalizedAccountId = accountId.trim();
const normalizedGatewayId = gatewayId.trim();
upsertProviderApiKeyProfile({
provider: "cloudflare-ai-gateway",
key: apiKey,
agentDir,
options,
metadata: {
accountId: normalizedAccountId,
gatewayId: normalizedGatewayId,
},
});
}
export async function setOpencodeZenApiKey(
key: SecretInput,
agentDir?: string,
options?: ApiKeyStorageOptions,
) {
await setSharedOpencodeApiKey(key, agentDir, options);
}
export async function setOpencodeGoApiKey(
key: SecretInput,
agentDir?: string,
options?: ApiKeyStorageOptions,
) {
await setSharedOpencodeApiKey(key, agentDir, options);
}
async function setSharedOpencodeApiKey(
key: SecretInput,
agentDir?: string,
options?: ApiKeyStorageOptions,
) {
for (const provider of ["opencode", "opencode-go"] as const) {
upsertProviderApiKeyProfile({ provider, key, agentDir, options });
}
}