@kianwoon/modelweaver 0.3.14 → 0.3.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/init-2GWQ546N.js +64 -0
- package/dist/init-2GWQ546N.js.map +1 -0
- package/package.json +1 -1
- package/dist/init-VLTKSOZN.js +0 -63
- package/dist/init-VLTKSOZN.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/init.ts","../src/presets.ts","../src/settings.ts"],"sourcesContent":["// src/init.ts — Interactive setup wizard for ModelWeaver\nimport prompts from 'prompts';\nimport { getPresets, getPreset, type ProviderPreset } from './presets.js';\nimport { stringify as stringifyYaml } from 'yaml';\nimport { writeFileSync, existsSync, readFileSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { readSettings, backupSettings, mergeSettings, writeSettings, getSettingsPath } from './settings.js';\nimport net from 'node:net';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface ConfiguredProvider {\n id: string;\n name: string;\n baseUrl: string;\n envKey: string;\n apiKey: string;\n authType: \"anthropic\" | \"bearer\";\n models: Record<string, string>;\n}\n\ninterface ConfiguredModel {\n alias: string; // user-facing name for /model and availableModels\n provider: string; // provider ID\n model: string; // actual model name sent to provider API\n fallbacks: { provider: string; model: string }[];\n}\n\n/** Lightweight representation of a provider found in existing config.yaml.\n * Used for display and pre-fill; no API key resolution or validation. */\ninterface ExistingProvider {\n id: string;\n baseUrl: string;\n envKey: string;\n authType: \"anthropic\" | \"bearer\";\n timeout: number;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst CANCEL = { onCancel: () => { console.log('\\n Setup cancelled. No files were changed.'); process.exit(0); } };\n\nconst GREEN = '\\x1B[32m';\nconst RED = '\\x1B[31m';\nconst CYAN = '\\x1B[36m';\nconst BOLD = '\\x1B[1m';\nconst RESET = '\\x1B[0m';\n\nfunction check(msg: string) { console.log(` ${GREEN}\\u2713${RESET} ${msg}`); }\nfunction fail(msg: string) { console.log(` ${RED}\\u2717${RESET} ${msg}`); }\n\n// ---------------------------------------------------------------------------\n// [Improvement 6] clearScreen — separator instead of full clear\n// ---------------------------------------------------------------------------\n\nfunction clearScreen(): void {\n console.log(`\\n${'\\u2500'.repeat(56)}\\n`);\n}\n\n// ---------------------------------------------------------------------------\n// API key test (unchanged)\n// ---------------------------------------------------------------------------\n\nexport async function testApiKey(\n baseUrl: string,\n apiKey: string,\n preset: ProviderPreset,\n): Promise<{ ok: boolean; error?: string }> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 5_000);\n\n const headers: Record<string, string> =\n preset.authType === 'anthropic'\n ? { 'x-api-key': apiKey, 'anthropic-version': '2023-06-01', 'anthropic-beta': 'interleaved-thinking-2025-05-14', 'content-type': 'application/json' }\n : { Authorization: `Bearer ${apiKey}`, 'content-type': 'application/json' };\n\n try {\n const res = await fetch(`${baseUrl}${preset.testPath}`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ model: preset.models.sonnet, max_tokens: 1, messages: [{ role: 'user', content: 'hi' }] }),\n signal: controller.signal,\n });\n\n if (res.status === 401 || res.status === 403) return { ok: false, error: 'Invalid API key' };\n if (res.status === 200 || res.status === 400 || res.status === 429) return { ok: true };\n // Check for \"insufficient balance\" — key is valid, account just has no credits\n try {\n const body = await res.json() as { error?: { message?: string } };\n if (body.error?.message?.includes('insufficient balance')) {\n return { ok: true };\n }\n } catch { /* ignore parse errors */ }\n return { ok: false, error: `Unexpected status ${res.status}` };\n } catch (err: unknown) {\n if ((err as Error).name === 'AbortError') return { ok: false, error: 'Request timed out' };\n return { ok: false, error: 'Network error \\u2014 endpoint unreachable' };\n } finally {\n clearTimeout(timeout);\n }\n}\n\n// ---------------------------------------------------------------------------\n// [Improvement 1] detectEnvApiKey — auto-detect existing keys\n// ---------------------------------------------------------------------------\n\nfunction detectEnvApiKey(preset: ProviderPreset): { found: boolean; key: string; source: string } {\n // dotenv.config() already loads ~/.modelweaver/.env into process.env in index.ts\n // before runInit() is called, so a single check suffices.\n const envVal = process.env[preset.envKey];\n if (envVal && envVal.trim()) {\n return { found: true, key: envVal.trim(), source: 'environment' };\n }\n return { found: false, key: '', source: '' };\n}\n\n// ---------------------------------------------------------------------------\n// [Improvement 4] calculateTotalSteps — step counter\n// ---------------------------------------------------------------------------\n\nfunction calculateTotalSteps(selectedProviderCount: number, quick: boolean): number {\n if (quick) {\n return 3;\n }\n // Normal mode: N (configure each provider) + model config (1) + server (1) + confirm (1)\n return selectedProviderCount + 1 + 1 + 1;\n}\n\n// ---------------------------------------------------------------------------\n// [Improvement 7] buildSummaryTable — formatted summary\n// ---------------------------------------------------------------------------\n\nfunction buildSummaryTable(\n providers: ConfiguredProvider[],\n models: ConfiguredModel[],\n server: { port: number; host: string },\n): string {\n const lines: string[] = [];\n const W = 56;\n\n lines.push(`${CYAN}\\u250c${'\\u2500'.repeat(W)}\\u2510${RESET}`);\n lines.push(`${CYAN}\\u2502${RESET}${BOLD} ModelWeaver Configuration Summary${''.padEnd(W - 33)}${CYAN}\\u2502${RESET}`);\n lines.push(`${CYAN}\\u251c${'\\u2500'.repeat(W)}\\u2524${RESET}`);\n lines.push(`${CYAN}\\u2502${RESET} ${BOLD}Server:${RESET} ${server.host}:${server.port}${''.padEnd(W - 8 - `${server.host}:${server.port}`.length)}${CYAN}\\u2502${RESET}`);\n lines.push(`${CYAN}\\u251c${'\\u2500'.repeat(W)}\\u2524${RESET}`);\n\n for (const m of models) {\n const provider = providers.find(p => p.id === m.provider);\n const pName = provider ? provider.name : m.provider;\n const info = `${m.alias.padEnd(16)} ${pName} \\u2192 ${m.model}`;\n lines.push(`${CYAN}\\u2502${RESET} ${info}${''.padEnd(Math.max(0, W - info.length - 2))}${CYAN}\\u2502${RESET}`);\n for (const fb of m.fallbacks) {\n const fbProvider = providers.find(p => p.id === fb.provider);\n const fbPName = fbProvider ? fbProvider.name : fb.provider;\n const fbInfo = ` fallback: ${fbPName} \\u2192 ${fb.model}`;\n lines.push(`${CYAN}\\u2502${RESET} ${fbInfo}${''.padEnd(Math.max(0, W - fbInfo.length - 2))}${CYAN}\\u2502${RESET}`);\n }\n }\n\n lines.push(`${CYAN}\\u2514${'\\u2500'.repeat(W)}\\u2518${RESET}`);\n return lines.join('\\n');\n}\n\n/** Build a formatted table showing existing configured providers. */\nfunction buildExistingProvidersTable(\n existingProviders: Map<string, ExistingProvider>,\n): string {\n const lines: string[] = [];\n const W = 56;\n const providers = [...existingProviders.entries()];\n\n lines.push(`${CYAN}${'\\u250c' + '\\u2500'.repeat(W) + '\\u2510'}${RESET}`);\n lines.push(`${CYAN}\\u2502${RESET}${BOLD} Currently Configured Providers${''.padEnd(W - 30)}${CYAN}\\u2502${RESET}`);\n lines.push(`${CYAN}\\u251c${'\\u2500'.repeat(W)}\\u2524${RESET}`);\n\n for (const [id, p] of providers) {\n lines.push(`${CYAN}\\u2502${RESET} ${BOLD}${id}${RESET}${''.padEnd(Math.max(0, 20 - id.length))} ${p.baseUrl}${''.padEnd(Math.max(0, W - 22 - p.baseUrl.length))}${CYAN}\\u2502${RESET}`);\n const envLabel = p.envKey || '(hardcoded key)';\n const padding = Math.max(0, W - 22 - envLabel.length - p.authType.length);\n lines.push(`${CYAN}\\u2502${RESET} env: ${envLabel} auth: ${p.authType}${''.padEnd(padding)}${CYAN}\\u2502${RESET}`);\n }\n\n lines.push(`${CYAN}${'\\u2514' + '\\u2500'.repeat(W) + '\\u2518'}${RESET}`);\n return lines.join('\\n');\n}\n\n/** Merge freshly configured providers with untouched existing providers.\n * Used for routing selection and summary display. */\nfunction buildAllProviders(\n configured: ConfiguredProvider[],\n existingMap: Map<string, ExistingProvider>,\n): ConfiguredProvider[] {\n const touchedIds = new Set(configured.map(p => p.id));\n const result = [...configured];\n\n for (const [id, ep] of existingMap.entries()) {\n if (!touchedIds.has(id)) {\n const preset = getPreset(id);\n result.push({\n id,\n name: preset?.name ?? id,\n baseUrl: ep.baseUrl,\n envKey: ep.envKey,\n apiKey: \"\",\n authType: ep.authType,\n models: preset?.models ?? { sonnet: \"\", opus: \"\", haiku: \"\" },\n });\n }\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Wizard steps\n// ---------------------------------------------------------------------------\n\n// [Modified] selectProviders — supports singleSelect for --quick mode, excludeIds for add mode\nasync function selectProviders(options?: { singleSelect?: boolean; excludeIds?: Set<string> }): Promise<string[]> {\n let allPresets = getPresets();\n if (options?.excludeIds) {\n allPresets = allPresets.filter(p => !options.excludeIds!.has(p.id));\n }\n\n if (allPresets.length === 0) return [];\n\n if (options?.singleSelect) {\n const { providerId } = await prompts(\n {\n type: 'select',\n name: 'providerId',\n message: 'Select a provider:',\n choices: [\n { title: '\\u2B05 Go back', value: '__back__' },\n ...allPresets.map((p) => ({ title: p.name, value: p.id, description: p.baseUrl })),\n ],\n },\n CANCEL,\n );\n return [providerId as string];\n }\n\n const { providerIds } = await prompts(\n {\n type: 'multiselect',\n name: 'providerIds',\n message: 'Select providers to configure:',\n choices: allPresets.map((p) => ({ title: p.name, value: p.id, description: p.baseUrl })),\n min: 1,\n },\n CANCEL,\n );\n return providerIds as string[];\n}\n\n// [Modified] configureProvider — auto-detect env keys + step counter + existing provider pre-fill\nasync function configureProvider(\n id: string,\n stepInfo?: { current: number; total: number },\n existing?: ExistingProvider,\n): Promise<ConfiguredProvider | null> {\n const preset = getPreset(id);\n if (!preset) {\n console.error(` Error: Unknown provider \"${id}\". Skipping.`);\n return null;\n }\n\n const effectiveEnvKey = existing?.envKey ?? preset.envKey;\n const effectiveBaseUrl = existing?.baseUrl ?? preset.baseUrl;\n const effectiveAuthType = existing?.authType ?? preset.authType;\n\n // [Improvement 1] Auto-detect existing env key — check custom env key first if editing\n let detected = detectEnvApiKey(preset);\n if (existing?.envKey && existing.envKey !== preset.envKey) {\n const customDetected = detectEnvApiKey({ ...preset, envKey: existing.envKey });\n if (customDetected.found) detected = customDetected;\n }\n\n if (detected.found) {\n process.stdout.write(` Testing API key for ${preset.name} (from ${detected.source})...`);\n const result = await testApiKey(effectiveBaseUrl, detected.key, preset);\n process.stdout.write('\\r' + ' '.repeat(60) + '\\r');\n\n if (result.ok) {\n check(`${preset.name}: using existing ${effectiveEnvKey} (${detected.source})`);\n return {\n id, name: preset.name, baseUrl: effectiveBaseUrl,\n envKey: effectiveEnvKey, apiKey: detected.key,\n authType: effectiveAuthType, models: preset.models,\n };\n }\n\n // Key found but invalid — fall through to prompt\n console.log(` ${RED}\\u26A0${RESET} Existing ${effectiveEnvKey} (${detected.source}) is invalid, please provide a new key.`);\n }\n\n const stepLabel = stepInfo ? `[Step ${stepInfo.current} of ${stepInfo.total}] ` : '';\n\n const MAX_RETRIES = 3;\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n const { baseUrl } = await prompts(\n { type: 'text', name: 'baseUrl', message: `${stepLabel}[${preset.name}] Base URL:`, initial: effectiveBaseUrl },\n CANCEL,\n );\n\n // Validate the base URL format\n try {\n new URL(baseUrl as string);\n } catch {\n console.log(\" Invalid URL format. Please try again.\");\n if (attempt < MAX_RETRIES - 1) continue;\n const { retry } = await prompts(\n { type: 'confirm', name: 'retry', message: `Retry with a valid URL? (${attempt + 1}/${MAX_RETRIES - 1} retries used)`, initial: true },\n CANCEL,\n );\n if (!retry) break;\n continue;\n }\n\n const { apiKey } = await prompts(\n { type: 'password', name: 'apiKey', message: `${stepLabel}[${preset.name}] API key:` },\n CANCEL,\n );\n\n // Spinner-style test\n process.stdout.write(` Testing API key for ${preset.name}...`);\n const result = await testApiKey(baseUrl as string, apiKey as string, preset);\n process.stdout.write('\\r' + ' '.repeat(60) + '\\r');\n\n if (result.ok) {\n check(`${preset.name} API key accepted`);\n return { id, name: preset.name, baseUrl: baseUrl as string, envKey: effectiveEnvKey, apiKey: apiKey as string, authType: effectiveAuthType, models: preset.models };\n }\n\n fail(`${preset.name}: ${result.error}`);\n\n if (attempt < MAX_RETRIES - 1) {\n const { retry } = await prompts(\n { type: 'confirm', name: 'retry', message: `Retry? (${attempt + 1}/${MAX_RETRIES - 1} retries used)`, initial: true },\n CANCEL,\n );\n if (!retry) break;\n }\n }\n\n console.log(` ${RED}Warning:${RESET} ${preset.name} will be skipped \\u2014 max retries (${MAX_RETRIES}) exceeded.`);\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Fallback configuration helper\n// ---------------------------------------------------------------------------\n\n/** Prompt the user to add fallback providers for a model. Returns the fallbacks array. */\nasync function configureFallbacks(\n alias: string,\n primaryProviderId: string,\n providers: ConfiguredProvider[],\n existingFallbacks: { provider: string; model: string }[] = [],\n): Promise<{ provider: string; model: string }[]> {\n const fallbacks = [...existingFallbacks];\n\n while (true) {\n const { addFallback } = await prompts(\n {\n type: 'confirm',\n name: 'addFallback',\n message: fallbacks.length === 0\n ? `Add a fallback provider for ${alias}?`\n : `Add another fallback provider for ${alias}?`,\n initial: false,\n },\n CANCEL,\n );\n\n if (!addFallback) break;\n\n const availableProviders = providers.filter(p => p.id !== primaryProviderId);\n if (availableProviders.length === 0) {\n console.log(` ${RED}No other providers available for fallback.${RESET}`);\n break;\n }\n\n const providerChoices = availableProviders.map((p) => ({ title: p.name, value: p.id }));\n const { providerId } = await prompts(\n {\n type: 'select',\n name: 'providerId',\n message: `Select fallback provider for ${alias}:`,\n choices: [\n { title: '\\u2B05 Go back', value: '__back__' },\n ...providerChoices,\n ],\n },\n CANCEL,\n );\n\n if (providerId === '__back__') continue;\n\n const selectedProvider = providers.find((p) => p.id === (providerId as string))!;\n const { modelName } = await prompts(\n {\n type: 'text',\n name: 'modelName',\n message: `[${selectedProvider.name}] Fallback model name:`,\n initial: '',\n },\n CANCEL,\n );\n\n fallbacks.push({\n provider: selectedProvider.id,\n model: (modelName as string).trim(),\n });\n\n check(`Added fallback: ${selectedProvider.id} \\u2192 ${(modelName as string).trim()}`);\n }\n\n return fallbacks;\n}\n\n// ---------------------------------------------------------------------------\n// N-model configuration\n// ---------------------------------------------------------------------------\n\n/** Build a formatted table showing existing modelRouting entries. */\nfunction buildExistingModelsTable(\n modelRouting: Map<string, { provider: string; model: string }[]>,\n): string {\n const lines: string[] = [];\n const W = 56;\n const entries = [...modelRouting.entries()];\n\n lines.push(`${CYAN}${'\\u250c' + '\\u2500'.repeat(W) + '\\u2510'}${RESET}`);\n lines.push(`${CYAN}\\u2502${RESET}${BOLD} Currently Configured Models${''.padEnd(W - 28)}${CYAN}\\u2502${RESET}`);\n lines.push(`${CYAN}\\u251c${'\\u2500'.repeat(W)}\\u2524${RESET}`);\n\n if (entries.length === 0) {\n lines.push(`${CYAN}\\u2502${RESET} (none)${''.padEnd(W - 7)}${CYAN}\\u2502${RESET}`);\n } else {\n for (const [alias, chain] of entries) {\n const primary = chain[0];\n const info = `${alias.padEnd(20)} ${primary.provider} \\u2192 ${primary.model}`;\n lines.push(`${CYAN}\\u2502${RESET} ${info}${''.padEnd(Math.max(0, W - info.length - 2))}${CYAN}\\u2502${RESET}`);\n for (let i = 1; i < chain.length; i++) {\n const fbInfo = ` fallback: ${chain[i].provider} \\u2192 ${chain[i].model}`;\n lines.push(`${CYAN}\\u2502${RESET} ${fbInfo}${''.padEnd(Math.max(0, W - fbInfo.length - 2))}${CYAN}\\u2502${RESET}`);\n }\n }\n }\n\n lines.push(`${CYAN}${'\\u2514' + '\\u2500'.repeat(W) + '\\u2518'}${RESET}`);\n return lines.join('\\n');\n}\n\nasync function configureModels(\n providers: ConfiguredProvider[],\n existingModels?: Map<string, { provider: string; model: string }[]>,\n): Promise<ConfiguredModel[]> {\n const models: ConfiguredModel[] = [];\n const hasExisting = existingModels && existingModels.size > 0;\n\n // Seed models from existing modelRouting\n if (hasExisting) {\n for (const [alias, chain] of existingModels!.entries()) {\n const primary = chain[0];\n models.push({\n alias,\n provider: primary.provider,\n model: primary.model,\n fallbacks: chain.slice(1),\n });\n }\n }\n\n console.log();\n console.log(' Configure models \\u2014 each model gets an alias that appears in Claude Code\\'s /model picker.');\n console.log(' The proxy will route requests matching the alias to the chosen provider.');\n console.log();\n\n if (hasExisting) {\n // Editing existing config: show current models, then offer add/edit/delete menu\n while (true) {\n console.log(buildExistingModelsTable(existingModels!));\n console.log();\n\n const { action } = await prompts({\n type: 'select',\n name: 'action',\n message: 'What would you like to do?',\n choices: [\n { title: 'Add new model', value: 'add', description: 'Add a model alias routed to a provider' },\n ...(models.length > 0 ? [{ title: 'Edit existing model', value: 'edit', description: 'Change alias, provider, or model name' }] : []),\n ...(models.length > 0 ? [{ title: 'Delete model', value: 'delete', description: 'Remove a model alias' }] : []),\n { title: 'Done', value: 'done', description: 'Continue to server configuration' },\n ],\n }, CANCEL);\n\n if (action === 'done') break;\n\n if (action === 'add') {\n const providerChoices = providers.map((p) => ({ title: p.name, value: p.id }));\n const { providerId } = await prompts(\n {\n type: 'select',\n name: 'providerId',\n message: 'Select provider:',\n choices: [\n { title: '\\u2B05 Go back', value: '__back__' },\n ...providerChoices,\n ],\n },\n CANCEL,\n );\n\n if (providerId === '__back__') continue;\n\n const selectedProvider = providers.find((p) => p.id === (providerId as string))!;\n const { alias } = await prompts(\n {\n type: 'text',\n name: 'alias',\n message: `[${selectedProvider.name}] Model alias (name in /model picker):`,\n initial: '',\n },\n CANCEL,\n );\n\n const { modelName } = await prompts(\n {\n type: 'text',\n name: 'modelName',\n message: `[${selectedProvider.name}] Actual model name (sent to provider API):`,\n initial: alias as string,\n },\n CANCEL,\n );\n\n const newModel: ConfiguredModel = {\n alias: (alias as string).trim(),\n provider: selectedProvider.id,\n model: (modelName as string).trim(),\n fallbacks: [],\n };\n\n // Configure fallbacks for this model\n newModel.fallbacks = await configureFallbacks(\n newModel.alias, newModel.provider, providers, newModel.fallbacks,\n );\n\n models.push(newModel);\n // Update the existing map so the table stays current (including fallbacks)\n existingModels!.set(newModel.alias, [\n { provider: newModel.provider, model: newModel.model },\n ...newModel.fallbacks,\n ]);\n check(`Added model: ${newModel.alias}`);\n }\n\n if (action === 'edit') {\n const modelChoices = models.map((m) => ({\n title: m.alias,\n value: m.alias,\n description: `${m.provider} \\u2192 ${m.model}`,\n }));\n const { editAlias } = await prompts({\n type: 'select',\n name: 'editAlias',\n message: 'Select model to edit:',\n choices: [\n { title: '\\u2B05 Go back', value: '__back__' },\n ...modelChoices,\n ],\n }, CANCEL);\n\n if (editAlias === '__back__') continue;\n\n const idx = models.findIndex((m) => m.alias === editAlias);\n if (idx === -1) continue;\n\n const current = models[idx];\n let currentFallbacks = [...current.fallbacks];\n\n // If alias changed, remove old entry from existing map\n const { alias } = await prompts(\n {\n type: 'text',\n name: 'alias',\n message: `Model alias:`,\n initial: current.alias,\n },\n CANCEL,\n );\n\n const providerChoices = providers.map((p) => ({ title: p.name, value: p.id }));\n const { providerId } = await prompts(\n {\n type: 'select',\n name: 'providerId',\n message: 'Select provider:',\n choices: [\n { title: '\\u2B05 Go back', value: '__back__' },\n ...providerChoices,\n ],\n },\n CANCEL,\n );\n\n if (providerId === '__back__') continue;\n\n const selectedProvider = providers.find((p) => p.id === (providerId as string))!;\n const { modelName } = await prompts(\n {\n type: 'text',\n name: 'modelName',\n message: `Actual model name:`,\n initial: current.model,\n },\n CANCEL,\n );\n\n const newAlias = (alias as string).trim();\n const newModel = (modelName as string).trim();\n\n // Fallback management loop\n while (true) {\n // Show current fallbacks\n if (currentFallbacks.length === 0) {\n console.log(` ${CYAN}No fallbacks configured.${RESET}`);\n } else {\n console.log(` ${CYAN}Current fallbacks:${RESET}`);\n for (let i = 0; i < currentFallbacks.length; i++) {\n const fb = currentFallbacks[i];\n const fbProvider = providers.find(p => p.id === fb.provider);\n const fbPName = fbProvider ? fbProvider.name : fb.provider;\n console.log(` ${i + 1}. ${fbPName} \\u2192 ${fb.model}`);\n }\n }\n console.log();\n\n const fallbackActions = [\n { title: 'Add fallback', value: 'add_fb' },\n ...(currentFallbacks.length > 0 ? [{ title: 'Remove fallback', value: 'remove_fb' }] : []),\n { title: 'Done editing fallbacks', value: 'done_fb' },\n ];\n\n const { fallbackAction } = await prompts({\n type: 'select',\n name: 'fallbackAction',\n message: 'Manage fallbacks:',\n choices: fallbackActions,\n }, CANCEL);\n\n if (fallbackAction === 'done_fb') break;\n\n if (fallbackAction === 'add_fb') {\n const newFb = await configureFallbacks(\n newAlias, selectedProvider.id, providers, currentFallbacks,\n );\n currentFallbacks = newFb;\n }\n\n if (fallbackAction === 'remove_fb') {\n const fbChoices = currentFallbacks.map((fb, i) => {\n const fbProvider = providers.find(p => p.id === fb.provider);\n const fbPName = fbProvider ? fbProvider.name : fb.provider;\n return { title: `${fbPName} \\u2192 ${fb.model}`, value: i };\n });\n const { removeIdx } = await prompts({\n type: 'select',\n name: 'removeIdx',\n message: 'Select fallback to remove:',\n choices: [\n { title: '\\u2B05 Go back', value: '__back__' },\n ...fbChoices,\n ],\n }, CANCEL);\n\n if (removeIdx !== '__back__') {\n const removed = currentFallbacks.splice(removeIdx as number, 1);\n check(`Removed fallback: ${removed[0].provider} \\u2192 ${removed[0].model}`);\n }\n }\n }\n\n // If alias changed, remove old entry from existing map\n if (newAlias !== current.alias) {\n existingModels!.delete(current.alias);\n }\n\n models[idx] = {\n alias: newAlias,\n provider: selectedProvider.id,\n model: newModel,\n fallbacks: currentFallbacks,\n };\n\n // Update existing map with full chain including fallbacks\n existingModels!.set(newAlias, [\n { provider: selectedProvider.id, model: newModel },\n ...currentFallbacks,\n ]);\n\n check(`Updated model: ${newAlias} (${selectedProvider.id} \\u2192 ${newModel})`);\n }\n\n if (action === 'delete') {\n const modelChoices = models.map((m) => ({\n title: m.alias,\n value: m.alias,\n description: `${m.provider} \\u2192 ${m.model}`,\n }));\n const { deleteAlias } = await prompts({\n type: 'select',\n name: 'deleteAlias',\n message: 'Select model to delete:',\n choices: [\n { title: '\\u2B05 Go back', value: '__back__' },\n ...modelChoices,\n ],\n }, CANCEL);\n\n if (deleteAlias === '__back__') continue;\n\n const idx = models.findIndex((m) => m.alias === deleteAlias);\n if (idx !== -1) {\n models.splice(idx, 1);\n existingModels!.delete(deleteAlias as string);\n check(`Deleted model: ${deleteAlias as string}`);\n }\n }\n\n clearScreen();\n }\n } else {\n // Fresh setup: auto-suggest one model per provider using preset defaults\n for (const provider of providers) {\n const { addModel } = await prompts(\n {\n type: 'confirm',\n name: 'addModel',\n message: `Add a model for ${provider.name}?`,\n initial: true,\n },\n CANCEL,\n );\n\n if (addModel) {\n const presetModel = provider.models?.sonnet || provider.models?.opus || provider.models?.haiku || '';\n const { alias } = await prompts(\n {\n type: 'text',\n name: 'alias',\n message: `[${provider.name}] Model alias (name in /model picker):`,\n initial: presetModel || provider.id,\n },\n CANCEL,\n );\n\n const { modelName } = await prompts(\n {\n type: 'text',\n name: 'modelName',\n message: `[${provider.name}] Actual model name (sent to provider API):`,\n initial: presetModel,\n },\n CANCEL,\n );\n\n const newModel: ConfiguredModel = {\n alias: (alias as string).trim(),\n provider: provider.id,\n model: (modelName as string).trim(),\n fallbacks: [],\n };\n\n // Configure fallbacks for this model\n newModel.fallbacks = await configureFallbacks(\n newModel.alias, newModel.provider, providers, newModel.fallbacks,\n );\n\n models.push(newModel);\n }\n }\n\n // Allow adding additional models\n while (true) {\n console.log();\n const { addMore } = await prompts(\n {\n type: 'confirm',\n name: 'addMore',\n message: models.length === 0\n ? 'Add a model?'\n : 'Add another model?',\n initial: models.length === 0,\n },\n CANCEL,\n );\n\n if (!addMore) break;\n\n const providerChoices = providers.map((p) => ({ title: p.name, value: p.id }));\n const { providerId } = await prompts(\n {\n type: 'select',\n name: 'providerId',\n message: 'Select provider:',\n choices: providerChoices,\n },\n CANCEL,\n );\n\n const selectedProvider = providers.find((p) => p.id === (providerId as string))!;\n const { alias } = await prompts(\n {\n type: 'text',\n name: 'alias',\n message: `[${selectedProvider.name}] Model alias:`,\n initial: '',\n },\n CANCEL,\n );\n\n const { modelName } = await prompts(\n {\n type: 'text',\n name: 'modelName',\n message: `[${selectedProvider.name}] Actual model name:`,\n initial: alias as string,\n },\n CANCEL,\n );\n\n const newModel: ConfiguredModel = {\n alias: (alias as string).trim(),\n provider: selectedProvider.id,\n model: (modelName as string).trim(),\n fallbacks: [],\n };\n\n // Configure fallbacks for this model\n newModel.fallbacks = await configureFallbacks(\n newModel.alias, newModel.provider, providers, newModel.fallbacks,\n );\n\n models.push(newModel);\n }\n }\n\n if (models.length === 0) {\n console.log(' No models configured.');\n } else {\n check(`${models.length} model(s) configured`);\n }\n\n return models;\n}\n\n// ---------------------------------------------------------------------------\n// Port collision detection\n// ---------------------------------------------------------------------------\n\nfunction isPortInUse(port: number, host: string): Promise<boolean> {\n return new Promise((resolve) => {\n const server = net.createServer();\n server.once('error', () => { server.close(); resolve(true); });\n server.once('listening', () => { server.close(); resolve(false); });\n server.listen(port, host);\n });\n}\n\n// [Modified] configureServer — supports useDefaults for --quick mode\nasync function configureServer(\n options?: { useDefaults?: boolean; stepInfo?: { current: number; total: number } },\n): Promise<{ port: number; host: string }> {\n if (options?.useDefaults) {\n return { port: 3456, host: 'localhost' };\n }\n\n const stepLabel = options?.stepInfo ? `[Step ${options.stepInfo.current} of ${options.stepInfo.total}] ` : '';\n\n const { port } = await prompts(\n { type: 'number', name: 'port', message: `${stepLabel}Server port:`, initial: 3456 },\n CANCEL,\n );\n const { host } = await prompts(\n { type: 'text', name: 'host', message: `${stepLabel}Server host:`, initial: 'localhost' },\n CANCEL,\n );\n\n // Port collision check\n if (await isPortInUse(port as number, host as string)) {\n console.log(` ${RED}\\u26A0 Warning:${RESET} Port ${port} is already in use on ${host}.`);\n const { proceed } = await prompts(\n { type: 'confirm', name: 'proceed', message: 'Use this port anyway?', initial: false },\n CANCEL,\n );\n if (!proceed) {\n console.log(' Please choose a different port and try again.');\n process.exit(1);\n }\n }\n\n return { port: port as number, host: host as string };\n}\n\ninterface SettingsConfig {\n defaultModel: string;\n availableModels: string[];\n}\n\nasync function configureClaudeCodeSettings(\n models: ConfiguredModel[],\n): Promise<SettingsConfig | null> {\n if (models.length === 0) return null;\n\n console.log();\n\n const { configure } = await prompts(\n {\n type: 'confirm',\n name: 'configure',\n message: 'Configure Claude Code to use ModelWeaver automatically?',\n initial: true,\n },\n CANCEL,\n );\n\n if (!configure) return null;\n\n const { defaultModel } = await prompts(\n {\n type: 'select',\n name: 'defaultModel',\n message: 'Select default model for Claude Code:',\n choices: models.map((m) => ({\n title: m.alias,\n description: `${m.provider} \\u2192 ${m.model}`,\n value: m.alias,\n })),\n },\n CANCEL,\n );\n\n const availableModels = models.map((m) => m.alias);\n\n return { defaultModel: defaultModel as string, availableModels };\n}\n\nfunction buildYamlConfig(\n providers: ConfiguredProvider[],\n models: ConfiguredModel[],\n server: { port: number; host: string },\n existingProviders?: Map<string, ExistingProvider>,\n existingModelRouting?: Map<string, { provider: string; model: string }[]>,\n): string {\n // Build modelRouting from configured models (primary + fallbacks)\n const modelRouting: Record<string, { provider: string; model: string }[]> = {};\n for (const m of models) {\n modelRouting[m.alias] = [\n { provider: m.provider, model: m.model },\n ...m.fallbacks,\n ];\n }\n // For any models in existing routing that are NOT in the current models list,\n // preserve them as-is (backward compatibility)\n if (existingModelRouting) {\n for (const [alias, chain] of existingModelRouting.entries()) {\n if (!modelRouting[alias]) {\n modelRouting[alias] = chain.map(e => ({ provider: e.provider, model: e.model }));\n }\n }\n }\n\n const configObj: {\n server: { port: number; host: string };\n providers: Record<string, Record<string, unknown>>;\n modelRouting: Record<string, { provider: string; model: string }[]>;\n } = {\n server,\n providers: {},\n modelRouting,\n };\n\n for (const p of providers) {\n const providerConfig: Record<string, unknown> = {\n baseUrl: p.baseUrl,\n apiKey: `\\${${p.envKey}}`,\n timeout: 30000,\n };\n if (p.authType === \"bearer\") {\n providerConfig.authType = \"bearer\";\n }\n configObj.providers[p.id] = providerConfig;\n }\n\n // Merge in untouched existing providers (preserved verbatim)\n if (existingProviders) {\n const touchedIds = new Set(providers.map(p => p.id));\n for (const [id, ep] of existingProviders.entries()) {\n if (!touchedIds.has(id)) {\n const providerConfig: Record<string, unknown> = {\n baseUrl: ep.baseUrl,\n apiKey: ep.envKey ? `\\${${ep.envKey}}` : \"\",\n timeout: ep.timeout,\n };\n if (ep.authType === \"bearer\") {\n providerConfig.authType = \"bearer\";\n }\n configObj.providers[id] = providerConfig;\n }\n }\n }\n\n return stringifyYaml(configObj);\n}\n\nfunction writeEnvFile(entries: ConfiguredProvider[]): void {\n const envDir = join(process.env.HOME || process.env.USERPROFILE || '', '.modelweaver');\n const envPath = join(envDir, '.env');\n mkdirSync(envDir, { recursive: true });\n let existing = '';\n\n if (existsSync(envPath)) {\n existing = readFileSync(envPath, 'utf-8');\n }\n\n if (existing && !existing.endsWith('\\n')) existing += '\\n';\n\n const lines: string[] = [];\n\n for (const entry of entries) {\n // Escape regex metacharacters in env key name\n const escapedKey = entry.envKey.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regex = new RegExp(`^${escapedKey}=.*$`, 'm');\n const quotedValue = entry.apiKey.includes('\"')\n ? (entry.apiKey.includes(\"'\") ? `'${entry.apiKey.replace(/'/g, \"'\\\\''\")}'` : `'${entry.apiKey}'`)\n : `\"${entry.apiKey}\"`;\n if (regex.test(existing)) {\n existing = existing.replace(regex, `${entry.envKey}=${quotedValue}`);\n } else {\n lines.push(`${entry.envKey}=${quotedValue}`);\n }\n }\n\n\n writeFileSync(envPath, existing + lines.join('\\n') + (lines.length > 0 ? '\\n' : ''), { mode: 0o600 });\n}\n\n// ---------------------------------------------------------------------------\n// [Improvement 3] runQuickInit — --quick / -q express mode\n// ---------------------------------------------------------------------------\n\nasync function runQuickInit(): Promise<void> {\n // Step 0 — TTY check\n if (!process.stdin.isTTY) {\n console.error('Error: modelweaver init --quick requires an interactive terminal.');\n process.exit(1);\n }\n\n // Peek at existing config for merge support\n const { peekConfig } = await import('./config.js');\n const existingPeek = peekConfig();\n const existingProviderMap = existingPeek?.providers ?? new Map();\n const existingModelRouting = existingPeek?.modelRouting ?? new Map();\n\n let configured: ConfiguredProvider[] = [];\n let configuredModels: ConfiguredModel[] = [];\n let server: { port: number; host: string };\n let yaml: string;\n\n const totalSteps = calculateTotalSteps(1, true);\n\n while (true) {\n // Welcome\n clearScreen();\n console.log(`\n${BOLD}${CYAN}\\u250C\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\u2500\n\\u2502 Welcome to ModelWeaver! \\u2501 Quick Setup \\u2502\n\\u2502 \\u2502\n\\u2501 ~${String(totalSteps).padEnd(3)} quick steps to get started \\u2501\n\\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518${RESET}\n`);\n\n // Step 1: Select single provider\n const selectedIds = await selectProviders({ singleSelect: true });\n\n if (selectedIds.length === 1 && selectedIds[0] === '__back__') {\n continue; // Go back — restart quick setup loop\n }\n\n // Step 2: Configure provider (auto-detects env key)\n configured = [];\n for (const id of selectedIds) {\n const provider = await configureProvider(id, { current: 1, total: totalSteps });\n if (provider) configured.push(provider);\n }\n\n if (configured.length === 0) {\n console.log(`\\n ${RED}No providers configured. Exiting.${RESET}\\n`);\n process.exit(1);\n }\n\n // Auto-configure models from single provider's presets\n const provider = configured[0];\n configuredModels = [];\n for (const [tier, modelName] of Object.entries(provider.models)) {\n if (modelName) {\n configuredModels.push({ alias: modelName, provider: provider.id, model: modelName, fallbacks: [] });\n }\n }\n\n // Server defaults (no prompts)\n server = { port: 3456, host: 'localhost' };\n\n // Step 3: Summary + Confirm\n yaml = buildYamlConfig(configured, configuredModels, server, existingProviderMap, existingModelRouting);\n console.log(`\\n${BOLD} Generated configuration:${RESET}\\n`);\n console.log(buildSummaryTable(configured, configuredModels, server));\n console.log();\n console.log(yaml.split('\\n').map((l) => ` ${l}`).join('\\n'));\n\n const { confirm } = await prompts(\n { type: 'confirm', name: 'confirm', message: `[Step 2 of ${totalSteps}] Write this configuration?`, initial: true },\n CANCEL,\n );\n\n if (confirm) break;\n\n console.log('\\n Restarting quick setup...\\n');\n }\n\n // Write files\n await writeConfigAndSettings(configured, configuredModels, server, yaml, totalSteps, true, !!existingPeek);\n}\n\n// ---------------------------------------------------------------------------\n// Shared file-writing + settings logic\n// ---------------------------------------------------------------------------\n\nasync function writeConfigAndSettings(\n configured: ConfiguredProvider[],\n models: ConfiguredModel[],\n server: { port: number; host: string },\n yaml: string,\n totalSteps: number,\n quick?: boolean,\n hasExisting?: boolean,\n): Promise<SettingsConfig | null> {\n const modelweaverDir = join(process.env.HOME || process.env.USERPROFILE || '', '.modelweaver');\n mkdirSync(modelweaverDir, { recursive: true });\n const configPath = join(modelweaverDir, 'config.yaml');\n if (existsSync(configPath) && hasExisting) {\n check(`Updating existing config at ${configPath}`);\n } else {\n check(`Writing new config to ${configPath}`);\n }\n writeFileSync(configPath, yaml);\n writeEnvFile(configured);\n\n // Signal daemon to reload config if it's running\n try {\n const { readPidFile, isProcessAlive } = await import('./daemon.js');\n const pid = await readPidFile();\n if (pid && isProcessAlive(pid)) {\n if (process.platform !== \"win32\") {\n try { process.kill(pid, 'SIGUSR1'); } catch { /* process may not exist */ }\n } else {\n console.log(\" Windows does not support SIGUSR1 \\u2014 run 'modelweaver reload' to pick up new config.\");\n }\n check('ModelWeaver daemon reloaded with new config');\n }\n } catch {\n // Daemon not running or daemon.js not available — silently ignore\n }\n\n // Configure Claude Code settings.json\n const result = await configureClaudeCodeSettings(models);\n\n if (result) {\n const baseUrl = server.host === 'localhost'\n ? `http://localhost:${server.port}`\n : `http://${server.host}:${server.port}`;\n\n const didBackup = backupSettings();\n if (didBackup) {\n console.log(` Backed up existing settings to settings.json.bak`);\n }\n\n const existing = readSettings();\n const merged = mergeSettings(existing, {\n baseUrl,\n defaultModel: result.defaultModel,\n availableModels: result.availableModels,\n });\n writeSettings(merged);\n\n check(`Claude Code settings updated at ${getSettingsPath()}`);\n console.log(` Proxy endpoint: ${baseUrl}`);\n console.log(` Default model: ${result.defaultModel}`);\n console.log(` Available models: ${result.availableModels.join(', ')}`);\n console.log();\n console.log(` ${GREEN}Restart Claude Code to apply changes.${RESET}`);\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Main wizard (normal mode)\n// ---------------------------------------------------------------------------\n\n// Phase constants for the phase-based loop\nconst PHASE_PROVIDERS = 0;\nconst PHASE_MODELS = 1;\nconst PHASE_SERVER = 2;\nconst PHASE_CONFIRM = 3;\n\nexport async function runInit(options?: { quick?: boolean }): Promise<void> {\n if (options?.quick) {\n return runQuickInit();\n }\n\n // Step 0 — TTY check\n if (!process.stdin.isTTY) {\n console.error('Error: modelweaver init requires an interactive terminal.');\n process.exit(1);\n }\n\n // Peek at existing config for provider detection + merge\n const { peekConfig } = await import('./config.js');\n const existingPeek = peekConfig();\n const existingProviderMap = existingPeek?.providers ?? new Map();\n const existingModelRouting = existingPeek?.modelRouting ?? new Map();\n const hasExisting = existingProviderMap.size > 0;\n\n // State that persists across phases (go-back preserves these)\n let configured: ConfiguredProvider[] = [];\n let configuredModels: ConfiguredModel[] = [];\n let allProviders: ConfiguredProvider[] = [];\n let server: { port: number; host: string } = { port: 3456, host: 'localhost' };\n let yaml: string;\n let settingsConfig: SettingsConfig | null = null;\n let useExistingModels = hasExisting;\n\n let phase = PHASE_PROVIDERS;\n\n while (true) {\n // ── PHASE: Provider configuration ──\n if (phase <= PHASE_PROVIDERS) {\n // Step 1 — Welcome\n clearScreen();\n console.log(`\n${BOLD}${CYAN}\\u2554\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2557\\u2500\n\\u2551 Welcome to ModelWeaver! \\u2551\n\\u2551 \\u2551\n\\u2551 This wizard will help you configure \\u2551\n\\u2551 your multi-provider model proxy. \\u2551\n\\u255A\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u255D${RESET}\n`);\n\n if (hasExisting) {\n // Show existing providers + action menu\n console.log(`\\n${buildExistingProvidersTable(existingProviderMap)}\\n`);\n\n const { action } = await prompts({\n type: 'select',\n name: 'action',\n message: 'What would you like to do?',\n choices: [\n { title: 'Add new provider(s)', value: 'add', description: 'Keep existing, add more' },\n { title: 'Edit existing provider', value: 'edit', description: 'Modify settings of a configured provider' },\n { title: 'Reconfigure all from scratch', value: 'reset', description: 'Start over (existing providers will be replaced)' },\n ],\n }, CANCEL);\n\n if (action === 'add') {\n const excludeIds = new Set(existingProviderMap.keys());\n const selectedIds = await selectProviders({ excludeIds });\n if (selectedIds.length === 0) {\n console.log(' No additional providers selected. All existing providers preserved.');\n }\n const totalSteps = calculateTotalSteps(\n existingProviderMap.size + selectedIds.length, false\n );\n configured = [];\n for (let i = 0; i < selectedIds.length; i++) {\n const provider = await configureProvider(\n selectedIds[i],\n { current: 1 + i, total: totalSteps }\n );\n if (provider) configured.push(provider);\n }\n } else if (action === 'edit') {\n const existingIds = [...existingProviderMap.keys()];\n const { editId } = await prompts({\n type: 'select',\n name: 'editId',\n message: 'Select provider to edit:',\n choices: [\n { title: '\\u2B05 Go back', value: '__back__' },\n ...existingIds.map(id => {\n const p = existingProviderMap.get(id)!;\n return { title: id, value: id, description: p.baseUrl };\n }),\n ],\n }, CANCEL);\n if (editId === '__back__') {\n continue; // Go back to the main action menu\n }\n const existing = existingProviderMap.get(editId as string)!;\n const totalSteps = calculateTotalSteps(existingProviderMap.size, false);\n const provider = await configureProvider(\n editId as string,\n { current: 1, total: totalSteps },\n existing,\n );\n configured = provider ? [provider] : [];\n } else {\n // 'reset' — fresh start, clear existing map so nothing gets merged\n existingProviderMap.clear();\n existingModelRouting.clear();\n useExistingModels = false;\n const selectedIds = await selectProviders();\n const totalSteps = calculateTotalSteps(selectedIds.length, false);\n configured = [];\n for (let i = 0; i < selectedIds.length; i++) {\n const provider = await configureProvider(selectedIds[i], { current: 1 + i, total: totalSteps });\n if (provider) configured.push(provider);\n }\n }\n\n if (configured.length === 0 && (existingProviderMap.size === 0)) {\n console.log(`\\n ${RED}No providers configured. Exiting.${RESET}\\n`);\n process.exit(1);\n }\n } else {\n // ── FRESH SETUP (original flow, no changes) ──\n const selectedIds = await selectProviders();\n const totalSteps = calculateTotalSteps(selectedIds.length, false);\n configured = [];\n for (let i = 0; i < selectedIds.length; i++) {\n const provider = await configureProvider(selectedIds[i], { current: 1 + i, total: totalSteps });\n if (provider) configured.push(provider);\n }\n\n if (configured.length === 0) {\n console.log(`\\n ${RED}No providers configured. Exiting.${RESET}\\n`);\n process.exit(1);\n }\n }\n\n // Build the full provider list: configured (new/edited) + untouched existing\n allProviders = buildAllProviders(configured, existingProviderMap);\n phase = PHASE_MODELS;\n }\n\n // ── PHASE: Model configuration ──\n if (phase <= PHASE_MODELS) {\n // Configure models (N-model flow)\n configuredModels = await configureModels(allProviders, useExistingModels ? existingModelRouting : undefined);\n\n // Navigation prompt: continue to server config or go back to providers\n const { nav } = await prompts({\n type: 'select',\n name: 'nav',\n message: 'Next step:',\n choices: [\n { title: 'Continue to server configuration', value: 'next', description: 'Configure port and host' },\n { title: 'Go back to provider configuration', value: 'back', description: 'Reconfigure providers' },\n ],\n }, CANCEL);\n\n if (nav === 'back') {\n phase = PHASE_PROVIDERS;\n continue;\n }\n\n phase = PHASE_SERVER;\n }\n\n // ── PHASE: Server configuration ──\n if (phase <= PHASE_SERVER) {\n // Server config\n console.log();\n const totalSteps = calculateTotalSteps(allProviders.length, false);\n const serverStep = allProviders.length + 2; // providers + models + server\n server = await configureServer({ stepInfo: { current: serverStep, total: totalSteps } });\n\n // Navigation prompt: continue to review or go back to models\n const { nav } = await prompts({\n type: 'select',\n name: 'nav',\n message: 'Next step:',\n choices: [\n { title: 'Review and write configuration', value: 'next', description: 'Confirm and save' },\n { title: 'Go back to model configuration', value: 'back', description: 'Reconfigure models' },\n ],\n }, CANCEL);\n\n if (nav === 'back') {\n phase = PHASE_MODELS;\n continue;\n }\n\n phase = PHASE_CONFIRM;\n }\n\n // ── PHASE: Review & confirm ──\n if (phase <= PHASE_CONFIRM) {\n // Review & confirm\n yaml = buildYamlConfig(allProviders, configuredModels, server, existingProviderMap, existingModelRouting);\n console.log(`\\n${BOLD} Generated configuration:${RESET}\\n`);\n console.log(buildSummaryTable(allProviders, configuredModels, server));\n console.log();\n console.log(yaml.split('\\n').map((l) => ` ${l}`).join('\\n'));\n\n const totalSteps = calculateTotalSteps(allProviders.length, false);\n const confirmStep = allProviders.length + 3; // providers + models + server + confirm\n const { confirm } = await prompts(\n { type: 'confirm', name: 'confirm', message: `[Step ${confirmStep} of ${totalSteps}] Write this configuration?`, initial: true },\n CANCEL,\n );\n\n if (confirm) break;\n\n // Go back to server configuration instead of restarting the entire wizard\n console.log('\\n Returning to server configuration...\\n');\n phase = PHASE_SERVER;\n continue;\n }\n }\n\n // Write files + settings\n const finalTotalSteps = calculateTotalSteps(configured.length, false);\n settingsConfig = await writeConfigAndSettings(configured, configuredModels, server, yaml, finalTotalSteps, false, hasExisting);\n\n // Step 8 — Success banner\n console.log(`\n${BOLD}${CYAN}\\u2554\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2557\n\\u2551 ModelWeaver is configured! \\u2551\n\\u2551 \\u2551\n${settingsConfig\n ? `\\u2551 Claude Code settings have been updated. \\u2551\n\\u2551 \\u2551\n\\u2551 Just restart Claude Code to get started. \\u2551`\n : `\\u2551 To use with Claude Code: \\u2551\n\\u2551 \\u2551\n\\u2551 Terminal 1: \\u2551\n\\u2551 modelweaver \\u2551\n\\u2551 \\u2551\n\\u2551 Terminal 2: \\u2551\n\\u2551 export ANTHROPIC_BASE_URL=\\\\ \\u2551\n\\u2551 http://localhost:${String(server.port).padEnd(25)}\\u2551\n\\u2551 claude \\u2551`\n}\n\\u255A\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u255D${RESET}\n`);\n}\n","/**\n * Provider preset templates for the ModelWeaver init wizard.\n */\n\nexport interface ProviderPreset {\n /** Machine name for config keys (e.g., \"anthropic\") */\n id: string;\n /** Display name (e.g., \"Anthropic\") */\n name: string;\n /** API base URL */\n baseUrl: string;\n /** Suggested env var name (e.g., \"ANTHROPIC_API_KEY\") */\n envKey: string;\n /** How to send the API key */\n authType: \"bearer\" | \"anthropic\";\n /** API endpoint path used for key validation */\n testPath: string;\n models: {\n sonnet: string;\n opus: string;\n haiku: string;\n };\n}\n\nconst PRESETS: ProviderPreset[] = [\n {\n id: \"anthropic\",\n name: \"Anthropic\",\n baseUrl: \"https://api.anthropic.com\",\n envKey: \"ANTHROPIC_API_KEY\",\n authType: \"anthropic\",\n testPath: \"/v1/messages\",\n models: {\n sonnet: \"claude-sonnet-4-20250514\",\n opus: \"claude-opus-4-20250514\",\n haiku: \"claude-haiku-4-5-20251001\",\n },\n },\n {\n id: \"openrouter\",\n name: \"OpenRouter\",\n baseUrl: \"https://openrouter.ai/api\",\n envKey: \"OPENROUTER_API_KEY\",\n authType: \"bearer\",\n testPath: \"/v1/chat/completions\",\n models: {\n sonnet: \"anthropic/claude-sonnet-4\",\n opus: \"anthropic/claude-opus-4\",\n haiku: \"anthropic/claude-haiku-4\",\n },\n },\n {\n id: \"together\",\n name: \"Together AI\",\n baseUrl: \"https://api.together.xyz\",\n envKey: \"TOGETHER_API_KEY\",\n authType: \"bearer\",\n testPath: \"/v1/chat/completions\",\n models: {\n sonnet: \"meta-llama/Llama-3.3-70B-Instruct-Turbo\",\n opus: \"meta-llama/Llama-3.3-70B-Instruct-Turbo\",\n haiku: \"meta-llama/Llama-3.3-70B-Instruct-Turbo\",\n },\n },\n {\n id: \"glm\",\n name: \"GLM (Z.ai)\",\n baseUrl: \"https://api.z.ai/api/anthropic\",\n envKey: \"GLM_API_KEY\",\n authType: \"anthropic\",\n testPath: \"/v1/messages\",\n models: {\n sonnet: \"claude-sonnet-4-20250514\",\n opus: \"claude-opus-4-20250514\",\n haiku: \"claude-haiku-4-5-20251001\",\n },\n },\n {\n id: \"minimax\",\n name: \"Minimax\",\n baseUrl: \"https://api.minimax.io/anthropic\",\n envKey: \"MINIMAX_API_KEY\",\n authType: \"anthropic\",\n testPath: \"/v1/messages\",\n models: {\n sonnet: \"MiniMax-M2.7\",\n opus: \"MiniMax-M2.7\",\n haiku: \"MiniMax-M2.7\",\n },\n },\n {\n id: \"fireworks\",\n name: \"Fireworks\",\n baseUrl: \"https://api.fireworks.ai/inference/v1\",\n envKey: \"FIREWORKS_API_KEY\",\n authType: \"bearer\",\n testPath: \"/chat/completions\",\n models: {\n sonnet: \"accounts/fireworks/models/claude-sonnet-4\",\n opus: \"accounts/fireworks/models/claude-opus-4\",\n haiku: \"accounts/fireworks/models/claude-haiku-4\",\n },\n },\n];\n\n/** Returns all available provider presets. */\nexport function getPresets(): ProviderPreset[] {\n return PRESETS;\n}\n\n/** Returns a single preset by its machine-readable id, or undefined if not found. */\nexport function getPreset(id: string): ProviderPreset | undefined {\n return PRESETS.find((p) => p.id === id);\n}\n","// src/settings.ts — Read/write/merge Claude Code settings.json\nimport { readFileSync, writeFileSync, existsSync, copyFileSync, mkdirSync, renameSync, unlinkSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\n\n// --- Types ---\n\nexport interface ClaudeSettings {\n env?: Record<string, string>;\n model?: string;\n [key: string]: unknown;\n}\n\nexport interface SettingsWriteOptions {\n baseUrl: string; // e.g., \"http://localhost:3456\"\n defaultModel?: string; // top-level model override\n tierModels?: { // tier alias overrides\n sonnet?: string;\n opus?: string;\n haiku?: string;\n };\n availableModels?: string[]; // model aliases for /model picker\n}\n\n// --- Paths ---\n\nconst CLAUDE_DIR = join(homedir(), \".claude\");\nconst SETTINGS_PATH = join(CLAUDE_DIR, \"settings.json\");\nconst BACKUP_PATH = join(CLAUDE_DIR, \"settings.json.bak\");\n\n// --- Public API ---\n\nexport function getSettingsPath(): string {\n return SETTINGS_PATH;\n}\n\n/**\n * Read ~/.claude/settings.json. Returns empty object if file doesn't exist.\n */\nexport function readSettings(): ClaudeSettings {\n if (!existsSync(SETTINGS_PATH)) return {};\n const raw = readFileSync(SETTINGS_PATH, \"utf-8\");\n try {\n return JSON.parse(raw) as ClaudeSettings;\n } catch (err) {\n // Log the error so the user knows settings failed to parse\n console.error(\"[settings] Failed to parse settings.json:\", err);\n throw err;\n }\n}\n\n/**\n * Backup existing settings.json to settings.json.bak.\n * Returns true if backup was created, false if no file to backup.\n */\nexport function backupSettings(): boolean {\n if (!existsSync(SETTINGS_PATH)) return false;\n console.log(\"[settings] Backing up existing settings to .bak\");\n copyFileSync(SETTINGS_PATH, BACKUP_PATH);\n return true;\n}\n\n/**\n * Merge model-routing fields into existing settings, preserving everything else.\n *\n * Strategy:\n * - Deep-merge `env` (overwrite only our keys, leave user's keys untouched)\n * - Set top-level `model` only if provided\n * - Preserve all other top-level keys (permissions, hooks, etc.)\n */\nexport function mergeSettings(\n existing: ClaudeSettings,\n options: SettingsWriteOptions\n): ClaudeSettings {\n const result: ClaudeSettings = { ...existing };\n\n // Deep-merge env\n result.env = { ...(existing.env || {}) };\n\n // Our keys to set\n const envKeys: Record<string, string> = {\n ANTHROPIC_BASE_URL: options.baseUrl,\n };\n\n for (const [key, value] of Object.entries(envKeys)) {\n result.env[key] = value;\n }\n\n // Tier alias overrides (only set if provided)\n if (options.tierModels) {\n const tierEnvMap: Record<string, string> = {\n sonnet: \"ANTHROPIC_DEFAULT_SONNET_MODEL\",\n opus: \"ANTHROPIC_DEFAULT_OPUS_MODEL\",\n haiku: \"ANTHROPIC_DEFAULT_HAIKU_MODEL\",\n };\n for (const [tier, envKey] of Object.entries(tierEnvMap)) {\n const modelValue = options.tierModels[tier as keyof typeof options.tierModels];\n if (modelValue) {\n result.env[envKey] = modelValue;\n }\n }\n }\n\n // Top-level model override\n if (options.defaultModel) {\n result.model = options.defaultModel;\n }\n\n // availableModels — set if provided, otherwise leave untouched\n if (options.availableModels && options.availableModels.length > 0) {\n result.availableModels = options.availableModels;\n }\n\n return result;\n}\n\n/**\n * Write settings to ~/.claude/settings.json.\n * Creates the directory if it doesn't exist.\n */\nexport function writeSettings(settings: ClaudeSettings): void {\n mkdirSync(dirname(SETTINGS_PATH), { recursive: true });\n const tmpPath = SETTINGS_PATH + \".tmp\";\n try {\n writeFileSync(tmpPath, JSON.stringify(settings, null, 2) + \"\\n\", \"utf-8\");\n renameSync(tmpPath, SETTINGS_PATH);\n } catch (err) {\n // Log the error so the user knows settings failed to write\n console.error(\"[settings] Failed to write settings.json:\", err);\n // Clean up temp file if it exists\n try { unlinkSync(tmpPath); } catch { /* ignore */ }\n throw err;\n }\n}\n"],"mappings":"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","names":["prompts","PRESETS","getPresets","getPreset","id","p","stringifyYaml","writeFileSync","existsSync","readFileSync","mkdirSync","join","readFileSync","writeFileSync","existsSync","copyFileSync","mkdirSync","renameSync","unlinkSync","join","dirname","homedir","CLAUDE_DIR","SETTINGS_PATH","BACKUP_PATH","getSettingsPath","readSettings","raw","err","backupSettings","mergeSettings","existing","options","result","envKeys","key","value","tierEnvMap","tier","envKey","modelValue","writeSettings","settings","tmpPath","net","CANCEL","GREEN","RED","CYAN","BOLD","RESET","check","msg","fail","clearScreen","testApiKey","baseUrl","apiKey","preset","controller","timeout","headers","res","err","detectEnvApiKey","envVal","calculateTotalSteps","selectedProviderCount","quick","buildSummaryTable","providers","models","server","lines","m","provider","p","pName","info","fb","fbProvider","fbInfo","buildExistingProvidersTable","existingProviders","id","envLabel","padding","buildAllProviders","configured","existingMap","touchedIds","result","ep","getPreset","selectProviders","options","allPresets","getPresets","providerId","prompts","providerIds","configureProvider","stepInfo","existing","effectiveEnvKey","effectiveBaseUrl","effectiveAuthType","detected","customDetected","stepLabel","MAX_RETRIES","attempt","retry","configureFallbacks","alias","primaryProviderId","existingFallbacks","fallbacks","addFallback","availableProviders","providerChoices","selectedProvider","modelName","buildExistingModelsTable","modelRouting","entries","chain","primary","i","configureModels","existingModels","hasExisting","action","newModel","modelChoices","editAlias","idx","current","currentFallbacks","newAlias","fbPName","fallbackActions","fallbackAction","fbChoices","removeIdx","removed","deleteAlias","addModel","presetModel","addMore","isPortInUse","port","host","resolve","configureServer","proceed","configureClaudeCodeSettings","configure","defaultModel","availableModels","buildYamlConfig","existingModelRouting","e","configObj","providerConfig","stringifyYaml","writeEnvFile","envDir","join","envPath","mkdirSync","existsSync","readFileSync","entry","escapedKey","regex","quotedValue","writeFileSync","runQuickInit","peekConfig","existingPeek","existingProviderMap","configuredModels","yaml","totalSteps","selectedIds","tier","l","confirm","writeConfigAndSettings","modelweaverDir","configPath","readPidFile","isProcessAlive","pid","backupSettings","readSettings","merged","mergeSettings","writeSettings","getSettingsPath","PHASE_PROVIDERS","PHASE_MODELS","PHASE_SERVER","PHASE_CONFIRM","runInit","allProviders","settingsConfig","useExistingModels","phase","excludeIds","existingIds","editId","nav","serverStep","confirmStep","finalTotalSteps"]}
|