Browse Source

feat(cli): enhance welcome flow with interactive model selection (#5084)

* feat(cli): enhance welcome flow with interactive model selection

- Added interactive list selection for providers and models using @inquirer/prompts
- Implemented dynamic model fetching for supported providers (OpenRouter, Ollama, etc.)
- Refactored model fetching logic into reusable fetchRouterModels service
- Made .env file optional for CLI execution
- Improved UI with better list pagination and clearer prompts

* fix(cli): use @inquirer/prompts select for account type prompt

Update promptOrganizationSelection to use select() from @inquirer/prompts
instead of inquirer.prompt() with type: 'list' for consistent rendering
of list choices across all terminal environments.

---------

Co-authored-by: Marius <[email protected]>
Montana Flynn 4 weeks ago
parent
commit
f0c79d27c4

+ 5 - 0
.changeset/cli-model-selection.md

@@ -0,0 +1,5 @@
+---
+"@kilocode/cli": minor
+---
+
+Improved CLI welcome flow: added interactive model selection list using `@inquirer/prompts`, updated provider selection to display a scrollable list, and refactored model fetching logic into a reusable service.

+ 1 - 0
cli/package.json

@@ -39,6 +39,7 @@
 		"@aws-sdk/client-bedrock-runtime": "^3.966.0",
 		"@aws-sdk/credential-providers": "^3.966.0",
 		"@google/genai": "^1.35.0",
+		"@inquirer/prompts": "^8.2.0",
 		"@kilocode/core-schemas": "workspace:^",
 		"@lmstudio/sdk": "^1.5.0",
 		"@mistralai/mistralai": "^1.11.0",

+ 61 - 14
cli/src/auth/index.ts

@@ -1,6 +1,14 @@
-import inquirer from "inquirer"
+import { select } from "@inquirer/prompts"
 import { loadConfig, saveConfig, CLIConfig } from "../config/index.js"
 import { authProviders } from "./providers/index.js"
+import { fetchRouterModels } from "../services/models/fetcher.js"
+import {
+	getModelsByProvider,
+	providerSupportsModelList,
+	getModelIdKey,
+	sortModelsByPreference,
+} from "../constants/providers/models.js"
+import type { ProviderName } from "../types/messages.js"
 import { withRawMode } from "./utils/terminal.js"
 
 /**
@@ -18,19 +26,14 @@ export default async function authWizard(): Promise<void> {
 		}))
 
 		// Prompt user to select a provider
-		// Use withRawMode to ensure arrow key navigation works in list prompts
-		// (required for inquirer v13+ which uses @inquirer/prompts internally)
-		const { selectedProvider } = await withRawMode(() =>
-			inquirer.prompt<{ selectedProvider: string }>([
-				{
-					type: "list",
-					name: "selectedProvider",
-					message: "Please select which provider you would like to use:",
-					choices: providerChoices,
-					loop: false,
-				},
-			]),
-		)
+		const selectedProvider = await withRawMode(() =>
+       select({
+         message: "Select an AI provider:",
+         choices: providerChoices,
+         loop: false,
+         pageSize: process.stdout.rows ? Math.min(20, process.stdout.rows - 2) : 10,
+       })
+     )
 
 		// Find the selected provider
 		const provider = authProviders.find((p) => p.value === selectedProvider)
@@ -52,6 +55,50 @@ export default async function authWizard(): Promise<void> {
 			process.exit(1)
 		}
 
+		// Model Selection
+		const providerId = authResult.providerConfig.provider as ProviderName
+
+		let routerModels = null
+		if (providerSupportsModelList(providerId)) {
+			console.log("\nFetching available models...")
+			try {
+				routerModels = await fetchRouterModels(authResult.providerConfig)
+			} catch (_) {
+				console.warn("Failed to fetch models, using defaults if available.")
+			}
+		}
+
+		const { models, defaultModel } = getModelsByProvider({
+			provider: providerId,
+			routerModels,
+			kilocodeDefaultModel: "",
+		})
+
+		const modelIds = sortModelsByPreference(models)
+
+		if (modelIds.length > 0) {
+			const modelChoices = modelIds.map((id) => {
+				const model = models[id]
+				return {
+					name: model?.displayName || id,
+					value: id,
+				}
+			})
+
+			const selectedModel = await withRawMode(() =>
+         select({
+           message: "Select a model to use:",
+           choices: modelChoices,
+           default: defaultModel,
+           loop: false,
+           pageSize: 10,
+         })
+       )
+
+			const modelKey = getModelIdKey(providerId)
+			authResult.providerConfig[modelKey] = selectedModel
+		}
+
 		// Save the configuration
 		const newConfig: CLIConfig = {
 			...config.config,

+ 6 - 0
cli/src/auth/providers/factory.ts

@@ -3,6 +3,7 @@ import type { ProviderName } from "../../types/messages.js"
 import { PROVIDER_REQUIRED_FIELDS } from "../../constants/providers/validation.js"
 import { FIELD_REGISTRY, isOptionalField, getProviderDefaultModel } from "../../constants/providers/settings.js"
 import { PROVIDER_LABELS } from "../../constants/providers/labels.js"
+import { isModelField } from "../../constants/providers/models.js"
 import inquirer from "inquirer"
 import { withRawMode } from "../utils/terminal.js"
 
@@ -20,6 +21,11 @@ function createGenericAuthFunction(providerName: ProviderName) {
 
 		// Build prompts from required fields
 		for (const field of requiredFields) {
+			// Skip model fields as they are handled by the main auth wizard
+			if (isModelField(field) || field === "apiModelId") {
+				continue
+			}
+
 			const fieldMeta = FIELD_REGISTRY[field]
 			if (!fieldMeta) {
 				// Skip fields without metadata

+ 7 - 11
cli/src/auth/providers/kilocode/shared.ts

@@ -1,7 +1,7 @@
 import { getApiUrl } from "@roo-code/types"
 import { openRouterDefaultModelId } from "@roo-code/types"
 import { z } from "zod"
-import inquirer from "inquirer"
+import { select } from "@inquirer/prompts"
 import { logs } from "../../../services/logs.js"
 import type { KilocodeOrganization, KilocodeProfileData } from "../../types.js"
 import { withRawMode } from "../../utils/terminal.js"
@@ -134,16 +134,12 @@ export async function promptOrganizationSelection(organizations: KilocodeOrganiz
 	]
 
 	// Use withRawMode to ensure arrow key navigation works in list prompts
-	// (required for inquirer v13+ which uses @inquirer/prompts internally)
-	const { accountType } = await withRawMode(() =>
-		inquirer.prompt<{ accountType: string }>([
-			{
-				type: "list",
-				name: "accountType",
-				message: "Select account type:",
-				choices: accountChoices,
-			},
-		]),
+	const accountType = await withRawMode(() =>
+		select({
+			message: "Select account type:",
+			choices: accountChoices,
+			loop: false,
+		}),
 	)
 
 	// Return organization ID if not personal

+ 2 - 109
cli/src/commands/models-api.ts

@@ -39,10 +39,9 @@ import {
 	type ModelInfo,
 	type RouterModels,
 } from "../constants/providers/models.js"
-import type { ProviderName, ExtensionMessage } from "../types/messages.js"
+import type { ProviderName } from "../types/messages.js"
 import type { CLIConfig, ProviderConfig } from "../config/types.js"
-import { createExtensionService, type ExtensionService } from "../services/extension.js"
-import { mapProviderToApiConfig } from "../config/mapper.js"
+import { fetchRouterModels } from "../services/models/fetcher.js"
 
 /**
  * Output format for the models API command
@@ -129,9 +128,6 @@ export function transformModelsToOutput(
 	}
 }
 
-/** Default timeout for router models request (30 seconds) */
-const ROUTER_MODELS_TIMEOUT_MS = 30000
-
 /**
  * Output result as JSON to stdout
  */
@@ -147,109 +143,6 @@ function outputError(message: string, code: string): never {
 	process.exit(1)
 }
 
-/**
- * Fetch router models from the extension
- *
- * This function:
- * 1. Creates an ExtensionService
- * 2. Initializes it (loads and activates the extension)
- * 3. Injects provider configuration
- * 4. Sends requestRouterModels message
- * 5. Waits for routerModels response with timeout
- * 6. Disposes the service
- *
- * @param provider - The provider configuration
- * @param timeoutMs - Timeout in milliseconds (default: 30000)
- * @returns RouterModels or null if fetch failed
- */
-async function fetchRouterModels(
-	provider: ProviderConfig,
-	timeoutMs: number = ROUTER_MODELS_TIMEOUT_MS,
-): Promise<RouterModels | null> {
-	let service: ExtensionService | null = null
-
-	try {
-		logs.info("Initializing extension to fetch router models", "ModelsAPI")
-
-		// Create extension service
-		service = createExtensionService({
-			workspace: process.cwd(),
-		})
-
-		// Initialize the service (loads and activates extension)
-		await service.initialize()
-		logs.debug("Extension service initialized", "ModelsAPI")
-
-		// Wait for the service to be ready
-		if (!service.isReady()) {
-			// Wait for the 'ready' event with timeout
-			await new Promise<void>((resolve, reject) => {
-				const timeout = setTimeout(() => {
-					reject(new Error("Extension service ready timeout"))
-				}, 10000)
-
-				service!.once("ready", () => {
-					clearTimeout(timeout)
-					resolve()
-				})
-			})
-		}
-
-		// Inject provider configuration
-		const apiConfiguration = mapProviderToApiConfig(provider)
-		const extensionHost = service.getExtensionHost()
-		await extensionHost.injectConfiguration({
-			apiConfiguration,
-			currentApiConfigName: provider.id,
-		})
-		logs.debug("Provider configuration injected", "ModelsAPI")
-
-		// Create a promise that resolves when we receive routerModels
-		const routerModelsPromise = new Promise<RouterModels | null>((resolve, reject) => {
-			const timeout = setTimeout(() => {
-				reject(new Error(`Router models request timed out after ${timeoutMs}ms`))
-			}, timeoutMs)
-
-			const messageHandler = (message: ExtensionMessage) => {
-				if (message.type === "routerModels" && message.routerModels) {
-					clearTimeout(timeout)
-					service!.off("message", messageHandler)
-					resolve(message.routerModels as RouterModels)
-				}
-			}
-
-			service!.on("message", messageHandler)
-		})
-
-		// Send requestRouterModels message
-		await service.sendWebviewMessage({
-			type: "requestRouterModels",
-		})
-		logs.debug("Sent requestRouterModels message", "ModelsAPI")
-
-		// Wait for response
-		const routerModels = await routerModelsPromise
-		logs.info("Received router models", "ModelsAPI", {
-			providerCount: routerModels ? Object.keys(routerModels).length : 0,
-		})
-
-		return routerModels
-	} catch (error) {
-		logs.error("Failed to fetch router models", "ModelsAPI", { error })
-		return null
-	} finally {
-		// Always dispose the service
-		if (service) {
-			try {
-				await service.dispose()
-				logs.debug("Extension service disposed", "ModelsAPI")
-			} catch (disposeError) {
-				logs.warn("Error disposing extension service", "ModelsAPI", { error: disposeError })
-			}
-		}
-	}
-}
-
 /**
  * Main models API command handler
  *

+ 111 - 0
cli/src/services/models/fetcher.ts

@@ -0,0 +1,111 @@
+import { logs } from "../../services/logs.js"
+import { createExtensionService, type ExtensionService } from "../../services/extension.js"
+import { mapProviderToApiConfig } from "../../config/mapper.js"
+import type { ProviderConfig } from "../../config/types.js"
+import type { RouterModels, ExtensionMessage } from "../../types/messages.js"
+
+/** Default timeout for router models request (30 seconds) */
+const ROUTER_MODELS_TIMEOUT_MS = 30000
+
+/**
+ * Fetch router models from the extension
+ *
+ * This function:
+ * 1. Creates an ExtensionService
+ * 2. Initializes it (loads and activates the extension)
+ * 3. Injects provider configuration
+ * 4. Sends requestRouterModels message
+ * 5. Waits for routerModels response with timeout
+ * 6. Disposes the service
+ *
+ * @param provider - The provider configuration
+ * @param timeoutMs - Timeout in milliseconds (default: 30000)
+ * @returns RouterModels or null if fetch failed
+ */
+export async function fetchRouterModels(
+	provider: ProviderConfig,
+	timeoutMs: number = ROUTER_MODELS_TIMEOUT_MS,
+): Promise<RouterModels | null> {
+	let service: ExtensionService | null = null
+
+	try {
+		logs.info("Initializing extension to fetch router models", "ModelFetcher")
+
+		// Create extension service
+		service = createExtensionService({
+			workspace: process.cwd(),
+		})
+
+		// Initialize the service (loads and activates extension)
+		await service.initialize()
+		logs.debug("Extension service initialized", "ModelFetcher")
+
+		// Wait for the service to be ready
+		if (!service.isReady()) {
+			// Wait for the 'ready' event with timeout
+			await new Promise<void>((resolve, reject) => {
+				const timeout = setTimeout(() => {
+					reject(new Error("Extension service ready timeout"))
+				}, 10000)
+
+				service!.once("ready", () => {
+					clearTimeout(timeout)
+					resolve()
+				})
+			})
+		}
+
+		// Inject provider configuration
+		const apiConfiguration = mapProviderToApiConfig(provider)
+		const extensionHost = service.getExtensionHost()
+		await extensionHost.injectConfiguration({
+			apiConfiguration,
+			currentApiConfigName: provider.id,
+		})
+		logs.debug("Provider configuration injected", "ModelFetcher")
+
+		// Create a promise that resolves when we receive routerModels
+		const routerModelsPromise = new Promise<RouterModels | null>((resolve, reject) => {
+			const timeout = setTimeout(() => {
+				reject(new Error(`Router models request timed out after ${timeoutMs}ms`))
+			}, timeoutMs)
+
+			const messageHandler = (message: ExtensionMessage) => {
+				if (message.type === "routerModels" && message.routerModels) {
+					clearTimeout(timeout)
+					service!.off("message", messageHandler)
+					resolve(message.routerModels as RouterModels)
+				}
+			}
+
+			service!.on("message", messageHandler)
+		})
+
+		// Send requestRouterModels message
+		await service.sendWebviewMessage({
+			type: "requestRouterModels",
+		})
+		logs.debug("Sent requestRouterModels message", "ModelFetcher")
+
+		// Wait for response
+		const routerModels = await routerModelsPromise
+		logs.info("Received router models", "ModelFetcher", {
+			providerCount: routerModels ? Object.keys(routerModels).length : 0,
+		})
+
+		return routerModels
+	} catch (error) {
+		logs.error("Failed to fetch router models", "ModelFetcher", { error })
+		return null
+	} finally {
+		// Always dispose the service
+		if (service) {
+			try {
+				await service.dispose()
+				logs.debug("Extension service disposed", "ModelFetcher")
+			} catch (disposeError) {
+				logs.warn("Error disposing extension service", "ModelFetcher", { error: disposeError })
+			}
+		}
+	}
+}

+ 126 - 76
pnpm-lock.yaml

@@ -607,6 +607,9 @@ importers:
       '@google/genai':
         specifier: ^1.35.0
         version: 1.35.0(@modelcontextprotocol/[email protected]([email protected])([email protected]))
+      '@inquirer/prompts':
+        specifier: ^8.2.0
+        version: 8.2.0(@types/[email protected])
       '@kilocode/core-schemas':
         specifier: workspace:^
         version: link:../packages/core-schemas
@@ -4969,8 +4972,12 @@ packages:
     resolution: {integrity: sha512-SYLX05PwJVnW+WVegZt1T4Ip1qba1ik+pNJPDiqvk6zS5Y/i8PhRzLpGEtVd7sW0G8cMtkD8t4AZYhQwm8vnww==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
 
-  '@inquirer/[email protected]':
-    resolution: {integrity: sha512-xtQP2eXMFlOcAhZ4ReKP2KZvDIBb1AnCfZ81wWXG3DXLVH0f0g4obE0XDPH+ukAEMRcZT0kdX2AS1jrWGXbpxw==}
+  '@inquirer/[email protected]':
+    resolution: {integrity: sha512-g44zhR3NIKVs0zUesa4iMzExmZpLUdTLRMCStqX3GE5NT6VkPcxQGJ+uC8tDgBUC/vB1rUhUd55cOf++4NZcmw==}
+    engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
+
+  '@inquirer/[email protected]':
+    resolution: {integrity: sha512-DrAMU3YBGMUAp6ArwTIp/25CNDtDbxk7UjIrrtM25JVVrlVYlVzHh5HR1BDFu9JMyUoZ4ZanzeaHqNDttf3gVg==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
     peerDependencies:
       '@types/node': '>=18'
@@ -4978,8 +4985,8 @@ packages:
       '@types/node':
         optional: true
 
-  '@inquirer/[email protected].3':
-    resolution: {integrity: sha512-lyEvibDFL+NA5R4xl8FUmNhmu81B+LDL9L/MpKkZlQDJZXzG8InxiqYxiAlQYa9cqLLhYqKLQwZqXmSTqCLjyw==}
+  '@inquirer/[email protected].4':
+    resolution: {integrity: sha512-WdaPe7foUnoGYvXzH4jp4wH/3l+dBhZ3uwhKjXjwdrq5tEIFaANxj6zrGHxLdsIA0yKM0kFPVcEalOZXBB5ISA==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
     peerDependencies:
       '@types/node': '>=18'
@@ -4996,8 +5003,8 @@ packages:
       '@types/node':
         optional: true
 
-  '@inquirer/[email protected]':
-    resolution: {integrity: sha512-wYyQo96TsAqIciP/r5D3cFeV8h4WqKQ/YOvTg5yOfP2sqEbVVpbxPpfV3LM5D0EP4zUI3EZVHyIUIllnoIa8OQ==}
+  '@inquirer/[email protected]':
+    resolution: {integrity: sha512-hV9o15UxX46OyQAtaoMqAOxGR8RVl1aZtDx1jHbCtSJy1tBdTfKxLPKf7utsE4cRy4tcmCQ4+vdV+ca+oNxqNA==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
     peerDependencies:
       '@types/node': '>=18'
@@ -5005,8 +5012,17 @@ packages:
       '@types/node':
         optional: true
 
-  '@inquirer/[email protected]':
-    resolution: {integrity: sha512-2oINvuL27ujjxd95f6K2K909uZOU2x1WiAl7Wb1X/xOtL8CgQ1kSxzykIr7u4xTkXkXOAkCuF45T588/YKee7w==}
+  '@inquirer/[email protected]':
+    resolution: {integrity: sha512-QI3Jfqcv6UO2/VJaEFONH8Im1ll++Xn/AJTBn9Xf+qx2M+H8KZAdQ5sAe2vtYlo+mLW+d7JaMJB4qWtK4BG3pw==}
+    engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
+    peerDependencies:
+      '@types/node': '>=18'
+    peerDependenciesMeta:
+      '@types/node':
+        optional: true
+
+  '@inquirer/[email protected]':
+    resolution: {integrity: sha512-0I/16YwPPP0Co7a5MsomlZLpch48NzYfToyqYAOWtBmaXSB80RiNQ1J+0xx2eG+Wfxt0nHtpEWSRr6CzNVnOGg==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
     peerDependencies:
       '@types/node': '>=18'
@@ -5023,8 +5039,8 @@ packages:
       '@types/node':
         optional: true
 
-  '@inquirer/[email protected].2':
-    resolution: {integrity: sha512-X/fMXK7vXomRWEex1j8mnj7s1mpnTeP4CO/h2gysJhHLT2WjBnLv4ZQEGpm/kcYI8QfLZ2fgW+9kTKD+jeopLg==}
+  '@inquirer/[email protected].3':
+    resolution: {integrity: sha512-LgyI7Agbda74/cL5MvA88iDpvdXI2KuMBCGRkbCl2Dg1vzHeOgs+s0SDcXV7b+WZJrv2+ERpWSM65Fpi9VfY3w==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
     peerDependencies:
       '@types/node': '>=18'
@@ -5036,8 +5052,12 @@ packages:
     resolution: {integrity: sha512-qXm6EVvQx/FmnSrCWCIGtMHwqeLgxABP8XgcaAoywsL0NFga9gD5kfG0gXiv80GjK9Hsoz4pgGwF/+CjygyV9A==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
 
-  '@inquirer/[email protected]':
-    resolution: {integrity: sha512-4R0TdWl53dtp79Vs6Df2OHAtA2FVNqya1hND1f5wjHWxZJxwDMSNB1X5ADZJSsQKYAJ5JHCTO+GpJZ42mK0Otw==}
+  '@inquirer/[email protected]':
+    resolution: {integrity: sha512-y09iGt3JKoOCBQ3w4YrSJdokcD8ciSlMIWsD+auPu+OZpfxLuyz+gICAQ6GCBOmJJt4KEQGHuZSVff2jiNOy7g==}
+    engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
+
+  '@inquirer/[email protected]':
+    resolution: {integrity: sha512-4B3s3jvTREDFvXWit92Yc6jF1RJMDy2VpSqKtm4We2oVU65YOh2szY5/G14h4fHlyQdpUmazU5MPCFZPRJ0AOw==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
     peerDependencies:
       '@types/node': '>=18'
@@ -5045,8 +5065,8 @@ packages:
       '@types/node':
         optional: true
 
-  '@inquirer/[email protected].3':
-    resolution: {integrity: sha512-TjQLe93GGo5snRlu83JxE38ZPqj5ZVggL+QqqAF2oBA5JOJoxx25GG3EGH/XN/Os5WOmKfO8iLVdCXQxXRZIMQ==}
+  '@inquirer/[email protected].4':
+    resolution: {integrity: sha512-CmMp9LF5HwE+G/xWsC333TlCzYYbXMkcADkKzcawh49fg2a1ryLc7JL1NJYYt1lJ+8f4slikNjJM9TEL/AljYQ==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
     peerDependencies:
       '@types/node': '>=18'
@@ -5054,8 +5074,8 @@ packages:
       '@types/node':
         optional: true
 
-  '@inquirer/[email protected].3':
-    resolution: {integrity: sha512-rCozGbUMAHedTeYWEN8sgZH4lRCdgG/WinFkit6ZPsp8JaNg2T0g3QslPBS5XbpORyKP/I+xyBO81kFEvhBmjA==}
+  '@inquirer/[email protected].4':
+    resolution: {integrity: sha512-ZCEPyVYvHK4W4p2Gy6sTp9nqsdHQCfiPXIP9LbJVW4yCinnxL/dDDmPaEZVysGrj8vxVReRnpfS2fOeODe9zjg==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
     peerDependencies:
       '@types/node': '>=18'
@@ -5063,8 +5083,8 @@ packages:
       '@types/node':
         optional: true
 
-  '@inquirer/prompts@8.1.0':
-    resolution: {integrity: sha512-LsZMdKcmRNF5LyTRuZE5nWeOjganzmN3zwbtNfcs6GPh3I2TsTtF1UYZlbxVfhxd+EuUqLGs/Lm3Xt4v6Az1wA==}
+  '@inquirer/prompts@8.2.0':
+    resolution: {integrity: sha512-rqTzOprAj55a27jctS3vhvDDJzYXsr33WXTjODgVOru21NvBo9yIgLIAf7SBdSV0WERVly3dR6TWyp7ZHkvKFA==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
     peerDependencies:
       '@types/node': '>=18'
@@ -5072,8 +5092,8 @@ packages:
       '@types/node':
         optional: true
 
-  '@inquirer/rawlist@5.1.0':
-    resolution: {integrity: sha512-yUCuVh0jW026Gr2tZlG3kHignxcrLKDR3KBp+eUgNz+BAdSeZk0e18yt2gyBr+giYhj/WSIHCmPDOgp1mT2niQ==}
+  '@inquirer/rawlist@5.2.0':
+    resolution: {integrity: sha512-CciqGoOUMrFo6HxvOtU5uL8fkjCmzyeB6fG7O1vdVAZVSopUBYECOwevDBlqNLyyYmzpm2Gsn/7nLrpruy9RFg==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
     peerDependencies:
       '@types/node': '>=18'
@@ -5081,8 +5101,8 @@ packages:
       '@types/node':
         optional: true
 
-  '@inquirer/search@4.0.3':
-    resolution: {integrity: sha512-lzqVw0YwuKYetk5VwJ81Ba+dyVlhseHPx9YnRKQgwXdFS0kEavCz2gngnNhnMIxg8+j1N/rUl1t5s1npwa7bqg==}
+  '@inquirer/search@4.1.0':
+    resolution: {integrity: sha512-EAzemfiP4IFvIuWnrHpgZs9lAhWDA0GM3l9F4t4mTQ22IFtzfrk8xbkMLcAN7gmVML9O/i+Hzu8yOUyAaL6BKA==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
     peerDependencies:
       '@types/node': '>=18'
@@ -5090,8 +5110,8 @@ packages:
       '@types/node':
         optional: true
 
-  '@inquirer/[email protected].3':
-    resolution: {integrity: sha512-M+ynbwS0ecQFDYMFrQrybA0qL8DV0snpc4kKevCCNaTpfghsRowRY7SlQBeIYNzHqXtiiz4RG9vTOeb/udew7w==}
+  '@inquirer/[email protected].4':
+    resolution: {integrity: sha512-s8KoGpPYMEQ6WXc0dT9blX2NtIulMdLOO3LA1UKOiv7KFWzlJ6eLkEYTDBIi+JkyKXyn8t/CD6TinxGjyLt57g==}
     engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
     peerDependencies:
       '@types/node': '>=18'
@@ -5108,6 +5128,15 @@ packages:
       '@types/node':
         optional: true
 
+  '@inquirer/[email protected]':
+    resolution: {integrity: sha512-cKZN7qcXOpj1h+1eTTcGDVLaBIHNMT1Rz9JqJP5MnEJ0JhgVWllx7H/tahUp5YEK1qaByH2Itb8wLG/iScD5kw==}
+    engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'}
+    peerDependencies:
+      '@types/node': '>=18'
+    peerDependenciesMeta:
+      '@types/node':
+        optional: true
+
   '@ioredis/[email protected]':
     resolution: {integrity: sha512-M/T6Zewn7sDaBQEqIZ8Rb+i9y8qfGmq+5SDFSf9sA2lUZTmdDLVdOiQaeDp+Q4wElZ9HG1GAX5KhDaidp6LQsQ==}
 
@@ -5376,6 +5405,7 @@ packages:
   '@lancedb/[email protected]':
     resolution: {integrity: sha512-hfzp498BfcCJ730fV1YGGoXVxRgE+W1n0D0KwanKlbt8bBPSQ6E6Tf8mPXc8rKdAXIRR3o5mTzMG3z3Fda+m3Q==}
     engines: {node: '>= 18'}
+    cpu: [x64, arm64]
     os: [darwin, linux, win32]
     peerDependencies:
       apache-arrow: '>=15.0.0 <=18.1.0'
@@ -25607,19 +25637,21 @@ snapshots:
 
   '@inquirer/[email protected]': {}
 
-  '@inquirer/[email protected](@types/[email protected])':
+  '@inquirer/[email protected]': {}
+
+  '@inquirer/[email protected](@types/[email protected])':
     dependencies:
-      '@inquirer/ansi': 2.0.2
-      '@inquirer/core': 11.1.0(@types/[email protected])
-      '@inquirer/figures': 2.0.2
-      '@inquirer/type': 4.0.2(@types/[email protected])
+      '@inquirer/ansi': 2.0.3
+      '@inquirer/core': 11.1.1(@types/[email protected])
+      '@inquirer/figures': 2.0.3
+      '@inquirer/type': 4.0.3(@types/[email protected])
     optionalDependencies:
       '@types/node': 25.0.3
 
-  '@inquirer/[email protected].3(@types/[email protected])':
+  '@inquirer/[email protected].4(@types/[email protected])':
     dependencies:
-      '@inquirer/core': 11.1.0(@types/[email protected])
-      '@inquirer/type': 4.0.2(@types/[email protected])
+      '@inquirer/core': 11.1.1(@types/[email protected])
+      '@inquirer/type': 4.0.3(@types/[email protected])
     optionalDependencies:
       '@types/node': 25.0.3
 
@@ -25635,18 +25667,30 @@ snapshots:
     optionalDependencies:
       '@types/node': 25.0.3
 
-  '@inquirer/[email protected](@types/[email protected])':
+  '@inquirer/[email protected](@types/[email protected])':
     dependencies:
-      '@inquirer/core': 11.1.0(@types/[email protected])
-      '@inquirer/external-editor': 2.0.2(@types/[email protected])
-      '@inquirer/type': 4.0.2(@types/[email protected])
+      '@inquirer/ansi': 2.0.3
+      '@inquirer/figures': 2.0.3
+      '@inquirer/type': 4.0.3(@types/[email protected])
+      cli-width: 4.1.0
+      mute-stream: 3.0.0
+      signal-exit: 4.1.0
+      wrap-ansi: 9.0.2
     optionalDependencies:
       '@types/node': 25.0.3
 
-  '@inquirer/[email protected](@types/[email protected])':
+  '@inquirer/e[email protected](@types/[email protected])':
     dependencies:
-      '@inquirer/core': 11.1.0(@types/[email protected])
-      '@inquirer/type': 4.0.2(@types/[email protected])
+      '@inquirer/core': 11.1.1(@types/[email protected])
+      '@inquirer/external-editor': 2.0.3(@types/[email protected])
+      '@inquirer/type': 4.0.3(@types/[email protected])
+    optionalDependencies:
+      '@types/node': 25.0.3
+
+  '@inquirer/[email protected](@types/[email protected])':
+    dependencies:
+      '@inquirer/core': 11.1.1(@types/[email protected])
+      '@inquirer/type': 4.0.3(@types/[email protected])
     optionalDependencies:
       '@types/node': 25.0.3
 
@@ -25657,7 +25701,7 @@ snapshots:
     optionalDependencies:
       '@types/node': 20.17.57
 
-  '@inquirer/[email protected].2(@types/[email protected])':
+  '@inquirer/[email protected].3(@types/[email protected])':
     dependencies:
       chardet: 2.1.1
       iconv-lite: 0.7.2
@@ -25666,64 +25710,66 @@ snapshots:
 
   '@inquirer/[email protected]': {}
 
-  '@inquirer/[email protected](@types/[email protected])':
+  '@inquirer/[email protected]': {}
+
+  '@inquirer/[email protected](@types/[email protected])':
     dependencies:
-      '@inquirer/core': 11.1.0(@types/[email protected])
-      '@inquirer/type': 4.0.2(@types/[email protected])
+      '@inquirer/core': 11.1.1(@types/[email protected])
+      '@inquirer/type': 4.0.3(@types/[email protected])
     optionalDependencies:
       '@types/node': 25.0.3
 
-  '@inquirer/[email protected].3(@types/[email protected])':
+  '@inquirer/[email protected].4(@types/[email protected])':
     dependencies:
-      '@inquirer/core': 11.1.0(@types/[email protected])
-      '@inquirer/type': 4.0.2(@types/[email protected])
+      '@inquirer/core': 11.1.1(@types/[email protected])
+      '@inquirer/type': 4.0.3(@types/[email protected])
     optionalDependencies:
       '@types/node': 25.0.3
 
-  '@inquirer/[email protected].3(@types/[email protected])':
+  '@inquirer/[email protected].4(@types/[email protected])':
     dependencies:
-      '@inquirer/ansi': 2.0.2
-      '@inquirer/core': 11.1.0(@types/[email protected])
-      '@inquirer/type': 4.0.2(@types/[email protected])
+      '@inquirer/ansi': 2.0.3
+      '@inquirer/core': 11.1.1(@types/[email protected])
+      '@inquirer/type': 4.0.3(@types/[email protected])
     optionalDependencies:
       '@types/node': 25.0.3
 
-  '@inquirer/prompts@8.1.0(@types/[email protected])':
-    dependencies:
-      '@inquirer/checkbox': 5.0.3(@types/[email protected])
-      '@inquirer/confirm': 6.0.3(@types/[email protected])
-      '@inquirer/editor': 5.0.3(@types/[email protected])
-      '@inquirer/expand': 5.0.3(@types/[email protected])
-      '@inquirer/input': 5.0.3(@types/[email protected])
-      '@inquirer/number': 4.0.3(@types/[email protected])
-      '@inquirer/password': 5.0.3(@types/[email protected])
-      '@inquirer/rawlist': 5.1.0(@types/[email protected])
-      '@inquirer/search': 4.0.3(@types/[email protected])
-      '@inquirer/select': 5.0.3(@types/[email protected])
+  '@inquirer/prompts@8.2.0(@types/[email protected])':
+    dependencies:
+      '@inquirer/checkbox': 5.0.4(@types/[email protected])
+      '@inquirer/confirm': 6.0.4(@types/[email protected])
+      '@inquirer/editor': 5.0.4(@types/[email protected])
+      '@inquirer/expand': 5.0.4(@types/[email protected])
+      '@inquirer/input': 5.0.4(@types/[email protected])
+      '@inquirer/number': 4.0.4(@types/[email protected])
+      '@inquirer/password': 5.0.4(@types/[email protected])
+      '@inquirer/rawlist': 5.2.0(@types/[email protected])
+      '@inquirer/search': 4.1.0(@types/[email protected])
+      '@inquirer/select': 5.0.4(@types/[email protected])
     optionalDependencies:
       '@types/node': 25.0.3
 
-  '@inquirer/rawlist@5.1.0(@types/[email protected])':
+  '@inquirer/rawlist@5.2.0(@types/[email protected])':
     dependencies:
-      '@inquirer/core': 11.1.0(@types/[email protected])
-      '@inquirer/type': 4.0.2(@types/[email protected])
+      '@inquirer/core': 11.1.1(@types/[email protected])
+      '@inquirer/type': 4.0.3(@types/[email protected])
     optionalDependencies:
       '@types/node': 25.0.3
 
-  '@inquirer/search@4.0.3(@types/[email protected])':
+  '@inquirer/search@4.1.0(@types/[email protected])':
     dependencies:
-      '@inquirer/core': 11.1.0(@types/[email protected])
-      '@inquirer/figures': 2.0.2
-      '@inquirer/type': 4.0.2(@types/[email protected])
+      '@inquirer/core': 11.1.1(@types/[email protected])
+      '@inquirer/figures': 2.0.3
+      '@inquirer/type': 4.0.3(@types/[email protected])
     optionalDependencies:
       '@types/node': 25.0.3
 
-  '@inquirer/[email protected].3(@types/[email protected])':
+  '@inquirer/[email protected].4(@types/[email protected])':
     dependencies:
-      '@inquirer/ansi': 2.0.2
-      '@inquirer/core': 11.1.0(@types/[email protected])
-      '@inquirer/figures': 2.0.2
-      '@inquirer/type': 4.0.2(@types/[email protected])
+      '@inquirer/ansi': 2.0.3
+      '@inquirer/core': 11.1.1(@types/[email protected])
+      '@inquirer/figures': 2.0.3
+      '@inquirer/type': 4.0.3(@types/[email protected])
     optionalDependencies:
       '@types/node': 25.0.3
 
@@ -25731,6 +25777,10 @@ snapshots:
     optionalDependencies:
       '@types/node': 25.0.3
 
+  '@inquirer/[email protected](@types/[email protected])':
+    optionalDependencies:
+      '@types/node': 25.0.3
+
   '@ioredis/[email protected]': {}
 
   '@isaacs/[email protected]': {}
@@ -30546,7 +30596,7 @@ snapshots:
       sirv: 3.0.1
       tinyglobby: 0.2.14
       tinyrainbow: 2.0.0
-      vitest: 3.2.4(@types/[email protected])(@types/node@25.0.3)(@vitest/[email protected])([email protected])([email protected])([email protected])([email protected])([email protected])([email protected])
+      vitest: 3.2.4(@types/[email protected])(@types/node@20.17.57)(@vitest/[email protected])([email protected])([email protected])([email protected])([email protected])([email protected])([email protected])
 
   '@vitest/[email protected]':
     dependencies:
@@ -36329,7 +36379,7 @@ snapshots:
     dependencies:
       '@inquirer/ansi': 2.0.2
       '@inquirer/core': 11.1.0(@types/[email protected])
-      '@inquirer/prompts': 8.1.0(@types/[email protected])
+      '@inquirer/prompts': 8.2.0(@types/[email protected])
       '@inquirer/type': 4.0.2(@types/[email protected])
       mute-stream: 3.0.0
       run-async: 4.0.6