fix(onboarding): hide image-only auth providers

This commit is contained in:
Vincent Koc
2026-03-21 07:42:32 -07:00
parent f10d054745
commit a3a5cad7d7
11 changed files with 158 additions and 16 deletions

View File

@@ -48,8 +48,15 @@ export type PluginManifestProviderAuthChoice = {
cliFlag?: string;
cliOption?: string;
cliDescription?: string;
/**
* Interactive onboarding surfaces where this auth choice should appear.
* Defaults to `["text-inference"]` when omitted.
*/
onboardingScopes?: PluginManifestOnboardingScope[];
};
export type PluginManifestOnboardingScope = "text-inference" | "image-generation";
export type PluginManifestLoadResult =
| { ok: true; manifest: PluginManifest; manifestPath: string }
| { ok: false; error: string; manifestPath: string };
@@ -107,6 +114,10 @@ function normalizeProviderAuthChoices(
const cliOption = typeof entry.cliOption === "string" ? entry.cliOption.trim() : "";
const cliDescription =
typeof entry.cliDescription === "string" ? entry.cliDescription.trim() : "";
const onboardingScopes = normalizeStringList(entry.onboardingScopes).filter(
(scope): scope is PluginManifestOnboardingScope =>
scope === "text-inference" || scope === "image-generation",
);
normalized.push({
provider,
method,
@@ -120,6 +131,7 @@ function normalizeProviderAuthChoices(
...(cliFlag ? { cliFlag } : {}),
...(cliOption ? { cliOption } : {}),
...(cliDescription ? { cliDescription } : {}),
...(onboardingScopes.length > 0 ? { onboardingScopes } : {}),
});
}
return normalized.length > 0 ? normalized : undefined;

View File

@@ -24,6 +24,7 @@ describe("provider auth choice manifest helpers", () => {
method: "api-key",
choiceId: "openai-api-key",
choiceLabel: "OpenAI API key",
onboardingScopes: ["text-inference"],
optionKey: "openaiApiKey",
cliFlag: "--openai-api-key",
cliOption: "--openai-api-key <key>",
@@ -40,6 +41,7 @@ describe("provider auth choice manifest helpers", () => {
methodId: "api-key",
choiceId: "openai-api-key",
choiceLabel: "OpenAI API key",
onboardingScopes: ["text-inference"],
optionKey: "openaiApiKey",
cliFlag: "--openai-api-key",
cliOption: "--openai-api-key <key>",

View File

@@ -16,6 +16,7 @@ export type ProviderAuthChoiceMetadata = {
cliFlag?: string;
cliOption?: string;
cliDescription?: string;
onboardingScopes?: ("text-inference" | "image-generation")[];
};
export type ProviderOnboardAuthFlag = {
@@ -52,6 +53,7 @@ export function resolveManifestProviderAuthChoices(params?: {
...(choice.cliFlag ? { cliFlag: choice.cliFlag } : {}),
...(choice.cliOption ? { cliOption: choice.cliOption } : {}),
...(choice.cliDescription ? { cliDescription: choice.cliDescription } : {}),
...(choice.onboardingScopes ? { onboardingScopes: choice.onboardingScopes } : {}),
})),
);
}

View File

@@ -27,6 +27,20 @@ function normalizeTextList(values: string[] | undefined): string[] | undefined {
return normalized.length > 0 ? normalized : undefined;
}
function normalizeOnboardingScopes(
values: Array<"text-inference" | "image-generation"> | undefined,
): Array<"text-inference" | "image-generation"> | undefined {
const normalized = Array.from(
new Set(
(values ?? []).filter(
(value): value is "text-inference" | "image-generation" =>
value === "text-inference" || value === "image-generation",
),
),
);
return normalized.length > 0 ? normalized : undefined;
}
function normalizeProviderWizardSetup(params: {
providerId: string;
pluginId: string;
@@ -79,6 +93,9 @@ function normalizeProviderWizardSetup(params: {
? { groupHint: normalizeText(params.setup.groupHint) }
: {}),
...(methodId && params.auth.some((method) => method.id === methodId) ? { methodId } : {}),
...(normalizeOnboardingScopes(params.setup.onboardingScopes)
? { onboardingScopes: normalizeOnboardingScopes(params.setup.onboardingScopes) }
: {}),
...(params.setup.modelAllowlist
? {
modelAllowlist: {

View File

@@ -79,6 +79,7 @@ describe("provider wizard boundaries", () => {
choiceLabel: "OpenAI API key",
groupId: "openai",
groupLabel: "OpenAI",
onboardingScopes: ["text-inference"],
},
run: vi.fn(),
},
@@ -92,6 +93,7 @@ describe("provider wizard boundaries", () => {
label: "OpenAI API key",
groupId: "openai",
groupLabel: "OpenAI",
onboardingScopes: ["text-inference"],
},
]);
expect(
@@ -106,6 +108,39 @@ describe("provider wizard boundaries", () => {
});
});
it("preserves onboarding scopes on wizard options", () => {
const provider = makeProvider({
id: "fal",
label: "fal",
auth: [
{
id: "api-key",
label: "fal API key",
kind: "api_key",
wizard: {
choiceId: "fal-api-key",
choiceLabel: "fal API key",
groupId: "fal",
groupLabel: "fal",
onboardingScopes: ["image-generation"],
},
run: vi.fn(),
},
],
});
resolvePluginProviders.mockReturnValue([provider]);
expect(resolveProviderWizardOptions({})).toEqual([
{
value: "fal-api-key",
label: "fal API key",
groupId: "fal",
groupLabel: "fal",
onboardingScopes: ["image-generation"],
},
]);
});
it("returns method wizard metadata for canonical choices", () => {
const provider = makeProvider({
id: "anthropic",

View File

@@ -20,6 +20,7 @@ export type ProviderWizardOption = {
groupId: string;
groupLabel: string;
groupHint?: string;
onboardingScopes?: Array<"text-inference" | "image-generation">;
};
export type ProviderModelPickerEntry = {
@@ -88,6 +89,7 @@ function buildSetupOptionForMethod(params: {
groupId: normalizedGroupId,
groupLabel: params.wizard.groupLabel?.trim() || params.provider.label,
groupHint: params.wizard.groupHint?.trim(),
...(params.wizard.onboardingScopes ? { onboardingScopes: params.wizard.onboardingScopes } : {}),
};
}

View File

@@ -593,6 +593,11 @@ export type ProviderPluginWizardSetup = {
groupLabel?: string;
groupHint?: string;
methodId?: string;
/**
* Interactive onboarding surfaces where this auth choice should appear.
* Defaults to `["text-inference"]` when omitted.
*/
onboardingScopes?: Array<"text-inference" | "image-generation">;
/**
* Optional model-allowlist prompt policy applied after this auth choice is
* selected in configure/onboarding flows.