Onboard: move volcengine/byteplus auth from .env to profiles
This commit is contained in:
committed by
Peter Steinberger
parent
2ef109f00a
commit
59e5f12bf9
@@ -1,5 +1,4 @@
|
||||
import { resolveEnvApiKey } from "../agents/model-auth.js";
|
||||
import { upsertSharedEnvVar } from "../infra/env-file.js";
|
||||
import {
|
||||
formatApiKeyPreview,
|
||||
normalizeApiKeyInput,
|
||||
@@ -7,6 +6,7 @@ import {
|
||||
} from "./auth-choice.api-key.js";
|
||||
import type { ApplyAuthChoiceParams, ApplyAuthChoiceResult } from "./auth-choice.apply.js";
|
||||
import { applyPrimaryModel } from "./model-picker.js";
|
||||
import { applyAuthProfileConfig, setByteplusApiKey } from "./onboard-auth.js";
|
||||
|
||||
/** Default model for BytePlus auth onboarding. */
|
||||
export const BYTEPLUS_DEFAULT_MODEL = "byteplus-plan/ark-code-latest";
|
||||
@@ -25,18 +25,13 @@ export async function applyAuthChoiceBytePlus(
|
||||
initialValue: true,
|
||||
});
|
||||
if (useExisting) {
|
||||
const result = upsertSharedEnvVar({
|
||||
key: "BYTEPLUS_API_KEY",
|
||||
value: envKey.apiKey,
|
||||
await setByteplusApiKey(envKey.apiKey, params.agentDir);
|
||||
const configWithAuth = applyAuthProfileConfig(params.config, {
|
||||
profileId: "byteplus:default",
|
||||
provider: "byteplus",
|
||||
mode: "api_key",
|
||||
});
|
||||
if (!process.env.BYTEPLUS_API_KEY) {
|
||||
process.env.BYTEPLUS_API_KEY = envKey.apiKey;
|
||||
}
|
||||
await params.prompter.note(
|
||||
`Copied BYTEPLUS_API_KEY to ${result.path} for launchd compatibility.`,
|
||||
"BytePlus API key",
|
||||
);
|
||||
const configWithModel = applyPrimaryModel(params.config, BYTEPLUS_DEFAULT_MODEL);
|
||||
const configWithModel = applyPrimaryModel(configWithAuth, BYTEPLUS_DEFAULT_MODEL);
|
||||
return {
|
||||
config: configWithModel,
|
||||
agentModelOverride: BYTEPLUS_DEFAULT_MODEL,
|
||||
@@ -55,17 +50,13 @@ export async function applyAuthChoiceBytePlus(
|
||||
}
|
||||
|
||||
const trimmed = normalizeApiKeyInput(String(key));
|
||||
const result = upsertSharedEnvVar({
|
||||
key: "BYTEPLUS_API_KEY",
|
||||
value: trimmed,
|
||||
await setByteplusApiKey(trimmed, params.agentDir);
|
||||
const configWithAuth = applyAuthProfileConfig(params.config, {
|
||||
profileId: "byteplus:default",
|
||||
provider: "byteplus",
|
||||
mode: "api_key",
|
||||
});
|
||||
process.env.BYTEPLUS_API_KEY = trimmed;
|
||||
await params.prompter.note(
|
||||
`Saved BYTEPLUS_API_KEY to ${result.path} for launchd compatibility.`,
|
||||
"BytePlus API key",
|
||||
);
|
||||
|
||||
const configWithModel = applyPrimaryModel(params.config, BYTEPLUS_DEFAULT_MODEL);
|
||||
const configWithModel = applyPrimaryModel(configWithAuth, BYTEPLUS_DEFAULT_MODEL);
|
||||
return {
|
||||
config: configWithModel,
|
||||
agentModelOverride: BYTEPLUS_DEFAULT_MODEL,
|
||||
|
||||
129
src/commands/auth-choice.apply.volcengine-byteplus.test.ts
Normal file
129
src/commands/auth-choice.apply.volcengine-byteplus.test.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { applyAuthChoiceBytePlus } from "./auth-choice.apply.byteplus.js";
|
||||
import { applyAuthChoiceVolcengine } from "./auth-choice.apply.volcengine.js";
|
||||
import {
|
||||
createAuthTestLifecycle,
|
||||
createExitThrowingRuntime,
|
||||
createWizardPrompter,
|
||||
readAuthProfilesForAgent,
|
||||
setupAuthTestEnv,
|
||||
} from "./test-wizard-helpers.js";
|
||||
|
||||
describe("volcengine/byteplus auth choice", () => {
|
||||
const lifecycle = createAuthTestLifecycle([
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_AGENT_DIR",
|
||||
"PI_CODING_AGENT_DIR",
|
||||
"VOLCANO_ENGINE_API_KEY",
|
||||
"BYTEPLUS_API_KEY",
|
||||
]);
|
||||
|
||||
async function setupTempState() {
|
||||
const env = await setupAuthTestEnv("openclaw-volc-byte-");
|
||||
lifecycle.setStateDir(env.stateDir);
|
||||
return env.agentDir;
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
await lifecycle.cleanup();
|
||||
});
|
||||
|
||||
it("stores volcengine env key as keyRef and configures auth profile", async () => {
|
||||
const agentDir = await setupTempState();
|
||||
process.env.VOLCANO_ENGINE_API_KEY = "volc-env-key";
|
||||
|
||||
const prompter = createWizardPrompter(
|
||||
{
|
||||
confirm: vi.fn(async () => true),
|
||||
text: vi.fn(async () => "unused"),
|
||||
},
|
||||
{ defaultSelect: "" },
|
||||
);
|
||||
const runtime = createExitThrowingRuntime();
|
||||
|
||||
const result = await applyAuthChoiceVolcengine({
|
||||
authChoice: "volcengine-api-key",
|
||||
config: {},
|
||||
prompter,
|
||||
runtime,
|
||||
setDefaultModel: true,
|
||||
});
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.config.auth?.profiles?.["volcengine:default"]).toMatchObject({
|
||||
provider: "volcengine",
|
||||
mode: "api_key",
|
||||
});
|
||||
|
||||
const parsed = await readAuthProfilesForAgent<{
|
||||
profiles?: Record<string, { key?: string; keyRef?: unknown }>;
|
||||
}>(agentDir);
|
||||
expect(parsed.profiles?.["volcengine:default"]).toMatchObject({
|
||||
keyRef: { source: "env", id: "VOLCANO_ENGINE_API_KEY" },
|
||||
});
|
||||
expect(parsed.profiles?.["volcengine:default"]?.key).toBeUndefined();
|
||||
});
|
||||
|
||||
it("stores byteplus env key as keyRef and configures auth profile", async () => {
|
||||
const agentDir = await setupTempState();
|
||||
process.env.BYTEPLUS_API_KEY = "byte-env-key";
|
||||
|
||||
const prompter = createWizardPrompter(
|
||||
{
|
||||
confirm: vi.fn(async () => true),
|
||||
text: vi.fn(async () => "unused"),
|
||||
},
|
||||
{ defaultSelect: "" },
|
||||
);
|
||||
const runtime = createExitThrowingRuntime();
|
||||
|
||||
const result = await applyAuthChoiceBytePlus({
|
||||
authChoice: "byteplus-api-key",
|
||||
config: {},
|
||||
prompter,
|
||||
runtime,
|
||||
setDefaultModel: true,
|
||||
});
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.config.auth?.profiles?.["byteplus:default"]).toMatchObject({
|
||||
provider: "byteplus",
|
||||
mode: "api_key",
|
||||
});
|
||||
|
||||
const parsed = await readAuthProfilesForAgent<{
|
||||
profiles?: Record<string, { key?: string; keyRef?: unknown }>;
|
||||
}>(agentDir);
|
||||
expect(parsed.profiles?.["byteplus:default"]).toMatchObject({
|
||||
keyRef: { source: "env", id: "BYTEPLUS_API_KEY" },
|
||||
});
|
||||
expect(parsed.profiles?.["byteplus:default"]?.key).toBeUndefined();
|
||||
});
|
||||
|
||||
it("stores explicit volcengine key when env is not used", async () => {
|
||||
const agentDir = await setupTempState();
|
||||
const prompter = createWizardPrompter(
|
||||
{
|
||||
confirm: vi.fn(async () => false),
|
||||
text: vi.fn(async () => "volc-manual-key"),
|
||||
},
|
||||
{ defaultSelect: "" },
|
||||
);
|
||||
const runtime = createExitThrowingRuntime();
|
||||
|
||||
const result = await applyAuthChoiceVolcengine({
|
||||
authChoice: "volcengine-api-key",
|
||||
config: {},
|
||||
prompter,
|
||||
runtime,
|
||||
setDefaultModel: true,
|
||||
});
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
const parsed = await readAuthProfilesForAgent<{
|
||||
profiles?: Record<string, { key?: string; keyRef?: unknown }>;
|
||||
}>(agentDir);
|
||||
expect(parsed.profiles?.["volcengine:default"]?.key).toBe("volc-manual-key");
|
||||
expect(parsed.profiles?.["volcengine:default"]?.keyRef).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,4 @@
|
||||
import { resolveEnvApiKey } from "../agents/model-auth.js";
|
||||
import { upsertSharedEnvVar } from "../infra/env-file.js";
|
||||
import {
|
||||
formatApiKeyPreview,
|
||||
normalizeApiKeyInput,
|
||||
@@ -7,6 +6,7 @@ import {
|
||||
} from "./auth-choice.api-key.js";
|
||||
import type { ApplyAuthChoiceParams, ApplyAuthChoiceResult } from "./auth-choice.apply.js";
|
||||
import { applyPrimaryModel } from "./model-picker.js";
|
||||
import { applyAuthProfileConfig, setVolcengineApiKey } from "./onboard-auth.js";
|
||||
|
||||
/** Default model for Volcano Engine auth onboarding. */
|
||||
export const VOLCENGINE_DEFAULT_MODEL = "volcengine-plan/ark-code-latest";
|
||||
@@ -25,18 +25,13 @@ export async function applyAuthChoiceVolcengine(
|
||||
initialValue: true,
|
||||
});
|
||||
if (useExisting) {
|
||||
const result = upsertSharedEnvVar({
|
||||
key: "VOLCANO_ENGINE_API_KEY",
|
||||
value: envKey.apiKey,
|
||||
await setVolcengineApiKey(envKey.apiKey, params.agentDir);
|
||||
const configWithAuth = applyAuthProfileConfig(params.config, {
|
||||
profileId: "volcengine:default",
|
||||
provider: "volcengine",
|
||||
mode: "api_key",
|
||||
});
|
||||
if (!process.env.VOLCANO_ENGINE_API_KEY) {
|
||||
process.env.VOLCANO_ENGINE_API_KEY = envKey.apiKey;
|
||||
}
|
||||
await params.prompter.note(
|
||||
`Copied VOLCANO_ENGINE_API_KEY to ${result.path} for launchd compatibility.`,
|
||||
"Volcano Engine API Key",
|
||||
);
|
||||
const configWithModel = applyPrimaryModel(params.config, VOLCENGINE_DEFAULT_MODEL);
|
||||
const configWithModel = applyPrimaryModel(configWithAuth, VOLCENGINE_DEFAULT_MODEL);
|
||||
return {
|
||||
config: configWithModel,
|
||||
agentModelOverride: VOLCENGINE_DEFAULT_MODEL,
|
||||
@@ -55,17 +50,13 @@ export async function applyAuthChoiceVolcengine(
|
||||
}
|
||||
|
||||
const trimmed = normalizeApiKeyInput(String(key));
|
||||
const result = upsertSharedEnvVar({
|
||||
key: "VOLCANO_ENGINE_API_KEY",
|
||||
value: trimmed,
|
||||
await setVolcengineApiKey(trimmed, params.agentDir);
|
||||
const configWithAuth = applyAuthProfileConfig(params.config, {
|
||||
profileId: "volcengine:default",
|
||||
provider: "volcengine",
|
||||
mode: "api_key",
|
||||
});
|
||||
process.env.VOLCANO_ENGINE_API_KEY = trimmed;
|
||||
await params.prompter.note(
|
||||
`Saved VOLCANO_ENGINE_API_KEY to ${result.path} for launchd compatibility.`,
|
||||
"Volcano Engine API Key",
|
||||
);
|
||||
|
||||
const configWithModel = applyPrimaryModel(params.config, VOLCENGINE_DEFAULT_MODEL);
|
||||
const configWithModel = applyPrimaryModel(configWithAuth, VOLCENGINE_DEFAULT_MODEL);
|
||||
return {
|
||||
config: configWithModel,
|
||||
agentModelOverride: VOLCENGINE_DEFAULT_MODEL,
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import {
|
||||
setByteplusApiKey,
|
||||
setCloudflareAiGatewayConfig,
|
||||
setMoonshotApiKey,
|
||||
setOpenaiApiKey,
|
||||
setVolcengineApiKey,
|
||||
} from "./onboard-auth.js";
|
||||
import {
|
||||
createAuthTestLifecycle,
|
||||
@@ -18,6 +20,8 @@ describe("onboard auth credentials secret refs", () => {
|
||||
"MOONSHOT_API_KEY",
|
||||
"OPENAI_API_KEY",
|
||||
"CLOUDFLARE_AI_GATEWAY_API_KEY",
|
||||
"VOLCANO_ENGINE_API_KEY",
|
||||
"BYTEPLUS_API_KEY",
|
||||
]);
|
||||
|
||||
afterEach(async () => {
|
||||
@@ -137,4 +141,28 @@ describe("onboard auth credentials secret refs", () => {
|
||||
});
|
||||
expect(parsed.profiles?.["openai:default"]?.key).toBeUndefined();
|
||||
});
|
||||
|
||||
it("stores env-backed volcengine and byteplus keys as keyRef", async () => {
|
||||
const env = await setupAuthTestEnv("openclaw-onboard-auth-credentials-volc-byte-");
|
||||
lifecycle.setStateDir(env.stateDir);
|
||||
process.env.VOLCANO_ENGINE_API_KEY = "volcengine-secret";
|
||||
process.env.BYTEPLUS_API_KEY = "byteplus-secret";
|
||||
|
||||
await setVolcengineApiKey("volcengine-secret");
|
||||
await setByteplusApiKey("byteplus-secret");
|
||||
|
||||
const parsed = await readAuthProfilesForAgent<{
|
||||
profiles?: Record<string, { key?: string; keyRef?: unknown }>;
|
||||
}>(env.agentDir);
|
||||
|
||||
expect(parsed.profiles?.["volcengine:default"]).toMatchObject({
|
||||
keyRef: { source: "env", id: "VOLCANO_ENGINE_API_KEY" },
|
||||
});
|
||||
expect(parsed.profiles?.["volcengine:default"]?.key).toBeUndefined();
|
||||
|
||||
expect(parsed.profiles?.["byteplus:default"]).toMatchObject({
|
||||
keyRef: { source: "env", id: "BYTEPLUS_API_KEY" },
|
||||
});
|
||||
expect(parsed.profiles?.["byteplus:default"]?.key).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -64,6 +64,7 @@ export {
|
||||
setOpenaiApiKey,
|
||||
setAnthropicApiKey,
|
||||
setCloudflareAiGatewayConfig,
|
||||
setByteplusApiKey,
|
||||
setQianfanApiKey,
|
||||
setGeminiApiKey,
|
||||
setKilocodeApiKey,
|
||||
@@ -80,6 +81,7 @@ export {
|
||||
setVeniceApiKey,
|
||||
setVercelAiGatewayApiKey,
|
||||
setXiaomiApiKey,
|
||||
setVolcengineApiKey,
|
||||
setZaiApiKey,
|
||||
setXaiApiKey,
|
||||
writeOAuthCredentials,
|
||||
|
||||
@@ -2,9 +2,7 @@ import { upsertAuthProfile } from "../../../agents/auth-profiles.js";
|
||||
import { normalizeProviderId } from "../../../agents/model-selection.js";
|
||||
import { parseDurationMs } from "../../../cli/parse-duration.js";
|
||||
import type { OpenClawConfig } from "../../../config/config.js";
|
||||
import { upsertSharedEnvVar } from "../../../infra/env-file.js";
|
||||
import type { RuntimeEnv } from "../../../runtime.js";
|
||||
import { shortenHomePath } from "../../../utils.js";
|
||||
import { normalizeSecretInput } from "../../../utils/normalize-secret-input.js";
|
||||
import { buildTokenProfileId, validateAnthropicSetupToken } from "../../auth-token.js";
|
||||
import { applyGoogleGeminiModelDefault } from "../../google-gemini-model-default.js";
|
||||
@@ -34,6 +32,7 @@ import {
|
||||
applyZaiConfig,
|
||||
setAnthropicApiKey,
|
||||
setCloudflareAiGatewayConfig,
|
||||
setByteplusApiKey,
|
||||
setQianfanApiKey,
|
||||
setGeminiApiKey,
|
||||
setKilocodeApiKey,
|
||||
@@ -46,6 +45,7 @@ import {
|
||||
setOpencodeZenApiKey,
|
||||
setOpenrouterApiKey,
|
||||
setSyntheticApiKey,
|
||||
setVolcengineApiKey,
|
||||
setXaiApiKey,
|
||||
setVeniceApiKey,
|
||||
setTogetherApiKey,
|
||||
@@ -344,14 +344,12 @@ export async function applyNonInteractiveAuthChoice(params: {
|
||||
if (!resolved) {
|
||||
return null;
|
||||
}
|
||||
if (resolved.source !== "profile") {
|
||||
const result = upsertSharedEnvVar({
|
||||
key: "VOLCANO_ENGINE_API_KEY",
|
||||
value: resolved.key,
|
||||
});
|
||||
process.env.VOLCANO_ENGINE_API_KEY = resolved.key;
|
||||
runtime.log(`Saved VOLCANO_ENGINE_API_KEY to ${shortenHomePath(result.path)}`);
|
||||
}
|
||||
await setVolcengineApiKey(resolved.key);
|
||||
nextConfig = applyAuthProfileConfig(nextConfig, {
|
||||
profileId: "volcengine:default",
|
||||
provider: "volcengine",
|
||||
mode: "api_key",
|
||||
});
|
||||
return applyPrimaryModel(nextConfig, "volcengine-plan/ark-code-latest");
|
||||
}
|
||||
|
||||
@@ -367,14 +365,12 @@ export async function applyNonInteractiveAuthChoice(params: {
|
||||
if (!resolved) {
|
||||
return null;
|
||||
}
|
||||
if (resolved.source !== "profile") {
|
||||
const result = upsertSharedEnvVar({
|
||||
key: "BYTEPLUS_API_KEY",
|
||||
value: resolved.key,
|
||||
});
|
||||
process.env.BYTEPLUS_API_KEY = resolved.key;
|
||||
runtime.log(`Saved BYTEPLUS_API_KEY to ${shortenHomePath(result.path)}`);
|
||||
}
|
||||
await setByteplusApiKey(resolved.key);
|
||||
nextConfig = applyAuthProfileConfig(nextConfig, {
|
||||
profileId: "byteplus:default",
|
||||
provider: "byteplus",
|
||||
mode: "api_key",
|
||||
});
|
||||
return applyPrimaryModel(nextConfig, "byteplus-plan/ark-code-latest");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user