From 9fd0f7cd349dc6dec03508395db5c3d3226963d2 Mon Sep 17 00:00:00 2001 From: Patrick Erichsen Date: Mon, 20 Apr 2026 19:42:41 -0700 Subject: [PATCH] wizard: support searchable select, restore hint in search haystack --- src/commands/auth-choice-prompt.ts | 1 + src/flows/channel-setup.ts | 1 + src/wizard/clack-prompter.ts | 35 +++++++++++++++++++++++------- src/wizard/prompts.ts | 1 + 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/commands/auth-choice-prompt.ts b/src/commands/auth-choice-prompt.ts index e3d360376ee..e50d58da784 100644 --- a/src/commands/auth-choice-prompt.ts +++ b/src/commands/auth-choice-prompt.ts @@ -30,6 +30,7 @@ export async function promptAuthChoiceGrouped(params: { const providerSelection = (await params.prompter.select({ message: "Model/auth provider", options: providerOptions, + searchable: true, })) as string; if (providerSelection === "skip") { diff --git a/src/flows/channel-setup.ts b/src/flows/channel-setup.ts index 6faf4160430..08da270bf7e 100644 --- a/src/flows/channel-setup.ts +++ b/src/flows/channel-setup.ts @@ -598,6 +598,7 @@ export async function setupChannels( }, ], initialValue: quickstartDefault, + searchable: true, }); if (choice !== "__skip__") { await handleChannelChoice(choice); diff --git a/src/wizard/clack-prompter.ts b/src/wizard/clack-prompter.ts index 26addff29c0..7ffcf01bf37 100644 --- a/src/wizard/clack-prompter.ts +++ b/src/wizard/clack-prompter.ts @@ -1,4 +1,5 @@ import { + autocomplete, autocompleteMultiselect, cancel, confirm, @@ -62,17 +63,31 @@ export function createClackPrompter(): WizardPrompter { note: async (message, title) => { emitNote(message, title); }, - select: async (params) => - guardCancel( + select: async (params) => { + const options = params.options.map((opt) => { + const base = { value: opt.value, label: opt.label }; + return opt.hint === undefined ? base : { ...base, hint: stylePromptHint(opt.hint) }; + }) as Option<(typeof params.options)[number]["value"]>[]; + + if (params.searchable) { + return guardCancel( + await autocomplete({ + message: stylePromptMessage(params.message), + options, + initialValue: params.initialValue, + filter: tokenizedOptionFilter, + }), + ); + } + + return guardCancel( await select({ message: stylePromptMessage(params.message), - options: params.options.map((opt) => { - const base = { value: opt.value, label: opt.label }; - return opt.hint === undefined ? base : { ...base, hint: stylePromptHint(opt.hint) }; - }) as Option<(typeof params.options)[number]["value"]>[], + options, initialValue: params.initialValue, }), - ), + ); + }, multiselect: async (params) => { const options = params.options.map((opt) => { const base = { value: opt.value, label: opt.label }; @@ -132,7 +147,11 @@ export function createClackPrompter(): WizardPrompter { }, stop: (message) => { osc.done(); - spin.stop(message); + if (message === undefined) { + spin.clear(); + } else { + spin.stop(message); + } }, }; }, diff --git a/src/wizard/prompts.ts b/src/wizard/prompts.ts index 9d90a6f23d0..1b620ea545c 100644 --- a/src/wizard/prompts.ts +++ b/src/wizard/prompts.ts @@ -8,6 +8,7 @@ export type WizardSelectParams = { message: string; options: Array>; initialValue?: T; + searchable?: boolean; }; export type WizardMultiSelectParams = {