wizard: add explicit skip option to plugin setup (#63436)

* Wizard: allow skipping plugin setup

* Agents: reset nodes tool test modules
This commit is contained in:
pashpashpash
2026-04-08 18:35:39 -07:00
committed by GitHub
parent 5b28ab83ef
commit 0faae33b0c
3 changed files with 73 additions and 6 deletions

View File

@@ -105,6 +105,9 @@ function expectNodePairApproveScopes(scopes: string[]): void {
describe("createNodesTool screen_record duration guardrails", () => {
beforeAll(async () => {
// The agents lane runs on the shared non-isolated runner, so clear any
// cached prior import before wiring this file's gateway/media mocks.
vi.resetModules();
({ createNodesTool } = await import("./nodes-tool.js"));
});

View File

@@ -215,6 +215,63 @@ describe("discoverUnconfiguredPlugins", () => {
});
describe("setupPluginConfig", () => {
it("allows skipping plugin setup from the multiselect prompt", async () => {
loadPluginManifestRegistry.mockReturnValue({
plugins: [
{
...makeManifestPlugin("device-pairing", {
enabled: { label: "Enable pairing" },
}),
enabledByDefault: true,
},
],
});
const note = vi.fn(async () => {});
const select = vi.fn(async () => {
throw new Error("select should not run when plugin setup is skipped");
});
const text = vi.fn(async () => {
throw new Error("text should not run when plugin setup is skipped");
});
const confirm = vi.fn(async () => {
throw new Error("confirm should not run when plugin setup is skipped");
});
const result = await setupPluginConfig({
config: {
plugins: {
entries: {
"device-pairing": {
enabled: true,
},
},
},
},
prompter: {
intro: vi.fn(async () => {}),
outro: vi.fn(async () => {}),
note,
select: select as unknown as WizardPrompter["select"],
multiselect: vi.fn(async () => ["__skip__"]) as unknown as WizardPrompter["multiselect"],
text,
confirm,
progress: vi.fn(() => ({ update: vi.fn(), stop: vi.fn() })),
},
});
expect(result).toEqual({
plugins: {
entries: {
"device-pairing": {
enabled: true,
},
},
},
});
expect(note).not.toHaveBeenCalled();
});
it("writes dotted uiHint values into nested plugin config", async () => {
loadPluginManifestRegistry.mockReturnValue({
plugins: [

View File

@@ -311,15 +311,22 @@ export async function setupPluginConfig(params: {
const selected = await params.prompter.multiselect({
message: "Configure plugins (select to set up now, or skip)",
options: unconfigured.map((p) => ({
value: p.id,
label: p.name,
hint: `${Object.keys(p.uiHints).length} field${Object.keys(p.uiHints).length === 1 ? "" : "s"}`,
})),
options: [
{
value: "__skip__",
label: "Skip for now",
hint: "Continue without configuring plugins",
},
...unconfigured.map((p) => ({
value: p.id,
label: p.name,
hint: `${Object.keys(p.uiHints).length} field${Object.keys(p.uiHints).length === 1 ? "" : "s"}`,
})),
],
});
let config = params.config;
for (const pluginId of selected) {
for (const pluginId of selected.filter((value) => value !== "__skip__")) {
const plugin = unconfigured.find((p) => p.id === pluginId);
if (!plugin) {
continue;