Onboarding: support plugin-owned interactive channel flows (#27191)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 53872cf8e7
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
This commit is contained in:
Gustavo Madeira Santana
2026-02-26 01:14:57 -05:00
committed by GitHub
parent 39a1c13635
commit f08fe02a1b
6 changed files with 426 additions and 7 deletions

View File

@@ -27,7 +27,9 @@ import {
listChannelOnboardingAdapters,
} from "./onboarding/registry.js";
import type {
ChannelOnboardingConfiguredResult,
ChannelOnboardingDmPolicy,
ChannelOnboardingResult,
ChannelOnboardingStatus,
SetupChannelsOptions,
} from "./onboarding/types.js";
@@ -488,6 +490,26 @@ export async function setupChannels(
return true;
};
const applyOnboardingResult = async (channel: ChannelChoice, result: ChannelOnboardingResult) => {
next = result.cfg;
if (result.accountId) {
recordAccount(channel, result.accountId);
}
addSelection(channel);
await refreshStatus(channel);
};
const applyCustomOnboardingResult = async (
channel: ChannelChoice,
result: ChannelOnboardingConfiguredResult,
) => {
if (result === "skip") {
return false;
}
await applyOnboardingResult(channel, result);
return true;
};
const configureChannel = async (channel: ChannelChoice) => {
const adapter = getChannelOnboardingAdapter(channel);
if (!adapter) {
@@ -503,17 +525,29 @@ export async function setupChannels(
shouldPromptAccountIds,
forceAllowFrom: forceAllowFromChannels.has(channel),
});
next = result.cfg;
if (result.accountId) {
recordAccount(channel, result.accountId);
}
addSelection(channel);
await refreshStatus(channel);
await applyOnboardingResult(channel, result);
};
const handleConfiguredChannel = async (channel: ChannelChoice, label: string) => {
const plugin = getChannelPlugin(channel);
const adapter = getChannelOnboardingAdapter(channel);
if (adapter?.configureWhenConfigured) {
const custom = await adapter.configureWhenConfigured({
cfg: next,
runtime,
prompter,
options,
accountOverrides,
shouldPromptAccountIds,
forceAllowFrom: forceAllowFromChannels.has(channel),
configured: true,
label,
});
if (!(await applyCustomOnboardingResult(channel, custom))) {
return;
}
return;
}
const supportsDisable = Boolean(
options?.allowDisable && (plugin?.config.setAccountEnabled || adapter?.disable),
);
@@ -615,9 +649,27 @@ export async function setupChannels(
}
const plugin = getChannelPlugin(channel);
const adapter = getChannelOnboardingAdapter(channel);
const label = plugin?.meta.label ?? catalogEntry?.meta.label ?? channel;
const status = statusByChannel.get(channel);
const configured = status?.configured ?? false;
if (adapter?.configureInteractive) {
const custom = await adapter.configureInteractive({
cfg: next,
runtime,
prompter,
options,
accountOverrides,
shouldPromptAccountIds,
forceAllowFrom: forceAllowFromChannels.has(channel),
configured,
label,
});
if (!(await applyCustomOnboardingResult(channel, custom))) {
return;
}
return;
}
if (configured) {
await handleConfiguredChannel(channel, label);
return;