mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-05 03:31:51 +00:00
fix(onboard): validate reset preflight (#111348)
This commit is contained in:
committed by
GitHub
parent
a868d34804
commit
d4ed08994d
35
src/plugins/provider-api-key-auth.test.ts
Normal file
35
src/plugins/provider-api-key-auth.test.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { createProviderApiKeyAuthMethod } from "./provider-api-key-auth.js";
|
||||
|
||||
describe("createProviderApiKeyAuthMethod", () => {
|
||||
it("exposes side-effect-free non-interactive credential validation", async () => {
|
||||
const method = createProviderApiKeyAuthMethod({
|
||||
providerId: "example",
|
||||
methodId: "api-key",
|
||||
label: "Example",
|
||||
optionKey: "exampleApiKey",
|
||||
flagName: "--example-api-key",
|
||||
envVar: "EXAMPLE_API_KEY",
|
||||
promptMessage: "Example API key",
|
||||
});
|
||||
const resolveApiKey = vi.fn(async () => ({ key: "test-token", source: "flag" as const }));
|
||||
|
||||
const valid = await method.validateNonInteractive?.({
|
||||
authChoice: "example-api-key",
|
||||
config: {},
|
||||
baseConfig: {},
|
||||
opts: { exampleApiKey: "test-token" },
|
||||
runtime: { log: vi.fn(), error: vi.fn(), exit: vi.fn() } as unknown as RuntimeEnv,
|
||||
resolveApiKey,
|
||||
});
|
||||
|
||||
expect(valid).toBe(true);
|
||||
expect(resolveApiKey).toHaveBeenCalledWith({
|
||||
provider: "example",
|
||||
flagValue: "test-token",
|
||||
flagName: "--example-api-key",
|
||||
envVar: "EXAMPLE_API_KEY",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -13,6 +13,10 @@ import type {
|
||||
ProviderPluginWizardSetup,
|
||||
} from "./types.js";
|
||||
|
||||
type ProviderAuthMethodNonInteractiveValidationContext = Parameters<
|
||||
NonNullable<ProviderAuthMethod["validateNonInteractive"]>
|
||||
>[0];
|
||||
|
||||
type ProviderApiKeyAuthMethodOptions = {
|
||||
providerId: string;
|
||||
methodId: string;
|
||||
@@ -107,6 +111,18 @@ async function applyApiKeyConfig(params: {
|
||||
export function createProviderApiKeyAuthMethod(
|
||||
params: ProviderApiKeyAuthMethodOptions,
|
||||
): ProviderAuthMethod {
|
||||
const resolveNonInteractiveCredential = async (
|
||||
ctx: ProviderAuthMethodNonInteractiveValidationContext,
|
||||
) => {
|
||||
const opts = ctx.opts as Record<string, unknown> | undefined;
|
||||
return await ctx.resolveApiKey({
|
||||
provider: params.providerId,
|
||||
flagValue: resolveStringOption(opts, params.optionKey),
|
||||
flagName: params.flagName,
|
||||
envVar: params.envVar,
|
||||
...(params.allowProfile === false ? { allowProfile: false } : {}),
|
||||
});
|
||||
};
|
||||
return {
|
||||
id: params.methodId,
|
||||
label: params.label,
|
||||
@@ -179,15 +195,9 @@ export function createProviderApiKeyAuthMethod(
|
||||
...(params.defaultModel ? { defaultModel: params.defaultModel } : {}),
|
||||
};
|
||||
},
|
||||
validateNonInteractive: async (ctx) => Boolean(await resolveNonInteractiveCredential(ctx)),
|
||||
runNonInteractive: async (ctx) => {
|
||||
const opts = ctx.opts as Record<string, unknown> | undefined;
|
||||
const resolved = await ctx.resolveApiKey({
|
||||
provider: params.providerId,
|
||||
flagValue: resolveStringOption(opts, params.optionKey),
|
||||
flagName: params.flagName,
|
||||
envVar: params.envVar,
|
||||
...(params.allowProfile === false ? { allowProfile: false } : {}),
|
||||
});
|
||||
const resolved = await resolveNonInteractiveCredential(ctx);
|
||||
if (!resolved) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -113,6 +113,11 @@ export type ProviderAuthMethodNonInteractiveContext = {
|
||||
) => ApiKeyCredential | null;
|
||||
};
|
||||
|
||||
type ProviderAuthMethodNonInteractiveValidationContext = Omit<
|
||||
ProviderAuthMethodNonInteractiveContext,
|
||||
"toApiKeyCredential"
|
||||
>;
|
||||
|
||||
/** Read-only context for app-guided discovery of already available inference. */
|
||||
export type ProviderAppGuidedSetupContext = {
|
||||
config: OpenClawConfig;
|
||||
@@ -156,6 +161,10 @@ export type ProviderAuthMethod = {
|
||||
runNonInteractive?: (
|
||||
ctx: ProviderAuthMethodNonInteractiveContext,
|
||||
) => Promise<OpenClawConfig | null>;
|
||||
/** Side-effect-free prerequisite validation used before destructive reset handling. */
|
||||
validateNonInteractive?: (
|
||||
ctx: ProviderAuthMethodNonInteractiveValidationContext,
|
||||
) => Promise<boolean>;
|
||||
/** Provider-owned local model discovery for the shared guided setup ladder. */
|
||||
appGuidedSetup?: ProviderAppGuidedSetup;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user