@mikedown/core 0.3.0 → 0.4.0
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/CHANGELOG.md +12 -1
- package/README.md +1 -1
- package/dist/ai/engines-page.d.ts +11 -4
- package/dist/ai/engines-page.js +5 -4
- package/dist/ai/index.d.ts +1201 -10
- package/dist/ai/index.js +297 -8
- package/dist/{ai-ui-C7ENTWWU.js → ai-ui-QFYFN73D.js} +3165 -138
- package/dist/ai-ui-QFYFN73D.js.map +1 -0
- package/dist/{chunk-QDVY7WW6.js → chunk-APPBNQEY.js} +53 -2
- package/dist/chunk-APPBNQEY.js.map +1 -0
- package/dist/{chunk-7A5HEPLK.js → chunk-DWXGWVA3.js} +850 -12
- package/dist/chunk-DWXGWVA3.js.map +1 -0
- package/dist/{chunk-JZWKEBCI.js → chunk-IWCXWUWW.js} +3260 -201
- package/dist/chunk-IWCXWUWW.js.map +1 -0
- package/dist/{chunk-LXZG7IKN.js → chunk-N4N54LK2.js} +2 -2
- package/dist/chunk-N4N54LK2.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +399 -38
- package/dist/index.js.map +1 -1
- package/dist/schema-DVfssxQX.d.ts +100 -0
- package/dist/styles.css +943 -4
- package/dist/{types-CsVNVSNY.d.ts → types-2TZErbJr.d.ts} +25 -3
- package/dist/{types-CgEeIUhi.d.ts → types-DO8UBybZ.d.ts} +316 -7
- package/package.json +1 -1
- package/dist/ai-ui-C7ENTWWU.js.map +0 -1
- package/dist/chunk-7A5HEPLK.js.map +0 -1
- package/dist/chunk-JZWKEBCI.js.map +0 -1
- package/dist/chunk-LXZG7IKN.js.map +0 -1
- package/dist/chunk-QDVY7WW6.js.map +0 -1
- package/dist/schema-DYzxkuSb.d.ts +0 -46
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ai-settings-model.ts","../src/ai-settings-session.ts","../src/ai-local-setup.ts","../src/ai-settings-dom.ts","../src/ai-engine-form.ts","../src/ai-routing-section.ts","../src/ai-setup-wizard.ts","../src/ai-engines-page.ts"],"sourcesContent":["/**\n * Pure helpers behind the AI settings tab (`ai-settings.ts`) and the sidebar\n * indicator chip: which engine/model pairs a picker may offer, the warnings an\n * engine row shows, the route a task would really get, draft edits that must\n * keep unknown keys, and the chip's text. No DOM here, so all of it is unit\n * tested without mounting the modal.\n *\n * Settings objects carry keys this version does not know (a newer version's);\n * every edit spreads the object it changes rather than rebuilding it.\n */\n\nimport {\n AI_ENGINE_PRESETS,\n AI_TASKS,\n DEFAULT_CONTEXT_TOKENS,\n DEFAULT_LOCAL_NETWORKS,\n aiConsentHost,\n detectCapabilities,\n detectLocality,\n engineLocality,\n generateAiId,\n getAiTask,\n isHostEngineKind,\n isKnownEngineKind,\n localityMismatch,\n mergeDiscoveredModels,\n localDefaultModel,\n missingCapabilities,\n presetForEngine,\n resolveRoute,\n serializeAiSettings,\n whatIsSent,\n withThinkingLevel,\n} from './ai';\nimport type {\n AiCapabilityFlag,\n AiCapabilityRequirements,\n AiDiscoveredModel,\n AiEngineConfig,\n AiEngineKind,\n AiEnginePreset,\n AiEngineStatus,\n AiErrorCode,\n AiLocalServerProbe,\n AiLocality,\n AiModelCapabilities,\n AiModelConfig,\n AiPopularRule,\n AiPresetFamily,\n AiRoute,\n AiRouteResolution,\n AiSendsScope,\n AiServedBy,\n AiSettings,\n AiSettingsPatch,\n AiThinkingLevel,\n} from './ai';\nimport type { AiHostTier } from './ai-lite';\n\n// ── Host tier ───────────────────────────────────────────────────────────────\n\n// In ai-lite.ts: the editor needs it before the AI UI loads.\nexport { aiHostTier, type AiHostTier } from './ai-lite';\n\n// ── Labels ──────────────────────────────────────────────────────────────────\n\nexport const AI_ENGINE_KIND_LABELS: Readonly<Record<AiEngineKind, string>> = {\n 'openai-compatible': 'OpenAI-compatible',\n lmstudio: 'LM Studio',\n ollama: 'Ollama',\n anthropic: 'Anthropic',\n openai: 'OpenAI',\n 'vscode-lm': 'GitHub Copilot (VS Code)',\n};\n\nexport function engineKindLabel(kind: string): string {\n return isKnownEngineKind(kind) ? AI_ENGINE_KIND_LABELS[kind] : `Unknown (${kind})`;\n}\n\n/** Chips in the models table, in display order. `stream` is assumed and not shown. */\nexport const AI_CAPABILITY_CHIPS: ReadonlyArray<{ flag: AiCapabilityFlag; label: string; title: string }> = [\n { flag: 'chat', label: 'chat', title: 'Chat and instruct completions' },\n { flag: 'vision', label: 'vision', title: 'Image inputs' },\n { flag: 'json', label: 'json', title: 'JSON mode or reliable structured output' },\n { flag: 'tools', label: 'tools', title: 'Function calling' },\n { flag: 'fim', label: 'fim', title: 'Fill-in-the-middle (inline suggestions)' },\n { flag: 'embed', label: 'embed', title: 'Embeddings' },\n];\n\nconst CAPABILITY_WORDS: Record<keyof AiModelCapabilities, string> = {\n chat: 'chat',\n stream: 'streaming',\n vision: 'vision',\n json: 'JSON output',\n tools: 'tools',\n fim: 'fill-in-the-middle',\n embed: 'embeddings',\n contextTokens: 'a large enough context window',\n};\n\nexport function engineDisplayName(engine: Pick<AiEngineConfig, 'id' | 'name'>): string {\n return engine.name.trim() || engine.id;\n}\n\nexport function modelDisplayName(model: Pick<AiModelConfig, 'id' | 'label'>): string {\n return model.label?.trim() || model.id;\n}\n\n/** `127.0.0.1:8000` or `api.anthropic.com`, for the engine row's subline. */\nexport function shortUrl(baseUrl: string): string {\n const stripped = baseUrl.trim().replace(/^[a-z][a-z0-9+.-]*:\\/\\//i, '');\n const authority = stripped.split(/[/?#]/, 1)[0];\n return authority || baseUrl.trim();\n}\n\n/** 262144 to \"256k\", 200000 to \"200k\", 8192 to \"8k\". */\nexport function formatTokens(tokens: number | null | undefined): string {\n const n = tokens ?? DEFAULT_CONTEXT_TOKENS;\n if (n >= 1024 * 1024 && n % (1024 * 1024) === 0) {return `${n / (1024 * 1024)}M`;}\n if (n >= 1000000 && n % 1000000 === 0) {return `${n / 1000000}M`;}\n if (n >= 1024 && n % 1024 === 0) {return `${n / 1024}k`;}\n if (n >= 1000 && n % 1000 === 0) {return `${n / 1000}k`;}\n return String(n);\n}\n\n// ── Drafts and ids ──────────────────────────────────────────────────────────\n\n/** A deep, plain-JSON copy the tab can edit without touching the host's object. */\nexport function cloneAiSettings(settings: AiSettings): AiSettings {\n return JSON.parse(JSON.stringify(settings)) as AiSettings;\n}\n\n/** A fresh engine id that no engine in `existing` uses. Ids are never shown or edited. */\nexport function uniqueEngineId(name: string, existing: Iterable<string>): string {\n const taken = new Set(existing);\n let id = generateAiId(name);\n while (taken.has(id)) {id = generateAiId(name);}\n return id;\n}\n\nexport function engineFromPreset(preset: AiEnginePreset, existingIds: Iterable<string>): AiEngineConfig {\n const engine: AiEngineConfig = {\n id: uniqueEngineId(preset.name, existingIds),\n name: preset.name,\n kind: preset.kind,\n baseUrl: preset.baseUrl,\n enabled: true,\n locality: 'auto',\n discovery: 'auto',\n models: [],\n };\n if (preset.apiKeyEnv) {engine.apiKeyEnv = preset.apiKeyEnv;}\n if (preset.apiKeyFile) {engine.apiKeyFile = { ...preset.apiKeyFile };}\n return engine;\n}\n\n/**\n * Group presets for the quick-start cards by family (where they run). `host`\n * presets (VS Code's Copilot models) are kept apart: they show only where\n * the host reports one (`detectHostEngines`).\n */\nexport function groupPresets(presets: readonly AiEnginePreset[]): { local: AiEnginePreset[]; cloud: AiEnginePreset[]; host: AiEnginePreset[] } {\n const groups: { local: AiEnginePreset[]; cloud: AiEnginePreset[]; host: AiEnginePreset[] } = { local: [], cloud: [], host: [] };\n for (const p of presets) {groups[p.family].push(p);}\n return groups;\n}\n\n/** Replace one engine (by id), keeping the order. */\nexport function withEngine(settings: AiSettings, engine: AiEngineConfig): AiSettings {\n return { ...settings, engines: settings.engines.map((e) => (e.id === engine.id ? engine : e)) };\n}\n\n/** Drop an engine and every route that points at it. */\nexport function removeEngine(settings: AiSettings, engineId: string): AiSettings {\n const tasks: Record<string, AiRoute> = {};\n for (const [task, route] of Object.entries(settings.routing.tasks)) {\n if (route.engineId !== engineId) {tasks[task] = route;}\n }\n const def = settings.routing.default?.engineId === engineId ? null : settings.routing.default;\n return {\n ...settings,\n engines: settings.engines.filter((e) => e.id !== engineId),\n routing: { ...settings.routing, default: def, tasks },\n };\n}\n\n/** Drop routes to one model (after it is removed from its engine). */\nexport function removeRoutesTo(settings: AiSettings, engineId: string, modelId: string): AiSettings {\n const hits = (r: AiRoute | null | undefined) => !!r && r.engineId === engineId && r.modelId === modelId;\n const tasks: Record<string, AiRoute> = {};\n for (const [task, route] of Object.entries(settings.routing.tasks)) {\n if (!hits(route)) {tasks[task] = route;}\n }\n return { ...settings, routing: { ...settings.routing, default: hits(settings.routing.default) ? null : settings.routing.default, tasks } };\n}\n\nexport function withModel(engine: AiEngineConfig, model: AiModelConfig): AiEngineConfig {\n return { ...engine, models: engine.models.map((m) => (m.id === model.id ? model : m)) };\n}\n\n/** Flip one capability chip. Any hand edit makes the row `user`, so re-discovery leaves it alone. */\nexport function toggleModelCapability(model: AiModelConfig, flag: AiCapabilityFlag): AiModelConfig {\n return {\n ...model,\n capabilities: { ...model.capabilities, [flag]: !model.capabilities[flag] },\n capabilitiesSource: 'user',\n };\n}\n\n/** Set the context window; null means unknown (treated as the default). */\nexport function setModelContextTokens(model: AiModelConfig, tokens: number | null): AiModelConfig {\n return { ...model, capabilities: { ...model.capabilities, contextTokens: tokens }, capabilitiesSource: 'user' };\n}\n\n/** Parse the context field: blank is unknown, otherwise a positive whole number. */\nexport function parseContextTokens(text: string): { ok: true; value: number | null } | { ok: false; error: string } {\n const t = text.trim().replace(/[_,\\s]/g, '');\n if (!t) {return { ok: true, value: null };}\n const m = /^(\\d+(?:\\.\\d+)?)([kKmM]?)$/.exec(t);\n if (!m) {return { ok: false, error: 'Enter a number of tokens, such as 32768 or 32k.' };}\n const scale = m[2] === '' ? 1 : m[2].toLowerCase() === 'k' ? 1024 : 1024 * 1024;\n const value = Math.round(Number(m[1]) * scale);\n if (!Number.isFinite(value) || value <= 0) {return { ok: false, error: 'Enter a number of tokens, such as 32768 or 32k.' };}\n return { ok: true, value };\n}\n\n/** Add a model by hand. It stays put when a later discovery does not list it. */\nexport function addManualModel(engine: AiEngineConfig, rawId: string): { ok: true; engine: AiEngineConfig; model: AiModelConfig } | { ok: false; error: string } {\n const id = rawId.trim();\n if (!id) {return { ok: false, error: 'Enter the model id the server knows it by.' };}\n if (engine.models.some((m) => m.id === id)) {return { ok: false, error: `${id} is already in the list.` };}\n const model: AiModelConfig = {\n id,\n enabled: true,\n capabilities: detectCapabilities(id, isKnownEngineKind(engine.kind) ? engine.kind : undefined).capabilities,\n capabilitiesSource: 'heuristic',\n manual: true,\n };\n return { ok: true, engine: { ...engine, models: [...engine.models, model] }, model };\n}\n\n/**\n * The Local networks field: one entry per line (commas work too). An entry\n * is an IPv4 address or CIDR range (`10.0.98.0/24`) or a host-name suffix\n * (`.ts.net`), the two forms `detectLocality` understands. Blank restores\n * the defaults. Any bad entry fails the whole edit, so a typo never saves a\n * range that silently matches nothing.\n */\nexport function parseLocalNetworksText(text: string): { ok: true; value: string[] } | { ok: false; error: string } {\n const entries = [...new Set(text.split(/[\\s,]+/).map((e) => e.trim().toLowerCase()).filter((e) => e.length > 0))];\n if (entries.length === 0) {return { ok: true, value: [...DEFAULT_LOCAL_NETWORKS] };}\n const bad: string[] = [];\n for (const entry of entries) {\n const numeric = /^\\d/.test(entry);\n const valid = numeric\n ? /^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})(?:\\/(\\d{1,2}))?$/.test(entry)\n && entry.split('/')[0].split('.').every((p) => Number(p) <= 255)\n && Number(entry.split('/')[1] ?? 0) <= 32\n : /^\\.?[a-z0-9]([a-z0-9.-]*[a-z0-9])?$/.test(entry);\n if (!valid) {bad.push(entry);}\n }\n if (bad.length > 0) {\n return { ok: false, error: `Not a network or host name: ${bad.join(', ')}. Use an IPv4 range like 10.0.98.0/24 or a suffix like .ts.net.` };\n }\n return { ok: true, value: entries };\n}\n\n/**\n * The per-model `requestOverrides` editor. Blank clears it; anything else\n * must be a JSON object, which is merged into the request body last.\n */\nexport function parseRequestOverrides(text: string): { ok: true; value: Record<string, unknown> | undefined } | { ok: false; error: string } {\n const t = text.trim();\n if (!t) {return { ok: true, value: undefined };}\n let parsed: unknown;\n try {\n parsed = JSON.parse(t);\n } catch (err) {\n const detail = err instanceof Error ? err.message.replace(/^JSON\\.parse:\\s*/, '') : '';\n return { ok: false, error: detail ? `Not valid JSON: ${detail}` : 'Not valid JSON.' };\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return { ok: false, error: 'Must be a JSON object, such as { \"reasoning_effort\": \"low\" }.' };\n }\n return { ok: true, value: parsed as Record<string, unknown> };\n}\n\nexport function formatRequestOverrides(value: Record<string, unknown> | undefined): string {\n return value && Object.keys(value).length > 0 ? JSON.stringify(value, null, 2) : '';\n}\n\n/**\n * Merge a `discoverModels` result into the draft engine. Models the host\n * marks missing are left out of the discovered list, so the merge marks\n * them missing too (manual models excepted).\n */\nexport function mergeDiscoveryStatus(engine: AiEngineConfig, status: AiEngineStatus): AiEngineConfig {\n const discovered: AiDiscoveredModel[] = status.models\n .filter((m) => !m.missing)\n .map((m) => {\n const d: AiDiscoveredModel = { id: m.id, capabilities: m.capabilities, source: m.source === 'endpoint' ? 'endpoint' : 'heuristic' };\n if (m.label !== undefined) {d.label = m.label;}\n if (m.loaded !== undefined) {d.loaded = m.loaded;}\n return d;\n });\n const kind = isKnownEngineKind(engine.kind) ? engine.kind : undefined;\n return { ...engine, models: mergeDiscoveredModels(engine.models, discovered, kind) };\n}\n\n/** True when the fields the host needs to reach an engine differ (so Test must save first). */\nexport function connectionDiffers(a: AiEngineConfig | undefined, b: AiEngineConfig | undefined): boolean {\n if (!a || !b) {return a !== b;}\n return a.kind !== b.kind\n || a.baseUrl !== b.baseUrl\n || (a.apiKeyEnv ?? '') !== (b.apiKeyEnv ?? '')\n || a.locality !== b.locality\n || a.enabled !== b.enabled\n || a.discovery !== b.discovery;\n}\n\n/**\n * The `saveSettings` patch for the tab: only the `ai.*` keys whose value\n * changed, so opening and saving the modal never writes AI keys the user did\n * not touch into their settings file.\n */\nexport function changedAiPatch(original: AiSettings, draft: AiSettings): AiSettingsPatch {\n const before = serializeAiSettings(original) as Record<string, unknown>;\n const after = serializeAiSettings(draft) as Record<string, unknown>;\n const patch: AiSettingsPatch = {};\n for (const [key, value] of Object.entries(after)) {\n if (JSON.stringify(value) !== JSON.stringify(before[key])) {patch[key as `ai.${string}`] = value;}\n }\n return patch;\n}\n\n// ── Locality and engine issues ──────────────────────────────────────────────\n\nexport interface EngineLocalityInfo {\n /** What the router uses. */\n locality: AiLocality;\n /** What the URL says, whatever the pin. */\n detected: AiLocality;\n /** A pin that disagrees with the URL. */\n mismatch: boolean;\n}\n\nexport function engineLocalityInfo(engine: AiEngineConfig, localNetworks: readonly string[]): EngineLocalityInfo {\n return {\n locality: engineLocality(engine, localNetworks),\n detected: detectLocality(engine.baseUrl, localNetworks),\n mismatch: localityMismatch(engine, localNetworks),\n };\n}\n\nexport interface EngineIssue {\n level: 'warning' | 'info';\n /** Short tag for the row (pill or tooltip). */\n code: 'unsupportedKind' | 'badUrl' | 'noKey' | 'cloudBlocked' | 'localityMismatch';\n text: string;\n}\n\n/** A base URL the host can fetch: http(s) with a host. Empty string when fine, else the problem. */\nexport function baseUrlProblem(baseUrl: string): string {\n const t = baseUrl.trim();\n if (!t) {return 'Enter the server address, such as http://127.0.0.1:8000/v1.';}\n if (!/^https?:\\/\\//i.test(t)) {return 'Start the address with http:// or https://.';}\n try {\n const u = new URL(t);\n if (!u.hostname) {return 'The address has no host name.';}\n } catch {\n return 'This is not a valid address.';\n }\n return '';\n}\n\n/**\n * What an engine row warns about. `hasKey` comes from the host's status\n * (or the tab's own record of a key it just stored).\n */\nexport function engineIssues(engine: AiEngineConfig, settings: AiSettings, hasKey: boolean): EngineIssue[] {\n const issues: EngineIssue[] = [];\n if (!isKnownEngineKind(engine.kind)) {\n issues.push({ level: 'warning', code: 'unsupportedKind', text: `This version does not support the engine kind \"${String(engine.kind)}\". It is kept, but never used.` });\n }\n // A host kind (`vscode-lm`) has no address and no key.\n const hostKind = isHostEngineKind(engine.kind);\n const urlProblem = hostKind ? '' : baseUrlProblem(engine.baseUrl);\n if (urlProblem) {issues.push({ level: 'warning', code: 'badUrl', text: urlProblem });}\n const info = engineLocalityInfo(engine, settings.localNetworks);\n if (!hostKind && info.locality === 'cloud' && !hasKey && !engine.apiKeyEnv?.trim() && !engine.apiKeyFile?.path.trim()) {\n issues.push({ level: 'warning', code: 'noKey', text: 'No API key. Store one, or name the environment variable or key file that holds it.' });\n }\n if (info.mismatch) {\n issues.push({\n level: 'warning',\n code: 'localityMismatch',\n text: info.locality === 'cloud'\n ? 'Pinned to cloud, but the address looks local.'\n : 'Pinned to local, but the address looks like a cloud server. Text sent to it leaves this network.',\n });\n }\n if (info.locality === 'cloud' && !settings.allowCloud) {\n issues.push({ level: 'info', code: 'cloudBlocked', text: 'Blocked by Allow cloud.' });\n }\n return issues;\n}\n\n// ── Route pickers ───────────────────────────────────────────────────────────\n\nexport interface RoutePairOption {\n engineId: string;\n modelId: string;\n engineName: string;\n modelName: string;\n isLocal: boolean;\n /** False when the pair can never serve this route (the option is listed disabled). */\n selectable: boolean;\n /** Why it is not selectable, or a caveat on a selectable one (blocked by Allow cloud, failed test). */\n note?: string;\n}\n\nexport interface RouteRequirements {\n requires: AiCapabilityRequirements;\n requiresAny?: readonly AiCapabilityFlag[];\n}\n\n/** The default route serves any task without its own route: it needs chat. */\nexport const DEFAULT_ROUTE_REQUIREMENTS: RouteRequirements = { requires: { chat: true } };\n\nexport function taskRequirements(taskId: string): RouteRequirements {\n const task = getAiTask(taskId);\n return task ? { requires: task.requires, requiresAny: task.requiresAny } : { requires: {} };\n}\n\nfunction lackingText(lacking: Array<keyof AiModelCapabilities>): string {\n return `lacks ${lacking.map((c) => CAPABILITY_WORDS[c] ?? c).join(', ')}`;\n}\n\n/**\n * Every engine/model pair for a picker, in registry order. Pairs that can\n * never serve the route (engine or model off, model no longer listed, a\n * missing capability, an unknown engine kind) are marked not selectable with\n * the reason. Cloud pairs stay selectable while Allow cloud is off (the user\n * may be setting routes up first) but carry a note.\n */\nexport function routePairs(settings: AiSettings, statuses: readonly AiEngineStatus[], req: RouteRequirements): RoutePairOption[] {\n const statusById = new Map(statuses.map((s) => [s.engineId, s]));\n const out: RoutePairOption[] = [];\n for (const engine of settings.engines) {\n const status = statusById.get(engine.id);\n const isLocal = engineLocality(engine, settings.localNetworks) === 'local';\n for (const model of engine.models) {\n const option: RoutePairOption = {\n engineId: engine.id,\n modelId: model.id,\n engineName: engineDisplayName(engine),\n modelName: modelDisplayName(model),\n isLocal,\n selectable: false,\n };\n const lacking = missingCapabilities(model.capabilities, req.requires, req.requiresAny);\n if (!isKnownEngineKind(engine.kind)) {option.note = 'engine kind not supported';}\n else if (!engine.enabled) {option.note = 'engine is off';}\n else if (!model.enabled) {option.note = 'model is off';}\n else if (model.missing || status?.models.find((m) => m.id === model.id)?.missing) {option.note = 'no longer listed';}\n else if (lacking.length > 0) {option.note = lackingText(lacking);}\n else {\n option.selectable = true;\n if (!isLocal && !settings.allowCloud) {option.note = 'blocked by Allow cloud';}\n else if (status?.ok === false) {option.note = 'failed its last test';}\n }\n out.push(option);\n }\n }\n return out;\n}\n\nexport function routeKey(route: AiRoute | null | undefined): string {\n return route ? `${route.engineId}\\u0000${route.modelId}` : '';\n}\n\nexport function parseRouteKey(key: string): AiRoute | null {\n const i = key.indexOf('\\u0000');\n if (i <= 0 || i === key.length - 1) {return null;}\n return { engineId: key.slice(0, i), modelId: key.slice(i + 1) };\n}\n\n/** \"oMLX · Qwen 3.8 Flash Next\", or the raw ids for a route that no longer resolves. */\nexport function routeLabel(settings: AiSettings, route: AiRoute): string {\n const engine = settings.engines.find((e) => e.id === route.engineId);\n const model = engine?.models.find((m) => m.id === route.modelId);\n return `${engine ? engineDisplayName(engine) : route.engineId} · ${model ? modelDisplayName(model) : route.modelId}`;\n}\n\n/** Feature id used only to ask the router about a task (no feature gate, no extra needs). */\nconst PREVIEW_FEATURE = '\\u0000aiSettingsPreview';\n\n/**\n * The route a task would really get right now, as the router sees it, with\n * AI and the feature assumed on and no consent answers yet (a cloud engine\n * that would ask first counts as usable).\n */\nexport function previewTaskRoute(settings: AiSettings, statuses: readonly AiEngineStatus[], task: string): AiRouteResolution {\n const probe: AiSettings = { ...settings, enabled: true, features: { ...settings.features, [PREVIEW_FEATURE]: { enabled: true } } };\n return resolveRoute(probe, statuses, {}, { feature: PREVIEW_FEATURE, task });\n}\n\nexport interface TaskRouteNote {\n level: 'warning' | 'info';\n text: string;\n}\n\n/**\n * The warning under a task row: its route (own or default) cannot serve it,\n * with what serves it instead or that nothing will. Null when the route is\n * fine, or when the task has no route and no default exists yet.\n */\nexport function taskRouteNote(settings: AiSettings, statuses: readonly AiEngineStatus[], task: string): TaskRouteNote | null {\n const own = settings.routing.tasks[task];\n if (!own && !settings.routing.default) {return null;}\n const r = previewTaskRoute(settings, statuses, task);\n if ('unusable' in r) {\n // A task nobody routed is only informational (most setups have no embeddings model, say).\n if (!own) {return { level: 'info', text: `No model can serve this yet. ${r.reason}` };}\n const tail = settings.routing.fallback === 'none' ? 'Fallback is off, so this task will not run.' : 'No fallback can serve it either.';\n return { level: 'warning', text: `${r.reason} ${tail}` };\n }\n if (r.viaFallback) {\n return { level: own ? 'warning' : 'info', text: `${r.reason ?? 'The route is unavailable.'} Falls back to ${routeLabel(settings, r)}.` };\n }\n return null;\n}\n\n/** Task ids saved in `routing.tasks` that this version's taxonomy does not know. */\nexport function unknownRoutedTasks(settings: AiSettings): string[] {\n const known = new Set(AI_TASKS.map((t) => t.id));\n return Object.keys(settings.routing.tasks).filter((t) => !known.has(t));\n}\n\n/**\n * Make an engine the default: its first pair that can serve the default\n * route. Null when it has none (no models yet, or none with chat).\n */\nexport function defaultRouteForEngine(settings: AiSettings, statuses: readonly AiEngineStatus[], engineId: string): AiRoute | null {\n const pair = routePairs(settings, statuses, DEFAULT_ROUTE_REQUIREMENTS).find((p) => p.engineId === engineId && p.selectable);\n return pair ? { engineId: pair.engineId, modelId: pair.modelId } : null;\n}\n\n/**\n * Whether the default route can serve a request as saved: an enabled engine\n * of a known kind and an enabled, still listed chat model. The Engines page\n * opened by \"Set up\" turns AI on at Done only then (B3).\n */\nexport function hasUsableDefaultRoute(settings: Pick<AiSettings, 'engines' | 'routing'>): boolean {\n const route = settings.routing.default;\n const engine = route && settings.engines.find((e) => e.id === route.engineId);\n if (!route || !engine || !engine.enabled || !isKnownEngineKind(engine.kind)) {return false;}\n const model = engine.models.find((m) => m.id === route.modelId);\n return !!model && model.enabled && !model.missing && model.capabilities.chat;\n}\n\n// ── Local server detection ──────────────────────────────────────────────────\n\n/** One local quick-start card after detection. */\nexport interface LocalServerCard {\n presetId: string;\n baseUrl: string;\n running: boolean;\n /** Models the server listed, when it answered with a list. */\n models?: number;\n latencyMs?: number;\n /** An engine at this address already exists (`engineId`): the card opens it instead of adding another. */\n alreadyAdded: boolean;\n engineId?: string;\n}\n\n/** Scheme, host and port, with `localhost` and `127.0.0.1` the same, plus the path without a trailing slash. */\nfunction addressKey(url: string): string {\n try {\n const u = new URL(url.trim());\n const host = u.hostname === 'localhost' || u.hostname === '[::1]' ? '127.0.0.1' : u.hostname;\n return `${u.protocol}//${host}:${u.port || (u.protocol === 'https:' ? '443' : '80')}${u.pathname.replace(/\\/+$/, '')}`.toLowerCase();\n } catch {\n return url.trim().toLowerCase().replace(/\\/+$/, '');\n }\n}\n\n/**\n * The local cards' order after a detection: servers that answered and are\n * not set up yet first (most models first), then the ones that did not\n * answer, then those that already have an engine. Ties keep the probe order\n * (the presets'). An engine counts as this preset's when it has the same kind\n * and address and does not look like another preset's (oMLX and vLLM share\n * port 8000; `presetForEngine` tells them apart by key variable).\n */\nexport function rankLocalCandidates(\n probes: readonly AiLocalServerProbe[],\n existingEngines: readonly Pick<AiEngineConfig, 'id' | 'kind' | 'baseUrl' | 'apiKeyEnv'>[],\n presets: readonly AiEnginePreset[] = AI_ENGINE_PRESETS,\n): LocalServerCard[] {\n const cards = probes.map((probe, index) => {\n const preset = presets.find((p) => p.id === probe.presetId);\n const engine = preset && existingEngines.find((e) =>\n e.kind === preset.kind\n && addressKey(e.baseUrl) === addressKey(probe.baseUrl)\n && (presetForEngine(e, presets)?.id ?? preset.id) === preset.id);\n const card: LocalServerCard = { presetId: probe.presetId, baseUrl: probe.baseUrl, running: probe.ok, alreadyAdded: !!engine };\n if (engine) {card.engineId = engine.id;}\n if (probe.ok && probe.models !== undefined) {card.models = probe.models;}\n if (probe.latencyMs !== undefined) {card.latencyMs = probe.latencyMs;}\n return { card, index };\n });\n const rank = (c: LocalServerCard) => (c.alreadyAdded ? 2 : c.running ? 0 : 1);\n return cards\n .sort((a, b) => rank(a.card) - rank(b.card)\n || (a.card.running && b.card.running ? (b.card.models ?? 0) - (a.card.models ?? 0) : 0)\n || a.index - b.index)\n .map((x) => x.card);\n}\n\n// ── Indicator chip ──────────────────────────────────────────────────────────\n\nexport type AiIndicatorTone = 'off' | 'on' | 'local' | 'cloud' | 'none';\n\nexport interface AiIndicatorState {\n /** Visible text, e.g. \"AI: local · oMLX · Qwen 3.8 Flash Next\". */\n text: string;\n tone: AiIndicatorTone;\n /** Tooltip. */\n title: string;\n /** A fallback served the last request. */\n fallback: boolean;\n /** The serving engine's pinned locality disagrees with its address. */\n warn: boolean;\n}\n\n/**\n * What served a request, plus the request's feature and scope when the\n * editor knows them (the popover attaches them), so the chip can say what\n * was sent. Hosts never set the extra fields.\n */\nexport type AiServedRequest = AiServedBy & { feature?: string; sends?: AiSendsScope };\n\nexport interface AiIndicatorInput {\n settings: AiSettings;\n statuses: readonly AiEngineStatus[];\n tier: AiHostTier;\n /** What served the last request, if anything has. */\n served: AiServedRequest | null;\n viaFallback: boolean;\n}\n\n/** \" It sent text to api.anthropic.com: the selected text ….\" for a cloud request; empty for a local one. */\nfunction cloudSentNote(settings: AiSettings, served: AiServedRequest): string {\n if (served.isLocal) {return '';}\n const engine = served.engineId ? settings.engines.find((e) => e.id === served.engineId) : undefined;\n const host = engine ? aiConsentHost(engine) : null;\n const what = served.feature || served.sends ? whatIsSent(served.feature, served.sends) : '';\n if (host) {return what ? ` It sent text to ${host}: ${what}.` : ` It sent text to ${host}.`;}\n return what ? ` It sent ${what}.` : '';\n}\n\nfunction servedLabels(settings: AiSettings, served: AiServedBy): { engine: string; model: string; warn: boolean } {\n const engine = served.engineId ? settings.engines.find((e) => e.id === served.engineId) : undefined;\n const model = engine?.models.find((m) => m.id === served.modelId);\n return {\n engine: served.engineName || (engine ? engineDisplayName(engine) : served.engineId ?? ''),\n model: model ? modelDisplayName(model) : served.modelId,\n warn: engine ? localityMismatch(engine, settings.localNetworks) : false,\n };\n}\n\n/**\n * The sidebar chip. Null hides it: AI has never been set up (off with no\n * engines), so a release that ships AI dark shows nothing new. Otherwise\n * `AI: off`, the engine and model that served the last request, the route\n * the next request would take (before anything was sent), `AI: no model\n * chosen`, or `AI: on` for a host that routes by itself. The tooltip ends\n * with what a click opens (`openAiFromChip`): the Tasks page when no model\n * is chosen, the AI tab otherwise.\n */\n/** The chip tooltip's last sentence: what a click opens (U7). */\nexport const AI_CHIP_CLICK_SETTINGS = 'Click for AI settings.';\nexport const AI_CHIP_CLICK_CHOOSE = 'Click to choose a model.';\n\n/** The task the chip previews when nothing has been sent yet. */\nfunction indicatorTask(): string {\n return getAiTask('rewrite') ? 'rewrite' : AI_TASKS[0].id;\n}\n\n/**\n * Whether a settings change moved where the next request goes (a new default\n * engine or model, a task route). The chip drops its \"last served\" label\n * when it did, so it previews the new route, like the VS Code status bar.\n */\nexport function aiNextRouteChanged(before: AiSettings, after: AiSettings, statuses: readonly AiEngineStatus[]): boolean {\n const key = (s: AiSettings): string | null => {\n const r = previewTaskRoute(s, statuses, indicatorTask());\n return 'unusable' in r ? null : `${r.engineId}\\n${r.modelId}`;\n };\n return key(before) !== key(after);\n}\n\nexport function aiIndicatorState(input: AiIndicatorInput): AiIndicatorState | null {\n const { settings, statuses, tier, served, viaFallback } = input;\n if (!settings.enabled) {\n if (settings.engines.length === 0) {return null;}\n return { text: 'AI: off', tone: 'off', title: `AI features are turned off. ${AI_CHIP_CLICK_SETTINGS}`, fallback: false, warn: false };\n }\n if (served) {\n const where = served.isLocal ? 'local' : 'cloud';\n const l = servedLabels(settings, served);\n const parts = [`AI: ${where}`, l.engine, l.model].filter(Boolean);\n const text = parts.join(' · ') + (viaFallback ? ' (fallback)' : '');\n const title = `Last request served by ${l.engine} · ${l.model}, ${served.isLocal ? 'on this network' : 'a cloud engine'}${viaFallback ? ', through the fallback route' : ''}.${cloudSentNote(settings, served)}${l.warn ? ' Its pinned locality disagrees with its address.' : ''} ${AI_CHIP_CLICK_SETTINGS}`;\n return { text, tone: where, title, fallback: viaFallback, warn: l.warn };\n }\n if (tier === 1) {\n return { text: 'AI: on', tone: 'on', title: `AI features are on. ${AI_CHIP_CLICK_SETTINGS}`, fallback: false, warn: false };\n }\n const r = previewTaskRoute(settings, statuses, indicatorTask());\n if ('unusable' in r) {\n return { text: 'AI: no model chosen', tone: 'none', title: `${r.reason} ${AI_CHIP_CLICK_CHOOSE}`, fallback: false, warn: false };\n }\n const engine = settings.engines.find((e) => e.id === r.engineId);\n const where = r.isLocal ? 'local' : 'cloud';\n const label = routeLabel(settings, r);\n const warn = engine ? localityMismatch(engine, settings.localNetworks) : false;\n return {\n text: `AI: ${where} · ${label}${r.viaFallback ? ' (fallback)' : ''}`,\n tone: where,\n title: `Requests go to ${label}${r.isLocal ? '' : ', a cloud engine'}. Nothing has been sent yet. ${AI_CHIP_CLICK_SETTINGS}`,\n fallback: r.viaFallback,\n warn,\n };\n}\n\n// ── Express engine form ─────────────────────────────────────────────────────\n\n/** What the Express form needs to know about an engine's preset, real or inferred. */\nexport interface EngineFormPreset {\n /** Preset id, or `custom` for an engine no preset fits. */\n id: string;\n /** Preset name (\"LM Studio\"), used in failure copy. */\n name: string;\n family: AiPresetFamily;\n needsKey: boolean;\n keyHint: string;\n /** Where the provider makes API keys (cloud presets); the key hint links to it. */\n keyUrl?: string;\n /** The provider's API pricing page (cloud presets), for the \"Pricing\" link beside the key link. */\n pricingUrl?: string;\n popular: readonly AiPopularRule[];\n}\n\n/**\n * The preset behind a saved engine (see `presetForEngine`), or a stand-in\n * whose family follows the engine's locality: a hand-made engine on a cloud\n * address gets the cloud form.\n */\nexport function enginePreset(engine: AiEngineConfig, localNetworks: readonly string[]): EngineFormPreset {\n const p = presetForEngine(engine);\n if (p) {\n return {\n id: p.id,\n name: p.name,\n family: p.family,\n needsKey: p.needsKey,\n keyHint: p.keyHint,\n ...(p.keyUrl ? { keyUrl: p.keyUrl } : {}),\n ...(p.pricingUrl ? { pricingUrl: p.pricingUrl } : {}),\n popular: p.popular ?? [],\n };\n }\n const family: AiPresetFamily = engineLocality(engine, localNetworks) === 'local' ? 'local' : 'cloud';\n return {\n id: 'custom',\n name: engineDisplayName(engine),\n family,\n needsKey: family === 'cloud',\n keyHint: family === 'cloud' ? 'The API key from the provider’s console.' : 'Leave blank if the server has no auth.',\n popular: [],\n };\n}\n\nexport type ExpressField = 'name' | 'key' | 'baseUrl' | 'models' | 'defaultModel' | 'thinking' | 'enabled';\nexport type AdvancedField = 'kind' | 'baseUrl' | 'locality' | 'key' | 'keyEnv' | 'keyFile' | 'discovery' | 'modelsTable';\n\n/**\n * Which fields the Express form shows for a preset (design call 1), in\n * order, and which sit under Advanced. Cloud: the key, never the URL. Local:\n * the URL, and the key only when the server expects one (or for Custom);\n * otherwise the key moves under Advanced, so nothing is lost.\n */\nexport function expressFields(preset: Pick<EngineFormPreset, 'id' | 'family' | 'needsKey'>): { express: ExpressField[]; advanced: AdvancedField[] } {\n // Built into the host (VS Code's Copilot models): no address, no key, no thinking fields.\n if (preset.family === 'host') {\n return { express: ['name', 'models', 'defaultModel', 'enabled'], advanced: ['discovery', 'modelsTable'] };\n }\n if (preset.family === 'cloud') {\n return {\n express: ['name', 'key', 'models', 'defaultModel', 'thinking', 'enabled'],\n advanced: ['kind', 'baseUrl', 'locality', 'keyEnv', 'keyFile', 'discovery', 'modelsTable'],\n };\n }\n const keyExpress = preset.needsKey || preset.id === 'custom';\n return {\n express: keyExpress\n ? ['name', 'baseUrl', 'key', 'models', 'defaultModel', 'thinking', 'enabled']\n : ['name', 'baseUrl', 'models', 'defaultModel', 'thinking', 'enabled'],\n advanced: keyExpress\n ? ['kind', 'locality', 'keyEnv', 'keyFile', 'discovery', 'modelsTable']\n : ['kind', 'locality', 'key', 'keyEnv', 'keyFile', 'discovery', 'modelsTable'],\n };\n}\n\n/**\n * The setup wizard's compact form (W12, W13): the key, the URL on local\n * servers and one model. Name, Default model, Thinking and Enabled stay on\n * the full Engines page, and so does the models table (setup is one single\n * choice, never per-model settings). `key` brings a local server's key out of Advanced\n * (it rejected the request without one, or already has one).\n */\nexport function setupFields(preset: Pick<EngineFormPreset, 'id' | 'family' | 'needsKey'>, o: { key?: boolean } = {}): { express: ExpressField[]; advanced: AdvancedField[] } {\n const { express, advanced } = expressFields(preset);\n const kept = express.filter((f) => f === 'key' || f === 'baseUrl' || f === 'models');\n if (o.key && preset.family === 'local' && !kept.includes('key')) {\n kept.splice(kept.indexOf('models'), 0, 'key');\n return { express: kept, advanced: advanced.filter((f) => f !== 'key' && f !== 'modelsTable') };\n }\n return { express: kept, advanced: advanced.filter((f) => f !== 'modelsTable') };\n}\n\nexport interface ModelPickerOption {\n id: string;\n /** Display name (label or id). */\n name: string;\n /** The label differs from the id (the row shows both). */\n hasLabel: boolean;\n enabled: boolean;\n loaded: boolean;\n missing: boolean;\n manual: boolean;\n /** Can chat: only these can be the default model or the setup choice. */\n chat: boolean;\n /** Can be picked at all: a chat or an embeddings model. A converter or a speculative-decoding drafter (`chat: false`, no `embed`) is shown greyed out. */\n usable: boolean;\n}\n\n/**\n * The models picker's rows: filtered by id or label (case-insensitive),\n * loaded models first on LM Studio, models the server no longer lists last;\n * otherwise in the engine's order.\n */\nexport function modelPickerOptions(engine: AiEngineConfig, status: AiEngineStatus | undefined, filter = ''): ModelPickerOption[] {\n const loaded = new Map((status?.models ?? []).map((m) => [m.id, !!m.loaded]));\n const needle = filter.trim().toLowerCase();\n const rows = engine.models\n .map((m, index): ModelPickerOption & { index: number } => ({\n id: m.id,\n name: modelDisplayName(m),\n hasLabel: !!m.label?.trim() && m.label.trim() !== m.id,\n enabled: m.enabled,\n loaded: loaded.get(m.id) ?? false,\n missing: !!(m.missing || status?.models.find((s) => s.id === m.id)?.missing),\n manual: !!m.manual,\n chat: !!m.capabilities.chat,\n usable: !!(m.capabilities.chat || m.capabilities.embed),\n index,\n }))\n .filter((o) => !needle || o.id.toLowerCase().includes(needle) || o.name.toLowerCase().includes(needle));\n const rank = (o: ModelPickerOption) => (o.missing ? 2 : engine.kind === 'lmstudio' && o.loaded ? 0 : 1);\n rows.sort((a, b) => rank(a) - rank(b) || a.index - b.index);\n return rows.map(({ index: _index, ...o }) => o);\n}\n\n/** \"312 models, 2 picked\". Missing models are not counted. */\nexport function modelCountLine(engine: AiEngineConfig): string {\n const listed = engine.models.filter((m) => !m.missing);\n const picked = listed.filter((m) => m.enabled).length;\n if (listed.length === 0) {return 'No models yet';}\n return `${listed.length} ${listed.length === 1 ? 'model' : 'models'}, ${picked} picked`;\n}\n\n/**\n * Merge a discovery with OPEN-12's enabled rule: new models arrive off unless\n * `picked` names them. On a local engine the models the server has loaded\n * (chat or embeddings) arrive on too, and an engine with nothing picked yet\n * gets its default (`localDefaultModel`: a loaded chat model) picked and\n * moved first, where the star and the default route look. With none loaded\n * nothing is picked, and the user chooses. Models already in the engine keep\n * their own `enabled`.\n */\nexport function applyDiscoveryForFamily(\n engine: AiEngineConfig,\n status: AiEngineStatus,\n family: AiPresetFamily,\n picked: Iterable<string> = [],\n): AiEngineConfig {\n const merged = mergeDiscoveryStatus(engine, status);\n const before = new Set(engine.models.map((m) => m.id));\n const pick = new Set(picked);\n const loaded = new Set(status.models.filter((m) => m.loaded && !m.missing).map((m) => m.id));\n const arrivesOn = (m: AiModelConfig) =>\n pick.has(m.id) || (family === 'local' && loaded.has(m.id) && (m.capabilities.chat || m.capabilities.embed));\n let models = merged.models.map((m) => (before.has(m.id) ? m : { ...m, enabled: arrivesOn(m) }));\n const hadPick = engine.models.some((m) => m.enabled && !m.missing);\n if (family === 'local' && !hadPick) {\n // Only from the new arrivals: a model the user turned off stays off.\n const choices = models\n .filter((m) => !before.has(m.id))\n .map((m) => ({ id: m.id, chat: m.capabilities.chat, missing: m.missing, loaded: loaded.has(m.id) }));\n const def = localDefaultModel(choices);\n const chosen = models.find((m) => m.id === def);\n if (chosen) {models = [{ ...chosen, enabled: true }, ...models.filter((m) => m !== chosen)];}\n }\n return { ...merged, models };\n}\n\n/** Numbers in an id, split into a version (short numbers) and a date stamp (6+ digits). */\nfunction versionOf(id: string): { version: number[]; date: number } {\n const version: number[] = [];\n let date = 0;\n for (const n of id.match(/\\d+/g) ?? []) {\n if (n.length >= 6) {date = Math.max(date, Number(n));} else {version.push(Number(n));}\n }\n return { version, date };\n}\n\n/** Negative when `a` should rank first: a `prefer` match (a `-latest` alias), then the newer version. */\nfunction compareNewest(a: string, b: string, prefer?: RegExp): number {\n if (prefer) {\n const pa = prefer.test(a) ? 0 : 1;\n const pb = prefer.test(b) ? 0 : 1;\n if (pa !== pb) {return pa - pb;}\n }\n const va = versionOf(a);\n const vb = versionOf(b);\n for (let i = 0; i < Math.max(va.version.length, vb.version.length); i++) {\n const d = (vb.version[i] ?? 0) - (va.version[i] ?? 0);\n if (d !== 0) {return d;}\n }\n // An undated alias outranks its dated snapshots; among snapshots, the latest date.\n if (va.date !== vb.date) {return va.date === 0 ? -1 : vb.date === 0 ? 1 : vb.date - va.date;}\n return a.length - b.length || a.localeCompare(b);\n}\n\n/**\n * The Popular group: for each of the preset's rules, the newest listed model\n * that matches, in rule order. No hardcoded ids: whatever the endpoint lists\n * today decides.\n */\nexport function popularModels<M extends Pick<AiModelConfig, 'id'> & { missing?: boolean }>(\n preset: Pick<EngineFormPreset, 'popular'> | Pick<AiEnginePreset, 'popular'>,\n models: readonly M[],\n): M[] {\n const out: M[] = [];\n for (const rule of preset.popular ?? []) {\n const hits = models.filter((m) => !m.missing && rule.match.test(m.id) && !(rule.exclude?.test(m.id)) && !out.includes(m));\n if (hits.length === 0) {continue;}\n out.push(hits.slice().sort((a, b) => compareNewest(a.id, b.id, rule.prefer))[0]);\n }\n return out;\n}\n\n/**\n * The model to pick after a cloud engine's first fetch: the first Popular\n * model that can chat, else the only chat model when there is just one.\n * Null when there is nothing sensible to guess.\n */\nexport function autoPickDefault(\n preset: Pick<EngineFormPreset, 'popular'> | Pick<AiEnginePreset, 'popular'>,\n models: readonly AiModelConfig[],\n): string | null {\n const chat = (m: AiModelConfig) => !m.missing && m.capabilities.chat;\n const popular = popularModels(preset, models).find(chat);\n if (popular) {return popular.id;}\n const chatModels = models.filter(chat);\n return chatModels.length === 1 ? chatModels[0].id : null;\n}\n\n/**\n * The model to pick after a host engine's first fetch (VS Code's Copilot\n * models, which have no Popular rules): the first listed chat model, in the\n * host's own order. Null when none can chat.\n */\nexport function firstChatModelId(models: readonly AiModelConfig[]): string | null {\n return models.find((m) => !m.missing && m.capabilities.chat)?.id ?? null;\n}\n\n/**\n * The engine's Default model: the default route's model when this is the\n * default engine, else its first enabled model that is still listed (which\n * is what the star picks). Null when nothing is enabled.\n */\nexport function engineDefaultModelId(settings: AiSettings, engineId: string): string | null {\n const engine = settings.engines.find((e) => e.id === engineId);\n if (!engine) {return null;}\n const def = settings.routing.default;\n if (def?.engineId === engineId && engine.models.some((m) => m.id === def.modelId)) {return def.modelId;}\n return engine.models.find((m) => m.enabled && !m.missing)?.id ?? null;\n}\n\n/**\n * Make a model the engine's Default model: it is enabled and moved first\n * (so the star and a routing row pick it, no new settings key), and it\n * becomes the default route when this is the default engine or no default\n * route exists yet.\n */\nexport function setEngineDefaultModel(settings: AiSettings, engineId: string, modelId: string): AiSettings {\n const engine = settings.engines.find((e) => e.id === engineId);\n const model = engine?.models.find((m) => m.id === modelId);\n // Only a chat model can be a default (not embeddings, a converter or an MTP drafter).\n if (!engine || !model || !model.capabilities.chat) {return settings;}\n const models = [{ ...model, enabled: true }, ...engine.models.filter((m) => m.id !== modelId)];\n const next = withEngine(settings, { ...engine, models });\n const def = settings.routing.default;\n if (!def || def.engineId === engineId) {\n return { ...next, routing: { ...next.routing, default: { ...(def ?? {}), engineId, modelId } } };\n }\n return next;\n}\n\n/**\n * An engine that cannot be saved yet: enabled, it lists chat models, but none\n * is picked, so it has no default model (Q1). An engine with no models listed\n * (a server that is off, a cloud engine without a key) is not held back: there\n * is nothing to pick yet.\n */\nexport function engineNeedsModelPick(engine: AiEngineConfig): boolean {\n if (!engine.enabled) {return false;}\n const chat = engine.models.filter((m) => !m.missing && m.capabilities.chat);\n return chat.length > 0 && !chat.some((m) => m.enabled);\n}\n\n/** The first engine Done must stop at (`engineNeedsModelPick`), or null. */\nexport function firstEngineNeedingPick(settings: Pick<AiSettings, 'engines'>): AiEngineConfig | null {\n return settings.engines.find(engineNeedsModelPick) ?? null;\n}\n\n/**\n * Turn one model on or off in the picker. Picking a chat model while no\n * default route exists makes it the default (key = done, without a trip to\n * the star); turning off the default route's model moves the route to the\n * engine's next enabled model (or clears it).\n */\nexport function setModelPicked(settings: AiSettings, engineId: string, modelId: string, enabled: boolean): AiSettings {\n const engine = settings.engines.find((e) => e.id === engineId);\n const model = engine?.models.find((m) => m.id === modelId);\n if (!engine || !model) {return settings;}\n const next = withEngine(settings, withModel(engine, { ...model, enabled }));\n const def = next.routing.default;\n if (enabled && !def && model.capabilities.chat && engine.enabled) {\n return { ...next, routing: { ...next.routing, default: { engineId, modelId } } };\n }\n if (enabled || def?.engineId !== engineId || def.modelId !== modelId) {return next;}\n const replacement = next.engines.find((e) => e.id === engineId)?.models.find((m) => m.enabled && !m.missing);\n return { ...next, routing: { ...next.routing, default: replacement ? { ...def, modelId: replacement.id } : null } };\n}\n\n/**\n * The setup form's single choice (W16): the chosen model becomes the engine's\n * Default model, and the one the form chose before it (`previous`, its own\n * earlier pick or the auto-pick) is turned off, so setup leaves one model\n * picked. Models picked elsewhere are left alone.\n */\nexport function chooseSetupModel(settings: AiSettings, engineId: string, modelId: string, previous?: string | null): AiSettings {\n const next = setEngineDefaultModel(settings, engineId, modelId);\n if (next === settings || !previous || previous === modelId) {return next;}\n return setModelPicked(next, engineId, previous, false);\n}\n\n/** Set (or with null, clear) a model's thinking level inside its `requestOverrides`. */\nexport function setModelThinking(model: AiModelConfig, kind: string, level: AiThinkingLevel | null, local: boolean): AiModelConfig {\n const next: AiModelConfig = { ...model };\n const overrides = withThinkingLevel(kind, model.requestOverrides, level, { local });\n if (overrides) {next.requestOverrides = overrides;} else {delete next.requestOverrides;}\n return next;\n}\n\n// ── Auto-fetch ──────────────────────────────────────────────────────────────\n\n/** What can set off a model fetch in the Express form. */\nexport type AutoFetchEvent = 'open' | 'key' | 'url' | 'manual' | 'retry' | 'save';\n\n/** A snapshot of the form fields that matter for fetching, plus the event that changed them. */\nexport interface AutoFetchState {\n event: AutoFetchEvent;\n family: AiPresetFamily;\n /** What is in the key field (not the stored key, which the form never sees). */\n key: string;\n baseUrl: string;\n discovery: 'auto' | 'manual';\n /** The host has never probed or discovered this engine. */\n neverProbed?: boolean;\n /** The host has a key for the engine (stored, a variable or a key file), whatever the field says. */\n hasKey?: boolean;\n /** Models the engine has in settings now. */\n modelCount?: number;\n /** The URL or key the last fetch ran for, so a blur without a change does not fetch again. */\n fetchedFor?: string;\n}\n\nexport interface AutoFetchDecision {\n fetch: boolean;\n /** Wait this long first (a settling key); 0 runs now. */\n delayMs: number;\n /** Store the key field through `setSecret` before discovering (discovery reads the stored key). */\n storeKey: boolean;\n /** Drop a scheduled or running fetch (a newer trigger, or the key was emptied). */\n cancelPending: boolean;\n /** Value to remember as `fetchedFor` once the fetch runs. */\n fingerprint: string;\n}\n\n/** How long the key field must settle before it is stored and models are fetched (design call 3). */\nexport const AUTO_FETCH_KEY_DELAY_MS = 600;\n\n/** What a fetch ran for: the key field on a cloud engine, the URL on a local one. */\nexport function fetchFingerprint(family: AiPresetFamily, key: string, baseUrl: string): string {\n return family === 'cloud' ? `key:${key.trim()}` : `url:${baseUrl.trim()}`;\n}\n\nconst NO_FETCH = (cancelPending: boolean, fingerprint = ''): AutoFetchDecision => ({ fetch: false, delayMs: 0, storeKey: false, cancelPending, fingerprint });\n\n/**\n * When the Express form fetches models (design call 3), as plain data so\n * tests need no timers. Cloud: 600 ms after the key field settles on a new,\n * non-empty value, storing the key first, and on open for an engine with no\n * models that the host never probed but already has a key for (from\n * `ANTHROPIC_API_KEY` or a key file, B2). Local: when the URL changes (on\n * change or blur) to a new valid address, and when the form opens for an\n * engine the host never probed. Manual and Retry always run (the user\n * asked). A plain save never fetches; `discovery: manual` never auto-fetches.\n */\nexport function autoFetchDecision(prev: AutoFetchState | null, next: AutoFetchState): AutoFetchDecision {\n // A host engine (VS Code's Copilot models) has no address to check.\n const urlOk = next.family === 'host' || !baseUrlProblem(next.baseUrl);\n const key = next.key.trim();\n const cloudFingerprint = fetchFingerprint('cloud', key, next.baseUrl);\n const localFingerprint = fetchFingerprint('local', key, next.baseUrl);\n const fingerprint = next.family === 'cloud' ? cloudFingerprint : localFingerprint;\n if (next.event === 'save') {return NO_FETCH(false);}\n if (next.event === 'manual' || next.event === 'retry') {\n if (!urlOk || next.discovery === 'manual') {return NO_FETCH(false);}\n return { fetch: true, delayMs: 0, storeKey: next.family === 'cloud' ? !!key : false, cancelPending: true, fingerprint };\n }\n if (next.discovery === 'manual' || !urlOk) {return NO_FETCH(next.event === 'key' && !key);}\n if (next.family === 'cloud') {\n // The key came from a variable or a key file: the hard part is done, so fetch on open.\n if (next.event === 'open') {\n return next.hasKey && !next.modelCount && next.neverProbed\n ? { fetch: true, delayMs: 0, storeKey: false, cancelPending: true, fingerprint: cloudFingerprint }\n : NO_FETCH(false);\n }\n if (next.event !== 'key') {return NO_FETCH(false);}\n if (!key) {return NO_FETCH(true);}\n const already = (next.fetchedFor ?? prev?.fetchedFor) === cloudFingerprint;\n if (already || (prev && prev.key.trim() === key && prev.event === 'key')) {return NO_FETCH(false, cloudFingerprint);}\n return { fetch: true, delayMs: AUTO_FETCH_KEY_DELAY_MS, storeKey: true, cancelPending: true, fingerprint: cloudFingerprint };\n }\n if (next.event === 'open') {\n return next.neverProbed\n ? { fetch: true, delayMs: 0, storeKey: false, cancelPending: true, fingerprint: localFingerprint }\n : NO_FETCH(false, localFingerprint);\n }\n if (next.event === 'url') {\n if ((next.fetchedFor ?? prev?.fetchedFor) === localFingerprint) {return NO_FETCH(false, localFingerprint);}\n return { fetch: true, delayMs: 0, storeKey: false, cancelPending: true, fingerprint: localFingerprint };\n }\n // A key typed into a local engine's field is stored, but the URL drives fetching.\n return NO_FETCH(false);\n}\n\n// ── Fetch failures ──────────────────────────────────────────────────────────\n\nexport interface DiscoveryProblem {\n kind: 'unreachable' | 'auth' | 'empty' | 'other';\n text: string;\n /** Put focus back here (the key field after a rejected key). */\n focus?: 'key';\n /** Offer Retry. */\n retry: boolean;\n}\n\nconst AUTH_TEXT = /\\bHTTP 40[13]\\b|unauthori[sz]ed|forbidden|invalid[^.]*\\bkey|incorrect[^.]*\\bkey|api key|authentication/i;\nconst UNREACHABLE_TEXT = /could not reach|no answer|timed out|ECONNREFUSED|ENOTFOUND|EHOSTUNREACH|fetch failed|connection refused|network/i;\n\n/** The host's error code when it gave one, else read from the message (statuses carry text only). */\nexport function discoveryErrorCode(code: AiErrorCode | undefined, message: string | undefined): AiErrorCode {\n if (code && code !== 'unknown') {return code;}\n const text = message ?? '';\n if (AUTH_TEXT.test(text)) {return 'auth';}\n if (UNREACHABLE_TEXT.test(text)) {return 'unreachable';}\n return 'unknown';\n}\n\n/**\n * The inline message under Models after a fetch (design call 4), or null\n * when it went fine. Every failure still lets the user type a model id.\n */\nexport function discoveryProblem(input: {\n family: AiPresetFamily;\n presetName: string;\n baseUrl: string;\n ok: boolean;\n code?: AiErrorCode;\n message?: string;\n /** Models the server listed (missing ones excluded). */\n listed: number;\n}): DiscoveryProblem | null {\n if (input.ok) {\n return input.listed === 0\n ? { kind: 'empty', text: 'Server is up but no models are loaded.', retry: true }\n : null;\n }\n const code = discoveryErrorCode(input.code, input.message);\n // VS Code's Copilot models: no key or address to point at; the host's message says what to do.\n if (input.family === 'host') {\n return { kind: code === 'auth' ? 'auth' : 'other', text: input.message || `Could not list ${input.presetName}’s models.`, retry: true };\n }\n if (code === 'auth') {\n return { kind: 'auth', text: `Key rejected by ${shortUrl(input.baseUrl)}.`, focus: 'key', retry: true };\n }\n if (code === 'unreachable' && input.family === 'local') {\n const name = input.presetName.startsWith('Custom') ? 'the server' : input.presetName;\n return { kind: 'unreachable', text: `Nothing answered at ${input.baseUrl.trim()}. Is ${name} running?`, retry: true };\n }\n if (code === 'unreachable') {\n return { kind: 'unreachable', text: `Could not reach ${shortUrl(input.baseUrl)}.`, retry: true };\n }\n return { kind: 'other', text: input.message ? `Could not fetch models: ${input.message}` : 'Could not fetch models.', retry: true };\n}\n","/**\n * One editing session over the AI settings, shared by the Settings modal's AI\n * tab (`ai-settings.ts`) and the AI Engines page (`ai-engines-page.ts`): the\n * draft, the save patch, and the bookkeeping that keeps API keys and early\n * saves honest. No DOM; each view owns its own rendering and announcements.\n *\n * Everything edits a draft copy of the settings; `collect` gives only the\n * `ai.*` keys that changed. API keys never touch the draft: they go through\n * `host.ai.setSecret` as soon as a field settles, and a deleted engine's key\n * is dropped on `commit`. Test connection and fetching models need the host\n * to know the engine, so `ensureSaved` saves the engines first and waits for\n * the host's settings echo. `discard` takes back engines added in this\n * session that reached the host that way, and their keys.\n *\n * The page opened from the tab runs a child session (`fork`): it starts from\n * the tab's draft, shares what the session knows about the host (statuses,\n * stored keys), and on Done the tab `absorb`s the saved result.\n */\n\nimport { serializeAiSettings, toAiError } from './ai';\nimport type { AiEngineConfig, AiEngineStatus, AiKeySource, AiSettings, AiSettingsPatch, MikeDownAiHost } from './ai';\nimport type { AiHostTier } from './ai-settings-model';\nimport { aiHostTier, changedAiPatch, cloneAiSettings, connectionDiffers, removeEngine, withEngine } from './ai-settings-model';\n\nexport interface AiSettingsSessionOptions {\n ai: MikeDownAiHost;\n /** The settings the session starts from (the host's, or a parent session's draft). */\n settings: AiSettings;\n /** Last known engine statuses. */\n statuses: readonly AiEngineStatus[];\n /** The host's settings now (they change when the session saves engines before a test). */\n getHostSettings(): AiSettings;\n /** Persist an AI patch right away. Absent when the host cannot persist settings. */\n saveNow?(patch: AiSettingsPatch): void;\n /** Resolves with the host's next settings `accept` likes, or null after `timeoutMs`. */\n waitForSettings(accept: (s: AiSettings) => boolean, timeoutMs: number): Promise<AiSettings | null>;\n /** Fresh statuses (list, test, discover) for the editor's cache and the indicator. */\n onStatuses(statuses: AiEngineStatus[]): void;\n /** Statuses that arrive without the view asking (a host push, a settings refresh). Returns an unsubscribe. */\n subscribeStatuses?(listener: (statuses: AiEngineStatus[]) => void): () => void;\n /**\n * A child session opened while the parent's \"Enable AI features\" is ticked\n * but not saved: when this session saves anything, it saves\n * `ai.enabled: true` with it, so finishing on the Engines page keeps the\n * tick (Q2).\n */\n pendingEnable?: boolean;\n}\n\nexport interface AiSettingsSession {\n readonly ai: MikeDownAiHost;\n readonly tier: AiHostTier;\n /** Last known statuses by engine id (the engine form writes fresh ones here too). */\n readonly statuses: Map<string, AiEngineStatus>;\n /** The settings being edited. Views replace it with a new object on every change. */\n draft: AiSettings;\n /** What the draft started from, minus whatever a child session already saved. */\n readonly original: AiSettings;\n readonly options: AiSettingsSessionOptions;\n getEngine(id: string): AiEngineConfig | undefined;\n statusList(): AiEngineStatus[];\n hasKey(id: string): boolean;\n /** Where the engine's key comes from, when the host said (a key stored here counts as stored). */\n keySource(id: string): AiKeySource | undefined;\n /** Store or clear a key through `host.ai.setSecret`; resolves with an error message, or null when it worked. */\n setKey(id: string, value: string | null): Promise<string | null>;\n /** Make sure the host has this engine's connection fields before asking it to reach it. */\n ensureSaved(id: string): Promise<void>;\n /** True when Test and fetching will save the engine first. */\n savesFirst(id: string): boolean;\n /** Add an engine to the draft; it is taken back from the host if the session is discarded. */\n addEngine(engine: AiEngineConfig): void;\n /** Remove an engine (and the routes to it); its key is dropped on commit. */\n deleteEngine(id: string): void;\n updateEngine(id: string, patch: Partial<AiEngineConfig>): void;\n /** The `ai.*` keys that changed. */\n collect(): AiSettingsPatch;\n /** Closing now would lose something. */\n dirty(): boolean;\n /** Fresh statuses from the host (tier 2). Resolves true when they arrived. */\n refreshStatuses(): Promise<boolean>;\n /** Options for a child session that starts from this draft and shares what this one knows about the host. */\n fork(): AiSettingsSessionOptions & { keyOverride: Map<string, boolean>; statusMap: Map<string, AiEngineStatus> };\n /** A child saved `patch`, ending at `saved`: take it as the new draft, and as saved for those keys. */\n absorb(saved: AiSettings, patch: AiSettingsPatch): void;\n /** Closed without saving: take back engines added here that reached the host, drop their keys. */\n discard(): void;\n /** Saved: drop the keys of deleted engines. Returns a copy of the saved draft. */\n commit(): AiSettings;\n}\n\n/** How long Test and fetching models wait for the host to echo engines the session just saved. */\nconst SAVE_ECHO_TIMEOUT_MS = 4000;\n\nexport function createAiSettingsSession(\n options: AiSettingsSessionOptions & { keyOverride?: Map<string, boolean>; statusMap?: Map<string, AiEngineStatus> },\n): AiSettingsSession {\n const { ai } = options;\n let original = cloneAiSettings(options.settings);\n let draft = cloneAiSettings(options.settings);\n // A child session shares its parent's map, so a test or fetch on the page freshens the tab's dots too (F8).\n const statuses = options.statusMap ?? new Map<string, AiEngineStatus>(options.statuses.map((s) => [s.engineId, s]));\n /** `hasKey` learned from Store / Clear, ahead of the next status (shared with child sessions). */\n const keyOverride = options.keyOverride ?? new Map<string, boolean>();\n /** Engines deleted in this session: their keys are dropped on commit. */\n const deleted = new Set<string>();\n /** Engines this session stored a key for; dropped again if the session is discarded before the engine is saved. */\n const keysStored = new Set<string>();\n /** Engines added in this session (taken back from the host if the session is discarded). */\n const added = new Set<string>();\n\n const getEngine = (id: string) => draft.engines.find((e) => e.id === id);\n const statusList = () => [...statuses.values()];\n\n const session: AiSettingsSession = {\n ai,\n tier: aiHostTier(ai),\n statuses,\n options,\n get draft() { return draft; },\n set draft(next: AiSettings) { draft = next; },\n get original() { return original; },\n getEngine,\n statusList,\n hasKey: (id) => keyOverride.get(id) ?? statuses.get(id)?.hasKey ?? false,\n keySource: (id) => {\n const stored = keyOverride.get(id);\n return stored === undefined ? statuses.get(id)?.keySource : stored ? 'stored' : undefined;\n },\n\n async setKey(id, value) {\n if (!getEngine(id) || !ai.setSecret) {return 'This app cannot store keys.';}\n try {\n await ai.setSecret(id, value);\n keyOverride.set(id, value !== null);\n if (value !== null) {keysStored.add(id);} else {keysStored.delete(id);}\n return null;\n } catch (err) {\n return `The key could not be ${value !== null ? 'stored' : 'cleared'}: ${toAiError(err).message}`;\n }\n },\n\n async ensureSaved(id) {\n const engine = getEngine(id);\n if (!engine || !options.saveNow) {return;}\n if (!connectionDiffers(options.getHostSettings().engines.find((e) => e.id === id), engine)) {return;}\n options.saveNow({ 'ai.engines': serializeAiSettings(draft)['ai.engines'] });\n await options.waitForSettings((s) => !connectionDiffers(s.engines.find((e) => e.id === id), engine), SAVE_ECHO_TIMEOUT_MS);\n },\n\n savesFirst(id) {\n const engine = getEngine(id);\n return !!options.saveNow && !!engine && connectionDiffers(options.getHostSettings().engines.find((e) => e.id === id), engine);\n },\n\n addEngine(engine) {\n draft = { ...draft, engines: [...draft.engines, engine] };\n added.add(engine.id);\n },\n\n deleteEngine(id) {\n if (!getEngine(id)) {return;}\n draft = removeEngine(draft, id);\n deleted.add(id);\n },\n\n updateEngine(id, patch) {\n const current = getEngine(id);\n if (current) {draft = withEngine(draft, { ...current, ...patch });}\n },\n\n collect() {\n const patch = changedAiPatch(original, draft);\n if (options.pendingEnable && draft.enabled && Object.keys(patch).length > 0) {patch['ai.enabled'] = true;}\n return patch;\n },\n\n dirty() {\n if (Object.keys(changedAiPatch(original, draft)).length > 0) {return true;}\n // An added engine that Test saved early and then deleted again still sits on the host.\n return options.getHostSettings().engines.some((e) => added.has(e.id) && !getEngine(e.id));\n },\n\n async refreshStatuses() {\n if (!ai.listEngines) {return false;}\n try {\n const list = await ai.listEngines();\n for (const s of list) {statuses.set(s.engineId, s);}\n options.onStatuses(statusList());\n return true;\n } catch {\n return false; // keep the last known statuses\n }\n },\n\n fork() {\n return { ...options, settings: cloneAiSettings(draft), statuses: statusList(), keyOverride, statusMap: statuses };\n },\n\n absorb(saved, patch) {\n draft = cloneAiSettings(saved);\n original = withSavedAiKeys(original, saved, patch);\n },\n\n discard() {\n // Engines added in this session reach the host early (Test and fetching\n // save them first). Closing without saving takes them back.\n const host = options.getHostSettings();\n if (options.saveNow && host.engines.some((e) => added.has(e.id))) {\n const kept = { ...host, engines: host.engines.filter((e) => !added.has(e.id)) };\n options.saveNow({ 'ai.engines': serializeAiSettings(kept)['ai.engines'] });\n }\n // The host keeps a key for an engine id it has never seen; if that\n // engine was never saved, nothing would ever clean it up.\n if (!ai.setSecret) {return;}\n const saved = new Set(host.engines.filter((e) => !added.has(e.id)).map((e) => e.id));\n for (const id of keysStored) {\n if (!saved.has(id)) {ai.setSecret(id, null).catch(() => { /* best effort */ });}\n }\n },\n\n commit() {\n if (ai.setSecret) {\n for (const id of deleted) {\n if (getEngine(id)) {continue;}\n ai.setSecret(id, null).catch(() => { /* the host also drops orphaned keys */ });\n }\n }\n return cloneAiSettings(draft);\n },\n };\n return session;\n}\n\n/** `base` with the fields `patch` saved taken from `saved` (`ai.engines` → `engines`, ...). */\nexport function withSavedAiKeys(base: AiSettings, saved: AiSettings, patch: AiSettingsPatch): AiSettings {\n const next = { ...base } as Record<string, unknown>;\n const from = saved as unknown as Record<string, unknown>;\n for (const key of Object.keys(patch)) {\n const field = key.replace(/^ai\\./, '');\n if (field in from) {next[field] = JSON.parse(JSON.stringify(from[field]));}\n }\n return next as unknown as AiSettings;\n}\n","/**\n * Local server detection and the one-click local setup behind the first-run\n * panel (`ai-toolbar.ts`) and the quick-start cards (`ai-engines-page.ts`).\n *\n * Detection asks the host (`host.ai.detectLocalServers`) whether the local\n * presets' default addresses answer, and only when the user opens setup;\n * nothing here runs in the background or caches a result. The one-click\n * setup adds the preset's engine, fetches its models, makes its default\n * model (`applyDiscoveryForFamily`: the loaded one) the default route and\n * returns one patch with engines, routing and\n * `ai.enabled`, for the caller to save.\n *\n * The setup wizard's scan (`scanForSetup`) adds the hardware and VS Code's\n * Copilot models to a detection and asks `recommendSetupPath` which path to\n * lead with. The hardware is read once per host (it does not change); the\n * last scan is kept for the editor session, so the wizard opened from the\n * first-run panel lays out at once and freshens when its own scan lands.\n * No DOM.\n */\n\nimport { AI_ENGINE_PRESETS, AI_LOCAL_DETECT_TIMEOUT_MS, localDetectCandidates, recommendSetupPath, toAiError, vscodeLmAvailability } from './ai';\nimport type { AiEngineConfig, AiHardwareInfo, AiLocalServerProbe, AiRoute, AiSettings, AiSettingsPatch, AiSetupRecommendation, MikeDownAiHost } from './ai';\nimport { applyDiscoveryForFamily, defaultRouteForEngine, engineFromPreset, rankLocalCandidates, withEngine, type LocalServerCard } from './ai-settings-model';\nimport { createAiSettingsSession, type AiSettingsSessionOptions } from './ai-settings-session';\n\n/** The status line while detection runs (first-run panel, cards). */\nexport const AI_DETECT_LOOKING = 'Looking for local AI servers…';\n/** What both say when no local server answered. */\nexport const AI_DETECT_NONE = 'No local AI server found. Start LM Studio, Ollama or oMLX, then choose Look again.';\n\n/** Slack over the host's per-address cap for the round trip (postMessage, Tauri IPC). */\nconst DETECT_ROUND_TRIP_MS = 1500;\n\n/**\n * Ask the host which local servers answer (rank them with\n * `rankLocalCandidates`). Null when the host cannot detect, the request\n * failed, or it took too long: the callers then say nothing rather than\n * \"nothing found\".\n */\nexport async function detectLocalServers(ai: MikeDownAiHost, signal?: AbortSignal): Promise<AiLocalServerProbe[] | null> {\n if (!ai.detectLocalServers || signal?.aborted) {return null;}\n const controller = new AbortController();\n const onAbort = (): void => controller.abort();\n signal?.addEventListener('abort', onAbort, { once: true });\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<null>((resolve) => {\n timer = setTimeout(() => {\n controller.abort();\n resolve(null);\n }, AI_LOCAL_DETECT_TIMEOUT_MS + DETECT_ROUND_TRIP_MS);\n });\n try {\n const probes = await Promise.race([ai.detectLocalServers(localDetectCandidates(), controller.signal), timeout]);\n return !probes || controller.signal.aborted || !Array.isArray(probes) ? null : probes;\n } catch {\n return null;\n } finally {\n clearTimeout(timer);\n signal?.removeEventListener('abort', onAbort);\n }\n}\n\n/** What the first-run panel offers: the best running server that is not set up yet. */\nexport function bestLocalServer(probes: readonly AiLocalServerProbe[], engines: readonly AiEngineConfig[]): LocalServerCard | null {\n return rankLocalCandidates(probes, engines).find((c) => c.running && !c.alreadyAdded) ?? null;\n}\n\nexport interface LocalSetupResult {\n /** Engines, routing and `ai.enabled`, in one patch. */\n patch: AiSettingsPatch;\n /** The settings that patch leads to. */\n settings: AiSettings;\n engineId: string;\n route: AiRoute;\n}\n\n/**\n * \"Use LM Studio\": add the preset's engine, fetch its models, make its\n * default model the default route and turn AI on (none loaded: it fails and\n * asks for a pick in Set up). The host needs to know the\n * engine before it can fetch, so the engine is saved (quietly) first, as Test\n * and fetching do on the Engines page; when anything fails it is taken back\n * and this rejects with an `Error` whose message can be shown as is.\n */\nexport async function setUpLocalEngine(options: AiSettingsSessionOptions, presetId: string): Promise<LocalSetupResult> {\n const preset = AI_ENGINE_PRESETS.find((p) => p.id === presetId && p.family === 'local');\n if (!preset) {throw new Error('That local server is not one MikeDown knows.');}\n const { ai } = options;\n if (!ai.discoverModels) {throw new Error('This app cannot fetch models.');}\n const session = createAiSettingsSession(options);\n const engine = engineFromPreset(preset, session.draft.engines.map((e) => e.id));\n session.addEngine(engine);\n const fail = (message: string): never => {\n session.discard();\n throw new Error(message);\n };\n\n await session.ensureSaved(engine.id);\n let status;\n try {\n status = await ai.discoverModels(engine.id);\n } catch (err) {\n return fail(`Could not fetch the models from ${preset.name}: ${toAiError(err).message}`);\n }\n if (status.ok === false) {return fail(`Could not fetch the models from ${preset.name}${status.error ? `: ${status.error}` : '.'}`);}\n session.statuses.set(engine.id, status);\n options.onStatuses(session.statusList());\n session.draft = withEngine(session.draft, applyDiscoveryForFamily(engine, status, 'local'));\n\n const route = defaultRouteForEngine(session.draft, session.statusList(), engine.id);\n if (!route) {\n // Chat models, but none loaded: no guess, the user picks one in Set up.\n const canChat = session.getEngine(engine.id)?.models.some((m) => !m.missing && m.capabilities.chat);\n return fail(canChat\n ? `${preset.name} has no model loaded. Load one there, or choose Set up to pick one.`\n : `${preset.name} has no chat model loaded or downloaded yet.`);\n }\n session.draft = { ...session.draft, routing: { ...session.draft.routing, default: route } };\n\n const patch: AiSettingsPatch = { ...session.collect(), 'ai.enabled': true };\n const settings = { ...session.commit(), enabled: true };\n return { patch, settings, engineId: engine.id, route };\n}\n\n// ── The setup wizard's scan ─────────────────────────────────────────────────\n\n/** What the wizard knows about this machine when it lays out its first step. */\nexport interface AiSetupScan {\n recommendation: AiSetupRecommendation;\n /** Every local candidate as detection found it; null when the host cannot look, or the look failed. */\n probes: AiLocalServerProbe[] | null;\n hardware: AiHardwareInfo | null;\n /** VS Code's Copilot models (`vscodeLmAvailability`); null on a host without them. */\n vscodeLm: { available: boolean; models: number } | null;\n}\n\n/** How long the wizard waits for VS Code to list its Copilot models. */\nconst HOST_ENGINES_TIMEOUT_MS = 3000;\n\nconst hardwareByHost = new WeakMap<MikeDownAiHost, Promise<AiHardwareInfo | null>>();\nconst scanByHost = new WeakMap<MikeDownAiHost, AiSetupScan>();\n\n/** True when the host can tell the wizard anything (servers, hardware or Copilot); otherwise the scan is instant. */\nexport function canScanForSetup(ai: MikeDownAiHost): boolean {\n return !!(ai.detectLocalServers || ai.hardwareInfo || ai.detectHostEngines);\n}\n\n/** The answers `setupHardware` already has, so a view built later reads them at once. */\nconst hardwareKnown = new WeakMap<MikeDownAiHost, AiHardwareInfo>();\n\n/** This machine's hardware, asked once per host (it does not change); null when the host cannot tell. */\nexport function setupHardware(ai: MikeDownAiHost): Promise<AiHardwareInfo | null> {\n let info = hardwareByHost.get(ai);\n if (!info) {\n info = ai.hardwareInfo\n ? ai.hardwareInfo().then((h) => (h && typeof h === 'object' ? h : null), () => null)\n : Promise.resolve(null);\n info = info.then((h) => {\n if (h) {hardwareKnown.set(ai, h);}\n return h;\n });\n hardwareByHost.set(ai, info);\n }\n return info;\n}\n\n/**\n * The hardware `setupHardware` already answered with, or null before it has\n * (or when the host cannot tell). Synchronous, so the models picker of a form\n * opened later groups by size on its first render, like the first open (Q5).\n */\nexport function knownHardware(ai: MikeDownAiHost): AiHardwareInfo | null {\n return hardwareKnown.get(ai) ?? null;\n}\n\n/** Whether VS Code offers a Copilot model; null on a host without the method, or when it did not answer in time. */\nexport async function hostEngineAvailability(ai: MikeDownAiHost, signal?: AbortSignal): Promise<{ available: boolean; models: number } | null> {\n if (!ai.detectHostEngines || signal?.aborted) {return null;}\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<null>((resolve) => { timer = setTimeout(() => resolve(null), HOST_ENGINES_TIMEOUT_MS); });\n try {\n const probes = await Promise.race([ai.detectHostEngines(), timeout]);\n return probes && Array.isArray(probes) && !signal?.aborted ? vscodeLmAvailability(probes) : null;\n } catch {\n return null;\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** The last scan in this editor session, if any (the wizard lays out from it while a fresh one runs). */\nexport function lastSetupScan(ai: MikeDownAiHost): AiSetupScan | null {\n return scanByHost.get(ai) ?? null;\n}\n\n/** The recommendation from what is known without asking the host anything (no servers, no hardware). */\nexport function plainSetupScan(): AiSetupScan {\n return { recommendation: recommendSetupPath({ running: [], hardware: null }), probes: null, hardware: null, vscodeLm: null };\n}\n\n/**\n * Look for local servers (unless `probes` is given: the first-run panel\n * already looked), read the hardware (cached) and ask for Copilot's models,\n * then recommend a path. Kept as the session's last scan.\n */\nexport async function scanForSetup(ai: MikeDownAiHost, signal?: AbortSignal, probes?: AiLocalServerProbe[] | null): Promise<AiSetupScan> {\n const [found, hardware, vscodeLm] = await Promise.all([\n probes !== undefined ? Promise.resolve(probes) : detectLocalServers(ai, signal),\n setupHardware(ai),\n hostEngineAvailability(ai, signal),\n ]);\n const recommendation = recommendSetupPath({ running: found ?? [], hardware, ...(vscodeLm ? { vscodeLm } : {}) });\n const scan: AiSetupScan = { recommendation, probes: found, hardware, vscodeLm };\n if (!signal?.aborted) {scanByHost.set(ai, scan);}\n return scan;\n}\n","/**\n * Small DOM builders shared by the AI settings tab (`ai-settings.ts`), the\n * AI Engines page (`ai-engines-page.ts`) and the Express engine form\n * (`ai-engine-form.ts`): inline icons, kind glyphs, buttons, switches, notes,\n * the status dot and locality pills, and a rebuild helper that keeps\n * keyboard focus.\n *\n * Modal UI only: nothing here touches the editor document or its DOM.\n */\n\nimport { AI_CLOUD_PRIVACY, AI_HOST_PRIVACY, aiConsentStepNote } from './ai';\nimport type { AiEngineConfig, AiEngineStatus, AiProviderPolicy, AiSettings } from './ai';\nimport { engineLocalityInfo } from './ai-settings-model';\n\n// ── Icons (inline, currentColor) ────────────────────────────────────────────\n\nconst svg = (body: string, size = 14, extra = '') =>\n `<svg width=\"${size}\" height=\"${size}\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"${extra}>${body}</svg>`;\n\nexport const ICONS = {\n starOff: svg('<path d=\"M8 1.9l1.86 3.77 4.16.6-3.01 2.94.71 4.14L8 11.4l-3.72 1.95.71-4.14L1.98 6.27l4.16-.6z\"/>'),\n starOn: svg('<path d=\"M8 1.9l1.86 3.77 4.16.6-3.01 2.94.71 4.14L8 11.4l-3.72 1.95.71-4.14L1.98 6.27l4.16-.6z\" fill=\"currentColor\"/>'),\n trash: svg('<path d=\"M2.5 4h11M6.5 4V2.5h3V4M4 4l.7 9.5h6.6L12 4M6.6 6.5v4.5M9.4 6.5v4.5\"/>'),\n chevron: svg('<path d=\"M6 4l4 4-4 4\"/>', 12),\n plus: svg('<path d=\"M8 3v10M3 8h10\"/>', 12),\n local: svg('<path d=\"M2.5 7.5L8 3l5.5 4.5M4 6.5V13h8V6.5\"/>', 11),\n cloud: svg('<path d=\"M4.5 12.5h7a2.75 2.75 0 0 0 .3-5.48A4 4 0 0 0 4.1 7.6 2.5 2.5 0 0 0 4.5 12.5z\"/>', 11),\n warn: svg('<path d=\"M8 2.2l6.2 11H1.8z\"/><path d=\"M8 6.5v3M8 11.4v.1\"/>', 12),\n info: svg('<circle cx=\"8\" cy=\"8\" r=\"6\"/><path d=\"M8 7.2v3.8M8 5v.1\"/>', 12),\n check: svg('<path d=\"M3.5 8.5l3 3 6-7\"/>', 12),\n braces: svg('<path d=\"M6 2.5c-1.5 0-2 .7-2 2v1.6c0 .9-.5 1.4-1.4 1.9.9.5 1.4 1 1.4 1.9v1.6c0 1.3.5 2 2 2M10 2.5c1.5 0 2 .7 2 2v1.6c0 .9.5 1.4 1.4 1.9-.9.5-1.4 1-1.4 1.9v1.6c0 1.3-.5 2-2 2\"/>', 16),\n close: svg('<path d=\"M4 4l8 8M12 4l-8 8\"/>', 10),\n refresh: svg('<path d=\"M13 8a5 5 0 1 1-1.5-3.55M13 2.5v3h-3\"/>', 12),\n search: svg('<circle cx=\"7\" cy=\"7\" r=\"4.25\"/><path d=\"M10.2 10.2l3.3 3.3\"/>', 12),\n back: svg('<path d=\"M10 3.5L5.5 8l4.5 4.5\"/>', 14),\n routing: svg('<path d=\"M3 4h4.5a2 2 0 0 1 2 2v4a2 2 0 0 0 2 2H13M3 12h3M11 2.5L13 4l-2 1.5M11 10.5l2 1.5-2 1.5\"/>', 16),\n};\n\n/** Two-letter tiles for the kinds without a glyph; the generic kind gets braces. */\nconst KIND_MONOGRAMS: Record<string, string> = {\n lmstudio: 'LM',\n ollama: 'Ol',\n anthropic: 'An',\n openai: 'OA',\n 'vscode-lm': 'Co',\n};\n\nconst KNOWN_KINDS = new Set(['openai-compatible', 'lmstudio', 'ollama', 'anthropic', 'openai', 'vscode-lm']);\n\n/** The kind tile (a rounded square like an extension icon). */\nexport function kindGlyphHtml(kind: string, extra = ''): string {\n const known = KNOWN_KINDS.has(kind);\n const inner = !known ? '?' : kind === 'openai-compatible' ? ICONS.braces : KIND_MONOGRAMS[kind] ?? '?';\n return `<span class=\"ai-glyph ${extra}\" data-kind=\"${known ? kind : 'unknown'}\" aria-hidden=\"true\">${inner}</span>`;\n}\n\n// ── Experimental marking ────────────────────────────────────────────────────\n\nconst lowerFirst = (text: string) => text.charAt(0).toLowerCase() + text.slice(1);\n\n/** Shown on the AI tab, the AI Engines page and the toolbar's first-run panel. */\nexport const AI_EXPERIMENTAL_DISCLAIMER =\n 'AI features are experimental and may change or be removed. AI output can be wrong, so review it before you keep it. ' +\n `With a cloud engine, ${lowerFirst(AI_CLOUD_PRIVACY.leaves)} ${AI_CLOUD_PRIVACY.local}`;\n\n/** The \"Experimental\" pill beside an AI title. */\nexport function experimentalBadge(): HTMLSpanElement {\n return el('span', 'ai-experimental-badge', 'Experimental');\n}\n\n/** The disclaimer as a quiet paragraph. */\nexport function experimentalDisclaimer(className = ''): HTMLParagraphElement {\n return el('p', `ai-disclaimer${className ? ` ${className}` : ''}`, AI_EXPERIMENTAL_DISCLAIMER);\n}\n\n// ── Privacy card ────────────────────────────────────────────────────────────\n\n/** Something that may carry a provider policy: a preset, or `{ policy }`. */\nexport interface PrivacyPolicySource {\n policy?: AiProviderPolicy;\n}\n\nexport interface PrivacyCardOptions {\n /** Open a link through the host (`host.openLink`). Absent: the link is a plain anchor (`target=\"_blank\"`). */\n openLink?: (href: string) => void;\n /** Start as a closed disclosure with this summary (\"What is sent\"); `true` uses that default. */\n collapsed?: boolean | string;\n /** Start a collapsed card open (its state survives a rebuild when the caller keeps it). */\n open?: boolean;\n /** The disclosure opened or closed. */\n onToggle?(open: boolean): void;\n /** One more line under the policy links (the AI tab's consent line). */\n extra?: string;\n /**\n * An engine built into the host (VS Code's Copilot models): its own lines\n * (no API key; the text goes to GitHub's Copilot service under the user's\n * plan) instead of the cloud API ones.\n */\n hostEngine?: boolean;\n className?: string;\n}\n\n/** An external link that opens through the host (`host.openLink`) when it can, else a plain new-tab anchor. */\nexport function hostLink(label: string, url: string, openLink?: (href: string) => void, className = ''): HTMLAnchorElement {\n const a = el('a', `ai-link-btn${className ? ` ${className}` : ''}`, label);\n a.href = url;\n a.target = '_blank';\n a.rel = 'noopener noreferrer';\n a.title = url;\n if (openLink) {\n a.addEventListener('click', (e) => {\n e.preventDefault();\n openLink(url);\n });\n }\n return a;\n}\n\n/** A policy link that opens through the host when it can. */\nexport function policyLink(policy: AiProviderPolicy, openLink?: (href: string) => void): HTMLAnchorElement {\n return hostLink(policy.label, policy.url, openLink, 'ai-privacy-link');\n}\n\n/**\n * What happens to text sent to a cloud engine: the four `AI_CLOUD_PRIVACY`\n * lines, then the policy link of each source that has one (a preset, or the\n * presets of the cloud engines in use). A quiet note with a cloud glyph, not\n * a warning. `collapsed` makes it a \"What is sent\" disclosure.\n */\nexport function privacyCard(\n source?: PrivacyPolicySource | readonly PrivacyPolicySource[] | null,\n opts: PrivacyCardOptions = {},\n): HTMLElement {\n const list: readonly PrivacyPolicySource[] = !source ? [] : Array.isArray(source) ? source : [source as PrivacyPolicySource];\n const policies: AiProviderPolicy[] = [];\n for (const s of list) {\n if (s.policy && !policies.some((p) => p.url === s.policy!.url)) {policies.push(s.policy);}\n }\n\n const body = el('div', 'ai-privacy-body');\n const lines = el('ul', 'ai-privacy-lines');\n const texts = opts.hostEngine\n ? [AI_HOST_PRIVACY.leaves, AI_HOST_PRIVACY.terms, AI_HOST_PRIVACY.permission, AI_HOST_PRIVACY.local]\n : [AI_CLOUD_PRIVACY.leaves, AI_CLOUD_PRIVACY.terms, AI_CLOUD_PRIVACY.local, AI_CLOUD_PRIVACY.keys];\n for (const text of texts) {\n lines.append(el('li', '', text));\n }\n body.append(lines);\n for (const policy of policies) {\n const line = el('p', 'ai-privacy-policy');\n line.append(policyLink(policy, opts.openLink));\n // The host lines already say what the Copilot note says.\n if (policy.note && !opts.hostEngine) {line.append(el('span', 'ai-privacy-policy-note', ` ${policy.note}`));}\n body.append(line);\n }\n if (opts.extra) {body.append(el('p', 'ai-privacy-extra', opts.extra));}\n\n const className = `ai-privacy-card${opts.className ? ` ${opts.className}` : ''}`;\n const glyph = el('span', 'ai-privacy-glyph');\n glyph.innerHTML = ICONS.cloud;\n if (opts.collapsed) {\n const details = el('details', className);\n details.open = !!opts.open;\n const summary = el('summary', 'ai-privacy-summary');\n summary.append(glyph, el('span', '', typeof opts.collapsed === 'string' ? opts.collapsed : 'What is sent'));\n details.append(summary, body);\n if (opts.onToggle) {details.addEventListener('toggle', () => opts.onToggle!(details.open));}\n return details;\n }\n const card = el('div', className);\n const head = el('div', 'ai-privacy-head');\n head.append(glyph, el('span', '', opts.hostEngine ? 'GitHub Copilot and your text' : 'Cloud engines and your text'));\n card.append(head, body);\n return card;\n}\n\nexport interface CloudAccessOptions {\n /** Allow cloud engines, as the draft has it now. */\n allowed: boolean;\n onChange(allowed: boolean): void;\n /** The presets whose policy links the folded privacy card lists. */\n presets: readonly PrivacyPolicySource[];\n /** The host asks before a cloud engine's first request (`requestCloudConsent`). */\n hostAsks: boolean;\n /** Start the \"What this means\" fold open, and hear when it opens or closes (to keep it across rebuilds). */\n open?: boolean;\n onToggle?(open: boolean): void;\n openLink?: (href: string) => void;\n /** `data-fk` of the switch. */\n fk: string;\n}\n\n/**\n * **Allow cloud engines** where a cloud engine is added (F4, OQ5): the\n * switch, one line on what it means, and the privacy card folded under\n * \"What this means\" with the consent-step sentence (`aiConsentStepNote`).\n * The AI Engines page's cloud cards and the setup wizard share it.\n */\nexport function cloudAccessBox(o: CloudAccessOptions): HTMLElement {\n const box = el('div', 'ai-cloud-access');\n const row = el('div', 'ai-cloud-access-row');\n const toggle = switchInput(o.allowed, 'Allow cloud engines', o.fk);\n toggle.id = nextId('ai-allow-cloud');\n const label = el('label', 'ai-cloud-access-label', 'Allow cloud engines');\n label.htmlFor = toggle.id;\n const line = el('span', 'ai-cloud-access-line', 'Text you ask about is sent to the provider over the internet.');\n line.id = nextId('ai-allow-cloud-line');\n toggle.setAttribute('aria-describedby', line.id);\n toggle.addEventListener('change', () => o.onChange(toggle.checked));\n const text = el('div', 'ai-cloud-access-text');\n text.append(label, line);\n row.append(toggle, text);\n box.append(row, privacyCard(o.presets, {\n collapsed: 'What this means',\n open: o.open,\n onToggle: (open) => o.onToggle?.(open),\n openLink: o.openLink,\n extra: aiConsentStepNote(o.hostAsks),\n className: 'ai-cloud-access-privacy',\n }));\n return box;\n}\n\n/**\n * One privacy line plus \"Learn more\", for the first-run panel's \"Set up\n * another way…\" path; `onLearnMore` opens the page with the full card.\n */\nexport function privacyLine(onLearnMore: () => void): HTMLParagraphElement {\n const line = el('p', 'ai-privacy-line');\n const glyph = el('span', 'ai-privacy-glyph');\n glyph.innerHTML = ICONS.cloud;\n const more = button('ai-link-btn', 'Learn more', { fk: 'ai-privacy:learn-more' });\n more.addEventListener('click', () => onLearnMore());\n line.append(glyph, el('span', '', `A cloud engine sends text to the provider. ${AI_CLOUD_PRIVACY.local} `), more);\n return line;\n}\n\n// ── Small DOM helpers ───────────────────────────────────────────────────────\n\nlet uid = 0;\nexport const nextId = (prefix: string) => `${prefix}-${++uid}`;\n\nexport function el<K extends keyof HTMLElementTagNameMap>(tag: K, className?: string, text?: string): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n if (className) {node.className = className;}\n if (text !== undefined) {node.textContent = text;}\n return node;\n}\n\nexport function button(className: string, label: string, opts: { html?: string; ariaLabel?: string; title?: string; fk?: string } = {}): HTMLButtonElement {\n const b = el('button', className);\n b.type = 'button';\n if (opts.html !== undefined) {\n b.innerHTML = opts.html;\n if (label) {b.append(el('span', 'ai-btn-text', label));}\n } else {\n b.textContent = label;\n }\n if (opts.ariaLabel) {b.setAttribute('aria-label', opts.ariaLabel);}\n if (opts.title) {b.title = opts.title;}\n if (opts.fk) {b.dataset.fk = opts.fk;}\n return b;\n}\n\n/** A switch-styled checkbox (role=\"switch\"), labelled for screen readers. */\nexport function switchInput(checked: boolean, ariaLabel: string, fk?: string): HTMLInputElement {\n const input = el('input', 'ai-switch');\n input.type = 'checkbox';\n input.setAttribute('role', 'switch');\n input.checked = checked;\n input.setAttribute('aria-label', ariaLabel);\n if (fk) {input.dataset.fk = fk;}\n return input;\n}\n\nexport function note(level: 'warning' | 'info' | 'error' | 'ok', text: string, className = ''): HTMLDivElement {\n const n = el('div', `ai-note ai-note--${level}${className ? ` ${className}` : ''}`);\n const icon = el('span', 'ai-note-icon');\n icon.innerHTML = level === 'ok' ? ICONS.check : level === 'info' ? ICONS.info : ICONS.warn;\n n.append(icon, el('span', 'ai-note-text', text));\n return n;\n}\n\n/**\n * Rebuild `scope` and put focus (and the caret) back on the control with the\n * same `data-fk`, so re-rendering a list never throws the keyboard user out.\n */\nexport function keepFocus(scope: HTMLElement, rebuild: () => HTMLElement | void): void {\n const active = document.activeElement as HTMLElement | null;\n const key = active && scope.contains(active) ? active.dataset.fk : undefined;\n let sel: [number | null, number | null] | null = null;\n if (key && (active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement)) {\n try { sel = [active.selectionStart, active.selectionEnd]; } catch { sel = null; }\n }\n // A rebuild that swaps `scope` for a new node returns the new one.\n const target = rebuild() ?? scope;\n if (!key) {return;}\n const next = Array.from(target.querySelectorAll<HTMLElement>('[data-fk]')).find((n) => n.dataset.fk === key);\n if (!next) {return;}\n next.focus({ preventScroll: true });\n if (sel && (next instanceof HTMLInputElement || next instanceof HTMLTextAreaElement)) {\n try { next.setSelectionRange(sel[0], sel[1]); } catch { /* number inputs have no selection */ }\n }\n}\n\n// ── Engine status and locality ──────────────────────────────────────────────\n\n/**\n * The status dot with a terse label (\"42 ms\", \"Failed\"); the tooltip and the\n * accessible name say more. `compact` keeps only the dot on screen.\n */\nexport function statusBadge(status: AiEngineStatus | undefined, busy: 'test' | 'discover' | undefined, opts: { compact?: boolean } = {}): HTMLElement {\n const badge = el('span', `ai-status${opts.compact ? ' ai-status--compact' : ''}`);\n const dot = el('span', 'ai-status-dot');\n dot.setAttribute('aria-hidden', 'true');\n const text = el('span', 'ai-status-text');\n let state: string;\n let label: string;\n let title: string;\n if (busy) {\n state = 'busy';\n label = busy === 'test' ? 'Testing…' : 'Fetching…';\n title = busy === 'test' ? 'Testing the connection…' : 'Fetching models…';\n } else if (!status || status.ok === null) {\n // Neither a test nor a model fetch has reached the engine yet; either one sets the status (F8).\n state = 'unknown';\n label = 'Not tested';\n title = 'Not reached yet. Open the engine and fetch its models, or choose Test connection.';\n } else if (status.ok) {\n state = 'ok';\n label = status.latencyMs !== undefined ? `${Math.round(status.latencyMs)} ms` : 'OK';\n title = `Connected${status.latencyMs !== undefined ? ` in ${Math.round(status.latencyMs)} ms` : ''} on the last test or model fetch.`;\n } else {\n state = 'error';\n label = 'Failed';\n title = status.error ? `Last test failed: ${status.error}` : 'The last test failed.';\n }\n badge.dataset.state = state;\n badge.title = title;\n text.textContent = label;\n badge.append(dot, text);\n // The visible text is terse; screen readers get the tooltip.\n badge.setAttribute('aria-label', `Status: ${title}`);\n badge.setAttribute('role', 'img');\n return badge;\n}\n\n/**\n * The local/cloud pill, plus \"blocked by Allow cloud\" for a cloud engine while\n * cloud is off. `blocked: false` leaves that pill out (the Engines page head\n * says it with a button instead).\n */\nexport function localityPills(engine: AiEngineConfig, settings: AiSettings, opts: { blocked?: boolean } = {}): HTMLElement[] {\n const info = engineLocalityInfo(engine, settings.localNetworks);\n const pill = el('span', `ai-pill ai-pill--${info.locality}`);\n pill.innerHTML = info.locality === 'local' ? ICONS.local : ICONS.cloud;\n pill.append(el('span', '', info.locality === 'local' ? 'local' : 'cloud'));\n if (info.mismatch) {\n pill.classList.add('ai-pill--mismatch');\n pill.title = info.locality === 'cloud' ? 'Pinned to cloud, but the address looks local.' : 'Pinned to local, but the address looks like a cloud server.';\n }\n const pills = [pill];\n if (info.locality === 'cloud' && !settings.allowCloud && opts.blocked !== false) {\n const blocked = el('span', 'ai-pill ai-pill--blocked', 'blocked by Allow cloud');\n blocked.title = 'Turn on Allow cloud engines to route tasks here.';\n pills.push(blocked);\n }\n return pills;\n}\n","/**\n * The Express engine form (M3b): one engine's settings as a short sheet,\n * like a macOS \"Add Account\" form, with everything else folded under\n * Advanced.\n *\n * Express (design call 1): Name, API key (cloud, or a local server that\n * expects one), Base URL (local), Models (auto-fetched, a pick-or-type\n * combobox with a Popular group on cloud engines), Default model with its\n * Thinking level, Enabled. Advanced: kind, Base URL (cloud), locality, the key\n * on local servers that do not need one, key variable, key file, discovery\n * mode and the full M3 models table.\n *\n * Self-contained so the AI Engines page (M3c) can host it: the controller\n * owns the form's own state (fetches in flight, the Advanced fold, picker\n * filters, results) and reads and writes the settings draft only through\n * `EngineFormDeps`. It never touches the modal's layout or the editor.\n *\n * Fetching (design call 3): cloud engines store the key and fetch 600 ms\n * after the key field settles; local engines fetch when the URL changes and\n * when the form opens for an engine the host never probed. One discovery\n * runs per engine at a time; a newer trigger supersedes the running one,\n * whose result is dropped, and runs as soon as it settles.\n */\n\nimport { AI_ENGINE_KINDS, aiErrorCopy, aiProviderPolicy, formatModelSize, isHostEngineKind, isKnownEngineKind, modelMoeFastHint, thinkingChoices, thinkingLevelFrom, toAiError } from './ai';\nimport type { AiEngineConfig, AiEngineStatus, AiKeySource, AiLocalitySetting, AiModelConfig, AiModelSizeTag, AiSettings, AiThinkingLevel, MikeDownAiHost } from './ai';\nimport {\n AI_CAPABILITY_CHIPS,\n AI_ENGINE_KIND_LABELS,\n addManualModel,\n applyDiscoveryForFamily,\n autoFetchDecision,\n autoPickDefault,\n baseUrlProblem,\n chooseSetupModel,\n defaultRouteForEngine,\n discoveryProblem,\n engineDefaultModelId,\n engineDisplayName,\n engineKindLabel,\n engineLocalityInfo,\n enginePreset,\n expressFields,\n fetchFingerprint,\n firstChatModelId,\n formatRequestOverrides,\n formatTokens,\n modelCountLine,\n modelDisplayName,\n modelPickerOptions,\n parseContextTokens,\n parseRequestOverrides,\n popularModels,\n removeRoutesTo,\n setEngineDefaultModel,\n setModelContextTokens,\n setModelPicked,\n setModelThinking,\n setupFields,\n toggleModelCapability,\n withEngine,\n withModel,\n} from './ai-settings-model';\nimport type { AutoFetchEvent, AutoFetchState, DiscoveryProblem, EngineFormPreset, ModelPickerOption } from './ai-settings-model';\nimport { ICONS, button, el, hostLink, keepFocus, nextId, note, privacyCard, switchInput } from './ai-settings-dom';\n\n/** What else must re-render after a draft change made by the form. */\nexport interface EngineFormRefresh {\n /** The engine's row in the list (name, address, pills). */\n head?: boolean;\n /** The form itself (structure changed). */\n form?: boolean;\n /** The whole engine list (the enabled switch, the star). */\n list?: boolean;\n /** Routing pickers. */\n routing?: boolean;\n}\n\nexport interface EngineFormDeps {\n ai: MikeDownAiHost;\n getDraft(): AiSettings;\n setDraft(next: AiSettings, refresh: EngineFormRefresh): void;\n /** Re-render without a draft change (busy dots, results). */\n refresh(engineId: string, refresh: EngineFormRefresh): void;\n /** Last known statuses, shared with the host of the form (it reads them for the row dots). */\n statuses: Map<string, AiEngineStatus>;\n /** `statuses` changed; tell the editor's cache and the indicator. */\n onStatuses(): void;\n hasKey(engineId: string): boolean;\n /** Where the key came from, when the host said; without it the form guesses from the engine's settings. */\n keySource?(engineId: string): AiKeySource | undefined;\n /** Store (or with null, clear) a key through `host.ai.setSecret`. Resolves with an error message, or null when it worked. */\n setKey(engineId: string, value: string | null): Promise<string | null>;\n /** Make sure the host has this engine's connection fields before reaching it. */\n ensureSaved(engineId: string): Promise<void>;\n /** True when Test and Fetch will save the engine first (the host has different connection fields). */\n savesFirst(engineId: string): boolean;\n announce(text: string): void;\n /** Focus the control with this `data-fk` inside the mounted form. */\n focusKey(key: string): void;\n /** Open an external link through the host (the provider's policy, its key page). Absent: a plain anchor. */\n openLink?: (href: string) => void;\n /** A note to show right above the API key row (the setup wizard's subscription note), or null. */\n keyNote?(engine: AiEngineConfig, preset: EngineFormPreset): HTMLElement | null;\n /**\n * How a local model's size suits this machine (`modelSizeHint`, from the\n * size the server reported when it did), when the host reported its\n * hardware. The picker then groups local models by it.\n */\n modelSize?(modelId: string, sizeBytes?: number): AiModelSizeTag | undefined;\n}\n\nexport interface EngineFormController {\n /**\n * The form for one engine. Rebuilt on every render; state lives in the\n * controller. `privacy: false` leaves out the \"What is sent\" card (the\n * setup wizard's cloud step already shows \"What this means\" above it).\n * `setup: true` is the wizard's compact form (`setupFields`): no Name,\n * Default model or Enabled, the key note's link instead of the key hint,\n * no Test connection, and a single choice of model that is the default,\n * from the Popular group with the rest behind \"Show all models\".\n */\n build(engineId: string, opts?: FormBuildOptions): HTMLElement;\n /**\n * The form was just opened: fetch models when design call 3 says so, and\n * return the `data-fk` to focus (key for a new cloud engine, URL for a new\n * Custom one, the name otherwise). Null for a new local server from a\n * preset: focus the panel heading, not a field.\n */\n opened(engineId: string, opts?: { isNew?: boolean }): string | null;\n /** What the engine is busy with, for the row's status dot. */\n busy(engineId: string): 'test' | 'discover' | undefined;\n /**\n * Done found this engine with chat models listed but none picked (Q1): the\n * next build shows an error over the models list until a model is picked.\n * The host re-renders the form and focuses the list (`eng:<id>:pick` or\n * `eng:<id>:models`).\n */\n requirePick(engineId: string): void;\n /** The engine was deleted: drop its timers and state. */\n forget(engineId: string): void;\n /** Stop every timer (the modal closed). */\n dispose(): void;\n}\n\nexport interface FormBuildOptions {\n privacy?: boolean;\n setup?: boolean;\n}\n\n/** More models than this and the picker gets a filter field. */\nconst FILTER_THRESHOLD = 8;\n\n/** The picker's groups for local models when the host reported its hardware; `undefined` is a model whose id names no size. */\nconst SIZE_GROUPS: ReadonlyArray<{ tag: AiModelSizeTag | undefined; title: string }> = [\n { tag: 'fits', title: 'Runs well on this machine' },\n { tag: 'tight', title: 'A tight fit' },\n { tag: 'too large', title: 'Likely too large for this machine' },\n { tag: undefined, title: 'Size not in the name' },\n];\n\nconst SIZE_TITLES: Readonly<Record<AiModelSizeTag, string>> = {\n fits: 'Its size should run well in this machine’s memory (a 4-bit estimate).',\n tight: 'Near the limit of this machine’s memory: it may run slowly.',\n 'too large': 'Probably more than this machine’s memory holds. You can still pick it.',\n};\n\nconst LOCALITY_LABELS: Record<Exclude<AiLocalitySetting, 'auto'>, string> = {\n local: 'Local',\n cloud: 'Cloud',\n};\n\ninterface FetchState {\n /** Bumped by every trigger; a fetch whose number is stale drops its result. */\n seq: number;\n running: boolean;\n /** A newer trigger arrived while running: run again when it settles. */\n again: AutoFetchEvent | null;\n /** Pending settle timer (key field). */\n timer?: number;\n /** URL or key the last fetch ran for (see `autoFetchDecision`). */\n fetchedFor?: string;\n /** The event that set off the last fetch, for Retry. */\n lastEvent?: AutoFetchEvent;\n problem: DiscoveryProblem | null;\n /** The previous `autoFetchDecision` input. */\n prev: AutoFetchState | null;\n}\n\nexport function createEngineFormController(deps: EngineFormDeps): EngineFormController {\n const { ai } = deps;\n const fetches = new Map<string, FetchState>();\n const testing = new Set<string>();\n /** Test connection results per engine. */\n const results = new Map<string, { level: 'ok' | 'error' | 'info'; text: string }>();\n /** Key store and clear messages per engine, shown under the key field. */\n const keyResults = new Map<string, { level: 'error' | 'info'; text: string }>();\n /** Advanced folds opened while the modal is open. */\n const advancedOpen = new Set<string>();\n /** \"What is sent\" disclosures opened while the modal is open. */\n const privacyOpen = new Set<string>();\n /** What the user typed into a key field (kept across rebuilds until the modal closes). */\n const keyText = new Map<string, string>();\n /** Last key text stored per engine, so a settle that changed nothing does not store again. */\n const keyStored = new Map<string, string>();\n const keyTimers = new Map<string, number>();\n const pickerFilter = new Map<string, string>();\n /** Engines whose \"type a model id\" field was opened (small lists hide it). */\n const typeOpen = new Set<string>();\n const openOverrides = new Set<string>();\n /** Setup form: engines whose \"Show all models\" is open. */\n const showAll = new Set<string>();\n /** The model this form picked last per engine (the auto-pick or a setup choice), which a new setup choice replaces. */\n const formPicked = new Map<string, string>();\n const overrideErrors = new Map<string, { text: string; error: string }>();\n /** Engines Done stopped at because nothing is picked (Q1). */\n const pickRequired = new Set<string>();\n\n const getEngine = (id: string) => deps.getDraft().engines.find((e) => e.id === id);\n const presetOf = (engine: AiEngineConfig): EngineFormPreset => enginePreset(engine, deps.getDraft().localNetworks);\n const isLocal = (engine: AiEngineConfig) => engineLocalityInfo(engine, deps.getDraft().localNetworks).locality === 'local';\n\n function fetchState(id: string): FetchState {\n let st = fetches.get(id);\n if (!st) {\n st = { seq: 0, running: false, again: null, problem: null, prev: null };\n fetches.set(id, st);\n }\n return st;\n }\n\n // ── Draft edits ───────────────────────────────────────────────────────────\n\n function replaceEngine(engine: AiEngineConfig, refresh: EngineFormRefresh): void {\n deps.setDraft(withEngine(deps.getDraft(), engine), refresh);\n }\n\n function updateEngine(id: string, patch: Partial<AiEngineConfig>, refresh: EngineFormRefresh): void {\n const current = getEngine(id);\n if (current) {replaceEngine({ ...current, ...patch }, refresh);}\n }\n\n function updateModel(engineId: string, modelId: string, fn: (m: AiModelConfig) => AiModelConfig, refresh: EngineFormRefresh): void {\n const engine = getEngine(engineId);\n const model = engine?.models.find((m) => m.id === modelId);\n if (engine && model) {replaceEngine(withModel(engine, fn(model)), refresh);}\n }\n\n // ── Fetching ──────────────────────────────────────────────────────────────\n\n function snapshot(engine: AiEngineConfig, event: AutoFetchEvent): AutoFetchState {\n const st = fetchState(engine.id);\n const status = deps.statuses.get(engine.id);\n return {\n event,\n family: presetOf(engine).family,\n key: keyText.get(engine.id) ?? '',\n baseUrl: engine.baseUrl,\n discovery: engine.discovery,\n neverProbed: !status || status.ok === null,\n hasKey: deps.hasKey(engine.id),\n modelCount: engine.models.length,\n fetchedFor: st.fetchedFor,\n };\n }\n\n /** Run `autoFetchDecision` for an event and act on it. */\n function trigger(id: string, event: AutoFetchEvent): void {\n const engine = getEngine(id);\n if (!engine || !ai.discoverModels) {return;}\n const st = fetchState(id);\n const next = snapshot(engine, event);\n const decision = autoFetchDecision(st.prev, next);\n st.prev = next;\n if (decision.cancelPending) {\n window.clearTimeout(st.timer);\n st.timer = undefined;\n }\n if (!decision.fetch) {return;}\n if (decision.delayMs > 0) {\n st.timer = window.setTimeout(() => {\n st.timer = undefined;\n void runFetch(id, event);\n }, decision.delayMs);\n } else {\n void runFetch(id, event);\n }\n }\n\n async function runFetch(id: string, event: AutoFetchEvent): Promise<void> {\n const st = fetchState(id);\n const seq = ++st.seq;\n st.lastEvent = event;\n if (st.running) {\n // One discovery per engine: this one runs when the current one settles.\n st.again = event;\n return;\n }\n const engine = getEngine(id);\n if (!engine || !ai.discoverModels) {return;}\n st.running = true;\n st.problem = null;\n deps.refresh(id, { form: true, head: true });\n const preset = presetOf(engine);\n const name = engineDisplayName(engine);\n try {\n // Discovery runs host side against the stored key, so a key still in the field goes first.\n const typed = (keyText.get(id) ?? '').trim();\n if (ai.setSecret && typed && keyStored.get(id) !== typed) {\n const error = await deps.setKey(id, typed);\n if (error) {throw new Error(error);}\n keyStored.set(id, typed);\n }\n await deps.ensureSaved(id);\n const status = await ai.discoverModels(id);\n if (!status || typeof status !== 'object') {throw new Error('The app returned no model list.');}\n deps.statuses.set(id, status);\n deps.onStatuses();\n if (seq !== st.seq) {return;}\n const current = getEngine(id) ?? engine;\n if (status.ok === false) {\n st.problem = discoveryProblem({ family: preset.family, presetName: preset.name, baseUrl: current.baseUrl, ok: false, message: status.error, listed: 0 });\n } else {\n const hadPick = current.models.some((m) => m.enabled && !m.missing);\n let draft = withEngine(deps.getDraft(), applyDiscoveryForFamily(current, status, preset.family));\n const merged = draft.engines.find((e) => e.id === id) ?? current;\n let picked: string | null = null;\n // OPEN-12: key = done. The first fetch with nothing picked picks the usual default\n // (Copilot's models arrive unpicked too, and have no Popular rules: the host's first;\n // a local server's default is the loaded model the merge put first; none loaded, the form asks for a pick).\n if (!hadPick) {\n picked = preset.family === 'local'\n ? merged.models.find((m) => m.enabled && !m.missing && m.capabilities.chat)?.id ?? null\n : autoPickDefault(preset, merged.models) ?? (preset.family === 'host' ? firstChatModelId(merged.models) : null);\n if (picked) {\n draft = setEngineDefaultModel(draft, id, picked);\n formPicked.set(id, picked);\n }\n }\n // The first engine that can chat becomes the default route, so it works without a trip to the star.\n if (!draft.routing.default) {\n const route = defaultRouteForEngine(draft, [...deps.statuses.values()], id);\n if (route) {draft = setEngineDefaultModel(draft, id, route.modelId);}\n }\n const listed = merged.models.filter((m) => !m.missing).length;\n st.problem = discoveryProblem({ family: preset.family, presetName: preset.name, baseUrl: current.baseUrl, ok: true, listed });\n st.fetchedFor = fetchFingerprint(preset.family, keyText.get(id) ?? '', current.baseUrl);\n forgetStoredText(id);\n deps.setDraft(draft, { head: true, routing: true, list: !hadPick && !!picked });\n const pickedName = picked ? modelDisplayName(merged.models.find((m) => m.id === picked) ?? { id: picked }) : '';\n deps.announce(`${name}: ${listed} ${listed === 1 ? 'model' : 'models'} found${pickedName ? `. ${pickedName} picked as the default model` : ''}.`);\n }\n } catch (err) {\n if (seq !== st.seq) {return;}\n const e = toAiError(err);\n const current = getEngine(id) ?? engine;\n st.problem = discoveryProblem({ family: preset.family, presetName: preset.name, baseUrl: current.baseUrl, ok: false, code: e.code, message: e.message, listed: 0 });\n } finally {\n st.running = false;\n const again = st.again;\n st.again = null;\n if (again && seq !== st.seq) {\n void runFetch(id, again);\n } else if (getEngine(id)) {\n if (st.problem && st.problem.kind !== 'empty') {deps.announce(`${name}: ${st.problem.text}`);}\n deps.refresh(id, { form: true, head: true });\n if (st.problem?.focus === 'key') {\n deps.focusKey(`eng:${id}:key`);\n const active = document.activeElement;\n if (active instanceof HTMLInputElement) {active.select();}\n }\n }\n }\n }\n\n /**\n * Once a key is stored and working, the field goes back to its \"Stored\"\n * placeholder (the field is write-only). Text typed since is kept.\n */\n function forgetStoredText(id: string): void {\n const typed = keyText.get(id);\n if (typed !== undefined && typed.trim() === keyStored.get(id)) {keyText.delete(id);}\n }\n\n /** The key field settled (or Enter / blur): store it, then fetch when the decision says so. */\n async function settleKey(id: string): Promise<void> {\n window.clearTimeout(keyTimers.get(id));\n keyTimers.delete(id);\n const engine = getEngine(id);\n const typed = (keyText.get(id) ?? '').trim();\n if (!engine || !typed || keyStored.get(id) === typed || !ai.setSecret) {return;}\n const error = await deps.setKey(id, typed);\n if (error) {\n keyResults.set(id, { level: 'error', text: error });\n deps.refresh(id, { form: true });\n return;\n }\n keyStored.set(id, typed);\n keyResults.delete(id);\n const st = fetchState(id);\n if (st.problem?.kind !== 'auth') {forgetStoredText(id);}\n // A local server that rejected the key gets a fresh fetch with the new one.\n if (presetOf(engine).family === 'local') {\n if (st.problem?.kind === 'auth') {void runFetch(id, 'retry');} else {deps.refresh(id, { form: true });}\n return;\n }\n deps.refresh(id, { form: true });\n }\n\n async function runTest(id: string): Promise<void> {\n const engine = getEngine(id);\n if (!engine || !ai.testEngine || testing.has(id)) {return;}\n const name = engineDisplayName(engine);\n testing.add(id);\n results.delete(id);\n deps.refresh(id, { form: true, head: true });\n try {\n await deps.ensureSaved(id);\n const status = await ai.testEngine(id);\n deps.statuses.set(id, status);\n deps.onStatuses();\n if (status.ok) {\n const ms = status.latencyMs !== undefined ? ` in ${Math.round(status.latencyMs)} ms` : '';\n const n = status.models.filter((m) => !m.missing).length;\n const text = `Connected${ms}${n ? `. The server lists ${n} ${n === 1 ? 'model' : 'models'}.` : '.'}`;\n results.set(id, { level: 'ok', text });\n deps.announce(`${name}: ${text}`);\n } else {\n const text = `Failed${status.error ? `: ${status.error}` : '. The server did not answer.'}`;\n results.set(id, { level: 'error', text });\n deps.announce(`${name}: connection ${text.toLowerCase()}`);\n }\n } catch (err) {\n const e = toAiError(err);\n const copy = aiErrorCopy(e.code);\n const text = `${copy.title}${e.message && e.message !== copy.title ? `: ${e.message}` : '.'}`;\n results.set(id, { level: 'error', text });\n deps.announce(`${name}: ${text}`);\n } finally {\n testing.delete(id);\n deps.refresh(id, { form: true, head: true, routing: true });\n deps.focusKey(`eng:${id}:test`);\n }\n }\n\n /**\n * A new cloud engine whose preset names a key variable or file: the host\n * cannot say whether it has a key for an engine it has never seen, so save\n * it first (as Test does) and ask. A key found there fetches models at once\n * (B2), so a user with `ANTHROPIC_API_KEY` set is done after one click.\n */\n async function lookUpKey(id: string): Promise<void> {\n const engine = getEngine(id);\n if (!engine || !ai.listEngines || !ai.discoverModels || deps.hasKey(id) || !deps.savesFirst(id)) {return;}\n if (!engine.apiKeyEnv?.trim() && !engine.apiKeyFile?.path.trim()) {return;}\n try {\n await deps.ensureSaved(id);\n const status = (await ai.listEngines()).find((s) => s.engineId === id);\n // Typing a key since takes over; a deleted engine needs nothing.\n if (!status?.hasKey || !getEngine(id) || (keyText.get(id) ?? '').trim()) {return;}\n deps.statuses.set(id, status);\n deps.onStatuses();\n deps.refresh(id, { form: true, head: true });\n trigger(id, 'open');\n } catch {\n // No answer: the key field is still there.\n }\n }\n\n // ── The form ──────────────────────────────────────────────────────────────\n\n function build(id: string, opts: FormBuildOptions = {}): HTMLElement {\n const engine = getEngine(id);\n const wrap = el('div', 'ai-form');\n wrap.id = `ai-engine-editor-${id}`;\n if (!engine) {return wrap;}\n const preset = presetOf(engine);\n const setup = !!opts.setup;\n const fields = setup\n ? setupFields(preset, { key: fetchState(id).problem?.kind === 'auth' || deps.hasKey(id) })\n : expressFields(preset);\n wrap.dataset.family = preset.family;\n if (setup) {wrap.classList.add('ai-form--setup');}\n wrap.setAttribute('role', 'group');\n wrap.setAttribute('aria-label', `${engineDisplayName(engine)} settings`);\n\n // Cloud (and Copilot, which is cloud too): what happens to the text, folded at the head of the form.\n if ((preset.family === 'cloud' || preset.family === 'host') && opts.privacy !== false) {\n wrap.append(privacyCard({ policy: aiProviderPolicy(engine) }, {\n hostEngine: preset.family === 'host',\n collapsed: 'What is sent',\n open: privacyOpen.has(id),\n onToggle: (open) => { if (open) {privacyOpen.add(id);} else {privacyOpen.delete(id);} },\n openLink: deps.openLink,\n className: 'ai-form-privacy',\n }));\n }\n\n const sheet = el('div', 'ai-sheet');\n for (const field of fields.express) {\n // The note's \"Get a key\" line replaces the hint under the field (W11).\n const keyNote = field === 'key' && ai.setSecret ? deps.keyNote?.(engine, preset) ?? null : null;\n const row = field === 'key' ? buildKey(engine, preset, { hint: !keyNote }) : buildExpressField(engine, preset, field, setup);\n if (!row) {continue;}\n if (keyNote) {sheet.append(keyNote);}\n sheet.append(row);\n }\n wrap.append(sheet);\n // Setup: a model list that loads is the test, so no Test connection.\n if (!setup) {wrap.append(buildActions(engine));}\n wrap.append(...buildAdvanced(engine, preset, fields.advanced));\n return wrap;\n }\n\n /** One labelled line of the sheet: label column, control, optional caption. */\n function sheetRow(label: string, control: HTMLElement, opts: { forId?: string; caption?: HTMLElement | string; className?: string } = {}): HTMLElement {\n const row = el('div', `ai-sheet-row${opts.className ? ` ${opts.className}` : ''}`);\n const lbl = el('label', 'ai-sheet-label', label);\n if (opts.forId) {lbl.htmlFor = opts.forId;}\n const body = el('div', 'ai-sheet-body');\n body.append(control);\n if (opts.caption) {\n body.append(typeof opts.caption === 'string' ? el('div', 'ai-caption', opts.caption) : opts.caption);\n }\n row.append(lbl, body);\n return row;\n }\n\n function buildExpressField(engine: AiEngineConfig, preset: EngineFormPreset, field: string, setup: boolean): HTMLElement | null {\n switch (field) {\n case 'name': return buildName(engine);\n case 'key': return buildKey(engine, preset);\n case 'baseUrl': return buildUrl(engine, preset, 'express');\n case 'models': return buildModelsPicker(engine, preset, setup);\n case 'defaultModel': return buildDefaultModel(engine);\n case 'enabled': return buildEnabled(engine);\n default: return null; // `thinking` sits next to Default model.\n }\n }\n\n function buildName(engine: AiEngineConfig): HTMLElement {\n const id = engine.id;\n const input = el('input', 'settings-input ai-sheet-input');\n input.type = 'text';\n input.id = nextId('ai-name');\n input.value = engine.name;\n input.placeholder = 'Shown in pickers and the indicator';\n input.dataset.fk = `eng:${id}:name`;\n input.addEventListener('input', () => updateEngine(id, { name: input.value }, { head: true, routing: true }));\n return sheetRow('Name', input, { forId: input.id });\n }\n\n // ── API key ───────────────────────────────────────────────────────────────\n\n /** `hint: false` leaves out the key hint (the key note above the field has the link). */\n function buildKey(engine: AiEngineConfig, preset: EngineFormPreset, o: { hint?: boolean } = {}): HTMLElement | null {\n if (!ai.setSecret) {return null;}\n const id = engine.id;\n const has = deps.hasKey(id);\n const line = el('div', 'ai-key');\n const input = el('input', 'settings-input settings-input--grow ai-mono');\n input.type = 'password';\n input.id = nextId('ai-key');\n input.autocomplete = 'off';\n input.spellcheck = false;\n input.dataset.fk = `eng:${id}:key`;\n input.setAttribute('aria-label', `API key for ${engineDisplayName(engine)}`);\n input.value = keyText.get(id) ?? '';\n const source = has ? deps.keySource?.(id) : undefined;\n const fromFile = has && (source ? source === 'file' : !keyStored.has(id) && !!engine.apiKeyFile?.path);\n const fromEnv = has && source === 'env';\n input.placeholder = fromFile || fromEnv ? 'Found' : has ? 'Stored' : 'Paste your key';\n const problem = fetchState(id).problem;\n if (problem?.kind === 'auth') {input.setAttribute('aria-invalid', 'true');}\n input.addEventListener('input', () => {\n keyText.set(id, input.value);\n input.removeAttribute('aria-invalid');\n window.clearTimeout(keyTimers.get(id));\n const st = fetchState(id);\n if (presetOf(getEngine(id) ?? engine).family === 'cloud') {\n // Cloud: the decision stores the key and fetches once the field settles.\n trigger(id, 'key');\n if (!st.timer && input.value.trim()) {keyTimers.set(id, window.setTimeout(() => { void settleKey(id); }, 600));}\n } else if (input.value.trim()) {\n keyTimers.set(id, window.setTimeout(() => { void settleKey(id); }, 600));\n }\n });\n const flush = () => {\n const st = fetchState(id);\n if (st.timer) {\n // A cloud fetch was waiting for the field to settle: run it now.\n window.clearTimeout(st.timer);\n st.timer = undefined;\n void runFetch(id, 'key');\n } else if (keyTimers.has(id)) {\n void settleKey(id);\n }\n };\n input.addEventListener('keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); flush(); } });\n input.addEventListener('blur', flush);\n line.append(input);\n // A key from a variable or a key file is not stored here: there is nothing to clear.\n if (has && source !== 'env' && source !== 'file') {\n const clear = button('settings-btn', 'Clear', { fk: `eng:${id}:key-clear`, ariaLabel: `Clear the stored API key for ${engineDisplayName(engine)}` });\n clear.addEventListener('click', () => { void clearKey(id); });\n line.append(clear);\n }\n\n const caption = el('div', 'ai-caption ai-key-caption');\n const result = keyResults.get(id);\n if (result) {\n caption.append(note(result.level, result.text));\n } else if (fromEnv) {\n caption.innerHTML = `<span class=\"ai-key-state\">${ICONS.check}<span>Key found</span></span>`;\n caption.append(' in ', el('code', 'ai-key-env', engine.apiKeyEnv ?? 'a variable'), '. Paste a key to use another one.');\n } else if (fromFile) {\n caption.innerHTML = `<span class=\"ai-key-state\">${ICONS.check}<span>Key found</span></span>`;\n caption.append(` in ${engine.apiKeyFile?.path ?? 'the key file'}${source ? '' : ' (or stored here)'}. Paste a key to use another one.`);\n } else if (has) {\n caption.innerHTML = `<span class=\"ai-key-state\">${ICONS.check}<span>Stored</span></span>`;\n caption.append(' in the system’s secure storage. Paste a new key to replace it.');\n } else if (o.hint === false) {\n // The note above carries the key link.\n } else if (preset.keyUrl) {\n caption.append(hostLink(preset.keyHint, preset.keyUrl, deps.openLink, 'ai-key-link'));\n } else {\n caption.textContent = preset.keyHint;\n }\n return sheetRow('API key', line, { forId: input.id, caption: caption.childNodes.length > 0 ? caption : undefined, className: 'ai-key-row' });\n }\n\n async function clearKey(id: string): Promise<void> {\n const engine = getEngine(id);\n if (!engine) {return;}\n keyText.delete(id);\n keyStored.delete(id);\n const error = await deps.setKey(id, null);\n keyResults.set(id, error\n ? { level: 'error', text: error }\n : { level: 'info', text: engine.apiKeyEnv ? `Key cleared. ${engine.apiKeyEnv} is used if it is set.` : engine.apiKeyFile ? 'Key cleared. The key file is used if it has a key.' : 'Key cleared.' });\n deps.refresh(id, { form: true, head: true });\n deps.focusKey(`eng:${id}:key`);\n }\n\n // ── Base URL ──────────────────────────────────────────────────────────────\n\n function buildUrl(engine: AiEngineConfig, preset: EngineFormPreset, where: 'express' | 'advanced'): HTMLElement {\n const id = engine.id;\n const input = el('input', 'settings-input ai-sheet-input ai-mono');\n input.type = 'url';\n input.id = nextId('ai-url');\n input.spellcheck = false;\n input.autocomplete = 'off';\n input.placeholder = 'http://127.0.0.1:8000/v1';\n input.value = engine.baseUrl;\n input.dataset.fk = `eng:${id}:url`;\n const error = el('div', 'ai-field-error');\n error.id = nextId('ai-url-error');\n error.setAttribute('aria-live', 'polite');\n input.setAttribute('aria-describedby', error.id);\n const show = () => {\n const problem = baseUrlProblem(input.value);\n error.textContent = problem;\n input.setAttribute('aria-invalid', String(!!problem));\n };\n input.addEventListener('input', () => {\n updateEngine(id, { baseUrl: input.value.trim() }, { head: true });\n // Keep a half-typed address quiet; flag it once it stops looking like one.\n if (error.textContent) {show();}\n });\n // `change` fires on blur after an edit: the URL settled, so fetch from it.\n input.addEventListener('change', () => {\n show();\n deps.refresh(id, { routing: true });\n if (preset.family === 'local') {trigger(id, 'url');}\n });\n if (engine.baseUrl) {show();}\n const body = el('div', 'ai-url');\n body.append(input, error);\n const caption = where === 'express' ? 'The one thing that changes per machine. Usually ends in /v1.' : 'The server address. Cloud presets fill it in.';\n return sheetRow('Base URL', body, { forId: input.id, caption });\n }\n\n // ── Models picker ─────────────────────────────────────────────────────────\n\n /** A local engine's size tag per model (the server's reported size first), or null when the host gave no hardware. */\n function sizeTagFor(engineId: string, preset: EngineFormPreset): ((modelId: string) => AiModelSizeTag | undefined) | null {\n if (preset.family !== 'local' || !deps.modelSize) {return null;}\n const bytes = new Map((deps.statuses.get(engineId)?.models ?? []).map((m) => [m.id, m.sizeBytes]));\n return (modelId) => deps.modelSize?.(modelId, bytes.get(modelId));\n }\n\n /** \"Pick a model\" for a local engine that lists chat models but has none picked (in setup: none chosen). */\n function localPickNote(engine: AiEngineConfig, preset: EngineFormPreset, setup: boolean): HTMLElement | null {\n const chat = engine.models.filter((m) => !m.missing && m.capabilities.chat);\n if (chat.length === 0) {return null;}\n const chosenId = engineDefaultModelId(deps.getDraft(), engine.id);\n const picked = setup\n ? chat.some((m) => m.id === chosenId && m.enabled)\n : chat.some((m) => m.enabled);\n if (picked) {\n pickRequired.delete(engine.id);\n return null;\n }\n // Done stopped here: say why, as an error, on any engine.\n if (pickRequired.has(engine.id)) {\n const line = note('error', `Pick at least one model before you choose Done. ${engineDisplayName(engine)} needs a default model to answer.`, 'ai-pick-note');\n line.setAttribute('role', 'alert');\n return line;\n }\n if (preset.family !== 'local') {return null;}\n const sizeOf = sizeTagFor(engine.id, preset);\n const facts = new Map((deps.statuses.get(engine.id)?.models ?? []).map((m) => [m.id, m]));\n const tagged = chat.some((m) => (sizeOf && sizeOf(m.id) !== undefined) || !!facts.get(m.id)?.sizeBytes || !!modelMoeFastHint(m.id, facts.get(m.id)?.moe, sizeOf?.(m.id)));\n const text = `Pick a model to start with. No chat model is loaded in ${engineDisplayName(engine)}, so none was chosen for you${tagged ? '; the tags give size and speed hints' : ''}.`;\n const line = note('info', text, 'ai-pick-note');\n line.setAttribute('role', 'status');\n return line;\n }\n\n /**\n * `setup`: one model, which is the default (W16); cloud engines show the\n * Popular group with the rest behind \"Show all models\" (W15); nothing until\n * a key exists, and no typing an id before there are models (W13).\n */\n function buildModelsPicker(engine: AiEngineConfig, preset: EngineFormPreset, setup = false): HTMLElement | null {\n const id = engine.id;\n const st = fetchState(id);\n const keyless = preset.family === 'cloud' && !deps.hasKey(id) && !(keyText.get(id) ?? '').trim();\n if (setup && keyless && engine.models.length === 0 && !st.running && !st.problem) {return null;}\n const box = el('div', 'ai-picker');\n const labelId = nextId('ai-models-label');\n const listId = nextId('ai-models-list');\n\n // Head: label with a spinner while fetching, the count, Fetch models.\n const head = el('div', 'ai-picker-head');\n const label = el('span', 'ai-picker-label', setup ? 'Model' : 'Models');\n label.id = labelId;\n if (st.running) {\n const spin = el('span', 'ai-spinner');\n spin.setAttribute('aria-hidden', 'true');\n label.append(spin);\n box.setAttribute('aria-busy', 'true');\n }\n // Setup has no \"N picked\": one model is chosen, and Show all models carries the count.\n const countLine = (e: AiEngineConfig) => (st.running ? 'Fetching…' : setup ? '' : modelCountLine(e));\n const count = el('span', 'ai-models-count', countLine(engine));\n head.append(label, count);\n if (ai.discoverModels && !(setup && keyless)) {\n // \"Fetch models\" the first time; once there is a list, it refreshes it.\n const fetchBtn = button('ai-link-btn', engine.models.length > 0 ? 'Refresh models' : 'Fetch models', { html: ICONS.refresh, fk: `eng:${id}:fetch` });\n const urlBad = !isHostEngineKind(engine.kind) && !!baseUrlProblem(engine.baseUrl);\n if (st.running) {fetchBtn.setAttribute('aria-disabled', 'true');}\n fetchBtn.disabled = engine.discovery === 'manual' || urlBad;\n if (engine.discovery === 'manual') {fetchBtn.title = 'The model list is manual for this engine (see Advanced).';}\n fetchBtn.addEventListener('click', () => {\n if (!st.running) {trigger(id, 'manual');}\n });\n head.append(fetchBtn);\n }\n box.append(head);\n\n // A local server with nothing loaded and no sizes to go by: no default was guessed, so say so.\n const pickNote = localPickNote(engine, preset, setup);\n if (pickNote && !st.running && !st.problem) {box.append(pickNote);}\n\n const listed = engine.models.filter((m) => !m.missing).length;\n const popularIds = preset.family === 'cloud' ? popularModels(preset, engine.models).map((m) => m.id) : [];\n // Setup: the chosen model is the Default model; Popular only, unless the choice is not in it.\n const chosen = () => (setup ? engineDefaultModelId(deps.getDraft(), id) : null);\n const chosenAtBuild = chosen();\n const collapsed = setup && popularIds.length > 0 && !showAll.has(id) && (!chosenAtBuild || popularIds.includes(chosenAtBuild));\n // Setup has no models table to add an id in, so an empty list (a server that lists nothing) gets the field.\n const showInput = setup\n ? !collapsed && (engine.models.length > 0\n ? engine.models.length > FILTER_THRESHOLD || typeOpen.has(id) || !!pickerFilter.get(id)\n : !keyless && !st.running)\n : engine.models.length > FILTER_THRESHOLD || engine.models.length === 0 || typeOpen.has(id) || !!pickerFilter.get(id);\n // Local models by how they suit this machine, when the host said what it is (a hint, never a gate).\n const sizeOf = sizeTagFor(id, preset);\n\n // Combobox: filter, pick or type (design call 6).\n let input: HTMLInputElement | null = null;\n if (showInput) {\n const field = el('div', 'ai-combo');\n const icon = el('span', 'ai-combo-icon');\n icon.innerHTML = ICONS.search;\n input = el('input', 'settings-input ai-combo-input');\n input.type = 'text';\n input.spellcheck = false;\n input.autocomplete = 'off';\n input.dataset.fk = `eng:${id}:pick`;\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-expanded', 'true');\n input.setAttribute('aria-controls', listId);\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-label', engine.models.length > 0 ? `Filter models of ${engineDisplayName(engine)}, or type a model id to add it` : `Type a model id for ${engineDisplayName(engine)}`);\n input.placeholder = engine.models.length > FILTER_THRESHOLD ? `Search ${listed} models, or type an id` : 'Type a model id, then Enter';\n input.value = pickerFilter.get(id) ?? '';\n field.append(icon, input);\n box.append(field);\n }\n\n const list = el('ul', 'ai-listbox');\n list.id = listId;\n list.setAttribute('role', 'listbox');\n list.setAttribute('aria-multiselectable', String(!setup));\n if (setup) {list.classList.add('ai-listbox--single');}\n list.setAttribute('aria-labelledby', labelId);\n // Without the text field the list takes focus itself.\n if (!input) {\n list.tabIndex = 0;\n list.dataset.fk = `eng:${id}:models`;\n }\n box.append(list);\n\n let active = -1;\n let options: ModelPickerOption[] = [];\n const optionId = (i: number) => `${listId}-o${i}`;\n const focusTarget = () => input ?? list;\n\n /** Highlight option `i` (-1: none). */\n function setActive(i: number): void {\n active = i >= 0 && i < options.length ? i : -1;\n list.querySelectorAll('.ai-option.is-active').forEach((n) => n.classList.remove('is-active'));\n const target = focusTarget();\n if (active < 0) {\n target.removeAttribute('aria-activedescendant');\n return;\n }\n const node = Array.from(list.querySelectorAll<HTMLElement>('.ai-option')).find((n) => n.id === optionId(active));\n node?.classList.add('is-active');\n node?.scrollIntoView?.({ block: 'nearest' });\n target.setAttribute('aria-activedescendant', optionId(active));\n }\n\n function renderList(): void {\n const filter = collapsed ? '' : pickerFilter.get(id) ?? '';\n const current = getEngine(id) ?? engine;\n const all = modelPickerOptions(current, deps.statuses.get(id), filter);\n const popular = all.filter((o) => popularIds.includes(o.id)).sort((a, b) => popularIds.indexOf(a.id) - popularIds.indexOf(b.id));\n const rest = collapsed ? [] : all.filter((o) => !popularIds.includes(o.id));\n const sizes = sizeOf ? new Map(rest.map((o) => [o.id, sizeOf(o.id)])) : null;\n const sized = !!sizes && [...sizes.values()].some((t) => t !== undefined);\n const bySize = (tag: AiModelSizeTag | undefined) => rest.filter((o) => sizes?.get(o.id) === tag);\n options = sized\n ? [...SIZE_GROUPS.flatMap((g) => bySize(g.tag))]\n : [...popular, ...rest];\n list.replaceChildren();\n let index = 0;\n const group = (title: string, items: ModelPickerOption[]) => {\n if (items.length === 0) {return;}\n const g = el('li', 'ai-listbox-group');\n g.setAttribute('role', 'presentation');\n const heading = el('div', 'ai-listbox-heading', title);\n heading.id = nextId('ai-group');\n const ul = el('ul', 'ai-listbox-items');\n ul.setAttribute('role', 'group');\n ul.setAttribute('aria-labelledby', heading.id);\n for (const o of items) {ul.append(optionNode(o, index++));}\n g.append(heading, ul);\n list.append(g);\n };\n if (sized) {\n for (const g of SIZE_GROUPS) {group(g.title, bySize(g.tag));}\n } else if (popular.length > 0) {\n group('Popular', popular);\n group('All models', rest);\n } else {\n for (const o of rest) {list.append(optionNode(o, index++));}\n }\n if (options.length === 0) {\n const empty = el('li', 'ai-listbox-empty');\n empty.setAttribute('role', 'presentation');\n empty.textContent = filter.trim()\n ? `No model matches “${filter.trim()}”. Press Enter to add it by id.`\n : st.running\n ? 'Fetching models…'\n : keyless\n ? 'Paste your key and the models appear here.'\n : setup ? 'No models yet. Fetch them from the server.' : 'No models yet. Fetch them from the server, or type an id.';\n list.append(empty);\n }\n setActive(Math.min(active, options.length - 1));\n }\n\n function optionNode(o: ModelPickerOption, i: number): HTMLElement {\n const li = el('li', 'ai-option');\n li.id = optionId(i);\n li.setAttribute('role', 'option');\n const on = setup ? o.id === chosen() : o.enabled;\n li.setAttribute('aria-selected', String(on));\n li.dataset.modelId = o.id;\n li.classList.toggle('is-missing', o.missing);\n li.classList.toggle('is-on', on);\n // Not a chat model (in setup: the choice is the default, so chat only); shown greyed, never picked.\n const unusable = !(setup ? o.chat : o.usable);\n if (unusable) {\n li.classList.add('is-unusable');\n li.setAttribute('aria-disabled', 'true');\n }\n const check = el('span', 'ai-option-check');\n check.setAttribute('aria-hidden', 'true');\n check.innerHTML = ICONS.check;\n const names = el('span', 'ai-option-names');\n names.append(el('span', 'ai-option-name', o.name));\n if (o.hasLabel) {names.append(el('span', 'ai-option-id', o.id));}\n li.append(check, names);\n const tags = el('span', 'ai-option-tags');\n if (o.loaded) {\n const t = el('span', 'ai-tag ai-tag--loaded', 'loaded');\n t.title = 'Loaded in memory on the server right now.';\n tags.append(t);\n }\n if (o.missing) {\n const t = el('span', 'ai-tag ai-tag--missing', 'not listed');\n t.title = 'The last fetch did not list this model. It is kept, but never routed.';\n tags.append(t);\n }\n if (o.manual) {tags.append(el('span', 'ai-tag', 'typed in'));}\n if (unusable) {\n const t = el('span', 'ai-tag ai-tag--unusable', o.usable ? 'not for chat' : 'not a chat model');\n t.title = o.usable ? 'An embeddings model: it cannot be the model this engine answers with.' : 'This model cannot answer (a converter or a draft model for another model), so it cannot be picked.';\n tags.append(t);\n }\n // Local rows: how fast (a mixture of experts that fits here) and how big, when known. Hints only; they never pick.\n const facts = preset.family === 'local' ? deps.statuses.get(id)?.models.find((m) => m.id === o.id) : undefined;\n const size = sizeOf?.(o.id);\n const moe = preset.family === 'local' ? modelMoeFastHint(o.id, facts?.moe, size) : null;\n if (moe) {\n const t = el('span', 'ai-tag ai-tag--moe', 'MoE · fast');\n t.title = moe.activeBillions !== null\n ? `A mixture of experts: about ${moe.activeBillions}B parameters work per token, so it runs much faster than its size suggests.`\n : 'A mixture of experts: only part of it works per token, so it runs much faster than its size suggests.';\n tags.append(t);\n }\n if (facts?.sizeBytes) {\n const t = el('span', 'ai-tag ai-tag--bytes', formatModelSize(facts.sizeBytes));\n t.title = 'Its size, as the server reports it.';\n tags.append(t);\n }\n if (size) {\n const t = el('span', `ai-tag ai-tag--size ai-tag--${size.replace(' ', '-')}`, size);\n t.title = SIZE_TITLES[size];\n tags.append(t);\n }\n if (tags.childElementCount > 0) {li.append(tags);}\n // Keep focus in the field while clicking a row.\n li.addEventListener('mousedown', (e) => e.preventDefault());\n li.addEventListener('click', () => {\n active = i;\n pick(o.id);\n });\n return li;\n }\n\n /** Toggle a model, or in setup choose it. */\n function pick(modelId: string): void {\n const o = options.find((x) => x.id === modelId);\n if (o && !(setup ? o.chat : o.usable)) {\n deps.announce(`${o.name} is not a chat model, so it cannot be picked.`);\n return;\n }\n if (setup) {choose(modelId);} else {toggle(modelId);}\n }\n\n function choose(modelId: string): void {\n const model = getEngine(id)?.models.find((m) => m.id === modelId);\n if (!model || chosen() === modelId) {return;}\n deps.setDraft(chooseSetupModel(deps.getDraft(), id, modelId, formPicked.get(id)), { head: true, list: true, routing: true });\n formPicked.set(id, modelId);\n deps.announce(`${modelDisplayName(model)} chosen.`);\n refreshAfterPick();\n }\n\n function toggle(modelId: string): void {\n const current = getEngine(id);\n const model = current?.models.find((m) => m.id === modelId);\n if (!current || !model) {return;}\n const enabled = !model.enabled;\n deps.setDraft(setModelPicked(deps.getDraft(), id, modelId, enabled), { head: true, routing: true });\n deps.announce(`${modelDisplayName(model)} ${enabled ? 'picked' : 'removed'}.`);\n refreshAfterPick();\n }\n\n /** Rebuild the parts a pick changes (count, Default model) without dropping focus or the scroll position. */\n function refreshAfterPick(): void {\n const scroll = list.scrollTop;\n const current = getEngine(id) ?? engine;\n count.textContent = countLine(current);\n renderList();\n list.scrollTop = scroll;\n // The \"Pick a model\" line comes and goes with the pick.\n const pickNote = localPickNote(current, preset, setup);\n const shown = box.querySelector(':scope > .ai-pick-note');\n if (shown && !pickNote) {shown.remove();} else if (!shown && pickNote) {head.after(pickNote);}\n const form = box.closest('.ai-form');\n const def = form?.querySelector('.ai-default-row');\n const fresh = buildDefaultModel(current);\n if (def && fresh) {keepFocus(def as HTMLElement, () => { def.replaceWith(fresh); return fresh; });}\n focusTarget().focus({ preventScroll: true });\n }\n\n function addTyped(text: string): void {\n const current = getEngine(id);\n if (!current) {return;}\n const exact = current.models.find((m) => m.id === text);\n if (exact) {\n if (setup) {choose(exact.id);} else if (!exact.enabled) {toggle(exact.id);}\n return;\n }\n const r = addManualModel(current, text);\n if (!r.ok) {\n deps.announce(r.error);\n return;\n }\n let next = withEngine(deps.getDraft(), r.engine);\n // Like a pick: with no default route yet, a typed chat model becomes it.\n if (!next.routing.default && r.model.capabilities.chat && r.engine.enabled) {next = setEngineDefaultModel(next, id, r.model.id);}\n // Setup: a typed id is the choice.\n if (setup) {\n next = chooseSetupModel(next, id, r.model.id, formPicked.get(id));\n formPicked.set(id, r.model.id);\n }\n deps.setDraft(next, { head: true, list: !deps.getDraft().routing.default && !!next.routing.default, routing: true });\n pickerFilter.delete(id);\n // Keep the field after a typed id, even on a short list, so the next one can follow.\n typeOpen.add(id);\n deps.announce(`Added ${r.model.id}.`);\n deps.refresh(id, { form: true });\n deps.focusKey(`eng:${id}:pick`);\n }\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n e.preventDefault();\n if (options.length === 0) {return;}\n const step = e.key === 'ArrowDown' ? 1 : -1;\n setActive(active < 0 ? (step > 0 ? 0 : options.length - 1) : (active + step + options.length) % options.length);\n } else if (e.key === 'Home' && !input) {\n e.preventDefault();\n setActive(0);\n } else if (e.key === 'End' && !input) {\n e.preventDefault();\n setActive(options.length - 1);\n } else if (e.key === 'Enter' || (e.key === ' ' && !input)) {\n e.preventDefault();\n const typed = input?.value.trim() ?? '';\n if (active >= 0 && options[active]) {pick(options[active].id);} else if (typed) {addTyped(typed);}\n } else if (e.key === 'Escape') {\n // Clear the filter or the highlight first; only a calm field lets Escape close the modal.\n if (input?.value) {\n e.preventDefault();\n e.stopPropagation();\n input.value = '';\n pickerFilter.delete(id);\n active = -1;\n renderList();\n } else if (active >= 0) {\n e.preventDefault();\n e.stopPropagation();\n setActive(-1);\n }\n }\n };\n if (input) {\n const field = input;\n field.addEventListener('keydown', onKey);\n field.addEventListener('input', () => {\n pickerFilter.set(id, field.value);\n active = field.value.trim() ? 0 : -1;\n renderList();\n });\n } else {\n list.addEventListener('keydown', onKey);\n list.addEventListener('focus', () => { if (active < 0 && options.length > 0) {setActive(0);} });\n }\n renderList();\n\n // The rest of a cloud provider's list, in setup.\n if (setup && popularIds.length > 0 && (collapsed || showAll.has(id))) {\n const more = button('ai-link-btn ai-show-all', collapsed ? `Show all models (${listed})` : 'Show popular only', { fk: `eng:${id}:show-all` });\n more.setAttribute('aria-expanded', String(!collapsed));\n more.setAttribute('aria-controls', listId);\n more.addEventListener('click', () => {\n if (collapsed) {showAll.add(id);} else {\n showAll.delete(id);\n pickerFilter.delete(id);\n }\n deps.refresh(id, { form: true });\n deps.focusKey(`eng:${id}:show-all`);\n });\n box.append(more);\n }\n\n // Small lists hide the field; typing an id is one click away (in setup, once the whole list shows).\n if (!input && (!setup || (!collapsed && engine.models.length > 0))) {\n const typeBtn = button('ai-link-btn ai-type-btn', 'Type a model id…', { fk: `eng:${id}:type-open` });\n typeBtn.addEventListener('click', () => {\n typeOpen.add(id);\n deps.refresh(id, { form: true });\n deps.focusKey(`eng:${id}:pick`);\n });\n box.append(typeBtn);\n }\n\n // Failures and the empty list (design call 4).\n const problem = st.problem;\n if (problem && !st.running) {\n const line = el('div', `ai-fetch-note ai-fetch-note--${problem.kind}`);\n line.setAttribute('role', 'status');\n line.append(note(problem.kind === 'empty' ? 'info' : 'error', problem.text));\n if (problem.retry && ai.discoverModels) {\n const retry = button('ai-link-btn', 'Retry', { fk: `eng:${id}:retry` });\n retry.addEventListener('click', () => {\n // Retry re-runs the same trigger (a key fetch stores the field first, as before).\n void runFetch(id, st.lastEvent ?? 'retry');\n });\n line.append(retry);\n }\n box.append(line);\n }\n\n const row = el('div', 'ai-sheet-row ai-sheet-row--block');\n row.append(box);\n return row;\n }\n\n // ── Default model and thinking ────────────────────────────────────────────\n\n function buildDefaultModel(engine: AiEngineConfig): HTMLElement | null {\n const id = engine.id;\n const draft = deps.getDraft();\n // Only a chat model can be the default (not embeddings, a converter or an MTP drafter).\n const enabled = engine.models.filter((m) => m.enabled && !m.missing && m.capabilities.chat);\n const stored = engineDefaultModelId(draft, id);\n const current = stored && enabled.some((m) => m.id === stored) ? stored : null;\n const line = el('div', 'ai-default');\n const select = el('select', 'settings-input ai-default-select');\n select.id = nextId('ai-default');\n select.dataset.fk = `eng:${id}:default-model`;\n if (enabled.length === 0) {\n const o = el('option', '', 'Pick a model above');\n o.value = '';\n select.append(o);\n select.disabled = true;\n } else {\n for (const m of enabled) {\n const o = el('option', '', modelDisplayName(m));\n o.value = m.id;\n select.append(o);\n }\n select.value = current ?? enabled[0].id;\n }\n select.addEventListener('change', () => {\n deps.setDraft(setEngineDefaultModel(deps.getDraft(), id, select.value), { head: true, list: true, routing: true });\n const model = getEngine(id)?.models.find((m) => m.id === select.value);\n if (model) {deps.announce(`Default model: ${modelDisplayName(model)}.`);}\n });\n line.append(select);\n\n // Thinking applies to the default model; kinds with no known mapping hide it.\n const model = engine.models.find((m) => m.id === (current ?? enabled[0]?.id));\n const thinking = model ? buildThinkingSelect(engine, model, 'express') : null;\n if (thinking) {\n const wrap = el('label', 'ai-thinking');\n wrap.append(el('span', 'ai-thinking-label', 'Thinking'), thinking);\n line.append(wrap);\n }\n const isDefaultEngine = draft.routing.default?.engineId === id;\n const caption = enabled.length === 0\n ? 'Pick at least one model to use this engine.'\n : isDefaultEngine\n ? 'Serves every task without its own route.'\n : draft.routing.default\n ? 'Used when this engine is picked for a task, or made the default (the star).'\n : 'Becomes the default route once you pick it.';\n return sheetRow('Default model', line, { forId: select.id, caption, className: 'ai-default-row' });\n }\n\n function buildThinkingSelect(engine: AiEngineConfig, model: AiModelConfig, where: 'express' | 'table'): HTMLSelectElement | null {\n const choices = thinkingChoices(engine.kind);\n if (choices.length === 0) {return null;}\n const id = engine.id;\n const select = el('select', `settings-input ${where === 'table' ? 'settings-input--small ' : ''}ai-thinking-select`);\n select.dataset.fk = where === 'express' ? `eng:${id}:thinking` : `model:${id}:${model.id}:thinking`;\n select.setAttribute('aria-label', `Thinking for ${modelDisplayName(model)}`);\n select.title = 'How hard the model thinks before it answers. Default sends nothing (the model decides).';\n const dflt = el('option', '', 'Default');\n dflt.value = '';\n select.append(dflt);\n for (const c of choices) {\n const o = el('option', '', c.label);\n o.value = c.level;\n select.append(o);\n }\n select.value = thinkingLevelFrom(engine.kind, model.requestOverrides) ?? '';\n select.addEventListener('change', () => {\n const level = (select.value || null) as AiThinkingLevel | null;\n const current = getEngine(id);\n if (!current) {return;}\n updateModel(id, model.id, (m) => setModelThinking(m, current.kind, level, isLocal(current)), {});\n // The overrides editor under Advanced shows the same JSON.\n if (advancedOpen.has(id)) {deps.refresh(id, { form: true });}\n });\n return select;\n }\n\n function buildEnabled(engine: AiEngineConfig): HTMLElement {\n const id = engine.id;\n const toggle = switchInput(engine.enabled, `Enable ${engineDisplayName(engine)}`, `eng:${id}:enabled`);\n toggle.id = nextId('ai-enabled');\n toggle.addEventListener('change', () => updateEngine(id, { enabled: toggle.checked }, { list: true, routing: true }));\n const line = el('div', 'ai-enabled-line');\n line.append(toggle, el('span', 'ai-caption', 'Engines that are off are never routed.'));\n return sheetRow('Enabled', line, { forId: toggle.id });\n }\n\n // ── Test connection ───────────────────────────────────────────────────────\n\n function buildActions(engine: AiEngineConfig): HTMLElement {\n const id = engine.id;\n const row = el('div', 'ai-form-actions');\n if (ai.testEngine) {\n const busy = testing.has(id);\n const test = button('settings-btn settings-btn--secondary', busy ? 'Testing…' : 'Test connection', { fk: `eng:${id}:test` });\n // Busy buttons stay focusable (aria-disabled) so the keyboard is not dropped mid-probe.\n if (busy) {test.setAttribute('aria-disabled', 'true');}\n test.disabled = !isHostEngineKind(engine.kind) && !!baseUrlProblem(engine.baseUrl);\n test.addEventListener('click', () => { void runTest(id); });\n row.append(test);\n if (deps.savesFirst(id)) {row.append(el('span', 'ai-caption', 'Testing saves this engine first, so the app can reach it.'));}\n }\n const result = results.get(id);\n if (result) {row.append(note(result.level, result.text, 'ai-result'));}\n return row;\n }\n\n // ── Advanced ──────────────────────────────────────────────────────────────\n\n function buildAdvanced(engine: AiEngineConfig, preset: EngineFormPreset, fields: string[]): HTMLElement[] {\n const id = engine.id;\n const open = advancedOpen.has(id);\n const panelId = `ai-advanced-${id}`;\n const toggle = button('ai-disclosure', 'Advanced', { html: ICONS.chevron, fk: `eng:${id}:advanced` });\n toggle.setAttribute('aria-expanded', String(open));\n toggle.setAttribute('aria-controls', panelId);\n toggle.addEventListener('click', () => {\n if (advancedOpen.has(id)) {advancedOpen.delete(id);} else {advancedOpen.add(id);}\n deps.refresh(id, { form: true });\n deps.focusKey(`eng:${id}:advanced`);\n });\n const panel = el('div', 'ai-advanced');\n panel.id = panelId;\n panel.hidden = !open;\n if (!open) {return [toggle, panel];}\n\n const rows: HTMLElement[] = [];\n for (const field of fields) {\n if (field === 'kind') {rows.push(buildKind(engine));}\n if (field === 'baseUrl') {rows.push(buildUrl(engine, preset, 'advanced'));}\n if (field === 'locality') {rows.push(buildLocality(engine));}\n if (field === 'key') {\n const key = buildKey(engine, preset);\n if (key) {rows.push(key);}\n }\n if (field === 'keyEnv') {rows.push(buildKeyEnv(engine));}\n if (field === 'keyFile') {rows.push(buildKeyFile(engine));}\n if (field === 'discovery') {rows.push(buildDiscovery(engine));}\n }\n const sheet = el('div', 'ai-sheet ai-sheet--advanced');\n sheet.append(...rows);\n panel.append(sheet);\n if (fields.includes('modelsTable')) {panel.append(buildModelsTable(engine));}\n return [toggle, panel];\n }\n\n function buildKind(engine: AiEngineConfig): HTMLElement {\n const id = engine.id;\n const select = el('select', 'settings-input');\n select.id = nextId('ai-kind');\n select.dataset.fk = `eng:${id}:kind`;\n // Host kinds (`vscode-lm`) are added from their card, never picked here.\n for (const kind of AI_ENGINE_KINDS) {\n if (isHostEngineKind(kind) && kind !== engine.kind) {continue;}\n const o = el('option', '', AI_ENGINE_KIND_LABELS[kind]);\n o.value = kind;\n select.append(o);\n }\n if (!isKnownEngineKind(engine.kind)) {\n const o = el('option', '', engineKindLabel(engine.kind));\n o.value = engine.kind;\n select.prepend(o);\n }\n select.value = engine.kind;\n select.addEventListener('change', () => updateEngine(id, { kind: select.value as AiEngineConfig['kind'] }, { form: true, head: true, routing: true }));\n return sheetRow('Kind', select, { forId: select.id, caption: 'How MikeDown talks to the server.' });\n }\n\n function buildLocality(engine: AiEngineConfig): HTMLElement {\n const id = engine.id;\n const select = el('select', 'settings-input');\n select.id = nextId('ai-locality');\n select.dataset.fk = `eng:${id}:locality`;\n const autoOption = el('option');\n autoOption.value = 'auto';\n select.append(autoOption);\n for (const [value, label] of Object.entries(LOCALITY_LABELS)) {\n const o = el('option', '', label);\n o.value = value;\n select.append(o);\n }\n select.value = engine.locality;\n const info = engineLocalityInfo(engine, deps.getDraft().localNetworks);\n autoOption.textContent = `Auto (detected: ${info.detected})`;\n const body = el('div', 'ai-locality');\n body.append(select);\n if (info.mismatch) {\n body.append(note('warning', info.locality === 'cloud' ? 'Pinned to cloud, but the address looks local.' : 'Pinned to local, but the address looks like a cloud server. Text sent to it leaves this network.', 'ai-locality-note'));\n }\n select.addEventListener('change', () => updateEngine(id, { locality: select.value as AiLocalitySetting }, { form: true, head: true, routing: true }));\n return sheetRow('Locality', body, { forId: select.id, caption: 'Auto decides from the address. Cloud engines need Allow cloud.' });\n }\n\n function buildKeyEnv(engine: AiEngineConfig): HTMLElement {\n const id = engine.id;\n const input = el('input', 'settings-input settings-input--medium ai-mono');\n input.type = 'text';\n input.id = nextId('ai-env');\n input.spellcheck = false;\n input.autocomplete = 'off';\n input.placeholder = 'NAME_OF_VARIABLE';\n input.value = engine.apiKeyEnv ?? '';\n input.dataset.fk = `eng:${id}:env`;\n input.addEventListener('input', () => {\n const v = input.value.trim();\n const current = getEngine(id);\n if (!current) {return;}\n const next: AiEngineConfig = { ...current };\n if (v) {next.apiKeyEnv = v;} else {delete next.apiKeyEnv;}\n replaceEngine(next, { head: true });\n });\n return sheetRow('Key from variable', input, {\n forId: input.id,\n // Desktop opened from the Dock has no shell environment (F10).\n caption: ai.shellEnv === false\n ? 'This app does not read shell variables when opened from the Dock; use the key file or paste the key.'\n : 'Used when no key is stored, for example OMLX_API_KEY. Apps opened from the Dock or Start menu may not see variables set in a shell profile.',\n });\n }\n\n function buildKeyFile(engine: AiEngineConfig): HTMLElement {\n const id = engine.id;\n const line = el('div', 'ai-key');\n const path = el('input', 'settings-input settings-input--grow ai-mono');\n const json = el('input', 'settings-input settings-input--medium ai-mono');\n for (const input of [path, json]) {\n input.type = 'text';\n input.spellcheck = false;\n input.autocomplete = 'off';\n }\n path.id = nextId('ai-keyfile');\n path.placeholder = '~/path/to/settings.json';\n json.placeholder = 'auth.api_key';\n path.value = engine.apiKeyFile?.path ?? '';\n json.value = engine.apiKeyFile?.jsonPath ?? '';\n path.dataset.fk = `eng:${id}:keyfile-path`;\n json.dataset.fk = `eng:${id}:keyfile-json`;\n path.setAttribute('aria-label', `Key file path for ${engineDisplayName(engine)}`);\n json.setAttribute('aria-label', `Key file JSON path for ${engineDisplayName(engine)}`);\n const save = () => {\n const current = getEngine(id);\n if (!current) {return;}\n const p = path.value.trim();\n const j = json.value.trim();\n const next: AiEngineConfig = { ...current };\n // Both parts are needed; a half-filled pair is not saved.\n if (p && j) {next.apiKeyFile = { ...current.apiKeyFile, path: p, jsonPath: j };} else {delete next.apiKeyFile;}\n replaceEngine(next, { head: true });\n };\n path.addEventListener('input', save);\n json.addEventListener('input', save);\n line.append(path, json);\n return sheetRow('Key file', line, {\n forId: path.id,\n caption: 'Used when no key is stored and the variable is unset: a JSON file in your home folder and the dotted path to the key inside it. Works for apps opened from the Dock or Start menu.',\n });\n }\n\n function buildDiscovery(engine: AiEngineConfig): HTMLElement {\n const id = engine.id;\n const select = el('select', 'settings-input');\n select.id = nextId('ai-discovery');\n select.dataset.fk = `eng:${id}:discovery`;\n for (const [value, label] of [['auto', 'Ask the server'], ['manual', 'Manual only']] as const) {\n const o = el('option', '', label);\n o.value = value;\n select.append(o);\n }\n select.value = engine.discovery;\n select.addEventListener('change', () => updateEngine(id, { discovery: select.value as 'auto' | 'manual' }, { form: true }));\n return sheetRow('Model list', select, { forId: select.id, caption: 'Ask the server which models it has (merged with any you add), or keep only the models you add by hand.' });\n }\n\n // ── Full models table (M3, under Advanced) ────────────────────────────────\n\n function buildModelsTable(engine: AiEngineConfig): HTMLElement {\n const id = engine.id;\n const box = el('div', 'ai-models');\n const head = el('div', 'ai-models-head');\n const missing = engine.models.filter((m) => m.missing).length;\n head.append(el('span', 'settings-label', 'All models'));\n head.append(el('span', 'ai-models-count', engine.models.length === 0\n ? 'none yet'\n : `${engine.models.length}${missing ? `, ${missing} not listed` : ''}`));\n box.append(head);\n\n if (engine.models.length === 0) {\n box.append(el('div', 'ai-models-empty', engine.discovery === 'auto' && ai.discoverModels\n ? 'Fetch models to list what the server offers, or add one by id.'\n : 'Add the models this engine serves by id.'));\n } else {\n const list = el('div', 'ai-model-list');\n list.setAttribute('role', 'list');\n list.setAttribute('aria-label', `Models of ${engineDisplayName(engine)}`);\n const loaded = new Map((deps.statuses.get(id)?.models ?? []).map((m) => [m.id, m.loaded]));\n for (const model of engine.models) {list.append(buildModelItem(engine, model, loaded.get(model.id)));}\n box.append(list);\n }\n\n const add = el('div', 'ai-model-add');\n const addInput = el('input', 'settings-input settings-input--small settings-input--grow ai-mono');\n addInput.type = 'text';\n addInput.placeholder = 'Model id, such as qwen3-coder-30b';\n addInput.spellcheck = false;\n addInput.setAttribute('aria-label', `Add a model to ${engineDisplayName(engine)} by id`);\n addInput.dataset.fk = `eng:${id}:add-model`;\n const addBtn = button('settings-btn', 'Add model', { html: ICONS.plus, fk: `eng:${id}:add-model-btn` });\n const addError = el('div', 'ai-field-error');\n addError.id = nextId('ai-add-model-error');\n addInput.setAttribute('aria-describedby', addError.id);\n const doAdd = () => {\n const current = getEngine(id);\n if (!current) {return;}\n const r = addManualModel(current, addInput.value);\n if (!r.ok) {\n addError.textContent = r.error;\n addInput.setAttribute('aria-invalid', 'true');\n addInput.focus();\n return;\n }\n replaceEngine(r.engine, { form: true, routing: true });\n deps.announce(`Added ${r.model.id}.`);\n deps.focusKey(`eng:${id}:add-model`);\n };\n addBtn.addEventListener('click', doAdd);\n addInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); doAdd(); } });\n addInput.addEventListener('input', () => { addError.textContent = ''; addInput.removeAttribute('aria-invalid'); });\n add.append(addInput, addBtn);\n box.append(add, addError);\n return box;\n }\n\n function buildModelItem(engine: AiEngineConfig, model: AiModelConfig, loaded: boolean | undefined): HTMLElement {\n const engineId = engine.id;\n const mfk = (name: string) => `model:${engineId}:${model.id}:${name}`;\n const shown = modelDisplayName(model);\n const item = el('div', 'ai-model');\n item.setAttribute('role', 'listitem');\n item.classList.toggle('is-missing', !!model.missing);\n item.classList.toggle('is-off', !model.enabled);\n\n const top = el('div', 'ai-model-top');\n const enabled = el('input', 'ai-model-check');\n enabled.type = 'checkbox';\n enabled.checked = model.enabled;\n enabled.dataset.fk = mfk('enabled');\n enabled.setAttribute('aria-label', `Use ${shown}`);\n // A model that can neither chat nor embed (a converter, an MTP drafter) cannot be used; one already on can still be turned off.\n if (!model.capabilities.chat && !model.capabilities.embed && !model.enabled) {\n enabled.disabled = true;\n enabled.title = 'Not a chat model: it cannot be picked.';\n }\n enabled.addEventListener('change', () => {\n deps.setDraft(setModelPicked(deps.getDraft(), engineId, model.id, enabled.checked), { form: true, head: true, routing: true });\n });\n\n const names = el('div', 'ai-model-names');\n const label = el('input', 'ai-model-label');\n label.type = 'text';\n label.value = model.label ?? '';\n label.placeholder = model.id;\n label.spellcheck = false;\n label.dataset.fk = mfk('label');\n label.setAttribute('aria-label', `Display name for ${model.id}`);\n label.addEventListener('input', () => updateModel(engineId, model.id, (m) => {\n const next = { ...m };\n if (label.value.trim()) {next.label = label.value;} else {delete next.label;}\n return next;\n }, { routing: true }));\n names.append(label);\n if (model.label) {names.append(el('span', 'ai-model-id', model.id));}\n\n const tags = el('div', 'ai-model-tags');\n if (loaded) {\n const t = el('span', 'ai-tag ai-tag--loaded', 'loaded');\n t.title = 'Loaded in memory on the server right now.';\n tags.append(t);\n }\n if (model.missing) {\n const t = el('span', 'ai-tag ai-tag--missing', 'not listed');\n t.title = 'The last discovery did not list this model. It is kept, but never routed.';\n tags.append(t);\n }\n if (model.manual) {tags.append(el('span', 'ai-tag', 'added by hand'));}\n\n const ctxWrap = el('label', 'ai-model-context');\n const ctxInput = el('input', 'settings-input settings-input--small ai-context-input');\n ctxInput.type = 'text';\n ctxInput.inputMode = 'numeric';\n ctxInput.value = model.capabilities.contextTokens !== null ? String(model.capabilities.contextTokens) : '';\n ctxInput.placeholder = formatTokens(null);\n ctxInput.dataset.fk = mfk('context');\n ctxInput.setAttribute('aria-label', `Context window of ${shown}, in tokens`);\n ctxInput.title = `Context window in tokens (${formatTokens(model.capabilities.contextTokens)}). Blank means unknown.`;\n ctxInput.addEventListener('change', () => {\n const r = parseContextTokens(ctxInput.value);\n if (!r.ok) {\n ctxInput.setAttribute('aria-invalid', 'true');\n ctxInput.title = r.error;\n deps.announce(r.error);\n return;\n }\n ctxInput.removeAttribute('aria-invalid');\n updateModel(engineId, model.id, (m) => setModelContextTokens(m, r.value), { form: true, routing: true });\n });\n ctxWrap.append(ctxInput, el('span', 'ai-context-unit', 'ctx'));\n\n const hasOverrides = !!model.requestOverrides && Object.keys(model.requestOverrides).length > 0;\n const ovKey = `${engineId}\\u0000${model.id}`;\n const ovOpen = openOverrides.has(ovKey) || overrideErrors.has(ovKey);\n const overridesId = nextId('ai-overrides');\n const ovBtn = button(`ai-icon-btn ai-overrides-btn${hasOverrides ? ' has-value' : ''}`, '', {\n html: '<span aria-hidden=\"true\">{ }</span>',\n ariaLabel: `Request overrides for ${shown}`,\n title: hasOverrides ? 'Request overrides (set)' : 'Request overrides',\n fk: mfk('overrides'),\n });\n ovBtn.setAttribute('aria-expanded', String(ovOpen));\n ovBtn.setAttribute('aria-controls', overridesId);\n ovBtn.addEventListener('click', () => {\n if (openOverrides.has(ovKey)) {openOverrides.delete(ovKey);} else {openOverrides.add(ovKey);}\n deps.refresh(engineId, { form: true });\n if (openOverrides.has(ovKey)) {deps.focusKey(mfk('overrides-text'));}\n });\n\n const right = el('div', 'ai-model-right');\n const thinking = buildThinkingSelect(engine, model, 'table');\n if (thinking) {right.append(thinking);}\n right.append(ctxWrap, ovBtn);\n if (model.manual || model.missing) {\n const remove = button('ai-icon-btn ai-model-remove', '', { html: ICONS.close, ariaLabel: `Remove ${shown}`, title: 'Remove model', fk: mfk('remove') });\n remove.addEventListener('click', () => {\n const current = getEngine(engineId);\n if (!current) {return;}\n const index = current.models.findIndex((m) => m.id === model.id);\n const draft = removeRoutesTo(deps.getDraft(), engineId, model.id);\n deps.setDraft(withEngine(draft, { ...current, models: current.models.filter((m) => m.id !== model.id) }), { form: true, head: true, routing: true });\n deps.announce(`Removed ${shown}.`);\n const rest = getEngine(engineId)?.models ?? [];\n const next = rest[Math.min(index, rest.length - 1)];\n deps.focusKey(next ? `model:${engineId}:${next.id}:enabled` : `eng:${engineId}:add-model`);\n });\n right.append(remove);\n }\n top.append(enabled, names, tags, right);\n\n // Capability chips. Toggling one makes the row a user edit.\n const chips = el('div', 'ai-chips');\n chips.setAttribute('role', 'group');\n chips.setAttribute('aria-label', `Capabilities of ${shown}`);\n for (const chip of AI_CAPABILITY_CHIPS) {\n const on = model.capabilities[chip.flag];\n const b = button(`ai-chip${on ? ' is-on' : ''}`, chip.label, { title: `${chip.title}. Click to ${on ? 'turn off' : 'turn on'}.`, fk: mfk(`chip-${chip.flag}`) });\n b.setAttribute('aria-pressed', String(on));\n b.setAttribute('aria-label', `${chip.label}: ${chip.title}`);\n b.addEventListener('click', () => updateModel(engineId, model.id, (m) => toggleModelCapability(m, chip.flag), { form: true, routing: true }));\n chips.append(b);\n }\n const source = el('span', `ai-source ai-source--${model.capabilitiesSource}`, model.capabilitiesSource === 'user' ? 'edited' : model.capabilitiesSource === 'endpoint' ? 'from server' : 'guessed');\n source.title = model.capabilitiesSource === 'user'\n ? 'You edited these; discovery leaves them alone.'\n : model.capabilitiesSource === 'endpoint'\n ? 'Reported by the server; refreshed on discovery.'\n : 'Guessed from the model id; refreshed on discovery.';\n chips.append(source);\n item.append(top, chips);\n\n if (ovOpen) {\n const ov = el('div', 'ai-overrides');\n ov.id = overridesId;\n const area = el('textarea', 'settings-input ai-mono ai-overrides-text');\n area.rows = 3;\n area.spellcheck = false;\n area.dataset.fk = mfk('overrides-text');\n area.placeholder = '{ \"reasoning_effort\": \"low\" }';\n const pending = overrideErrors.get(ovKey);\n area.value = pending ? pending.text : formatRequestOverrides(model.requestOverrides);\n const help = el('div', 'settings-desc', 'JSON merged into every request body for this model, last, so it wins. The Thinking menu writes its fields here too.');\n const err = el('div', 'ai-field-error');\n err.id = nextId('ai-overrides-error');\n err.setAttribute('aria-live', 'polite');\n area.setAttribute('aria-describedby', err.id);\n area.setAttribute('aria-label', `Request overrides for ${shown}, as JSON`);\n if (pending) {\n err.textContent = pending.error;\n area.setAttribute('aria-invalid', 'true');\n }\n area.addEventListener('input', () => {\n const r = parseRequestOverrides(area.value);\n if (!r.ok) {\n overrideErrors.set(ovKey, { text: area.value, error: r.error });\n err.textContent = r.error;\n area.setAttribute('aria-invalid', 'true');\n return;\n }\n overrideErrors.delete(ovKey);\n err.textContent = '';\n area.removeAttribute('aria-invalid');\n updateModel(engineId, model.id, (m) => {\n const next = { ...m };\n if (r.value) {next.requestOverrides = r.value;} else {delete next.requestOverrides;}\n return next;\n }, {});\n ovBtn.classList.toggle('has-value', !!r.value);\n });\n ov.append(area, err, help);\n item.append(ov);\n }\n return item;\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────────\n\n return {\n build,\n opened(id, opts = {}) {\n const engine = getEngine(id);\n if (!engine) {return `eng:${id}:name`;}\n const family = presetOf(engine).family;\n trigger(id, 'open');\n if (opts.isNew && family === 'cloud') {void lookUpKey(id);}\n if (!opts.isNew) {return `eng:${id}:name`;}\n // Design call 2: the first field a new engine needs. A known local server is\n // already at its usual address, so nothing in the form (a stray key would wipe the URL).\n if (family === 'cloud' && ai.setSecret) {return `eng:${id}:key`;}\n if (family !== 'local') {return `eng:${id}:name`;}\n return presetOf(engine).id === 'custom' ? `eng:${id}:url` : null;\n },\n busy(id) {\n if (testing.has(id)) {return 'test';}\n return fetches.get(id)?.running ? 'discover' : undefined;\n },\n requirePick(id) {\n pickRequired.add(id);\n },\n forget(id) {\n pickRequired.delete(id);\n const st = fetches.get(id);\n if (st) {\n window.clearTimeout(st.timer);\n st.seq++;\n }\n window.clearTimeout(keyTimers.get(id));\n for (const map of [fetches, keyText, keyStored, keyTimers, pickerFilter, results] as Array<Map<string, unknown>>) {map.delete(id);}\n advancedOpen.delete(id);\n typeOpen.delete(id);\n showAll.delete(id);\n formPicked.delete(id);\n },\n dispose() {\n for (const st of fetches.values()) {\n window.clearTimeout(st.timer);\n st.seq++;\n }\n for (const t of keyTimers.values()) {window.clearTimeout(t);}\n keyTimers.clear();\n keyText.clear();\n },\n };\n}\n","/**\n * Tasks, \"which model does what\" (M3, moved onto the AI Engines page in\n * M3c; the file keeps its old name): the default model,\n * the fallback mode and one route per task. Built from the Settings modal's\n * own rows (`MikeDownSettingsSectionContext`) so it sits flush with them.\n *\n * Reads and writes the draft only through `RoutingDeps`; the host of the\n * section re-renders whatever else depends on the routes.\n *\n * Modal UI only: nothing here touches the editor document or its DOM.\n */\n\nimport { AI_FALLBACK_MODES, AI_TASKS } from './ai';\nimport type { AiEngineStatus, AiFallbackMode, AiRoute, AiSettings } from './ai';\nimport {\n DEFAULT_ROUTE_REQUIREMENTS,\n parseRouteKey,\n routeKey,\n routeLabel,\n routePairs,\n taskRequirements,\n taskRouteNote,\n unknownRoutedTasks,\n} from './ai-settings-model';\nimport type { RouteRequirements } from './ai-settings-model';\nimport { el, keepFocus, note } from './ai-settings-dom';\nimport type { MikeDownSettingsSectionContext } from './types';\n\nexport interface RoutingDeps {\n getDraft(): AiSettings;\n /** The routes changed; `defaultChanged` when the default model did. */\n setDraft(next: AiSettings, change: { defaultChanged: boolean }): void;\n statusList(): AiEngineStatus[];\n}\n\nexport interface RoutingSection {\n element: HTMLElement;\n /** Rebuild from the draft, keeping focus. */\n render(): void;\n}\n\nexport const FALLBACK_LABELS: Record<AiFallbackMode, string> = {\n none: 'Nothing (the feature is unavailable)',\n default: 'Use the default model',\n anyLocal: 'Default, then any local model',\n any: 'Default, any local, then cloud',\n};\n\nexport function createRoutingSection(ctx: MikeDownSettingsSectionContext, deps: RoutingDeps): RoutingSection {\n const body = el('div', 'ai-routing');\n\n function buildRouteSelect(current: AiRoute | null | undefined, req: RouteRequirements, o: { fk: string; ariaLabel: string; defaultText?: string }): HTMLSelectElement {\n const draft = deps.getDraft();\n const select = el('select', 'settings-input ai-route-select');\n select.dataset.fk = o.fk;\n select.setAttribute('aria-label', o.ariaLabel);\n const pairs = routePairs(draft, deps.statusList(), req);\n const first = el('option', '', o.defaultText ?? (pairs.some((p) => p.selectable) ? 'Choose a model…' : draft.engines.length === 0 ? 'Add an engine first' : 'No model can serve this'));\n first.value = '';\n select.append(first);\n\n const currentKey = routeKey(current);\n if (current && !pairs.some((p) => routeKey(p) === currentKey)) {\n const gone = el('option', '', `${routeLabel(draft, current)} (not found)`);\n gone.value = currentKey;\n select.append(gone);\n }\n const byEngine = new Map<string, typeof pairs>();\n for (const p of pairs) {\n const list = byEngine.get(p.engineId) ?? [];\n list.push(p);\n byEngine.set(p.engineId, list);\n }\n for (const list of byEngine.values()) {\n const group = el('optgroup');\n group.label = `${list[0].engineName} (${list[0].isLocal ? 'local' : 'cloud'})`;\n for (const p of list) {\n // The engine repeats in the text because a closed select shows only the option.\n const o2 = el('option', '', `${p.engineName} · ${p.modelName}${p.note ? ` (${p.note})` : ''}`);\n o2.value = routeKey(p);\n o2.disabled = !p.selectable && routeKey(p) !== currentKey;\n group.append(o2);\n }\n select.append(group);\n }\n select.value = currentKey;\n if (select.value !== currentKey) {select.value = '';}\n return select;\n }\n\n function render(): void {\n keepFocus(body, () => {\n body.replaceChildren();\n const draft = deps.getDraft();\n\n // Default route and fallback.\n const defRow = ctx.makeRow('Default model', 'Serves every task without its own route. Needs chat.', 'inline');\n const defSelect = buildRouteSelect(draft.routing.default, DEFAULT_ROUTE_REQUIREMENTS, { fk: 'route:default', ariaLabel: 'Default model' });\n defSelect.addEventListener('change', () => {\n const d = deps.getDraft();\n deps.setDraft({ ...d, routing: { ...d.routing, default: parseRouteKey(defSelect.value) } }, { defaultChanged: true });\n render();\n });\n defRow.append(defSelect);\n const defNote = taskRouteNote({ ...draft, routing: { ...draft.routing, tasks: {} } }, deps.statusList(), 'chat');\n if (draft.routing.default && defNote) {defRow.append(note(defNote.level, defNote.text, 'ai-row-note'));}\n\n const fbField = ctx.makeSelectRow<AiFallbackMode>(\n 'When a route is unavailable',\n 'What to try when a task’s model is off, unreachable or lacks what the task needs. Fallback never moves a local route to a cloud engine unless you pick the last option.',\n draft.routing.fallback,\n AI_FALLBACK_MODES.map((m) => ({ value: m, label: FALLBACK_LABELS[m] })),\n );\n fbField.select.dataset.fk = 'route:fallback';\n fbField.select.addEventListener('change', () => {\n const d = deps.getDraft();\n deps.setDraft({ ...d, routing: { ...d.routing, fallback: fbField.select.value as AiFallbackMode } }, { defaultChanged: false });\n render();\n });\n const top = ctx.makeGroup(defRow, fbField.row);\n\n // One row per task, plus tasks a newer version saved.\n const defaultText = draft.routing.default ? `Default: ${routeLabel(draft, draft.routing.default)}` : 'Default (none set)';\n const taskRows: HTMLElement[] = [];\n const taskRow = (taskId: string, label: string, description: string, req: RouteRequirements, hostOnly: boolean) => {\n const row = ctx.makeRow(label, description, 'inline');\n row.classList.add('ai-task-row');\n if (hostOnly) {\n row.append(el('span', 'ai-muted', 'Handled by the app'));\n taskRows.push(row);\n return;\n }\n const select = buildRouteSelect(draft.routing.tasks[taskId], req, { fk: `route:task:${taskId}`, ariaLabel: `Model for ${label}`, defaultText });\n select.addEventListener('change', () => {\n const d = deps.getDraft();\n const tasks = { ...d.routing.tasks };\n const route = parseRouteKey(select.value);\n // Spread the saved route so keys a newer version added survive.\n if (route) {tasks[taskId] = { ...(tasks[taskId] ?? {}), ...route };} else {delete tasks[taskId];}\n deps.setDraft({ ...d, routing: { ...d.routing, tasks } }, { defaultChanged: false });\n render();\n });\n row.append(select);\n const n = taskRouteNote(draft, deps.statusList(), taskId);\n if (n) {row.append(note(n.level, n.text, 'ai-row-note'));}\n taskRows.push(row);\n };\n for (const task of AI_TASKS) {\n taskRow(task.id, task.label, task.description, taskRequirements(task.id), task.hostMethod === 'transcribe');\n }\n for (const taskId of unknownRoutedTasks(draft)) {\n taskRow(taskId, taskId, 'Saved by a newer version of MikeDown. Kept as is.', { requires: {} }, false);\n }\n const tasksHead = el('div', 'ai-subhead', 'Model per task');\n body.append(top, tasksHead, ctx.makeGroup(...taskRows));\n });\n }\n\n return { element: body, render };\n}\n","/**\n * The setup wizard (M1b): the AI Engines page's `'wizard'` section, opened by\n * the first-run panel's \"Set up\". Three steps, one decision each, like a\n * macOS \"Add Account\" sheet:\n *\n * 1. **Path.** What `recommendSetupPath` leads with: a running local server\n * (\"LM Studio is running on this Mac · 3 models\") or VS Code's Copilot\n * (\"Use GitHub Copilot, no key needed\") as one primary card, with\n * \"Connect a cloud provider\" under it; otherwise the cloud provider cards\n * lead, with Allow cloud and the privacy card. Local always sits under\n * **Advanced: run models on this machine**, with the hardware line.\n * 2. **Connect.** Cloud: the provider cards and the engine form's setup mode\n * inline (the subscription vs API key note, the key, then one model from\n * the Popular group). Local: the detected servers (Install links for the\n * ones not running, Look again) and the form, whose picker groups models\n * by size. Copilot: the form, when the one-click path could not finish.\n * 3. **Done.** \"Ready: <engine> · <model> · <Local | Cloud>\", the privacy\n * line for where the text goes, and Done.\n *\n * The page owns the session, the header (Back, the step dots, Skip) and Done;\n * the wizard owns the steps. Back returns to the previous step; Back on the\n * first step, Skip and Escape leave the page as Back does (AI stays off).\n * Done is the page's: it turns AI on (`turnOnWhenDone`) only with a usable\n * default route, which Continue makes the wizard's engine.\n *\n * Modal UI only: nothing here touches the editor document or its DOM.\n */\n\nimport { AI_CLOUD_PRIVACY, AI_ENGINE_PRESETS, AI_HOST_PRIVACY, aiConsentHost, aiConsentStepNote, hostOfUrl, isKnownEngineKind, presetForEngine } from './ai';\nimport type { AiEngineConfig, AiEnginePreset, AiProviderPolicy } from './ai';\nimport {\n applyDiscoveryForFamily,\n defaultRouteForEngine,\n engineDefaultModelId,\n engineDisplayName,\n engineFromPreset,\n engineLocalityInfo,\n firstChatModelId,\n groupPresets,\n modelDisplayName,\n rankLocalCandidates,\n setEngineDefaultModel,\n withEngine,\n type EngineFormPreset,\n type LocalServerCard,\n} from './ai-settings-model';\nimport type { EngineFormController, EngineFormRefresh } from './ai-engine-form';\nimport { AI_DETECT_LOOKING, AI_DETECT_NONE, canScanForSetup, lastSetupScan, plainSetupScan, scanForSetup, type AiSetupScan } from './ai-local-setup';\nimport type { AiSettingsSession } from './ai-settings-session';\nimport { ICONS, button, el, hostLink, keepFocus, kindGlyphHtml, nextId, note, privacyCard } from './ai-settings-dom';\nimport type { MikeDownSettingsSectionContext } from './types';\n\nexport type AiWizardStep = 'path' | 'cloud' | 'local' | 'copilot' | 'done';\n\n/** Steps shown in the header: path, connect (cloud, local or Copilot), done. */\nexport const AI_WIZARD_STEPS = 3;\n\nexport function wizardStepNumber(step: AiWizardStep): number {\n return step === 'path' ? 1 : step === 'done' ? 3 : 2;\n}\n\n/**\n * Above a cloud key field: subscriptions are not API access. Generic on\n * purpose; the links carry the provider's current facts.\n */\nexport const AI_SUBSCRIPTION_NOTE =\n 'Consumer subscriptions such as ChatGPT Plus or Claude Pro do not include API access. ' +\n 'An API key is billed separately by the provider, per use.';\n\n/** The subscription vs API key note with the preset's key and pricing links. */\nexport function subscriptionNote(\n preset: Pick<EngineFormPreset, 'name' | 'keyUrl' | 'pricingUrl'>,\n openLink?: (href: string) => void,\n /** The provider's data policy: its link joins the key and pricing links, and its caveat (OpenRouter passes requests on) follows. */\n policy?: Pick<AiProviderPolicy, 'url' | 'note'>,\n): HTMLElement {\n const box = el('div', 'ai-wizard-subscription');\n box.append(el('p', 'ai-wizard-subscription-text', AI_SUBSCRIPTION_NOTE));\n const links: [string, string][] = [];\n if (preset.keyUrl) {links.push([`${preset.name} API keys`, preset.keyUrl]);}\n if (preset.pricingUrl) {links.push(['Pricing', preset.pricingUrl]);}\n if (policy?.url) {links.push(['Privacy', policy.url]);}\n if (links.length > 0) {\n const line = el('p', 'ai-wizard-subscription-links');\n line.append('Get a key: ');\n links.forEach(([label, url], i) => {\n if (i > 0) {line.append(el('span', 'ai-wizard-sep', ' · '));}\n line.append(hostLink(label, url, openLink, 'ai-wizard-link'));\n });\n box.append(line);\n }\n if (policy?.note) {box.append(el('p', 'ai-wizard-subscription-links', policy.note));}\n return box;\n}\n\nexport interface SetupWizardDeps {\n session: AiSettingsSession;\n form: EngineFormController;\n ctx: MikeDownSettingsSectionContext;\n announce(text: string): void;\n focusKey(key: string): void;\n /** Flip Allow cloud in the draft (the page's switch logic and announcement). */\n setAllowCloud(on: boolean): void;\n /** `session.statuses` changed. */\n onStatuses(): void;\n /** The step changed: the page redraws its header line. */\n onStep(step: AiWizardStep): void;\n /** Done on the last step (the page's Done). */\n finish(): void;\n /** Back from the first step (the page's Back: asks first when something changed). */\n leave(): void;\n /** Leave the wizard for the full page, on this engine. */\n openEngine(engineId: string): void;\n /** Done turns AI on (opened from the first-run panel). */\n turnsOn: boolean;\n}\n\nexport interface SetupWizard {\n readonly element: HTMLElement;\n step(): AiWizardStep;\n /** The engine whose form shows, for the page's draft refreshes. */\n engineId(): string | null;\n back(): void;\n /** The form changed the draft or its own state (see `EngineFormRefresh`). */\n refresh(engineId: string | null, refresh: EngineFormRefresh): void;\n focus(): void;\n dispose(): void;\n}\n\nexport function createSetupWizard(deps: SetupWizardDeps): SetupWizard {\n const { session, form, ctx } = deps;\n const { ai } = session;\n const groups = groupPresets(AI_ENGINE_PRESETS);\n\n let step: AiWizardStep = 'path';\n const history: AiWizardStep[] = [];\n let engineId: string | null = null;\n /** Engines this wizard added; one it moves away from is taken back. */\n const added = new Set<string>();\n let scan: AiSetupScan | null = canScanForSetup(ai) ? lastSetupScan(ai) : plainSetupScan();\n let scanning = false;\n let scanAbort: AbortController | null = null;\n /** The preset a one-click connect is working on. */\n let connecting: string | null = null;\n /** Why the one-click connect stopped, shown over the form it fell back to. */\n let connectError: string | null = null;\n let advancedOpen = false;\n let cloudPrivacyOpen = false;\n let disposed = false;\n\n const element = el('div', 'ai-wizard');\n const column = el('div', 'ai-wizard-column');\n element.append(column);\n\n // ── Scan ──────────────────────────────────────────────────────────────────\n\n function rescan(): void {\n if (!canScanForSetup(ai) || disposed) {return;}\n scanAbort?.abort();\n const controller = new AbortController();\n scanAbort = controller;\n scanning = true;\n if (step === 'local') {deps.announce(AI_DETECT_LOOKING);}\n redrawScanned();\n void scanForSetup(ai, controller.signal).then((fresh) => {\n if (disposed || controller.signal.aborted) {return;}\n scanAbort = null;\n scanning = false;\n scan = fresh;\n redrawScanned();\n if (step === 'local') {deps.announce(detectionSummary());}\n });\n }\n\n /** A scan started or landed: redraw the steps that show it, keeping focus. */\n function redrawScanned(): void {\n if (step === 'path' || step === 'local') {render();}\n }\n\n function localCards(): LocalServerCard[] | null {\n return scan?.probes ? rankLocalCandidates(scan.probes, session.draft.engines) : null;\n }\n\n function detectionSummary(): string {\n const cards = localCards();\n if (!cards) {return 'Could not look for local AI servers.';}\n const running = cards.filter((c) => c.running);\n return running.length === 0 ? AI_DETECT_NONE : `Running on this computer: ${running.map((c) => presetName(c.presetId)).join(', ')}.`;\n }\n\n // ── Engines ───────────────────────────────────────────────────────────────\n\n const presetById = (id: string) => AI_ENGINE_PRESETS.find((p) => p.id === id);\n const presetName = (id: string) => presetById(id)?.name ?? id;\n const machine = () => (scan?.hardware?.platform === 'darwin' ? 'Mac' : 'computer');\n\n /** The engine for a preset: one already set up from it, else a new one. */\n function engineFor(preset: AiEnginePreset): { id: string; isNew: boolean } {\n const card = preset.family === 'local' ? localCards()?.find((c) => c.presetId === preset.id && c.alreadyAdded && c.engineId) : undefined;\n const existing = card?.engineId && session.getEngine(card.engineId)\n ? session.getEngine(card.engineId)\n : preset.family !== 'local' ? session.draft.engines.find((e) => presetForEngine(e)?.id === preset.id) : undefined;\n if (existing) {return { id: existing.id, isNew: false };}\n const engine = engineFromPreset(preset, session.draft.engines.map((e) => e.id));\n session.addEngine(engine);\n added.add(engine.id);\n return { id: engine.id, isNew: true };\n }\n\n /** Make `id` the wizard's engine; one the wizard added before it is taken back. */\n function useEngine(id: string): void {\n if (engineId && engineId !== id && added.has(engineId)) {\n session.deleteEngine(engineId);\n form.forget(engineId);\n added.delete(engineId);\n }\n engineId = id;\n connectError = null;\n }\n\n const currentEngine = (): AiEngineConfig | undefined => (engineId ? session.getEngine(engineId) : undefined);\n\n /** The engine's default model when it can serve the default route as saved, else null. */\n function readyModel(engine: AiEngineConfig | undefined): string | null {\n if (!engine || !engine.enabled || !isKnownEngineKind(engine.kind)) {return null;}\n const usable = (m: AiEngineConfig['models'][number] | undefined) => !!m && m.enabled && !m.missing && m.capabilities.chat;\n const id = engineDefaultModelId(session.draft, engine.id);\n const model = id ? engine.models.find((m) => m.id === id) : undefined;\n // A local server lists embedding models too: the first chat model then.\n return usable(model) ? model!.id : engine.models.find(usable)?.id ?? null;\n }\n\n function cloudBlocked(engine: AiEngineConfig): boolean {\n return !session.draft.allowCloud && engineLocalityInfo(engine, session.draft.localNetworks).locality === 'cloud';\n }\n\n /** Route every task without its own route to the wizard's engine. */\n function makeDefault(id: string, modelId: string): void {\n const draft = setEngineDefaultModel(session.draft, id, modelId);\n session.draft = { ...draft, routing: { ...draft.routing, default: { engineId: id, modelId } } };\n }\n\n /** Cloud and Copilot need Allow cloud; choosing one says yes to it (the consent step still asks per engine). */\n function allowCloudFor(preset: AiEnginePreset): void {\n if (preset.family !== 'local' && !session.draft.allowCloud) {deps.setAllowCloud(true);}\n }\n\n // ── Steps ─────────────────────────────────────────────────────────────────\n\n function go(next: AiWizardStep, o: { push?: boolean } = {}): void {\n if (o.push !== false && next !== step) {history.push(step);}\n step = next;\n render({ fresh: true });\n deps.onStep(step);\n }\n\n /** One-click: a running server or Copilot, straight to Done when its models answer. */\n async function connect(preset: AiEnginePreset): Promise<void> {\n if (connecting) {return;}\n allowCloudFor(preset);\n const { id } = engineFor(preset);\n useEngine(id);\n const fallback: AiWizardStep = preset.family === 'host' ? 'copilot' : 'local';\n if (!ai.discoverModels) {\n go(fallback);\n return;\n }\n connecting = preset.id;\n render();\n deps.announce(`Setting up ${preset.name}…`);\n try {\n await session.ensureSaved(id);\n const status = await ai.discoverModels(id);\n if (disposed || engineId !== id) {return;}\n if (status && typeof status === 'object') {\n session.statuses.set(id, status);\n deps.onStatuses();\n }\n if (!status || status.ok === false) {throw new Error(status?.error || `Could not fetch the models from ${preset.name}.`);}\n const engine = session.getEngine(id);\n if (!engine) {return;}\n session.draft = withEngine(session.draft, applyDiscoveryForFamily(engine, status, preset.family));\n const fresh = session.getEngine(id)!;\n const modelId = preset.family === 'local'\n ? defaultRouteForEngine(session.draft, session.statusList(), id)?.modelId ?? null\n : firstChatModelId(fresh.models);\n if (!modelId && preset.family === 'local' && fresh.models.some((m) => !m.missing && m.capabilities.chat)) {\n // Chat models, but none loaded: the form asks for a pick (no error).\n connecting = null;\n go(fallback);\n form.opened(id);\n deps.announce(`${preset.name}: pick a model to start with.`);\n return;\n }\n if (!modelId) {\n throw new Error(preset.family === 'host' ? 'Copilot lists no chat model for this account yet.' : `${preset.name} has no chat model loaded or downloaded yet.`);\n }\n makeDefault(id, modelId);\n connecting = null;\n go('done');\n } catch (err) {\n if (disposed) {return;}\n connecting = null;\n connectError = err instanceof Error && err.message ? err.message : `${preset.name} could not be set up.`;\n deps.announce(connectError);\n go(fallback);\n form.opened(id);\n }\n }\n\n /** Step 2: a provider or server card picked; its form opens under the cards. */\n function pick(preset: AiEnginePreset): void {\n allowCloudFor(preset);\n const { id, isNew } = engineFor(preset);\n useEngine(id);\n const target: AiWizardStep = preset.family === 'local' ? 'local' : preset.family === 'host' ? 'copilot' : 'cloud';\n if (step !== target) {\n go(target);\n } else {\n render();\n }\n const first = form.opened(id, { isNew: isNew && preset.family === 'cloud' });\n // A new cloud engine lands on its key; anything else keeps focus on the card.\n if (isNew && preset.family === 'cloud' && first) {deps.focusKey(first);}\n deps.announce(preset.family === 'cloud' ? `${preset.name}: paste your API key.` : `${preset.name}: fetching its models.`);\n }\n\n function continueToDone(): void {\n const engine = currentEngine();\n const modelId = readyModel(engine);\n if (!engine || !modelId || cloudBlocked(engine)) {return;}\n makeDefault(engine.id, modelId);\n go('done');\n }\n\n // ── Rendering ─────────────────────────────────────────────────────────────\n\n /** Rebuild the current step. `fresh` (a new step) scrolls up and focuses its title; otherwise focus stays put. */\n function render(o: { fresh?: boolean } = {}): void {\n if (disposed) {return;}\n keepFocus(column, () => {\n column.replaceChildren(...buildStep());\n });\n element.dataset.step = step;\n if (o.fresh) {\n element.scrollTop = 0;\n column.querySelector<HTMLElement>('.ai-wizard-title')?.focus({ preventScroll: true });\n }\n }\n\n function buildStep(): HTMLElement[] {\n switch (step) {\n case 'path': return buildPath();\n case 'cloud': return buildCloud();\n case 'local': return buildLocal();\n case 'copilot': return buildCopilot();\n case 'done': return buildDone();\n }\n }\n\n function heading(text: string, lede?: string): HTMLElement {\n const head = el('div', 'ai-wizard-head');\n const h = el('h3', 'ai-wizard-title', text);\n h.id = nextId('ai-wizard-title');\n h.tabIndex = -1;\n element.setAttribute('aria-labelledby', h.id);\n head.append(h);\n if (lede) {head.append(el('p', 'ai-wizard-lede', lede));}\n return head;\n }\n\n /** A large choice: glyph, a name line, a caption, a chevron. */\n function option(o: { fk: string; glyph: string; name: string; caption: string; lead?: boolean; state?: 'running' | 'busy'; onClick(): void }): HTMLButtonElement {\n const b = button(`ai-wizard-option${o.lead ? ' is-lead' : ''}`, '', { fk: o.fk });\n if (o.state) {b.dataset.state = o.state;}\n const glyph = el('span', 'ai-wizard-option-glyph');\n glyph.innerHTML = o.glyph;\n const text = el('span', 'ai-wizard-option-text');\n const name = el('span', 'ai-wizard-option-name');\n if (o.state === 'running') {\n const dot = el('span', 'ai-card-dot');\n dot.setAttribute('aria-hidden', 'true');\n name.append(dot);\n }\n name.append(el('span', '', o.name));\n text.append(name, el('span', 'ai-wizard-option-caption', o.caption));\n const chevron = el('span', 'ai-wizard-option-chevron');\n if (o.state === 'busy') {\n chevron.append(el('span', 'ai-spinner'));\n b.setAttribute('aria-busy', 'true');\n } else {\n chevron.innerHTML = ICONS.chevron;\n }\n chevron.setAttribute('aria-hidden', 'true');\n b.append(glyph, text, chevron);\n b.addEventListener('click', () => { if (!connecting) {o.onClick();} });\n return b;\n }\n\n function cloudGlyph(): string {\n return `<span class=\"ai-glyph ai-wizard-glyph-cloud\" aria-hidden=\"true\">${ICONS.cloud}</span>`;\n }\n\n // Step 1 ─────────────────────────────────────────────────────────────────\n\n function buildPath(): HTMLElement[] {\n const out: HTMLElement[] = [heading('How should MikeDown reach a model?', 'You can change it later in AI Engines.')];\n if (!scan) {\n const wait = el('div', 'ai-wizard-scanning');\n wait.setAttribute('role', 'status');\n wait.append(el('span', 'ai-spinner'), el('span', '', 'Checking this machine…'));\n out.push(wait);\n return out;\n }\n const rec = scan.recommendation;\n const copilot = scan.vscodeLm?.available ? groups.host.find((p) => p.kind === 'vscode-lm') : undefined;\n const running = rec.path === 'runningLocal' && rec.running ? presetById(rec.running.presetId) : undefined;\n const options = el('div', 'ai-wizard-options');\n\n if (running && rec.running) {\n const models = rec.running.models;\n options.append(option({\n fk: `wiz:use:${running.id}`,\n glyph: kindGlyphHtml(running.kind),\n name: `${running.name} is running on this ${machine()}${models !== undefined ? ` · ${models} ${models === 1 ? 'model' : 'models'}` : ''}`,\n caption: connecting === running.id ? `Setting up ${running.name}…` : 'Use it. Text stays on this machine.',\n lead: true,\n state: connecting === running.id ? 'busy' : 'running',\n onClick: () => { void connect(running); },\n }));\n }\n if (copilot) {\n options.append(option({\n fk: 'wiz:use:copilot',\n glyph: kindGlyphHtml(copilot.kind),\n name: 'Use GitHub Copilot, no key needed',\n caption: connecting === copilot.id\n ? 'Fetching Copilot’s models…'\n : `Through your Copilot plan in VS Code. ${AI_HOST_PRIVACY.permission}`,\n lead: rec.path === 'vscodeLm',\n ...(connecting === copilot.id ? { state: 'busy' as const } : {}),\n onClick: () => { void connect(copilot); },\n }));\n }\n\n if (options.childElementCount > 0) {\n options.append(option({\n fk: 'wiz:cloud',\n glyph: cloudGlyph(),\n name: 'Connect a cloud provider',\n caption: 'Paste an API key from Anthropic, OpenAI or another provider.',\n onClick: () => go('cloud'),\n }));\n out.push(options);\n } else {\n out.push(buildCloudGroup());\n }\n out.push(buildAdvanced());\n if (scanning) {\n const line = el('div', 'ai-wizard-quiet', 'Checking this machine again…');\n line.setAttribute('role', 'status');\n out.push(line);\n }\n return out;\n }\n\n /** The cloud provider cards with the Allow cloud statement and the privacy card (cloud-first step 1, and step 2). */\n function buildCloudGroup(o: { title?: boolean } = {}): HTMLElement {\n const section = el('section', 'ai-wizard-group');\n const headingId = nextId('ai-wizard-group');\n if (o.title !== false) {\n const h = el('div', 'ai-cards-heading');\n h.id = headingId;\n h.innerHTML = ICONS.cloud;\n h.append(el('span', '', 'Connect a cloud provider'));\n section.append(h, el('div', 'ai-cards-explainer', 'Paste a key from the provider. It bills your account for what you use.'));\n section.setAttribute('aria-labelledby', headingId);\n }\n // Picking a provider turns Allow cloud on (pick()), so it is a statement here, not a switch.\n const access = el('div', 'ai-cloud-access ai-wizard-cloud-access');\n access.append(\n el('p', 'ai-wizard-cloud-line', ai.requestCloudConsent\n ? 'Choosing a provider turns on cloud engines; MikeDown still asks before the first request in each workspace.'\n : 'Choosing a provider turns on cloud engines.'),\n // No policy links here: the chosen provider's note and the consent dialog carry its own.\n privacyCard(null, {\n collapsed: 'What this means',\n open: cloudPrivacyOpen,\n onToggle: (open) => { cloudPrivacyOpen = open; },\n openLink: ctx.openLink,\n // The line above already says the host asks first.\n ...(ai.requestCloudConsent ? {} : { extra: aiConsentStepNote(false) }),\n className: 'ai-cloud-access-privacy',\n }),\n );\n section.append(access);\n const grid = el('div', 'ai-cards-grid');\n grid.setAttribute('role', 'group');\n grid.setAttribute('aria-label', 'Cloud providers');\n const picked = currentEngine();\n const pickedPreset = picked ? presetForEngine(picked)?.id : undefined;\n for (const preset of groups.cloud) {\n const card = button('ai-card', '', { fk: `wiz:card:${preset.id}` });\n card.innerHTML = kindGlyphHtml(preset.kind);\n const text = el('span', 'ai-card-text');\n text.append(el('span', 'ai-card-name', preset.name), el('span', 'ai-card-caption', preset.caption));\n card.append(text);\n const on = step === 'cloud' && pickedPreset === preset.id;\n card.setAttribute('aria-pressed', String(on));\n card.classList.toggle('is-selected', on);\n card.addEventListener('click', () => pick(preset));\n grid.append(card);\n }\n section.append(grid);\n return section;\n }\n\n function buildAdvanced(): HTMLElement {\n const box = el('div', 'ai-wizard-advanced');\n const panelId = nextId('ai-wizard-advanced');\n const toggle = button('ai-disclosure', 'Advanced: run models on this machine', { html: ICONS.chevron, fk: 'wiz:advanced' });\n toggle.setAttribute('aria-expanded', String(advancedOpen));\n toggle.setAttribute('aria-controls', panelId);\n toggle.addEventListener('click', () => {\n advancedOpen = !advancedOpen;\n render();\n });\n const panel = el('div', 'ai-wizard-advanced-panel');\n panel.id = panelId;\n panel.hidden = !advancedOpen;\n const hw = scan?.recommendation.hardwareLine;\n if (hw) {panel.append(el('p', 'ai-wizard-hardware', hw));}\n panel.append(el('p', 'ai-wizard-quiet', 'Your own model server, such as LM Studio or Ollama. Text never leaves this machine.'));\n const choose = button('settings-btn', 'Choose a local server', { fk: 'wiz:local' });\n choose.addEventListener('click', () => go('local'));\n panel.append(choose);\n box.append(toggle, panel);\n return box;\n }\n\n // Step 2 ─────────────────────────────────────────────────────────────────\n\n function formHolder(): HTMLElement | null {\n const engine = currentEngine();\n if (!engine) {return null;}\n const holder = el('div', 'ai-wizard-form');\n if (connectError) {holder.append(note('error', connectError, 'ai-wizard-error'));}\n holder.append(buildForm(engine.id));\n return holder;\n }\n\n /**\n * The engine form in its setup mode (the key, then one model that is the\n * default). On the cloud step \"What this means\" above already says what is\n * sent, so the form's card is left out.\n */\n function buildForm(id: string): HTMLElement {\n return form.build(id, { privacy: step !== 'cloud', setup: true });\n }\n\n function footer(o: { label: string; fk: string; ready: boolean; hint?: string; onClick(): void }): HTMLElement {\n const bar = el('div', 'ai-wizard-footer');\n const hint = el('span', 'ai-wizard-hint', o.ready ? '' : o.hint ?? '');\n hint.id = nextId('ai-wizard-hint');\n const primary = button('settings-btn settings-btn--primary ai-wizard-next', o.label, { fk: o.fk });\n // aria-disabled, not disabled: focus stays on it while the form catches up.\n if (!o.ready) {\n primary.setAttribute('aria-disabled', 'true');\n primary.setAttribute('aria-describedby', hint.id);\n }\n primary.addEventListener('click', () => { if (o.ready) {o.onClick();} else if (o.hint) {deps.announce(o.hint);} });\n bar.append(hint, primary);\n return bar;\n }\n\n function continueFooter(): HTMLElement {\n const engine = currentEngine();\n const blocked = engine ? cloudBlocked(engine) : false;\n const ready = !!engine && !!readyModel(engine) && !blocked;\n const hint = !engine\n ? step === 'local' ? 'Pick a server to continue.' : 'Pick a provider to continue.'\n : blocked\n ? 'Turn on Allow cloud engines to use it.'\n : step === 'cloud' && !session.hasKey(engine.id)\n ? 'Paste your API key; the models appear, then Continue.'\n : 'Pick a chat model to continue.';\n return footer({ label: 'Continue', fk: 'wiz:continue', ready, hint, onClick: continueToDone });\n }\n\n function buildCloud(): HTMLElement[] {\n const out = [\n heading('Connect a cloud provider', 'Pick a provider and paste an API key. Text you ask about is sent to that provider.'),\n buildCloudGroup({ title: false }),\n ];\n const holder = formHolder();\n if (holder) {out.push(holder);}\n out.push(continueFooter());\n return out;\n }\n\n function buildLocal(): HTMLElement[] {\n const lede = scan?.recommendation.hardwareLine || 'Your own model server, on this computer or your network. Text never leaves it.';\n const out = [heading('Run models on this machine', lede)];\n const list = el('div', 'ai-wizard-servers');\n list.setAttribute('role', 'group');\n list.setAttribute('aria-label', 'Local servers');\n const cards = localCards();\n const byId = new Map(cards?.map((c) => [c.presetId, c]) ?? []);\n const ordered = cards\n ? [...cards.map((c) => presetById(c.presetId)).filter((p): p is AiEnginePreset => !!p && p.family === 'local'), ...groups.local.filter((p) => !byId.has(p.id))]\n : groups.local;\n for (const preset of ordered) {list.append(buildServer(preset, byId.get(preset.id)));}\n out.push(list);\n\n const detect = el('div', 'ai-cards-detect');\n const status = el('span', 'ai-cards-detect-text', scanning ? AI_DETECT_LOOKING : cards && !cards.some((c) => c.running) ? AI_DETECT_NONE : '');\n detect.append(status);\n if (ai.detectLocalServers) {\n const again = button('ai-link-btn ai-cards-again', 'Look again', { fk: 'wiz:look-again' });\n if (scanning) {again.setAttribute('aria-disabled', 'true');}\n again.addEventListener('click', () => { if (!scanning) {rescan();} });\n detect.append(again);\n }\n out.push(detect);\n const holder = formHolder();\n if (holder) {out.push(holder);}\n out.push(continueFooter());\n return out;\n }\n\n /** A local server: the card, and for one that is not running, where to get it. */\n function buildServer(preset: AiEnginePreset, found: LocalServerCard | undefined): HTMLElement {\n const row = el('div', 'ai-wizard-server');\n const card = button('ai-card', '', { fk: `wiz:card:${preset.id}` });\n card.innerHTML = kindGlyphHtml(preset.kind);\n const text = el('span', 'ai-card-text');\n text.append(el('span', 'ai-card-name', preset.name), el('span', 'ai-card-caption', preset.caption));\n const state = !found ? null : found.alreadyAdded && found.engineId && session.getEngine(found.engineId) ? 'added' : found.running ? 'running' : 'stopped';\n if (state) {\n card.dataset.state = state;\n const line = el('span', 'ai-card-state');\n if (state === 'running') {\n const dot = el('span', 'ai-card-dot');\n dot.setAttribute('aria-hidden', 'true');\n line.append(dot);\n }\n const count = found?.models !== undefined ? ` · ${found.models} ${found.models === 1 ? 'model' : 'models'}` : '';\n line.append(el('span', '', state === 'added' ? 'Added' : state === 'running' ? `Running${count}` : 'Not running'));\n text.append(line);\n }\n card.append(text);\n const picked = currentEngine();\n const on = !!picked && (picked.id === found?.engineId || (added.has(picked.id) && presetForEngine(picked)?.id === preset.id));\n card.setAttribute('aria-pressed', String(on));\n card.classList.toggle('is-selected', on);\n card.addEventListener('click', () => pick(preset));\n row.append(card);\n if (state === 'stopped' && preset.installUrl) {\n const help = el('div', 'ai-wizard-install');\n help.append(hostLink(`Install ${preset.name}`, preset.installUrl, ctx.openLink, 'ai-wizard-link'), el('span', '', ', then come back and choose Look again.'));\n row.append(help);\n }\n return row;\n }\n\n function buildCopilot(): HTMLElement[] {\n const out = [heading('GitHub Copilot', `Copilot’s models through your Copilot plan in VS Code. No key needed. ${AI_HOST_PRIVACY.permission}`)];\n const holder = formHolder();\n if (holder) {out.push(holder);}\n out.push(continueFooter());\n return out;\n }\n\n // Step 3 ─────────────────────────────────────────────────────────────────\n\n function buildDone(): HTMLElement[] {\n const engine = currentEngine();\n const modelId = readyModel(engine);\n if (!engine || !modelId) {\n // The engine changed under the wizard (deleted elsewhere): start again.\n return [heading('Set up AI', 'Something changed. Go back and choose again.')];\n }\n const local = engineLocalityInfo(engine, session.draft.localNetworks).locality === 'local';\n const model = engine.models.find((m) => m.id === modelId)!;\n const out: HTMLElement[] = [];\n const icon = el('span', 'ai-wizard-done-icon');\n icon.innerHTML = ICONS.check;\n icon.setAttribute('aria-hidden', 'true');\n const head = heading(`Ready: ${engineDisplayName(engine)} · ${modelDisplayName(model)} · ${local ? 'Local' : 'Cloud'}`);\n head.prepend(icon);\n out.push(head);\n\n // A choice of model when the engine offers more than one; the first is already picked.\n const chat = engine.models.filter((m) => m.enabled && !m.missing && m.capabilities.chat);\n if (chat.length > 1) {\n const row = el('div', 'ai-wizard-model');\n const select = el('select', 'settings-input ai-wizard-model-select');\n select.id = nextId('ai-wizard-model');\n select.dataset.fk = 'wiz:model';\n for (const m of chat) {\n const o = el('option', '', modelDisplayName(m));\n o.value = m.id;\n select.append(o);\n }\n select.value = modelId;\n select.addEventListener('change', () => {\n makeDefault(engine.id, select.value);\n render();\n const picked = engine.models.find((m) => m.id === select.value);\n if (picked) {deps.announce(`Default model: ${modelDisplayName(picked)}.`);}\n });\n const label = el('label', 'ai-wizard-model-label', 'Model');\n label.htmlFor = select.id;\n row.append(label, select);\n out.push(row);\n }\n\n const privacy = el('p', 'ai-wizard-privacy');\n const glyph = el('span', 'ai-privacy-glyph');\n glyph.innerHTML = local ? ICONS.local : ICONS.cloud;\n privacy.append(glyph, el('span', '', privacyText(engine, local)));\n out.push(privacy);\n\n const more = el('p', 'ai-wizard-quiet');\n if (!deps.turnsOn) {more.append('Choose Done to save. ');}\n const fine = button('ai-link-btn', 'Change settings in AI Engines', { fk: 'wiz:open-engine' });\n fine.addEventListener('click', () => deps.openEngine(engine.id));\n more.append(fine);\n out.push(more);\n out.push(footer({ label: deps.turnsOn ? 'Turn on AI' : 'Done', fk: 'wiz:done', ready: true, onClick: () => deps.finish() }));\n return out;\n }\n\n function privacyText(engine: AiEngineConfig, local: boolean): string {\n if (local) {return AI_CLOUD_PRIVACY.local;}\n if (presetForEngine(engine)?.family === 'host') {return `${AI_HOST_PRIVACY.leaves} ${aiConsentStepNote(!!ai.requestCloudConsent)}`;}\n const where = aiConsentHost(engine) || hostOfUrl(engine.baseUrl) || 'the provider';\n return `Text you ask about is sent over the internet to ${where}. ${aiConsentStepNote(!!ai.requestCloudConsent)}`;\n }\n\n // ── Handle ────────────────────────────────────────────────────────────────\n\n render();\n rescan();\n\n return {\n element,\n step: () => step,\n engineId: () => engineId,\n back() {\n if (connecting) {return;}\n const previous = history.pop();\n if (!previous) {\n deps.leave();\n return;\n }\n step = previous;\n connectError = null;\n render({ fresh: true });\n deps.onStep(step);\n },\n refresh(id, refresh) {\n if (disposed) {return;}\n if (refresh.form && id && id === engineId) {\n const current = column.querySelector<HTMLElement>('.ai-form');\n if (current) {\n keepFocus(current, () => {\n const fresh = buildForm(id);\n current.replaceWith(fresh);\n return fresh;\n });\n }\n }\n // Continue follows the form: a key stored, models fetched, a model picked.\n const bar = column.querySelector<HTMLElement>('.ai-wizard-footer');\n if (bar && step !== 'done' && step !== 'path') {keepFocus(bar, () => { const next = continueFooter(); bar.replaceWith(next); return next; });}\n },\n focus() {\n const target = column.querySelector<HTMLElement>('.ai-wizard-option.is-lead')\n ?? column.querySelector<HTMLElement>('.ai-wizard-option, .ai-card, .ai-wizard-next')\n ?? column.querySelector<HTMLElement>('.ai-wizard-title');\n target?.focus({ preventScroll: true });\n },\n dispose() {\n disposed = true;\n scanAbort?.abort();\n element.remove();\n },\n };\n}\n","/**\n * The AI Engines page (M3c): engines and routing on a full-size page of\n * their own, laid out like VS Code's Settings editor or the Network pane of\n * Apple's System Settings. A header with Back and Done; on the left a quiet\n * list of engines, then Tasks (which model does what), then Add engine; on\n * the right the selected engine's Express form (`ai-engine-form.ts`), the\n * Tasks section (`ai-routing-section.ts`) or the quick-start cards. Under 720 px the page\n * is one column: the list first, and picking an entry pushes its detail,\n * with Back returning to the list.\n *\n * Standalone and mountable: it renders into the container it is given and\n * touches nothing outside it (no modal, no editor, no `document.body`), so a\n * host can show it as an overlay (`editor.ts#showAiEnginesPage`) or, later,\n * in its own editor tab or window. Dialog semantics, the focus trap and\n * focus restore belong to whoever hosts it.\n *\n * Edits run in an `AiSettingsSession` (`ai-settings-session.ts`): Done hands\n * the changed `ai.*` keys to `onDone`; Back with unsaved changes asks\n * \"Discard changes?\" in the page, and discarding takes back engines added\n * here and their keys before `onCancel`. Opened by the first-run panel's\n * \"Set up\" (`turnOnWhenDone`), the header says AI turns on at Done, and Done\n * adds `ai.enabled: true` when the result has a usable default route; Back\n * leaves AI off.\n *\n * On a host that can look for local servers (`host.ai.detectLocalServers`),\n * the quick-start cards look when they first show and on \"Look again\": a\n * local card says Running · 3 models (and leads), Not running, or Added\n * (it opens the engine already set up there). Without the method the cards\n * are the plain list.\n *\n * The cloud cards carry the **Allow cloud engines** switch, one line on what\n * it means and the privacy card folded under \"What this means\"; it edits the\n * page's draft, so Done saves it with the rest. A cloud engine's head, while\n * the switch is off, says so with a \"Turn on cloud engines\" button (F4). On\n * VS Code, a \"Built into VS Code\" group offers GitHub Copilot when the host\n * reports a Copilot model (`detectHostEngines`).\n *\n * Opened on the `'wizard'` section (the first-run panel's \"Set up\" with no\n * engines yet, tier 2 only), the page shows the setup wizard\n * (`ai-setup-wizard.ts`) instead of the list and detail: the header says\n * \"Set up AI\" with the step dots and Skip, Back walks back through the\n * steps, and the wizard's Done is the page's Done. \"Change settings in AI Engines\"\n * leaves the wizard for the full page, in the same session.\n *\n * Modal UI only: nothing here touches the editor document or its DOM.\n */\n\nimport { AI_ENGINE_PRESETS, AI_HOST_PRESET_FAMILY, AI_PRESET_FAMILIES, aiProviderPolicy, modelSizeHint, presetForEngine } from './ai';\nimport { AI_DETECT_LOOKING, AI_DETECT_NONE, detectLocalServers, hostEngineAvailability, knownHardware, setupHardware } from './ai-local-setup';\nimport type { AiEngineConfig, AiEnginePreset, AiEngineStatus, AiHardwareInfo, AiLocalServerProbe, AiPresetFamilyInfo, AiRoute, AiSettings, AiSettingsPatch } from './ai';\nimport {\n defaultRouteForEngine,\n engineDisplayName,\n engineLocalityInfo,\n engineFromPreset,\n engineIssues,\n engineKindLabel,\n groupPresets,\n firstEngineNeedingPick,\n hasUsableDefaultRoute,\n rankLocalCandidates,\n routeLabel,\n shortUrl,\n type LocalServerCard,\n} from './ai-settings-model';\nimport { createEngineFormController } from './ai-engine-form';\nimport type { EngineFormRefresh } from './ai-engine-form';\nimport { createRoutingSection } from './ai-routing-section';\nimport { createAiSettingsSession } from './ai-settings-session';\nimport type { AiSettingsSessionOptions } from './ai-settings-session';\nimport { ICONS, button, cloudAccessBox, el, experimentalBadge, experimentalDisclaimer, keepFocus, kindGlyphHtml, localityPills, nextId, note, statusBadge, switchInput } from './ai-settings-dom';\nimport { AI_WIZARD_STEPS, createSetupWizard, subscriptionNote, wizardStepNumber, type AiWizardStep, type SetupWizard } from './ai-setup-wizard';\nimport type { MikeDownSettingsSectionContext } from './types';\n\nexport type AiEnginesPageSection = 'engines' | 'routing' | 'wizard';\n\nexport interface AiEnginesPageOptions extends AiSettingsSessionOptions {\n /**\n * What to show first: an engine, the routing section, or the setup wizard\n * (tier 2 only). Default: the first engine (the cards when there is none).\n */\n initial?: { engineId?: string; section?: AiEnginesPageSection };\n /** Shared with the session that opened the page (stored-key knowledge). */\n keyOverride?: Map<string, boolean>;\n /** Shared with the session that opened the page (engine statuses). */\n statusMap?: Map<string, AiEngineStatus>;\n /** Done: the `ai.*` keys that changed (possibly none) and the settings they lead to. */\n onDone(patch: AiSettingsPatch, settings: AiSettings): void;\n /** Back without saving; the page already took back what it added. */\n onCancel(): void;\n /**\n * Opened to set AI up while it is off: Done also turns AI on (`ai.enabled`\n * in the patch) when the result has a usable default route.\n */\n turnOnWhenDone?: boolean;\n}\n\nexport interface AiEnginesPageHandle {\n /** Tear down (timers, listeners) and leave the container empty. Unresolved changes are discarded. */\n dispose(): void;\n /** Focus where a keyboard user should land: the selected list entry, or the detail when it was pushed. */\n focus(): void;\n}\n\n/** Narrower than this and the page is one column. */\nconst NARROW_PX = 720;\n\ntype Selection = { kind: 'engine'; id: string } | { kind: 'routing' } | { kind: 'add' };\n\nexport function mountAiEnginesPage(container: HTMLElement, ctx: MikeDownSettingsSectionContext, opts: AiEnginesPageOptions): AiEnginesPageHandle {\n const session = createAiSettingsSession(opts);\n const { ai } = session;\n const getEngine = (id: string) => session.getEngine(id);\n /** The setup wizard while it shows; the list and detail wait underneath, unrendered. */\n let wizard: SetupWizard | null = null;\n /** This machine, once the host said (the models picker's size groups). Known at once when asked before (Q5). */\n let hardware: AiHardwareInfo | null = knownHardware(ai);\n\n let selection: Selection = initialSelection();\n let narrow = false;\n /** Narrow layout only: which pane shows. */\n let view: 'list' | 'detail' = opts.initial?.engineId || opts.initial?.section === 'routing' ? 'detail' : 'list';\n let confirmDeleteId: string | null = null;\n let confirmDiscard = false;\n let finished = false;\n /** One-line notes under an engine's header (the star found no model to make the default). */\n const headNotes = new Map<string, { level: 'info' | 'warning'; text: string }>();\n\n function initialSelection(): Selection {\n const engines = session.draft.engines;\n if (opts.initial?.section === 'routing') {return { kind: 'routing' };}\n const wanted = opts.initial?.engineId && engines.find((e) => e.id === opts.initial?.engineId);\n if (wanted) {return { kind: 'engine', id: wanted.id };}\n return engines[0] ? { kind: 'engine', id: engines[0].id } : { kind: 'add' };\n }\n const selectedEngineId = () => (selection.kind === 'engine' ? selection.id : null);\n\n // ── Shell ─────────────────────────────────────────────────────────────────\n\n const root = el('div', 'ai-page');\n const titleId = nextId('ai-page-title');\n\n const header = el('div', 'ai-page-header');\n const backBtn = button('ai-page-back', 'Back', { html: ICONS.back, fk: 'page:back' });\n backBtn.addEventListener('click', () => back());\n const title = el('h2', 'ai-page-title', 'AI Engines');\n title.id = titleId;\n const doneBtn = button('settings-btn settings-btn--primary ai-page-done', 'Done', { fk: 'page:done' });\n doneBtn.addEventListener('click', () => done());\n // The wizard's way out at any step: AI stays off (Back asks first when something changed).\n const skipBtn = button('settings-btn ai-page-done ai-page-skip', 'Skip', { fk: 'page:skip', title: 'Leave setup; AI stays off' });\n skipBtn.addEventListener('click', () => leave());\n skipBtn.hidden = true;\n const titleLine = el('div', 'ai-page-title-line');\n const titleNote = opts.turnOnWhenDone ? el('span', 'ai-page-title-note', 'AI turns on when you choose Done') : null;\n const stepper = el('span', 'ai-wizard-steps');\n stepper.hidden = true;\n titleLine.append(title, experimentalBadge(), stepper);\n if (titleNote) {titleLine.append(titleNote);}\n header.append(backBtn, titleLine, doneBtn, skipBtn);\n const disclaimer = experimentalDisclaimer('ai-page-disclaimer');\n\n const body = el('div', 'ai-page-body');\n const nav = el('nav', 'ai-page-nav');\n nav.setAttribute('aria-label', 'Engines and tasks');\n const detail = el('section', 'ai-page-detail');\n const detailId = nextId('ai-page-detail');\n detail.id = detailId;\n body.append(nav, detail);\n\n // Screen reader announcements for probe results and key changes.\n const live = el('div', 'ai-live');\n live.setAttribute('role', 'status');\n live.setAttribute('aria-live', 'polite');\n let liveTimer: number | undefined;\n function announce(text: string): void {\n window.clearTimeout(liveTimer);\n live.textContent = '';\n // A fresh text node after a tick, so repeating the same message is read again.\n liveTimer = window.setTimeout(() => { live.textContent = text; }, 40);\n }\n\n const confirmHost = el('div', 'ai-page-confirm-host');\n root.append(header, disclaimer, body, confirmHost, live);\n\n // ── The engine form and routing ───────────────────────────────────────────\n\n const form = createEngineFormController({\n ai,\n getDraft: () => session.draft,\n setDraft: (next, refresh) => {\n session.draft = next;\n applyRefresh(wizard ? wizard.engineId() : selectedEngineId(), refresh);\n },\n refresh: (engineId, refresh) => applyRefresh(engineId, refresh),\n statuses: session.statuses,\n onStatuses: () => opts.onStatuses(session.statusList()),\n hasKey: (id) => session.hasKey(id),\n keySource: (id) => session.keySource(id),\n setKey,\n ensureSaved: (id) => session.ensureSaved(id),\n savesFirst: (id) => session.savesFirst(id),\n announce,\n focusKey,\n openLink: ctx.openLink,\n // The subscription vs API key note sits over a cloud key field. The wizard always shows it; the full form shows it until a key is stored.\n keyNote: (engine, preset) => (preset.family === 'cloud' && (wizard || !session.hasKey(engine.id)) ? subscriptionNote(preset, ctx.openLink, aiProviderPolicy(engine)) : null),\n modelSize: (modelId, sizeBytes) => (hardware ? modelSizeHint(modelId, hardware, sizeBytes) : undefined),\n });\n\n const routing = createRoutingSection(ctx, {\n getDraft: () => session.draft,\n setDraft: (next, change) => {\n session.draft = next;\n if (change.defaultChanged) {renderNav();}\n else {refreshRoutingEntry();}\n },\n statusList: () => session.statusList(),\n });\n\n async function setKey(id: string, value: string | null): Promise<string | null> {\n const engine = getEngine(id);\n const error = await session.setKey(id, value);\n if (engine) {\n const name = engineDisplayName(engine);\n announce(error\n ? `The key for ${name} could not be ${value !== null ? 'stored' : 'cleared'}.`\n : value !== null ? `API key stored for ${name}.` : `API key cleared for ${name}.`);\n refreshHead(id);\n }\n return error;\n }\n\n function applyRefresh(engineId: string | null, refresh: EngineFormRefresh): void {\n if (wizard) {\n wizard.refresh(engineId, refresh);\n return;\n }\n if (refresh.list) {\n renderNav();\n renderDetailHead();\n } else if (refresh.head) {\n // A default model change moves the star; every row may need it.\n for (const e of session.draft.engines) {refreshNavItem(e.id);}\n refreshRoutingEntry();\n renderDetailHead();\n }\n if (refresh.form && engineId) {rerenderForm(engineId);}\n if (refresh.routing || refresh.list) {scheduleRouting();}\n }\n\n let routingQueued = false;\n function scheduleRouting(): void {\n if (routingQueued) {return;}\n routingQueued = true;\n queueMicrotask(() => {\n routingQueued = false;\n if (finished || wizard) {return;}\n refreshRoutingEntry();\n if (selection.kind === 'routing') {routing.render();}\n });\n }\n\n function refreshHead(engineId: string): void {\n refreshNavItem(engineId);\n if (selectedEngineId() === engineId) {renderDetailHead();}\n }\n\n function focusKey(key: string): void {\n const n = Array.from(root.querySelectorAll<HTMLElement>('[data-fk]')).find((x) => x.dataset.fk === key);\n n?.focus({ preventScroll: true });\n }\n\n // ── Left list ─────────────────────────────────────────────────────────────\n\n const navList = el('div', 'ai-nav-list');\n navList.setAttribute('role', 'list');\n navList.setAttribute('aria-label', 'Engines');\n const navEngines = el('div', 'ai-nav-group');\n const routingEntry = el('div', 'ai-nav-group ai-nav-group--tools');\n nav.append(navEngines, routingEntry);\n nav.addEventListener('keydown', onNavKeydown);\n\n function navButton(fk: string, selected: boolean): HTMLButtonElement {\n const b = button('ai-nav-btn', '', { fk });\n b.setAttribute('aria-controls', detailId);\n if (selected) {b.setAttribute('aria-current', 'true');}\n return b;\n }\n\n function renderNav(): void {\n if (wizard) {return;}\n keepFocus(nav, () => {\n navEngines.replaceChildren();\n const heading = el('div', 'ai-nav-heading', 'Engines');\n heading.setAttribute('aria-hidden', 'true');\n navEngines.append(heading);\n navList.replaceChildren();\n if (session.draft.engines.length === 0) {\n navEngines.append(el('div', 'ai-nav-empty', 'No engines yet'));\n } else {\n for (const engine of session.draft.engines) {navList.append(buildNavItem(engine));}\n navEngines.append(navList);\n }\n routingEntry.replaceChildren(buildRoutingEntry(), buildAddEntry());\n });\n }\n\n function buildNavItem(engine: AiEngineConfig): HTMLElement {\n const item = el('div', 'ai-nav-item');\n item.setAttribute('role', 'listitem');\n item.dataset.engineId = engine.id;\n fillNavItem(item, engine);\n return item;\n }\n\n function fillNavItem(item: HTMLElement, engine: AiEngineConfig): void {\n item.replaceChildren();\n const selected = selection.kind === 'engine' && selection.id === engine.id;\n const name = engineDisplayName(engine);\n item.classList.toggle('is-selected', selected);\n item.classList.toggle('is-disabled', !engine.enabled);\n\n const btn = navButton(`nav:eng:${engine.id}`, selected);\n btn.setAttribute('aria-label', `${name}, ${engineKindLabel(engine.kind)}`);\n btn.title = name;\n btn.innerHTML = kindGlyphHtml(engine.kind);\n const text = el('span', 'ai-nav-text');\n const line = el('span', 'ai-nav-name-line');\n line.append(el('span', 'ai-nav-name', name));\n const isDefault = session.draft.routing.default?.engineId === engine.id;\n if (isDefault) {\n const star = el('span', 'ai-nav-star');\n star.innerHTML = ICONS.starOn;\n star.title = 'Default engine';\n line.append(star);\n }\n // The pill sits on the second line so the name keeps its room.\n const subLine = el('span', 'ai-nav-sub-line');\n subLine.append(...localityPills(engine, session.draft).slice(0, 1), el('span', 'ai-nav-sub', shortUrl(engine.baseUrl) || 'no address'));\n text.append(line, subLine);\n btn.append(text, statusBadge(session.statuses.get(engine.id), form.busy(engine.id), { compact: true }));\n btn.addEventListener('click', () => select({ kind: 'engine', id: engine.id }));\n\n const enabled = switchInput(engine.enabled, `Enable ${name}`, `nav:eng:${engine.id}:enabled`);\n enabled.addEventListener('change', () => {\n session.updateEngine(engine.id, { enabled: enabled.checked });\n applyRefresh(engine.id, { list: true, form: true, routing: true });\n });\n item.append(btn, enabled);\n }\n\n function refreshNavItem(engineId: string): void {\n if (wizard) {return;}\n const engine = getEngine(engineId);\n const item = Array.from(navList.querySelectorAll<HTMLElement>('.ai-nav-item')).find((n) => n.dataset.engineId === engineId);\n if (!engine || !item) {return;}\n keepFocus(item, () => fillNavItem(item, engine));\n }\n\n function routingSubline(): string {\n const d = session.draft.routing.default;\n return d ? routeLabel(session.draft, d) : 'No default model';\n }\n\n function buildRoutingEntry(): HTMLElement {\n const btn = navButton('nav:routing', selection.kind === 'routing');\n btn.classList.add('ai-nav-btn--routing');\n const icon = el('span', 'ai-nav-icon');\n icon.innerHTML = ICONS.routing;\n const text = el('span', 'ai-nav-text');\n text.append(el('span', 'ai-nav-name', 'Tasks'), el('span', 'ai-nav-sub', routingSubline()));\n btn.append(icon, text);\n btn.addEventListener('click', () => select({ kind: 'routing' }));\n return btn;\n }\n\n function refreshRoutingEntry(): void {\n const sub = routingEntry.querySelector('.ai-nav-btn--routing .ai-nav-sub');\n if (sub) {sub.textContent = routingSubline();}\n }\n\n function buildAddEntry(): HTMLElement {\n const btn = navButton('nav:add', selection.kind === 'add');\n btn.classList.add('ai-nav-btn--add');\n const icon = el('span', 'ai-nav-icon');\n icon.innerHTML = ICONS.plus;\n btn.append(icon, el('span', 'ai-nav-name', 'Add engine'));\n btn.addEventListener('click', () => select({ kind: 'add' }));\n return btn;\n }\n\n /** Up and Down move between list entries, Home and End jump. */\n function onNavKeydown(e: KeyboardEvent): void {\n if (!['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(e.key)) {return;}\n const buttons = Array.from(nav.querySelectorAll<HTMLButtonElement>('.ai-nav-btn'));\n const at = buttons.indexOf(e.target as HTMLButtonElement);\n if (at < 0) {return;}\n e.preventDefault();\n const next = e.key === 'Home' ? 0 : e.key === 'End' ? buttons.length - 1\n : Math.max(0, Math.min(buttons.length - 1, at + (e.key === 'ArrowDown' ? 1 : -1)));\n buttons[next]?.focus();\n }\n\n // ── Detail pane ───────────────────────────────────────────────────────────\n\n const detailHead = el('div', 'ai-detail-head');\n const detailBody = el('div', 'ai-detail-body');\n detail.append(detailHead, detailBody);\n\n function select(next: Selection, o: { isNew?: boolean } = {}): void {\n const sameEngine = next.kind === 'engine' && selection.kind === 'engine' && selection.id === next.id;\n selection = next;\n confirmDeleteId = null;\n if (next.kind === 'engine') {headNotes.delete(next.id);}\n if (narrow) {view = 'detail';}\n applyLayout();\n renderNav();\n if (!sameEngine || o.isNew) {renderDetail();}\n let first: string | null = null;\n if (next.kind === 'engine' && (!sameEngine || o.isNew)) {first = form.opened(next.id, o);}\n if (o.isNew && first) {\n // A new engine lands on its first empty required field (design call 2).\n focusKey(first);\n if (first.endsWith(':url')) {\n const input = root.querySelector<HTMLInputElement>(`[data-fk=\"${first}\"]`);\n input?.select();\n }\n } else if (o.isNew || narrow) {\n // A new local server (nothing to type) or the narrow list going away: land on the heading.\n focusDetailTitle();\n }\n detail.scrollTop = 0;\n }\n\n function focusDetailTitle(): void {\n detailHead.querySelector<HTMLElement>('.ai-detail-title')?.focus({ preventScroll: true });\n }\n\n function renderDetail(): void {\n if (wizard) {return;}\n renderDetailHead();\n detailBody.replaceChildren();\n detail.dataset.kind = selection.kind;\n if (selection.kind === 'engine') {\n const engine = getEngine(selection.id);\n if (engine) {detailBody.append(form.build(engine.id));}\n } else if (selection.kind === 'routing') {\n routing.render();\n detailBody.append(routing.element);\n } else {\n detailBody.append(buildPresetCards());\n // The cards look once per page; \"Look again\" asks again.\n if (canDetect && !detectedOnce) {lookForLocalServers();}\n if (ai.detectHostEngines && hostAvailable === null) {lookForHostEngines();}\n }\n }\n\n function detailTitle(text: string): HTMLElement {\n const h = el('h3', 'ai-detail-title', text);\n h.id = nextId('ai-detail-title');\n // Focus target when the narrow layout pushes the detail.\n h.tabIndex = -1;\n detail.setAttribute('aria-labelledby', h.id);\n return h;\n }\n\n function renderDetailHead(): void {\n if (wizard) {return;}\n keepFocus(detailHead, () => {\n detailHead.replaceChildren();\n if (selection.kind === 'routing') {\n const icon = el('span', 'ai-detail-icon');\n icon.innerHTML = ICONS.routing;\n const main = el('div', 'ai-detail-main');\n main.append(detailTitle('Tasks'), el('div', 'ai-detail-sub', 'Which model does what. Tasks on Default use the default model.'));\n detailHead.append(icon, main);\n return;\n }\n if (selection.kind === 'add') {\n const icon = el('span', 'ai-detail-icon');\n icon.innerHTML = ICONS.plus;\n const main = el('div', 'ai-detail-main');\n const empty = session.draft.engines.length === 0;\n main.append(\n detailTitle(empty ? 'No engines yet' : 'Add an engine'),\n el('div', 'ai-detail-sub', `Two ways to connect: paste a cloud API key, or run models on your own machine.${session.draft.enabled ? '' : ' Nothing is sent until AI is on.'}`),\n );\n detailHead.append(icon, main);\n return;\n }\n const engine = getEngine(selection.id);\n if (!engine) {return;}\n fillEngineHead(engine);\n });\n }\n\n function fillEngineHead(engine: AiEngineConfig): void {\n const name = engineDisplayName(engine);\n const glyph = el('span', 'ai-detail-glyph');\n glyph.innerHTML = kindGlyphHtml(engine.kind);\n\n const main = el('div', 'ai-detail-main');\n const titleLine = el('div', 'ai-detail-title-line');\n // The head says \"blocked\" with a way out (below) instead of the bare pill.\n titleLine.append(detailTitle(name), ...localityPills(engine, session.draft, { blocked: false }));\n const models = engine.models.filter((m) => !m.missing).length;\n const picked = engine.models.filter((m) => !m.missing && m.enabled).length;\n const subParts = [engineKindLabel(engine.kind), shortUrl(engine.baseUrl) || 'no address'];\n if (engine.models.length > 0) {subParts.push(picked === models ? `${models} ${models === 1 ? 'model' : 'models'}` : `${picked} of ${models} models`);}\n main.append(titleLine, el('div', 'ai-detail-sub', subParts.join(' · ')));\n\n // The default engine shows a label, not a switch (Q3): the default moves by choosing another engine.\n const isDefault = session.draft.routing.default?.engineId === engine.id;\n let star: HTMLElement;\n if (isDefault) {\n star = el('span', 'ai-default-badge');\n star.innerHTML = ICONS.starOn;\n star.append(el('span', 'ai-btn-text', 'Default'));\n star.title = `Default: ${routeLabel(session.draft, session.draft.routing.default as AiRoute)}. To change it, choose Use by default on another engine, or pick the default model under Tasks.`;\n star.setAttribute('aria-label', `${name} is the default engine`);\n star.dataset.fk = `eng:${engine.id}:star`;\n // Focus can land here after \"Use by default\" turns into the label.\n star.tabIndex = -1;\n } else {\n star = button('settings-btn ai-default-btn', 'Use by default', {\n html: ICONS.starOff,\n title: 'Use this engine by default',\n fk: `eng:${engine.id}:star`,\n });\n star.addEventListener('click', () => makeDefault(engine.id));\n }\n\n const del = button('ai-icon-btn ai-delete-btn', '', { html: ICONS.trash, ariaLabel: `Delete ${name}`, title: 'Delete engine', fk: `eng:${engine.id}:delete` });\n del.addEventListener('click', () => {\n confirmDeleteId = engine.id;\n renderDetailHead();\n focusKey(`eng:${engine.id}:confirm-cancel`);\n });\n\n const actions = el('div', 'ai-detail-actions');\n actions.append(statusBadge(session.statuses.get(engine.id), form.busy(engine.id)), star, del);\n const top = el('div', 'ai-detail-top');\n top.append(glyph, main, actions);\n detailHead.append(top);\n\n // The form shows key, URL and locality problems at their fields; the pill says \"blocked\".\n const issues = engineIssues(engine, session.draft, session.hasKey(engine.id))\n .filter((i) => !['cloudBlocked', 'badUrl', 'localityMismatch', 'noKey'].includes(i.code));\n const headNote = headNotes.get(engine.id);\n if (issues.length > 0 || headNote) {\n const box = el('div', 'ai-engine-issues');\n for (const i of issues) {box.append(note(i.level, i.text));}\n if (headNote) {box.append(note(headNote.level, headNote.text, 'ai-result'));}\n detailHead.append(box);\n }\n if (cloudBlocked(engine)) {detailHead.append(buildCloudOffNote(engine));}\n if (confirmDeleteId === engine.id) {detailHead.append(buildDeleteConfirm(engine));}\n }\n\n function cloudBlocked(engine: AiEngineConfig): boolean {\n return !session.draft.allowCloud && engineLocalityInfo(engine, session.draft.localNetworks).locality === 'cloud';\n }\n\n /** A cloud engine while Allow cloud is off: say so, with the switch one click away (F4). */\n function buildCloudOffNote(engine: AiEngineConfig): HTMLElement {\n const box = el('div', 'ai-cloud-off');\n box.append(note('info', `Cloud engines are off, so nothing is sent to ${engineDisplayName(engine)} yet.`));\n const on = button('settings-btn ai-cloud-off-btn', 'Turn on cloud engines', { fk: `eng:${engine.id}:allow-cloud` });\n on.addEventListener('click', () => {\n setAllowCloud(true);\n headNotes.set(engine.id, { level: 'info', text: 'Cloud engines are on. Choose Done to save.' });\n renderDetailHead();\n focusKey(`eng:${engine.id}:star`);\n });\n box.append(on);\n return box;\n }\n\n /** Flip Allow cloud in the draft (Done saves it with the rest); the AI tab reads the same draft once the page is done. */\n function setAllowCloud(on: boolean): void {\n if (session.draft.allowCloud === on) {return;}\n session.draft = { ...session.draft, allowCloud: on };\n renderNav();\n const formEngine = wizard ? wizard.engineId() : selectedEngineId();\n if (formEngine) {rerenderForm(formEngine);}\n scheduleRouting();\n announce(on ? 'Cloud engines turned on. Choose Done to save.' : 'Cloud engines turned off. Choose Done to save.');\n }\n\n function rerenderForm(engineId: string): void {\n if (wizard) {\n wizard.refresh(engineId, { form: true });\n return;\n }\n if (selectedEngineId() !== engineId) {return;}\n const current = detailBody.querySelector<HTMLElement>('.ai-form');\n if (!current) {return;}\n keepFocus(current, () => {\n const fresh = form.build(engineId);\n current.replaceWith(fresh);\n return fresh;\n });\n }\n\n function buildDeleteConfirm(engine: AiEngineConfig): HTMLElement {\n const box = el('div', 'ai-confirm');\n box.setAttribute('role', 'group');\n const name = engineDisplayName(engine);\n box.setAttribute('aria-label', `Delete ${name}?`);\n const msg = el('span', 'ai-confirm-text', `Delete ${name}? Routes to it are cleared${ai.setSecret ? ' and its stored API key is removed' : ''} when you choose Done.`);\n const yes = button('settings-btn ai-btn--danger', 'Delete', { fk: `eng:${engine.id}:confirm-delete` });\n const no = button('settings-btn', 'Cancel', { fk: `eng:${engine.id}:confirm-cancel` });\n yes.addEventListener('click', () => deleteEngine(engine.id));\n no.addEventListener('click', () => {\n confirmDeleteId = null;\n renderDetailHead();\n focusKey(`eng:${engine.id}:delete`);\n });\n box.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n // Cancel the confirmation, not the page.\n e.preventDefault();\n e.stopPropagation();\n no.click();\n }\n });\n box.append(msg, yes, no);\n return box;\n }\n\n // ── Quick-start cards and local server detection ──────────────────────────\n\n /** The last detection while this page is open: null before it ran, when it failed, or on a host without it. */\n let probes: AiLocalServerProbe[] | null = null;\n let detectedOnce = false;\n let detecting = false;\n let detectAbort: AbortController | null = null;\n const canDetect = typeof ai.detectLocalServers === 'function';\n\n /** Look for local servers, then redraw the local cards and say what was found. */\n function lookForLocalServers(): void {\n if (!canDetect || finished) {return;}\n detectAbort?.abort();\n const controller = new AbortController();\n detectAbort = controller;\n detectedOnce = true;\n detecting = true;\n refreshLocalCards();\n announce(AI_DETECT_LOOKING);\n void detectLocalServers(ai, controller.signal).then((found) => {\n if (finished || controller.signal.aborted) {return;}\n detecting = false;\n detectAbort = null;\n probes = found;\n refreshLocalCards();\n announce(detectionSummary(localCards()));\n });\n }\n\n /** The probes ranked against the engines as they are now (an engine added here makes its card Added). */\n function localCards(): LocalServerCard[] | null {\n return probes ? rankLocalCandidates(probes, session.draft.engines) : null;\n }\n\n function detectionSummary(cards: LocalServerCard[] | null): string {\n if (!cards) {return 'Could not look for local AI servers.';}\n const running = cards.filter((c) => c.running);\n if (running.length === 0) {return AI_DETECT_NONE;}\n return `Running on this computer: ${running.map((c) => `${presetName(c.presetId)}${c.models !== undefined ? `, ${countText(c.models)}` : ''}${c.alreadyAdded ? ', added' : ''}`).join('; ')}.`;\n }\n\n function presetName(id: string): string {\n return AI_ENGINE_PRESETS.find((p) => p.id === id)?.name ?? id;\n }\n\n function countText(models: number): string {\n return `${models} ${models === 1 ? 'model' : 'models'}`;\n }\n\n /** VS Code offers a Copilot model: null before the page asked (or on a host that cannot say). */\n let hostAvailable: boolean | null = null;\n\n /** Ask once whether VS Code offers a Copilot model; the \"Built into VS Code\" group shows when it does. */\n function lookForHostEngines(): void {\n hostAvailable = false;\n void hostEngineAvailability(ai).then((found) => {\n if (finished || !found?.available) {return;}\n hostAvailable = true;\n if (selection.kind === 'add' && !wizard) {keepFocus(detailBody, () => { detailBody.replaceChildren(buildPresetCards()); });}\n });\n }\n\n /** The cards in two groups (three with Copilot), with the \"two ways to connect\" line over each (design call 2). */\n function buildPresetCards(): HTMLElement {\n const groups = groupPresets(AI_ENGINE_PRESETS);\n const box = el('div', 'ai-cards');\n const families: AiPresetFamilyInfo[] = hostAvailable ? [AI_HOST_PRESET_FAMILY, ...AI_PRESET_FAMILIES] : [...AI_PRESET_FAMILIES];\n for (const family of families) {\n const presets = groups[family.family];\n if (presets.length === 0) {continue;}\n const section = el('section', 'ai-cards-group');\n section.dataset.family = family.family;\n const headingId = nextId('ai-cards-heading');\n const heading = el('div', 'ai-cards-heading');\n heading.id = headingId;\n heading.innerHTML = family.family === 'local' ? ICONS.local : ICONS.cloud;\n heading.append(el('span', '', family.label));\n section.setAttribute('aria-labelledby', headingId);\n const grid = el('div', 'ai-cards-grid');\n grid.setAttribute('role', 'group');\n grid.setAttribute('aria-labelledby', headingId);\n section.append(heading, el('div', 'ai-cards-explainer', family.explainer));\n if (family.family === 'local') {\n section.append(grid);\n fillLocalGrid(grid, presets);\n if (canDetect) {section.append(buildDetectLine());}\n } else if (family.family === 'host') {\n section.append(grid);\n for (const preset of presets) {grid.append(buildCard(preset));}\n } else {\n // The switch and what it means sit where a cloud engine is added (F4, OQ5).\n section.append(buildCloudAccess(presets), grid);\n for (const preset of presets) {grid.append(buildCard(preset));}\n }\n box.append(section);\n }\n placeGroups(box);\n return box;\n }\n\n /**\n * Cloud leads, as in the setup wizard; a local server that is running and not\n * yet added leads instead (the wizard leads with it too). Copilot, when\n * offered, stays on top.\n */\n function placeGroups(box: HTMLElement): void {\n const localLeads = !!localCards()?.some((c) => c.running && !c.alreadyAdded);\n const order = localLeads ? ['host', 'local', 'cloud'] : ['host', 'cloud', 'local'];\n for (const family of order) {\n const section = box.querySelector(`:scope > .ai-cards-group[data-family=\"${family}\"]`);\n if (section) {box.append(section);}\n }\n }\n\n /** The \"What this means\" disclosure stays open across redraws while the page is open. */\n let cloudPrivacyOpen = false;\n\n /** Allow cloud engines over the cloud cards: the switch, one line, and the privacy card folded. */\n function buildCloudAccess(presets: AiEnginePreset[]): HTMLElement {\n return cloudAccessBox({\n allowed: session.draft.allowCloud,\n onChange: (on) => setAllowCloud(on),\n presets,\n hostAsks: !!ai.requestCloudConsent,\n open: cloudPrivacyOpen,\n onToggle: (open) => { cloudPrivacyOpen = open; },\n openLink: ctx.openLink,\n fk: 'cards:allow-cloud',\n });\n }\n\n /** Local cards in detection order (running first), Custom last; the preset order before a detection. */\n function fillLocalGrid(grid: HTMLElement, presets: AiEnginePreset[]): void {\n grid.replaceChildren();\n const cards = localCards();\n const byId = new Map(cards?.map((c) => [c.presetId, c]) ?? []);\n const ordered = cards\n ? [...cards.map((c) => presets.find((p) => p.id === c.presetId)).filter((p): p is AiEnginePreset => !!p), ...presets.filter((p) => !byId.has(p.id))]\n : presets;\n for (const preset of ordered) {grid.append(buildCard(preset, byId.get(preset.id)));}\n }\n\n function buildCard(preset: AiEnginePreset, found?: LocalServerCard): HTMLButtonElement {\n const card = button('ai-card', '', { fk: `card:${preset.id}`, ariaLabel: `Add ${preset.name}` });\n card.innerHTML = kindGlyphHtml(preset.kind);\n const text = el('span', 'ai-card-text');\n text.append(el('span', 'ai-card-name', preset.name), el('span', 'ai-card-caption', preset.caption));\n card.append(text);\n card.title = preset.caption;\n // A local card is added when its server's engine exists; a cloud card when an engine for that provider does.\n const cloudEngine = preset.family === 'cloud' ? session.draft.engines.find((e) => presetForEngine(e)?.id === preset.id) : undefined;\n const added = cloudEngine ? cloudEngine.id : found?.alreadyAdded && found.engineId && getEngine(found.engineId) ? found.engineId : null;\n if (cloudEngine) {\n card.dataset.state = 'added';\n text.append(el('span', 'ai-card-state', 'Added'));\n card.setAttribute('aria-label', `${preset.name}, added. Open it`);\n card.title = `${preset.name} is already set up. Open it.`;\n } else if (found) {\n const state = added ? 'added' : found.running ? 'running' : 'stopped';\n card.dataset.state = state;\n const label = state === 'added' ? 'Added'\n : state === 'running' ? `Running${found.models !== undefined ? ` · ${countText(found.models)}` : ''}`\n : 'Not running';\n const line = el('span', 'ai-card-state');\n if (state === 'running') {\n const dot = el('span', 'ai-card-dot');\n dot.setAttribute('aria-hidden', 'true');\n line.append(dot);\n }\n line.append(el('span', '', label));\n text.append(line);\n card.setAttribute('aria-label', added ? `${preset.name}, added. Open it` : `Add ${preset.name}, ${label.replace(' · ', ', ').toLowerCase()}`);\n if (added) {card.title = `${preset.name} is already set up. Open it.`;}\n }\n card.addEventListener('click', () => {\n if (added && getEngine(added)) {select({ kind: 'engine', id: added });} else {addEngine(preset);}\n });\n return card;\n }\n\n /** \"Looking for local AI servers…\" or what was found, then \"Look again\". */\n function buildDetectLine(): HTMLElement {\n const line = el('div', 'ai-cards-detect');\n const status = el('span', 'ai-cards-detect-text', detecting ? AI_DETECT_LOOKING\n : probes && !probes.some((p) => p.ok) ? AI_DETECT_NONE : '');\n const again = button('ai-link-btn ai-cards-again', 'Look again', { fk: 'cards:look-again' });\n // aria-disabled, not disabled: focus stays on it while it looks.\n if (detecting) {again.setAttribute('aria-disabled', 'true');}\n again.addEventListener('click', () => { if (!detecting) {lookForLocalServers();} });\n line.append(status, again);\n return line;\n }\n\n /** Redraw the local group in place, keeping focus on the same card. */\n function refreshLocalCards(): void {\n const section = detailBody.querySelector<HTMLElement>('.ai-cards-group[data-family=\"local\"]');\n if (!section || selection.kind !== 'add') {return;}\n keepFocus(section, () => {\n const grid = section.querySelector<HTMLElement>('.ai-cards-grid');\n if (grid) {fillLocalGrid(grid, groupPresets(AI_ENGINE_PRESETS).local);}\n const line = section.querySelector('.ai-cards-detect');\n if (line) {line.replaceWith(buildDetectLine());}\n });\n // A server that answered moves the local group up; keep the focus where it was.\n const box = section.parentElement;\n if (box) {keepFocus(box, () => { placeGroups(box); });}\n }\n\n // ── Edits ─────────────────────────────────────────────────────────────────\n\n function addEngine(preset: AiEnginePreset): void {\n const engine = engineFromPreset(preset, session.draft.engines.map((e) => e.id));\n session.addEngine(engine);\n select({ kind: 'engine', id: engine.id }, { isNew: true });\n scheduleRouting();\n announce(preset.family === 'cloud' ? `Added ${engine.name}. Paste your API key.`\n : preset.family === 'host' ? `Added ${engine.name}. Fetching its models.`\n : `Added ${engine.name}. Check the address; models are fetched from it.`);\n }\n\n function deleteEngine(id: string): void {\n const engine = getEngine(id);\n if (!engine) {return;}\n const index = session.draft.engines.findIndex((e) => e.id === id);\n session.deleteEngine(id);\n headNotes.delete(id);\n form.forget(id);\n confirmDeleteId = null;\n const next = session.draft.engines[Math.min(index, session.draft.engines.length - 1)];\n selection = next ? { kind: 'engine', id: next.id } : { kind: 'add' };\n renderNav();\n renderDetail();\n if (next) {form.opened(next.id);}\n announce(`Deleted ${engineDisplayName(engine)}. Choose Done to apply.`);\n focusKey(next ? `nav:eng:${next.id}` : 'nav:add');\n }\n\n /** \"Use by default\": this engine's default model becomes the default route. Already the default: nothing changes. */\n function makeDefault(engineId: string): void {\n const engine = getEngine(engineId);\n if (!engine) {return;}\n const name = engineDisplayName(engine);\n const draft = session.draft;\n if (draft.routing.default?.engineId === engineId) {return;}\n const route = defaultRouteForEngine(draft, session.statusList(), engineId);\n if (!route) {\n headNotes.set(engineId, { level: 'info', text: 'No model here can be the default yet. Pick or add a chat model first.' });\n announce(`${name} has no chat model to make the default yet.`);\n renderDetailHead();\n return;\n }\n session.draft = { ...draft, routing: { ...draft.routing, default: route } };\n announce(`Default model: ${routeLabel(session.draft, route)}.`);\n headNotes.delete(engineId);\n renderNav();\n renderDetailHead();\n rerenderForm(engineId);\n // The button became the Default label: keep focus there, not on the page.\n focusKey(`eng:${engineId}:star`);\n }\n\n // ── Back, Done and the discard confirmation ───────────────────────────────\n\n function back(): void {\n if (confirmDiscard) {\n hideDiscard();\n return;\n }\n if (wizard) {\n wizard.back();\n return;\n }\n if (narrow && view === 'detail') {\n view = 'list';\n applyLayout();\n focusSelectedEntry();\n return;\n }\n if (session.dirty()) {\n showDiscard();\n return;\n }\n cancel();\n }\n\n /** Close without saving: ask first when something changed (the wizard's Skip, and Back from its first step). */\n function leave(): void {\n if (session.dirty()) {showDiscard();} else {cancel();}\n }\n\n function cancel(): void {\n if (finished) {return;}\n finished = true;\n session.discard();\n opts.onCancel();\n }\n\n function done(): void {\n if (finished) {return;}\n // An engine with chat models listed and none picked has no default model: stop there (Q1).\n const unpicked = firstEngineNeedingPick(session.draft);\n if (unpicked) {\n requirePick(unpicked.id);\n return;\n }\n finished = true;\n const patch = session.collect();\n const saved = session.commit();\n // Set up from the first-run panel: AI turns on only with something to route to (B3).\n if (opts.turnOnWhenDone && !saved.enabled && hasUsableDefaultRoute(saved)) {\n patch['ai.enabled'] = true;\n saved.enabled = true;\n }\n opts.onDone(patch, saved);\n }\n\n /** Open the engine's form with the \"Pick at least one model\" error and focus its models list. */\n function requirePick(engineId: string): void {\n const engine = getEngine(engineId);\n if (!engine) {return;}\n form.requirePick(engineId);\n if (wizard) {\n leaveWizardFor(engineId);\n } else if (selection.kind !== 'engine' || selection.id !== engineId) {\n selection = { kind: 'engine', id: engineId };\n view = 'detail';\n applyLayout();\n renderNav();\n renderDetail();\n } else {\n rerenderForm(engineId);\n }\n announce(`Pick at least one model for ${engineDisplayName(engine)} before you choose Done.`);\n const target = Array.from(root.querySelectorAll<HTMLElement>('[data-fk]'))\n .find((n) => n.dataset.fk === `eng:${engineId}:pick` || n.dataset.fk === `eng:${engineId}:models`);\n target?.focus({ preventScroll: false });\n }\n\n function showDiscard(): void {\n confirmDiscard = true;\n const scrim = el('div', 'ai-page-confirm-scrim');\n const box = el('div', 'ai-page-confirm');\n box.setAttribute('role', 'alertdialog');\n const headId = nextId('ai-discard-title');\n const textId = nextId('ai-discard-text');\n box.setAttribute('aria-labelledby', headId);\n box.setAttribute('aria-describedby', textId);\n const head = el('div', 'ai-page-confirm-title', 'Discard changes?');\n head.id = headId;\n const text = el('div', 'ai-page-confirm-text', 'Your changes to engines and tasks have not been saved. Engines added here and their keys are removed.');\n text.id = textId;\n const keep = button('settings-btn', 'Keep editing', { fk: 'page:keep' });\n keep.addEventListener('click', () => hideDiscard());\n const discard = button('settings-btn ai-btn--danger', 'Discard', { fk: 'page:discard' });\n discard.addEventListener('click', () => cancel());\n const actions = el('div', 'ai-page-confirm-actions');\n actions.append(keep, discard);\n box.append(head, text, actions);\n scrim.append(box);\n confirmHost.replaceChildren(scrim);\n header.inert = true;\n body.inert = true;\n if (wizard) {wizard.element.inert = true;}\n keep.focus();\n }\n\n function hideDiscard(): void {\n confirmDiscard = false;\n confirmHost.replaceChildren();\n header.inert = false;\n body.inert = false;\n if (wizard) {wizard.element.inert = false;}\n backBtn.focus();\n }\n\n root.addEventListener('keydown', (e) => {\n if (e.key !== 'Escape' || e.defaultPrevented) {return;}\n // Escape is Back; nothing else (a modal under the page) should see it.\n e.preventDefault();\n e.stopPropagation();\n back();\n });\n\n // ── Layout ────────────────────────────────────────────────────────────────\n\n function applyLayout(): void {\n root.classList.toggle('is-narrow', narrow);\n root.dataset.view = narrow ? view : 'both';\n backBtn.setAttribute('aria-label', narrow && view === 'detail' ? 'Back to the list' : 'Back');\n }\n\n function measure(width: number): void {\n // Zero means \"not laid out\" (jsdom, a hidden host): keep two panes.\n const next = width > 0 && width < NARROW_PX;\n if (next === narrow) {return;}\n narrow = next;\n applyLayout();\n }\n\n function focusSelectedEntry(): void {\n const fk = selection.kind === 'engine' ? `nav:eng:${selection.id}` : selection.kind === 'routing' ? 'nav:routing' : 'nav:add';\n focusKey(fk);\n }\n\n let resizeObserver: ResizeObserver | null = null;\n if (typeof ResizeObserver === 'function') {\n resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[entries.length - 1];\n if (entry) {measure(entry.contentRect.width);}\n });\n resizeObserver.observe(container);\n }\n\n // ── Statuses ──────────────────────────────────────────────────────────────\n\n // Statuses pushed while the page is open refresh the dots and pickers in\n // place (no full rebuild, so typing is never interrupted).\n const unsubscribe = opts.subscribeStatuses?.((list) => {\n if (finished) {return;}\n for (const s of list) {\n if (!form.busy(s.engineId)) {session.statuses.set(s.engineId, s);}\n }\n for (const engine of session.draft.engines) {refreshNavItem(engine.id);}\n renderDetailHead();\n scheduleRouting();\n wizard?.refresh(null, {});\n });\n\n // ── The setup wizard ──────────────────────────────────────────────────────\n\n function startWizard(): void {\n const w = createSetupWizard({\n session,\n form,\n ctx,\n announce,\n focusKey,\n setAllowCloud,\n onStatuses: () => opts.onStatuses(session.statusList()),\n onStep: (step) => wizardHeader(step),\n finish: () => done(),\n leave,\n openEngine: (id) => leaveWizardFor(id),\n turnsOn: !!opts.turnOnWhenDone,\n });\n wizard = w;\n root.classList.add('ai-page--wizard');\n // The toolbar panel already showed the experimental note, and step 1 has its own privacy disclosure.\n disclaimer.hidden = true;\n body.hidden = true;\n root.insertBefore(w.element, body);\n wizardHeader(w.step());\n }\n\n /** The header line for a step: \"Set up AI\", the step dots, Skip (Done is the last step's own button). */\n function wizardHeader(step: AiWizardStep): void {\n const n = wizardStepNumber(step);\n title.textContent = 'Set up AI';\n stepper.hidden = false;\n stepper.replaceChildren();\n stepper.setAttribute('role', 'img');\n stepper.setAttribute('aria-label', `Step ${n} of ${AI_WIZARD_STEPS}`);\n for (let i = 1; i <= AI_WIZARD_STEPS; i++) {\n const dot = el('span', `ai-wizard-dot${i === n ? ' is-current' : i < n ? ' is-done' : ''}`);\n stepper.append(dot);\n }\n stepper.append(el('span', 'ai-wizard-steps-text', `${n} of ${AI_WIZARD_STEPS}`));\n if (titleNote) {titleNote.hidden = true;}\n doneBtn.hidden = true;\n skipBtn.hidden = step === 'done';\n backBtn.setAttribute('aria-label', n === 1 ? 'Back' : 'Back to the previous step');\n }\n\n /** \"Change settings in AI Engines\": the full page on the wizard's engine, same session. */\n function leaveWizardFor(engineId: string): void {\n const w = wizard;\n if (!w) {return;}\n wizard = null;\n w.dispose();\n root.classList.remove('ai-page--wizard');\n disclaimer.hidden = false;\n body.hidden = false;\n title.textContent = 'AI Engines';\n stepper.hidden = true;\n if (titleNote) {titleNote.hidden = false;}\n doneBtn.hidden = false;\n skipBtn.hidden = true;\n selection = getEngine(engineId) ? { kind: 'engine', id: engineId } : initialSelection();\n view = 'detail';\n applyLayout();\n renderNav();\n renderDetail();\n if (selection.kind === 'engine') {form.opened(selection.id);}\n if (narrow) {focusDetailTitle();} else {focusSelectedEntry();}\n }\n\n // ── Mount ─────────────────────────────────────────────────────────────────\n\n container.replaceChildren(root);\n measure(container.getBoundingClientRect().width);\n applyLayout();\n // A tier-1 host routes by itself: it never sees the wizard (nor this page).\n if (opts.initial?.section === 'wizard' && session.tier === 2) {\n startWizard();\n } else {\n renderNav();\n renderDetail();\n if (selection.kind === 'engine') {form.opened(selection.id);}\n }\n if (ai.hardwareInfo && !hardware) {\n // The first answer arrives after the form rendered: render it again so it groups and tags by size, as on a later open (Q5).\n void setupHardware(ai).then((info) => {\n if (finished || !info) {return;}\n hardware = info;\n const formEngine = wizard ? wizard.engineId() : selectedEngineId();\n if (formEngine) {rerenderForm(formEngine);}\n });\n }\n\n // Fresh statuses as the page opens: the dots should not be stale.\n if (session.tier === 2) {\n void session.refreshStatuses().then((ok) => {\n if (!ok || finished) {return;}\n for (const engine of session.draft.engines) {refreshNavItem(engine.id);}\n renderDetailHead();\n scheduleRouting();\n });\n }\n\n return {\n dispose(): void {\n // Torn down without Done or Back (the host closed): nothing is kept.\n if (!finished) {\n finished = true;\n session.discard();\n }\n finished = true;\n detectAbort?.abort();\n wizard?.dispose();\n window.clearTimeout(liveTimer);\n unsubscribe?.();\n resizeObserver?.disconnect();\n form.dispose();\n container.replaceChildren();\n },\n focus(): void {\n if (confirmDiscard) {\n focusKey('page:keep');\n } else if (wizard) {\n wizard.focus();\n } else if (narrow && view === 'detail') {\n focusDetailTitle();\n } else if (!narrow && selection.kind === 'routing') {\n focusKey('route:default');\n } else if (!narrow && selection.kind === 'add' && session.draft.engines.length === 0) {\n detailBody.querySelector<HTMLElement>('.ai-card')?.focus({ preventScroll: true });\n } else {\n focusSelectedEntry();\n }\n },\n };\n}\n"],"mappings":"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","names":["where","line","pickNote","model","titleLine"]}
|