@openeryc/pi-coding-agent 0.75.55 → 0.75.56
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 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +3 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/fetch-openai-models.d.ts +25 -0
- package/dist/core/fetch-openai-models.d.ts.map +1 -0
- package/dist/core/fetch-openai-models.js +107 -0
- package/dist/core/fetch-openai-models.js.map +1 -0
- package/dist/core/model-registry.d.ts +112 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +99 -2
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/settings-manager.d.ts +4 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +12 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +2 -2
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/model-hub.d.ts +115 -0
- package/dist/modes/interactive/components/model-hub.d.ts.map +1 -0
- package/dist/modes/interactive/components/model-hub.js +753 -0
- package/dist/modes/interactive/components/model-hub.js.map +1 -0
- package/dist/modes/interactive/components/model-selector.d.ts +2 -44
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +2 -275
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +308 -132
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/models.md +20 -0
- package/docs/providers.md +13 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-hub.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/model-hub.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Unified model hub: Select current model, manage cycle whitelist, manage custom providers.\n */\n\nimport { type Model, modelsAreEqual } from \"@openeryc/pi-ai\";\nimport {\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tInput,\n\tKey,\n\tmatchesKey,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@openeryc/pi-tui\";\nimport type { ModelRegistry } from \"../../../core/model-registry.ts\";\nimport type { SettingsManager } from \"../../../core/settings-manager.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyHint, keyText } from \"./keybinding-hints.ts\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type ModelHubTab = \"select\" | \"cycle\" | \"manage\";\n\ninterface ModelItem {\n\tprovider: string;\n\tid: string;\n\tmodel: Model<any>;\n}\n\ninterface ScopedModelItem {\n\tmodel: Model<any>;\n\tthinkingLevel?: string;\n}\n\ntype EnabledIds = string[] | null;\n\ntype SelectRow =\n\t| { kind: \"header\"; label: string }\n\t| { kind: \"collapsed\"; provider: string; count: number }\n\t| { kind: \"model\"; item: ModelItem; badges: string };\n\ntype ManageRow =\n\t| {\n\t\t\tkind: \"provider\";\n\t\t\tsource: \"models_json\" | \"openai_compatible\";\n\t\t\tid: string;\n\t\t\tlabel: string;\n\t\t\tdetail: string;\n\t }\n\t| { kind: \"action\"; action: \"add\"; label: string };\n\nexport interface ModelHubCallbacks {\n\tonSelectModel: (model: Model<any>) => void | Promise<void>;\n\tonCancel: () => void;\n\t/** Cycle tab: session-only scope change */\n\tonCycleChange: (enabledModelIds: string[] | null) => void | Promise<void>;\n\t/** Cycle tab: persist to settings */\n\tonCyclePersist: (enabledModelIds: string[] | null) => void | Promise<void>;\n\t/** Manage tab: open add-provider wizard (writes models.json by default) */\n\tonManageAdd: () => void | Promise<void>;\n\t/** Manage tab: edit existing custom/openai_compatible provider */\n\tonManageEdit: (source: \"models_json\" | \"openai_compatible\", providerId: string) => void | Promise<void>;\n\t/** Manage tab: remove provider */\n\tonManageRemove: (source: \"models_json\" | \"openai_compatible\", providerId: string) => void | Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// Pure helpers (exported for tests)\n// ---------------------------------------------------------------------------\n\nexport function formatTokenCount(count: number): string {\n\tif (count >= 1_000_000) {\n\t\tconst millions = count / 1_000_000;\n\t\treturn millions % 1 === 0 ? `${millions}M` : `${millions.toFixed(1)}M`;\n\t}\n\tif (count >= 1_000) {\n\t\tconst thousands = count / 1_000;\n\t\treturn thousands % 1 === 0 ? `${thousands}K` : `${thousands.toFixed(1)}K`;\n\t}\n\treturn count.toString();\n}\n\nfunction modelBadges(model: Model<any>): string {\n\tconst parts: string[] = [];\n\tif (model.reasoning) parts.push(\"R\");\n\tparts.push(formatTokenCount(model.contextWindow));\n\treturn parts.join(\" \");\n}\n\nfunction isEnabled(enabledIds: EnabledIds, id: string): boolean {\n\treturn enabledIds === null || enabledIds.includes(id);\n}\n\nfunction toggle(enabledIds: EnabledIds, id: string): EnabledIds {\n\tif (enabledIds === null) return [id];\n\tconst index = enabledIds.indexOf(id);\n\tif (index >= 0) return [...enabledIds.slice(0, index), ...enabledIds.slice(index + 1)];\n\treturn [...enabledIds, id];\n}\n\nfunction enableAll(enabledIds: EnabledIds, allIds: string[], targetIds?: string[]): EnabledIds {\n\tif (enabledIds === null) return null;\n\tconst targets = targetIds ?? allIds;\n\tconst result = [...enabledIds];\n\tfor (const id of targets) {\n\t\tif (!result.includes(id)) result.push(id);\n\t}\n\treturn result.length === allIds.length ? null : result;\n}\n\nfunction clearAll(enabledIds: EnabledIds, allIds: string[], targetIds?: string[]): EnabledIds {\n\tif (enabledIds === null) {\n\t\treturn targetIds ? allIds.filter((id) => !targetIds.includes(id)) : [];\n\t}\n\tconst targets = new Set(targetIds ?? enabledIds);\n\treturn enabledIds.filter((id) => !targets.has(id));\n}\n\nfunction move(enabledIds: EnabledIds, id: string, delta: number): EnabledIds {\n\tif (enabledIds === null) return null;\n\tconst list = [...enabledIds];\n\tconst index = list.indexOf(id);\n\tif (index < 0) return list;\n\tconst newIndex = index + delta;\n\tif (newIndex < 0 || newIndex >= list.length) return list;\n\tconst result = [...list];\n\t[result[index], result[newIndex]] = [result[newIndex], result[index]];\n\treturn result;\n}\n\nfunction getSortedIds(enabledIds: EnabledIds, allIds: string[]): string[] {\n\tif (enabledIds === null) return allIds;\n\tconst enabledSet = new Set(enabledIds);\n\treturn [...enabledIds, ...allIds.filter((id) => !enabledSet.has(id))];\n}\n\nexport function buildSelectRows(options: {\n\tmodels: ModelItem[];\n\tcurrentModel?: Model<any>;\n\trecentKeys: string[];\n\tquery: string;\n\texpandedProviders: Set<string>;\n\tcollapsedLimit?: number;\n}): SelectRow[] {\n\tconst { models, currentModel, recentKeys, query, expandedProviders, collapsedLimit = 12 } = options;\n\tconst rows: SelectRow[] = [];\n\n\tif (query) {\n\t\tconst filtered = fuzzyFilter(\n\t\t\tmodels,\n\t\t\tquery,\n\t\t\t({ id, provider, model }) => `${id} ${provider} ${provider}/${id} ${model.name ?? \"\"} ${provider} ${id}`,\n\t\t);\n\t\tfor (const item of filtered) {\n\t\t\trows.push({ kind: \"model\", item, badges: modelBadges(item.model) });\n\t\t}\n\t\treturn rows;\n\t}\n\n\tconst byKey = new Map(models.map((m) => [`${m.provider}/${m.id}`, m]));\n\tconst seen = new Set<string>();\n\n\t// Current first (if available)\n\tif (currentModel) {\n\t\tconst key = `${currentModel.provider}/${currentModel.id}`;\n\t\tconst item = byKey.get(key);\n\t\tif (item) {\n\t\t\trows.push({ kind: \"header\", label: \"Current\" });\n\t\t\trows.push({ kind: \"model\", item, badges: modelBadges(item.model) });\n\t\t\tseen.add(key);\n\t\t}\n\t}\n\n\t// Recent\n\tconst recentItems: ModelItem[] = [];\n\tfor (const key of recentKeys) {\n\t\tif (seen.has(key)) continue;\n\t\tconst item = byKey.get(key);\n\t\tif (item) {\n\t\t\trecentItems.push(item);\n\t\t\tseen.add(key);\n\t\t}\n\t}\n\tif (recentItems.length > 0) {\n\t\trows.push({ kind: \"header\", label: \"Recent\" });\n\t\tfor (const item of recentItems.slice(0, 8)) {\n\t\t\trows.push({ kind: \"model\", item, badges: modelBadges(item.model) });\n\t\t}\n\t}\n\n\t// Group remaining by provider\n\tconst byProvider = new Map<string, ModelItem[]>();\n\tfor (const item of models) {\n\t\tconst key = `${item.provider}/${item.id}`;\n\t\tif (seen.has(key)) continue;\n\t\tconst list = byProvider.get(item.provider) ?? [];\n\t\tlist.push(item);\n\t\tbyProvider.set(item.provider, list);\n\t}\n\n\tconst providers = [...byProvider.keys()].sort((a, b) => a.localeCompare(b));\n\tconst currentProvider = currentModel?.provider;\n\n\tfor (const provider of providers) {\n\t\tconst list = byProvider.get(provider) ?? [];\n\t\tlist.sort((a, b) => a.id.localeCompare(b.id));\n\t\tconst expand = expandedProviders.has(provider) || provider === currentProvider || list.length <= collapsedLimit;\n\n\t\trows.push({ kind: \"header\", label: provider });\n\t\tif (!expand) {\n\t\t\trows.push({ kind: \"collapsed\", provider, count: list.length });\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const item of list) {\n\t\t\trows.push({ kind: \"model\", item, badges: modelBadges(item.model) });\n\t\t}\n\t}\n\n\treturn rows;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport class ModelHubComponent extends Container implements Focusable {\n\tprivate searchInput: Input;\n\tprivate listContainer: Container;\n\tprivate headerText: Text;\n\tprivate footerText: Text;\n\tprivate hintText: Text;\n\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\n\tprivate tui: TUI;\n\tprivate currentModel?: Model<any>;\n\tprivate settingsManager: SettingsManager;\n\tprivate modelRegistry: ModelRegistry;\n\tprivate callbacks: ModelHubCallbacks;\n\n\tprivate tab: ModelHubTab;\n\tprivate allModels: ModelItem[] = [];\n\tprivate scopedModels: ReadonlyArray<ScopedModelItem>;\n\n\t// Select state\n\tprivate selectRows: SelectRow[] = [];\n\tprivate selectIndex = 0;\n\tprivate expandedProviders = new Set<string>();\n\n\t// Cycle state\n\tprivate cycleAllIds: string[] = [];\n\tprivate cycleModelsById = new Map<string, Model<any>>();\n\tprivate enabledIds: EnabledIds = null;\n\tprivate cycleItems: Array<{ fullId: string; model: Model<any>; enabled: boolean }> = [];\n\tprivate cycleIndex = 0;\n\tprivate cycleDirty = false;\n\n\t// Manage state\n\tprivate manageRows: ManageRow[] = [];\n\tprivate manageIndex = 0;\n\n\tprivate errorMessage?: string;\n\tprivate maxVisible = 10;\n\tprivate loadGeneration = 0;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tcurrentModel: Model<any> | undefined,\n\t\tsettingsManager: SettingsManager,\n\t\tmodelRegistry: ModelRegistry,\n\t\tscopedModels: ReadonlyArray<ScopedModelItem>,\n\t\tenabledModelIds: string[] | null,\n\t\tcallbacks: ModelHubCallbacks,\n\t\toptions?: { initialTab?: ModelHubTab; initialSearchInput?: string },\n\t) {\n\t\tsuper();\n\t\tthis.tui = tui;\n\t\tthis.currentModel = currentModel;\n\t\tthis.settingsManager = settingsManager;\n\t\tthis.modelRegistry = modelRegistry;\n\t\tthis.scopedModels = scopedModels;\n\t\tthis.callbacks = callbacks;\n\t\tthis.tab = options?.initialTab ?? \"select\";\n\t\tthis.enabledIds = enabledModelIds === null ? null : [...enabledModelIds];\n\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.headerText = new Text(this.getHeaderText(), 0, 0);\n\t\tthis.addChild(this.headerText);\n\t\tthis.hintText = new Text(this.getHintText(), 0, 0);\n\t\tthis.addChild(this.hintText);\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.searchInput = new Input();\n\t\tif (options?.initialSearchInput) {\n\t\t\tthis.searchInput.setValue(options.initialSearchInput);\n\t\t}\n\t\tthis.searchInput.onSubmit = () => this.handleConfirm();\n\t\tthis.addChild(this.searchInput);\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.footerText = new Text(this.getFooterText(), 0, 0);\n\t\tthis.addChild(this.footerText);\n\t\tthis.addChild(new DynamicBorder());\n\n\t\tvoid this.reload().then(() => {\n\t\t\tif (options?.initialSearchInput) {\n\t\t\t\tthis.applySearch();\n\t\t\t}\n\t\t\tthis.tui.requestRender();\n\t\t});\n\t}\n\n\t// ---- public helpers for tests ----\n\n\tgetTab(): ModelHubTab {\n\t\treturn this.tab;\n\t}\n\n\tgetSearchInput(): Input {\n\t\treturn this.searchInput;\n\t}\n\n\t/** Test helper: force reload completion */\n\tasync waitForLoad(): Promise<void> {\n\t\tawait this.reload();\n\t}\n\n\t// ---- load ----\n\n\tprivate async reload(): Promise<void> {\n\t\tconst gen = ++this.loadGeneration;\n\t\tthis.modelRegistry.refresh();\n\t\tconst loadError = this.modelRegistry.getError();\n\t\tif (loadError) {\n\t\t\tthis.errorMessage = loadError;\n\t\t} else {\n\t\t\tthis.errorMessage = undefined;\n\t\t}\n\n\t\ttry {\n\t\t\tconst available = this.modelRegistry.getAvailable();\n\t\t\tif (gen !== this.loadGeneration) return;\n\n\t\t\tthis.allModels = available.map((model) => ({\n\t\t\t\tprovider: model.provider,\n\t\t\t\tid: model.id,\n\t\t\t\tmodel,\n\t\t\t}));\n\n\t\t\t// Refresh scoped models against registry\n\t\t\tthis.scopedModels = this.scopedModels.map((scoped) => {\n\t\t\t\tconst refreshed = this.modelRegistry.find(scoped.model.provider, scoped.model.id);\n\t\t\t\treturn refreshed ? { ...scoped, model: refreshed } : scoped;\n\t\t\t});\n\n\t\t\tthis.cycleModelsById.clear();\n\t\t\tthis.cycleAllIds = [];\n\t\t\tfor (const item of this.allModels) {\n\t\t\t\tconst fullId = `${item.provider}/${item.id}`;\n\t\t\t\tthis.cycleModelsById.set(fullId, item.model);\n\t\t\t\tthis.cycleAllIds.push(fullId);\n\t\t\t}\n\n\t\t\tthis.rebuildManageRows();\n\t\t\tthis.applySearch();\n\t\t} catch (error) {\n\t\t\tthis.allModels = [];\n\t\t\tthis.errorMessage = error instanceof Error ? error.message : String(error);\n\t\t\tthis.applySearch();\n\t\t}\n\t}\n\n\tprivate rebuildManageRows(): void {\n\t\tconst rows: ManageRow[] = [];\n\t\trows.push({ kind: \"action\", action: \"add\", label: \"+ Add custom provider (models.json)\" });\n\n\t\tfor (const p of this.modelRegistry.listModelsJsonProviders()) {\n\t\t\tconst modelLabel =\n\t\t\t\tp.modelIds.length === 0\n\t\t\t\t\t? \"override only\"\n\t\t\t\t\t: `${p.modelIds.length} model${p.modelIds.length === 1 ? \"\" : \"s\"}`;\n\t\t\trows.push({\n\t\t\t\tkind: \"provider\",\n\t\t\t\tsource: \"models_json\",\n\t\t\t\tid: p.name,\n\t\t\t\tlabel: p.name,\n\t\t\t\tdetail: `${p.isBuiltIn ? \"built-in override\" : \"custom\"} · ${modelLabel}${p.baseUrl ? ` · ${p.baseUrl}` : \"\"}`,\n\t\t\t});\n\t\t}\n\n\t\tconst openaiCompat = this.modelRegistry.authStorage.getOpenAICompatibleProviders();\n\t\tfor (const [id, info] of Object.entries(openaiCompat)) {\n\t\t\trows.push({\n\t\t\t\tkind: \"provider\",\n\t\t\t\tsource: \"openai_compatible\",\n\t\t\t\tid,\n\t\t\t\tlabel: id,\n\t\t\t\tdetail: `openai-compatible · ${info.models.length} model${info.models.length === 1 ? \"\" : \"s\"} · ${info.baseUrl}`,\n\t\t\t});\n\t\t}\n\n\t\tthis.manageRows = rows;\n\t\tthis.manageIndex = Math.min(this.manageIndex, Math.max(0, rows.length - 1));\n\t}\n\n\t// ---- header / footer ----\n\n\tprivate getHeaderText(): string {\n\t\tconst tabs: Array<{ id: ModelHubTab; label: string }> = [\n\t\t\t{ id: \"select\", label: \"Select\" },\n\t\t\t{ id: \"cycle\", label: \"Cycle\" },\n\t\t\t{ id: \"manage\", label: \"Manage\" },\n\t\t];\n\t\tconst parts = tabs.map((t) => (t.id === this.tab ? theme.fg(\"accent\", t.label) : theme.fg(\"muted\", t.label)));\n\t\treturn `${theme.fg(\"muted\", \"Models: \")}${parts.join(theme.fg(\"muted\", \" | \"))}`;\n\t}\n\n\tprivate getHintText(): string {\n\t\tif (this.tab === \"select\") {\n\t\t\treturn (\n\t\t\t\tkeyHint(\"tui.input.tab\", \"tabs\") +\n\t\t\t\ttheme.fg(\"muted\", \" · type to search · Enter select · collapsed providers: Enter expand\")\n\t\t\t);\n\t\t}\n\t\tif (this.tab === \"cycle\") {\n\t\t\treturn (\n\t\t\t\tkeyHint(\"tui.input.tab\", \"tabs\") + theme.fg(\"muted\", ` · session-only until ${keyText(\"app.models.save\")}`)\n\t\t\t);\n\t\t}\n\t\treturn keyHint(\"tui.input.tab\", \"tabs\") + theme.fg(\"muted\", \" · Enter edit/add · Backspace/Delete remove\");\n\t}\n\n\tprivate getFooterText(): string {\n\t\tif (this.tab === \"select\") {\n\t\t\tconst modelCount = this.selectRows.filter((r) => r.kind === \"model\").length;\n\t\t\treturn theme.fg(\"dim\", ` ${modelCount} model${modelCount === 1 ? \"\" : \"s\"} · Esc cancel`);\n\t\t}\n\t\tif (this.tab === \"cycle\") {\n\t\t\tconst enabledCount = this.enabledIds?.length ?? this.cycleAllIds.length;\n\t\t\tconst allEnabled = this.enabledIds === null;\n\t\t\tconst countText = allEnabled ? \"all enabled\" : `${enabledCount}/${this.cycleAllIds.length} enabled`;\n\t\t\tconst parts = [\n\t\t\t\t`${keyText(\"tui.select.confirm\")} toggle`,\n\t\t\t\t`${keyText(\"app.models.enableAll\")} all`,\n\t\t\t\t`${keyText(\"app.models.clearAll\")} clear`,\n\t\t\t\t`${keyText(\"app.models.toggleProvider\")} provider`,\n\t\t\t\t`${keyText(\"app.models.reorderUp\")}/${keyText(\"app.models.reorderDown\")} reorder`,\n\t\t\t\t`${keyText(\"app.models.save\")} save`,\n\t\t\t\tcountText,\n\t\t\t];\n\t\t\treturn this.cycleDirty\n\t\t\t\t? theme.fg(\"dim\", ` ${parts.join(\" · \")} `) + theme.fg(\"warning\", \"(unsaved)\")\n\t\t\t\t: theme.fg(\"dim\", ` ${parts.join(\" · \")}`);\n\t\t}\n\t\treturn theme.fg(\"dim\", \" Enter open · Backspace delete · writing models.json drops comments/trailing commas\");\n\t}\n\n\tprivate setTab(tab: ModelHubTab): void {\n\t\tif (this.tab === tab) return;\n\t\tthis.tab = tab;\n\t\tthis.headerText.setText(this.getHeaderText());\n\t\tthis.hintText.setText(this.getHintText());\n\t\tthis.applySearch();\n\t}\n\n\tprivate cycleTab(): void {\n\t\tconst order: ModelHubTab[] = [\"select\", \"cycle\", \"manage\"];\n\t\tconst idx = order.indexOf(this.tab);\n\t\tthis.setTab(order[(idx + 1) % order.length]!);\n\t}\n\n\t// ---- list building ----\n\n\tprivate applySearch(): void {\n\t\tconst query = this.searchInput.getValue();\n\n\t\tif (this.tab === \"select\") {\n\t\t\tthis.selectRows = buildSelectRows({\n\t\t\t\tmodels: this.allModels,\n\t\t\t\tcurrentModel: this.currentModel,\n\t\t\t\trecentKeys: this.settingsManager.getRecentModels(),\n\t\t\t\tquery,\n\t\t\t\texpandedProviders: this.expandedProviders,\n\t\t\t});\n\t\t\t// Prefer current model selection\n\t\t\tconst currentIdx = this.selectRows.findIndex(\n\t\t\t\t(r) => r.kind === \"model\" && modelsAreEqual(this.currentModel, r.item.model),\n\t\t\t);\n\t\t\tthis.selectIndex =\n\t\t\t\tcurrentIdx >= 0 ? currentIdx : Math.min(this.selectIndex, Math.max(0, this.selectRows.length - 1));\n\t\t\t// Snap to first selectable if landing on header\n\t\t\tthis.ensureSelectableIndex(\"select\");\n\t\t} else if (this.tab === \"cycle\") {\n\t\t\tconst items = getSortedIds(this.enabledIds, this.cycleAllIds)\n\t\t\t\t.filter((id) => this.cycleModelsById.has(id))\n\t\t\t\t.map((id) => ({\n\t\t\t\t\tfullId: id,\n\t\t\t\t\tmodel: this.cycleModelsById.get(id)!,\n\t\t\t\t\tenabled: isEnabled(this.enabledIds, id),\n\t\t\t\t}));\n\t\t\tthis.cycleItems = query ? fuzzyFilter(items, query, (i) => `${i.model.id} ${i.model.provider}`) : items;\n\t\t\tthis.cycleIndex = Math.min(this.cycleIndex, Math.max(0, this.cycleItems.length - 1));\n\t\t} else {\n\t\t\tthis.rebuildManageRows();\n\t\t\tif (query) {\n\t\t\t\tthis.manageRows = fuzzyFilter(this.manageRows, query, (r) =>\n\t\t\t\t\tr.kind === \"action\" ? r.label : `${r.label} ${r.detail} ${r.id}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.manageIndex = Math.min(this.manageIndex, Math.max(0, this.manageRows.length - 1));\n\t\t}\n\n\t\tthis.updateList();\n\t\tthis.footerText.setText(this.getFooterText());\n\t}\n\n\tprivate ensureSelectableIndex(which: \"select\"): void {\n\t\tif (which !== \"select\" || this.selectRows.length === 0) return;\n\t\tif (this.selectRows[this.selectIndex]?.kind === \"header\") {\n\t\t\tconst next = this.selectRows.findIndex((r, i) => i >= this.selectIndex && r.kind !== \"header\");\n\t\t\tif (next >= 0) {\n\t\t\t\tthis.selectIndex = next;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst prev = [...this.selectRows]\n\t\t\t\t.map((r, i) => ({ r, i }))\n\t\t\t\t.reverse()\n\t\t\t\t.find(({ r }) => r.kind !== \"header\");\n\t\t\tif (prev) this.selectIndex = prev.i;\n\t\t}\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tif (this.errorMessage && this.tab !== \"manage\") {\n\t\t\tfor (const line of this.errorMessage.split(\"\\n\")) {\n\t\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"error\", line), 0, 0));\n\t\t\t}\n\t\t}\n\n\t\tif (this.tab === \"select\") {\n\t\t\tthis.renderSelectList();\n\t\t} else if (this.tab === \"cycle\") {\n\t\t\tthis.renderCycleList();\n\t\t} else {\n\t\t\tthis.renderManageList();\n\t\t}\n\t}\n\n\tprivate renderSelectList(): void {\n\t\tif (this.selectRows.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No matching models\"), 0, 0));\n\t\t\treturn;\n\t\t}\n\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectIndex - Math.floor(this.maxVisible / 2), this.selectRows.length - this.maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + this.maxVisible, this.selectRows.length);\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst row = this.selectRows[i]!;\n\t\t\tconst isSelected = i === this.selectIndex;\n\n\t\t\tif (row.kind === \"header\") {\n\t\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", ` ── ${row.label} ──`), 0, 0));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (row.kind === \"collapsed\") {\n\t\t\t\tconst prefix = isSelected ? theme.fg(\"accent\", \"→ \") : \" \";\n\t\t\t\tconst text = isSelected\n\t\t\t\t\t? theme.fg(\"accent\", `▸ ${row.provider} (${row.count})`)\n\t\t\t\t\t: theme.fg(\"muted\", `▸ ${row.provider} (${row.count})`);\n\t\t\t\tthis.listContainer.addChild(new Text(`${prefix}${text}`, 0, 0));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst isCurrent = modelsAreEqual(this.currentModel, row.item.model);\n\t\t\tconst prefix = isSelected ? theme.fg(\"accent\", \"→ \") : \" \";\n\t\t\tconst modelText = isSelected ? theme.fg(\"accent\", row.item.id) : row.item.id;\n\t\t\tconst providerBadge = theme.fg(\"muted\", ` [${row.item.provider}]`);\n\t\t\tconst badges = theme.fg(\"dim\", ` ${row.badges}`);\n\t\t\tconst check = isCurrent ? theme.fg(\"success\", \" ✓\") : \"\";\n\t\t\tthis.listContainer.addChild(new Text(`${prefix}${modelText}${providerBadge}${badges}${check}`, 0, 0));\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < this.selectRows.length) {\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(theme.fg(\"muted\", ` (${this.selectIndex + 1}/${this.selectRows.length})`), 0, 0),\n\t\t\t);\n\t\t}\n\n\t\tconst selected = this.selectRows[this.selectIndex];\n\t\tif (selected?.kind === \"model\") {\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", ` ${selected.item.model.name}`), 0, 0));\n\t\t}\n\t}\n\n\tprivate renderCycleList(): void {\n\t\tif (this.cycleItems.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No matching models\"), 0, 0));\n\t\t\treturn;\n\t\t}\n\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.cycleIndex - Math.floor(this.maxVisible / 2), this.cycleItems.length - this.maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + this.maxVisible, this.cycleItems.length);\n\t\tconst allEnabled = this.enabledIds === null;\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = this.cycleItems[i]!;\n\t\t\tconst isSelected = i === this.cycleIndex;\n\t\t\tconst prefix = isSelected ? theme.fg(\"accent\", \"→ \") : \" \";\n\t\t\tconst modelText = isSelected ? theme.fg(\"accent\", item.model.id) : item.model.id;\n\t\t\tconst providerBadge = theme.fg(\"muted\", ` [${item.model.provider}]`);\n\t\t\tconst status = allEnabled ? \"\" : item.enabled ? theme.fg(\"success\", \" ✓\") : theme.fg(\"dim\", \" ✗\");\n\t\t\tthis.listContainer.addChild(new Text(`${prefix}${modelText}${providerBadge}${status}`, 0, 0));\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < this.cycleItems.length) {\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(theme.fg(\"muted\", ` (${this.cycleIndex + 1}/${this.cycleItems.length})`), 0, 0),\n\t\t\t);\n\t\t}\n\n\t\tif (this.cycleItems.length > 0) {\n\t\t\tconst selected = this.cycleItems[this.cycleIndex];\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", ` ${selected?.model.name}`), 0, 0));\n\t\t}\n\t}\n\n\tprivate renderManageList(): void {\n\t\tif (this.manageRows.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No custom providers\"), 0, 0));\n\t\t\treturn;\n\t\t}\n\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.manageIndex - Math.floor(this.maxVisible / 2), this.manageRows.length - this.maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + this.maxVisible, this.manageRows.length);\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst row = this.manageRows[i]!;\n\t\t\tconst isSelected = i === this.manageIndex;\n\t\t\tconst prefix = isSelected ? theme.fg(\"accent\", \"→ \") : \" \";\n\t\t\tif (row.kind === \"action\") {\n\t\t\t\tconst text = isSelected ? theme.fg(\"accent\", row.label) : theme.fg(\"success\", row.label);\n\t\t\t\tthis.listContainer.addChild(new Text(`${prefix}${text}`, 0, 0));\n\t\t\t} else {\n\t\t\t\tconst text = isSelected ? theme.fg(\"accent\", row.label) : row.label;\n\t\t\t\tconst detail = theme.fg(\"muted\", ` ${row.detail}`);\n\t\t\t\tthis.listContainer.addChild(new Text(`${prefix}${text}`, 0, 0));\n\t\t\t\tthis.listContainer.addChild(new Text(`${detail}`, 0, 0));\n\t\t\t}\n\t\t}\n\t}\n\n\t// ---- input ----\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\n\t\tif (kb.matches(keyData, \"tui.input.tab\")) {\n\t\t\tthis.cycleTab();\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.cancel\") || matchesKey(keyData, Key.escape)) {\n\t\t\tthis.callbacks.onCancel();\n\t\t\treturn;\n\t\t}\n\n\t\tif (matchesKey(keyData, Key.ctrl(\"c\"))) {\n\t\t\tif (this.searchInput.getValue()) {\n\t\t\t\tthis.searchInput.setValue(\"\");\n\t\t\t\tthis.applySearch();\n\t\t\t} else {\n\t\t\t\tthis.callbacks.onCancel();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.tab === \"select\") {\n\t\t\tthis.handleSelectInput(keyData, kb);\n\t\t} else if (this.tab === \"cycle\") {\n\t\t\tthis.handleCycleInput(keyData, kb);\n\t\t} else {\n\t\t\tthis.handleManageInput(keyData, kb);\n\t\t}\n\t}\n\n\tprivate handleSelectInput(keyData: string, kb: ReturnType<typeof getKeybindings>): void {\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.selectRows.length === 0) return;\n\t\t\tlet next = this.selectIndex === 0 ? this.selectRows.length - 1 : this.selectIndex - 1;\n\t\t\t// Skip headers when moving\n\t\t\tfor (let guard = 0; guard < this.selectRows.length; guard++) {\n\t\t\t\tif (this.selectRows[next]?.kind !== \"header\") break;\n\t\t\t\tnext = next === 0 ? this.selectRows.length - 1 : next - 1;\n\t\t\t}\n\t\t\tthis.selectIndex = next;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.selectRows.length === 0) return;\n\t\t\tlet next = this.selectIndex === this.selectRows.length - 1 ? 0 : this.selectIndex + 1;\n\t\t\tfor (let guard = 0; guard < this.selectRows.length; guard++) {\n\t\t\t\tif (this.selectRows[next]?.kind !== \"header\") break;\n\t\t\t\tnext = next === this.selectRows.length - 1 ? 0 : next + 1;\n\t\t\t}\n\t\t\tthis.selectIndex = next;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tthis.handleConfirm();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.searchInput.handleInput(keyData);\n\t\tthis.applySearch();\n\t}\n\n\tprivate handleCycleInput(keyData: string, kb: ReturnType<typeof getKeybindings>): void {\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.cycleItems.length === 0) return;\n\t\t\tthis.cycleIndex = this.cycleIndex === 0 ? this.cycleItems.length - 1 : this.cycleIndex - 1;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.cycleItems.length === 0) return;\n\t\t\tthis.cycleIndex = this.cycleIndex === this.cycleItems.length - 1 ? 0 : this.cycleIndex + 1;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\n\t\tconst reorderUp = kb.matches(keyData, \"app.models.reorderUp\");\n\t\tconst reorderDown = kb.matches(keyData, \"app.models.reorderDown\");\n\t\tif (reorderUp || reorderDown) {\n\t\t\tif (this.enabledIds === null) return;\n\t\t\tconst item = this.cycleItems[this.cycleIndex];\n\t\t\tif (item && isEnabled(this.enabledIds, item.fullId)) {\n\t\t\t\tconst delta = reorderUp ? -1 : 1;\n\t\t\t\tconst currentIndex = this.enabledIds.indexOf(item.fullId);\n\t\t\t\tconst newIndex = currentIndex + delta;\n\t\t\t\tif (newIndex >= 0 && newIndex < this.enabledIds.length) {\n\t\t\t\t\tthis.enabledIds = move(this.enabledIds, item.fullId, delta);\n\t\t\t\t\tthis.cycleDirty = true;\n\t\t\t\t\tthis.cycleIndex += delta;\n\t\t\t\t\tthis.applySearch();\n\t\t\t\t\tvoid this.callbacks.onCycleChange(this.enabledIds === null ? null : [...this.enabledIds]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tconst item = this.cycleItems[this.cycleIndex];\n\t\t\tif (item) {\n\t\t\t\tthis.enabledIds = toggle(this.enabledIds, item.fullId);\n\t\t\t\tthis.cycleDirty = true;\n\t\t\t\tthis.applySearch();\n\t\t\t\tvoid this.callbacks.onCycleChange(this.enabledIds === null ? null : [...this.enabledIds]);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"app.models.enableAll\")) {\n\t\t\tconst targetIds = this.searchInput.getValue() ? this.cycleItems.map((i) => i.fullId) : undefined;\n\t\t\tthis.enabledIds = enableAll(this.enabledIds, this.cycleAllIds, targetIds);\n\t\t\tthis.cycleDirty = true;\n\t\t\tthis.applySearch();\n\t\t\tvoid this.callbacks.onCycleChange(this.enabledIds === null ? null : [...this.enabledIds]);\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"app.models.clearAll\")) {\n\t\t\tconst targetIds = this.searchInput.getValue() ? this.cycleItems.map((i) => i.fullId) : undefined;\n\t\t\tthis.enabledIds = clearAll(this.enabledIds, this.cycleAllIds, targetIds);\n\t\t\tthis.cycleDirty = true;\n\t\t\tthis.applySearch();\n\t\t\tvoid this.callbacks.onCycleChange(this.enabledIds === null ? null : [...this.enabledIds]);\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"app.models.toggleProvider\")) {\n\t\t\tconst item = this.cycleItems[this.cycleIndex];\n\t\t\tif (item) {\n\t\t\t\tconst provider = item.model.provider;\n\t\t\t\tconst providerIds = this.cycleAllIds.filter((id) => this.cycleModelsById.get(id)!.provider === provider);\n\t\t\t\tconst allOn = providerIds.every((id) => isEnabled(this.enabledIds, id));\n\t\t\t\tthis.enabledIds = allOn\n\t\t\t\t\t? clearAll(this.enabledIds, this.cycleAllIds, providerIds)\n\t\t\t\t\t: enableAll(this.enabledIds, this.cycleAllIds, providerIds);\n\t\t\t\tthis.cycleDirty = true;\n\t\t\t\tthis.applySearch();\n\t\t\t\tvoid this.callbacks.onCycleChange(this.enabledIds === null ? null : [...this.enabledIds]);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"app.models.save\")) {\n\t\t\tvoid this.callbacks.onCyclePersist(this.enabledIds === null ? null : [...this.enabledIds]);\n\t\t\tthis.cycleDirty = false;\n\t\t\tthis.footerText.setText(this.getFooterText());\n\t\t\treturn;\n\t\t}\n\n\t\tthis.searchInput.handleInput(keyData);\n\t\tthis.applySearch();\n\t}\n\n\tprivate handleManageInput(keyData: string, kb: ReturnType<typeof getKeybindings>): void {\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.manageRows.length === 0) return;\n\t\t\tthis.manageIndex = this.manageIndex === 0 ? this.manageRows.length - 1 : this.manageIndex - 1;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.manageRows.length === 0) return;\n\t\t\tthis.manageIndex = this.manageIndex === this.manageRows.length - 1 ? 0 : this.manageIndex + 1;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tthis.handleConfirm();\n\t\t\treturn;\n\t\t}\n\t\t// Backspace / Delete remove selected provider\n\t\tif (matchesKey(keyData, Key.backspace) || matchesKey(keyData, Key.delete)) {\n\t\t\tconst row = this.manageRows[this.manageIndex];\n\t\t\tif (row?.kind === \"provider\") {\n\t\t\t\tvoid this.callbacks.onManageRemove(row.source, row.id);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis.searchInput.handleInput(keyData);\n\t\tthis.applySearch();\n\t}\n\n\tprivate handleConfirm(): void {\n\t\tif (this.tab === \"select\") {\n\t\t\tconst row = this.selectRows[this.selectIndex];\n\t\t\tif (!row) return;\n\t\t\tif (row.kind === \"collapsed\") {\n\t\t\t\tthis.expandedProviders.add(row.provider);\n\t\t\t\tthis.applySearch();\n\t\t\t\t// Move selection to first model under that provider\n\t\t\t\tconst idx = this.selectRows.findIndex((r) => r.kind === \"model\" && r.item.provider === row.provider);\n\t\t\t\tif (idx >= 0) this.selectIndex = idx;\n\t\t\t\tthis.updateList();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (row.kind === \"model\") {\n\t\t\t\tthis.settingsManager.setDefaultModelAndProvider(row.item.model.provider, row.item.model.id);\n\t\t\t\tvoid this.callbacks.onSelectModel(row.item.model);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.tab === \"cycle\") {\n\t\t\tconst item = this.cycleItems[this.cycleIndex];\n\t\t\tif (item) {\n\t\t\t\tthis.enabledIds = toggle(this.enabledIds, item.fullId);\n\t\t\t\tthis.cycleDirty = true;\n\t\t\t\tthis.applySearch();\n\t\t\t\tvoid this.callbacks.onCycleChange(this.enabledIds === null ? null : [...this.enabledIds]);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst row = this.manageRows[this.manageIndex];\n\t\tif (!row) return;\n\t\tif (row.kind === \"action\" && row.action === \"add\") {\n\t\t\tvoid this.callbacks.onManageAdd();\n\t\t\treturn;\n\t\t}\n\t\tif (row.kind === \"provider\") {\n\t\t\tvoid this.callbacks.onManageEdit(row.source, row.id);\n\t\t}\n\t}\n\n\t/** Called by parent after manage mutation so list refreshes. */\n\tasync refreshAfterManage(): Promise<void> {\n\t\tawait this.reload();\n\t\tthis.tui.requestRender();\n\t}\n}\n\n/** Back-compat alias used by older tests/imports. */\nexport { ModelHubComponent as ModelSelectorComponent };\n"]}
|
|
@@ -1,47 +1,5 @@
|
|
|
1
|
-
import { type Model } from "@openeryc/pi-ai";
|
|
2
|
-
import { Container, type Focusable, Input, type TUI } from "@openeryc/pi-tui";
|
|
3
|
-
import type { ModelRegistry } from "../../../core/model-registry.ts";
|
|
4
|
-
import type { SettingsManager } from "../../../core/settings-manager.ts";
|
|
5
|
-
interface ScopedModelItem {
|
|
6
|
-
model: Model<any>;
|
|
7
|
-
thinkingLevel?: string;
|
|
8
|
-
}
|
|
9
1
|
/**
|
|
10
|
-
*
|
|
2
|
+
* Back-compat re-export. Prefer importing ModelHubComponent from model-hub.ts.
|
|
11
3
|
*/
|
|
12
|
-
export
|
|
13
|
-
private searchInput;
|
|
14
|
-
private _focused;
|
|
15
|
-
get focused(): boolean;
|
|
16
|
-
set focused(value: boolean);
|
|
17
|
-
private listContainer;
|
|
18
|
-
private allModels;
|
|
19
|
-
private scopedModelItems;
|
|
20
|
-
private activeModels;
|
|
21
|
-
private filteredModels;
|
|
22
|
-
private selectedIndex;
|
|
23
|
-
private currentModel?;
|
|
24
|
-
private settingsManager;
|
|
25
|
-
private modelRegistry;
|
|
26
|
-
private onSelectCallback;
|
|
27
|
-
private onCancelCallback;
|
|
28
|
-
private errorMessage?;
|
|
29
|
-
private tui;
|
|
30
|
-
private scopedModels;
|
|
31
|
-
private scope;
|
|
32
|
-
private scopeText?;
|
|
33
|
-
private scopeHintText?;
|
|
34
|
-
constructor(tui: TUI, currentModel: Model<any> | undefined, settingsManager: SettingsManager, modelRegistry: ModelRegistry, scopedModels: ReadonlyArray<ScopedModelItem>, onSelect: (model: Model<any>) => void, onCancel: () => void, initialSearchInput?: string);
|
|
35
|
-
private loadModels;
|
|
36
|
-
private sortModels;
|
|
37
|
-
private getScopeText;
|
|
38
|
-
private getScopeHintText;
|
|
39
|
-
private setScope;
|
|
40
|
-
private filterModels;
|
|
41
|
-
private updateList;
|
|
42
|
-
handleInput(keyData: string): void;
|
|
43
|
-
private handleSelect;
|
|
44
|
-
getSearchInput(): Input;
|
|
45
|
-
}
|
|
46
|
-
export {};
|
|
4
|
+
export { buildSelectRows, formatTokenCount, type ModelHubCallbacks, ModelHubComponent, ModelHubComponent as ModelSelectorComponent, type ModelHubTab, } from "./model-hub.ts";
|
|
47
5
|
//# sourceMappingURL=model-selector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/model-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAkB,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EACN,SAAS,EACT,KAAK,SAAS,EAGd,KAAK,EAGL,KAAK,GAAG,EACR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAWzE,UAAU,eAAe;IACxB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAID;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,SAAU,YAAW,SAAS;IACzE,OAAO,CAAC,WAAW,CAAQ;IAG3B,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IACD,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,YAAY,CAAmB;IACvC,OAAO,CAAC,cAAc,CAAmB;IACzC,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,YAAY,CAAC,CAAa;IAClC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,SAAS,CAAC,CAAO;IACzB,OAAO,CAAC,aAAa,CAAC,CAAO;IAE7B,YACC,GAAG,EAAE,GAAG,EACR,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,EACpC,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,aAAa,CAAC,eAAe,CAAC,EAC5C,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,EACrC,QAAQ,EAAE,MAAM,IAAI,EACpB,kBAAkB,CAAC,EAAE,MAAM,EA+D3B;YAEa,UAAU;IA8CxB,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,QAAQ;IAYhB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,UAAU;IAyDlB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAwCjC;IAED,OAAO,CAAC,YAAY;IAMpB,cAAc,IAAI,KAAK,CAEtB;CACD","sourcesContent":["import { type Model, modelsAreEqual } from \"@openeryc/pi-ai\";\nimport {\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tInput,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@openeryc/pi-tui\";\nimport type { ModelRegistry } from \"../../../core/model-registry.ts\";\nimport type { SettingsManager } from \"../../../core/settings-manager.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyHint } from \"./keybinding-hints.ts\";\n\ninterface ModelItem {\n\tprovider: string;\n\tid: string;\n\tmodel: Model<any>;\n}\n\ninterface ScopedModelItem {\n\tmodel: Model<any>;\n\tthinkingLevel?: string;\n}\n\ntype ModelScope = \"all\" | \"scoped\";\n\n/**\n * Component that renders a model selector with search\n */\nexport class ModelSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: Input;\n\n\t// Focusable implementation - propagate to searchInput for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\tprivate listContainer: Container;\n\tprivate allModels: ModelItem[] = [];\n\tprivate scopedModelItems: ModelItem[] = [];\n\tprivate activeModels: ModelItem[] = [];\n\tprivate filteredModels: ModelItem[] = [];\n\tprivate selectedIndex: number = 0;\n\tprivate currentModel?: Model<any>;\n\tprivate settingsManager: SettingsManager;\n\tprivate modelRegistry: ModelRegistry;\n\tprivate onSelectCallback: (model: Model<any>) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate errorMessage?: string;\n\tprivate tui: TUI;\n\tprivate scopedModels: ReadonlyArray<ScopedModelItem>;\n\tprivate scope: ModelScope = \"all\";\n\tprivate scopeText?: Text;\n\tprivate scopeHintText?: Text;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tcurrentModel: Model<any> | undefined,\n\t\tsettingsManager: SettingsManager,\n\t\tmodelRegistry: ModelRegistry,\n\t\tscopedModels: ReadonlyArray<ScopedModelItem>,\n\t\tonSelect: (model: Model<any>) => void,\n\t\tonCancel: () => void,\n\t\tinitialSearchInput?: string,\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.currentModel = currentModel;\n\t\tthis.settingsManager = settingsManager;\n\t\tthis.modelRegistry = modelRegistry;\n\t\tthis.scopedModels = scopedModels;\n\t\tthis.scope = scopedModels.length > 0 ? \"scoped\" : \"all\";\n\t\tthis.onSelectCallback = onSelect;\n\t\tthis.onCancelCallback = onCancel;\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add hint about model filtering\n\t\tif (scopedModels.length > 0) {\n\t\t\tthis.scopeText = new Text(this.getScopeText(), 0, 0);\n\t\t\tthis.addChild(this.scopeText);\n\t\t\tthis.scopeHintText = new Text(this.getScopeHintText(), 0, 0);\n\t\t\tthis.addChild(this.scopeHintText);\n\t\t} else {\n\t\t\tconst hintText = \"Only showing models from configured providers. Use /login to add providers.\";\n\t\t\tthis.addChild(new Text(theme.fg(\"warning\", hintText), 0, 0));\n\t\t}\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create search input\n\t\tthis.searchInput = new Input();\n\t\tif (initialSearchInput) {\n\t\t\tthis.searchInput.setValue(initialSearchInput);\n\t\t}\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\t// Enter on search input selects the first filtered item\n\t\t\tif (this.filteredModels[this.selectedIndex]) {\n\t\t\t\tthis.handleSelect(this.filteredModels[this.selectedIndex].model);\n\t\t\t}\n\t\t};\n\t\tthis.addChild(this.searchInput);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create list container\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Load models and do initial render\n\t\tthis.loadModels().then(() => {\n\t\t\tif (initialSearchInput) {\n\t\t\t\tthis.filterModels(initialSearchInput);\n\t\t\t} else {\n\t\t\t\tthis.updateList();\n\t\t\t}\n\t\t\t// Request re-render after models are loaded\n\t\t\tthis.tui.requestRender();\n\t\t});\n\t}\n\n\tprivate async loadModels(): Promise<void> {\n\t\tlet models: ModelItem[];\n\n\t\t// Refresh to pick up any changes to models.json\n\t\tthis.modelRegistry.refresh();\n\n\t\t// Check for models.json errors\n\t\tconst loadError = this.modelRegistry.getError();\n\t\tif (loadError) {\n\t\t\tthis.errorMessage = loadError;\n\t\t}\n\n\t\t// Load available models (built-in models still work even if models.json failed)\n\t\ttry {\n\t\t\tconst availableModels = await this.modelRegistry.getAvailable();\n\t\t\tmodels = availableModels.map((model: Model<any>) => ({\n\t\t\t\tprovider: model.provider,\n\t\t\t\tid: model.id,\n\t\t\t\tmodel,\n\t\t\t}));\n\t\t} catch (error) {\n\t\t\tthis.allModels = [];\n\t\t\tthis.scopedModelItems = [];\n\t\t\tthis.activeModels = [];\n\t\t\tthis.filteredModels = [];\n\t\t\tthis.errorMessage = error instanceof Error ? error.message : String(error);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.allModels = this.sortModels(models);\n\t\tthis.scopedModels = this.scopedModels.map((scoped) => {\n\t\t\tconst refreshed = this.modelRegistry.find(scoped.model.provider, scoped.model.id);\n\t\t\treturn refreshed ? { ...scoped, model: refreshed } : scoped;\n\t\t});\n\t\tthis.scopedModelItems = this.scopedModels.map((scoped) => ({\n\t\t\tprovider: scoped.model.provider,\n\t\t\tid: scoped.model.id,\n\t\t\tmodel: scoped.model,\n\t\t}));\n\t\tthis.activeModels = this.scope === \"scoped\" ? this.scopedModelItems : this.allModels;\n\t\tthis.filteredModels = this.activeModels;\n\t\tconst currentIndex = this.filteredModels.findIndex((item) => modelsAreEqual(this.currentModel, item.model));\n\t\tthis.selectedIndex =\n\t\t\tcurrentIndex >= 0 ? currentIndex : Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));\n\t}\n\n\tprivate sortModels(models: ModelItem[]): ModelItem[] {\n\t\tconst sorted = [...models];\n\t\t// Sort: current model first, then by provider\n\t\tsorted.sort((a, b) => {\n\t\t\tconst aIsCurrent = modelsAreEqual(this.currentModel, a.model);\n\t\t\tconst bIsCurrent = modelsAreEqual(this.currentModel, b.model);\n\t\t\tif (aIsCurrent && !bIsCurrent) return -1;\n\t\t\tif (!aIsCurrent && bIsCurrent) return 1;\n\t\t\treturn a.provider.localeCompare(b.provider);\n\t\t});\n\t\treturn sorted;\n\t}\n\n\tprivate getScopeText(): string {\n\t\tconst allText = this.scope === \"all\" ? theme.fg(\"accent\", \"all\") : theme.fg(\"muted\", \"all\");\n\t\tconst scopedText = this.scope === \"scoped\" ? theme.fg(\"accent\", \"scoped\") : theme.fg(\"muted\", \"scoped\");\n\t\treturn `${theme.fg(\"muted\", \"Scope: \")}${allText}${theme.fg(\"muted\", \" | \")}${scopedText}`;\n\t}\n\n\tprivate getScopeHintText(): string {\n\t\treturn keyHint(\"tui.input.tab\", \"scope\") + theme.fg(\"muted\", \" (all/scoped)\");\n\t}\n\n\tprivate setScope(scope: ModelScope): void {\n\t\tif (this.scope === scope) return;\n\t\tthis.scope = scope;\n\t\tthis.activeModels = this.scope === \"scoped\" ? this.scopedModelItems : this.allModels;\n\t\tconst currentIndex = this.activeModels.findIndex((item) => modelsAreEqual(this.currentModel, item.model));\n\t\tthis.selectedIndex = currentIndex >= 0 ? currentIndex : 0;\n\t\tthis.filterModels(this.searchInput.getValue());\n\t\tif (this.scopeText) {\n\t\t\tthis.scopeText.setText(this.getScopeText());\n\t\t}\n\t}\n\n\tprivate filterModels(query: string): void {\n\t\tthis.filteredModels = query\n\t\t\t? fuzzyFilter(\n\t\t\t\t\tthis.activeModels,\n\t\t\t\t\tquery,\n\t\t\t\t\t({ id, provider }) => `${id} ${provider} ${provider}/${id} ${provider} ${id}`,\n\t\t\t\t)\n\t\t\t: this.activeModels;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));\n\t\tthis.updateList();\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tconst maxVisible = 10;\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(maxVisible / 2), this.filteredModels.length - maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredModels.length);\n\n\t\t// Show visible slice of filtered models\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = this.filteredModels[i];\n\t\t\tif (!item) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst isCurrent = modelsAreEqual(this.currentModel, item.model);\n\n\t\t\tlet line = \"\";\n\t\t\tif (isSelected) {\n\t\t\t\tconst prefix = theme.fg(\"accent\", \"→ \");\n\t\t\t\tconst modelText = `${item.id}`;\n\t\t\t\tconst providerBadge = theme.fg(\"muted\", `[${item.provider}]`);\n\t\t\t\tconst checkmark = isCurrent ? theme.fg(\"success\", \" ✓\") : \"\";\n\t\t\t\tline = `${prefix + theme.fg(\"accent\", modelText)} ${providerBadge}${checkmark}`;\n\t\t\t} else {\n\t\t\t\tconst modelText = ` ${item.id}`;\n\t\t\t\tconst providerBadge = theme.fg(\"muted\", `[${item.provider}]`);\n\t\t\t\tconst checkmark = isCurrent ? theme.fg(\"success\", \" ✓\") : \"\";\n\t\t\t\tline = `${modelText} ${providerBadge}${checkmark}`;\n\t\t\t}\n\n\t\t\tthis.listContainer.addChild(new Text(line, 0, 0));\n\t\t}\n\n\t\t// Add scroll indicator if needed\n\t\tif (startIndex > 0 || endIndex < this.filteredModels.length) {\n\t\t\tconst scrollInfo = theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredModels.length})`);\n\t\t\tthis.listContainer.addChild(new Text(scrollInfo, 0, 0));\n\t\t}\n\n\t\t// Show error message or \"no results\" if empty\n\t\tif (this.errorMessage) {\n\t\t\t// Show error in red\n\t\t\tconst errorLines = this.errorMessage.split(\"\\n\");\n\t\t\tfor (const line of errorLines) {\n\t\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"error\", line), 0, 0));\n\t\t\t}\n\t\t} else if (this.filteredModels.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No matching models\"), 0, 0));\n\t\t} else {\n\t\t\tconst selected = this.filteredModels[this.selectedIndex];\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", ` Model Name: ${selected.model.name}`), 0, 0));\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (kb.matches(keyData, \"tui.input.tab\")) {\n\t\t\tif (this.scopedModelItems.length > 0) {\n\t\t\t\tconst nextScope: ModelScope = this.scope === \"all\" ? \"scoped\" : \"all\";\n\t\t\t\tthis.setScope(nextScope);\n\t\t\t\tif (this.scopeHintText) {\n\t\t\t\t\tthis.scopeHintText.setText(this.getScopeHintText());\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\t// Up arrow - wrap to bottom when at top\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.filteredModels.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.filteredModels.length - 1 : this.selectedIndex - 1;\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Down arrow - wrap to top when at bottom\n\t\telse if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.filteredModels.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.filteredModels.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Enter\n\t\telse if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tconst selectedModel = this.filteredModels[this.selectedIndex];\n\t\t\tif (selectedModel) {\n\t\t\t\tthis.handleSelect(selectedModel.model);\n\t\t\t}\n\t\t}\n\t\t// Escape or Ctrl+C\n\t\telse if (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t}\n\t\t// Pass everything else to search input\n\t\telse {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filterModels(this.searchInput.getValue());\n\t\t}\n\t}\n\n\tprivate handleSelect(model: Model<any>): void {\n\t\t// Save as new default\n\t\tthis.settingsManager.setDefaultModelAndProvider(model.provider, model.id);\n\t\tthis.onSelectCallback(model);\n\t}\n\n\tgetSearchInput(): Input {\n\t\treturn this.searchInput;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"model-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/model-selector.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACN,eAAe,EACf,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,iBAAiB,EACjB,iBAAiB,IAAI,sBAAsB,EAC3C,KAAK,WAAW,GAChB,MAAM,gBAAgB,CAAC","sourcesContent":["/**\n * Back-compat re-export. Prefer importing ModelHubComponent from model-hub.ts.\n */\nexport {\n\tbuildSelectRows,\n\tformatTokenCount,\n\ttype ModelHubCallbacks,\n\tModelHubComponent,\n\tModelHubComponent as ModelSelectorComponent,\n\ttype ModelHubTab,\n} from \"./model-hub.ts\";\n"]}
|
|
@@ -1,278 +1,5 @@
|
|
|
1
|
-
import { modelsAreEqual } from "@openeryc/pi-ai";
|
|
2
|
-
import { Container, fuzzyFilter, getKeybindings, Input, Spacer, Text, } from "@openeryc/pi-tui";
|
|
3
|
-
import { theme } from "../theme/theme.js";
|
|
4
|
-
import { DynamicBorder } from "./dynamic-border.js";
|
|
5
|
-
import { keyHint } from "./keybinding-hints.js";
|
|
6
1
|
/**
|
|
7
|
-
*
|
|
2
|
+
* Back-compat re-export. Prefer importing ModelHubComponent from model-hub.ts.
|
|
8
3
|
*/
|
|
9
|
-
export
|
|
10
|
-
searchInput;
|
|
11
|
-
// Focusable implementation - propagate to searchInput for IME cursor positioning
|
|
12
|
-
_focused = false;
|
|
13
|
-
get focused() {
|
|
14
|
-
return this._focused;
|
|
15
|
-
}
|
|
16
|
-
set focused(value) {
|
|
17
|
-
this._focused = value;
|
|
18
|
-
this.searchInput.focused = value;
|
|
19
|
-
}
|
|
20
|
-
listContainer;
|
|
21
|
-
allModels = [];
|
|
22
|
-
scopedModelItems = [];
|
|
23
|
-
activeModels = [];
|
|
24
|
-
filteredModels = [];
|
|
25
|
-
selectedIndex = 0;
|
|
26
|
-
currentModel;
|
|
27
|
-
settingsManager;
|
|
28
|
-
modelRegistry;
|
|
29
|
-
onSelectCallback;
|
|
30
|
-
onCancelCallback;
|
|
31
|
-
errorMessage;
|
|
32
|
-
tui;
|
|
33
|
-
scopedModels;
|
|
34
|
-
scope = "all";
|
|
35
|
-
scopeText;
|
|
36
|
-
scopeHintText;
|
|
37
|
-
constructor(tui, currentModel, settingsManager, modelRegistry, scopedModels, onSelect, onCancel, initialSearchInput) {
|
|
38
|
-
super();
|
|
39
|
-
this.tui = tui;
|
|
40
|
-
this.currentModel = currentModel;
|
|
41
|
-
this.settingsManager = settingsManager;
|
|
42
|
-
this.modelRegistry = modelRegistry;
|
|
43
|
-
this.scopedModels = scopedModels;
|
|
44
|
-
this.scope = scopedModels.length > 0 ? "scoped" : "all";
|
|
45
|
-
this.onSelectCallback = onSelect;
|
|
46
|
-
this.onCancelCallback = onCancel;
|
|
47
|
-
// Add top border
|
|
48
|
-
this.addChild(new DynamicBorder());
|
|
49
|
-
this.addChild(new Spacer(1));
|
|
50
|
-
// Add hint about model filtering
|
|
51
|
-
if (scopedModels.length > 0) {
|
|
52
|
-
this.scopeText = new Text(this.getScopeText(), 0, 0);
|
|
53
|
-
this.addChild(this.scopeText);
|
|
54
|
-
this.scopeHintText = new Text(this.getScopeHintText(), 0, 0);
|
|
55
|
-
this.addChild(this.scopeHintText);
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
const hintText = "Only showing models from configured providers. Use /login to add providers.";
|
|
59
|
-
this.addChild(new Text(theme.fg("warning", hintText), 0, 0));
|
|
60
|
-
}
|
|
61
|
-
this.addChild(new Spacer(1));
|
|
62
|
-
// Create search input
|
|
63
|
-
this.searchInput = new Input();
|
|
64
|
-
if (initialSearchInput) {
|
|
65
|
-
this.searchInput.setValue(initialSearchInput);
|
|
66
|
-
}
|
|
67
|
-
this.searchInput.onSubmit = () => {
|
|
68
|
-
// Enter on search input selects the first filtered item
|
|
69
|
-
if (this.filteredModels[this.selectedIndex]) {
|
|
70
|
-
this.handleSelect(this.filteredModels[this.selectedIndex].model);
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
this.addChild(this.searchInput);
|
|
74
|
-
this.addChild(new Spacer(1));
|
|
75
|
-
// Create list container
|
|
76
|
-
this.listContainer = new Container();
|
|
77
|
-
this.addChild(this.listContainer);
|
|
78
|
-
this.addChild(new Spacer(1));
|
|
79
|
-
// Add bottom border
|
|
80
|
-
this.addChild(new DynamicBorder());
|
|
81
|
-
// Load models and do initial render
|
|
82
|
-
this.loadModels().then(() => {
|
|
83
|
-
if (initialSearchInput) {
|
|
84
|
-
this.filterModels(initialSearchInput);
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
this.updateList();
|
|
88
|
-
}
|
|
89
|
-
// Request re-render after models are loaded
|
|
90
|
-
this.tui.requestRender();
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
async loadModels() {
|
|
94
|
-
let models;
|
|
95
|
-
// Refresh to pick up any changes to models.json
|
|
96
|
-
this.modelRegistry.refresh();
|
|
97
|
-
// Check for models.json errors
|
|
98
|
-
const loadError = this.modelRegistry.getError();
|
|
99
|
-
if (loadError) {
|
|
100
|
-
this.errorMessage = loadError;
|
|
101
|
-
}
|
|
102
|
-
// Load available models (built-in models still work even if models.json failed)
|
|
103
|
-
try {
|
|
104
|
-
const availableModels = await this.modelRegistry.getAvailable();
|
|
105
|
-
models = availableModels.map((model) => ({
|
|
106
|
-
provider: model.provider,
|
|
107
|
-
id: model.id,
|
|
108
|
-
model,
|
|
109
|
-
}));
|
|
110
|
-
}
|
|
111
|
-
catch (error) {
|
|
112
|
-
this.allModels = [];
|
|
113
|
-
this.scopedModelItems = [];
|
|
114
|
-
this.activeModels = [];
|
|
115
|
-
this.filteredModels = [];
|
|
116
|
-
this.errorMessage = error instanceof Error ? error.message : String(error);
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
this.allModels = this.sortModels(models);
|
|
120
|
-
this.scopedModels = this.scopedModels.map((scoped) => {
|
|
121
|
-
const refreshed = this.modelRegistry.find(scoped.model.provider, scoped.model.id);
|
|
122
|
-
return refreshed ? { ...scoped, model: refreshed } : scoped;
|
|
123
|
-
});
|
|
124
|
-
this.scopedModelItems = this.scopedModels.map((scoped) => ({
|
|
125
|
-
provider: scoped.model.provider,
|
|
126
|
-
id: scoped.model.id,
|
|
127
|
-
model: scoped.model,
|
|
128
|
-
}));
|
|
129
|
-
this.activeModels = this.scope === "scoped" ? this.scopedModelItems : this.allModels;
|
|
130
|
-
this.filteredModels = this.activeModels;
|
|
131
|
-
const currentIndex = this.filteredModels.findIndex((item) => modelsAreEqual(this.currentModel, item.model));
|
|
132
|
-
this.selectedIndex =
|
|
133
|
-
currentIndex >= 0 ? currentIndex : Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));
|
|
134
|
-
}
|
|
135
|
-
sortModels(models) {
|
|
136
|
-
const sorted = [...models];
|
|
137
|
-
// Sort: current model first, then by provider
|
|
138
|
-
sorted.sort((a, b) => {
|
|
139
|
-
const aIsCurrent = modelsAreEqual(this.currentModel, a.model);
|
|
140
|
-
const bIsCurrent = modelsAreEqual(this.currentModel, b.model);
|
|
141
|
-
if (aIsCurrent && !bIsCurrent)
|
|
142
|
-
return -1;
|
|
143
|
-
if (!aIsCurrent && bIsCurrent)
|
|
144
|
-
return 1;
|
|
145
|
-
return a.provider.localeCompare(b.provider);
|
|
146
|
-
});
|
|
147
|
-
return sorted;
|
|
148
|
-
}
|
|
149
|
-
getScopeText() {
|
|
150
|
-
const allText = this.scope === "all" ? theme.fg("accent", "all") : theme.fg("muted", "all");
|
|
151
|
-
const scopedText = this.scope === "scoped" ? theme.fg("accent", "scoped") : theme.fg("muted", "scoped");
|
|
152
|
-
return `${theme.fg("muted", "Scope: ")}${allText}${theme.fg("muted", " | ")}${scopedText}`;
|
|
153
|
-
}
|
|
154
|
-
getScopeHintText() {
|
|
155
|
-
return keyHint("tui.input.tab", "scope") + theme.fg("muted", " (all/scoped)");
|
|
156
|
-
}
|
|
157
|
-
setScope(scope) {
|
|
158
|
-
if (this.scope === scope)
|
|
159
|
-
return;
|
|
160
|
-
this.scope = scope;
|
|
161
|
-
this.activeModels = this.scope === "scoped" ? this.scopedModelItems : this.allModels;
|
|
162
|
-
const currentIndex = this.activeModels.findIndex((item) => modelsAreEqual(this.currentModel, item.model));
|
|
163
|
-
this.selectedIndex = currentIndex >= 0 ? currentIndex : 0;
|
|
164
|
-
this.filterModels(this.searchInput.getValue());
|
|
165
|
-
if (this.scopeText) {
|
|
166
|
-
this.scopeText.setText(this.getScopeText());
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
filterModels(query) {
|
|
170
|
-
this.filteredModels = query
|
|
171
|
-
? fuzzyFilter(this.activeModels, query, ({ id, provider }) => `${id} ${provider} ${provider}/${id} ${provider} ${id}`)
|
|
172
|
-
: this.activeModels;
|
|
173
|
-
this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));
|
|
174
|
-
this.updateList();
|
|
175
|
-
}
|
|
176
|
-
updateList() {
|
|
177
|
-
this.listContainer.clear();
|
|
178
|
-
const maxVisible = 10;
|
|
179
|
-
const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(maxVisible / 2), this.filteredModels.length - maxVisible));
|
|
180
|
-
const endIndex = Math.min(startIndex + maxVisible, this.filteredModels.length);
|
|
181
|
-
// Show visible slice of filtered models
|
|
182
|
-
for (let i = startIndex; i < endIndex; i++) {
|
|
183
|
-
const item = this.filteredModels[i];
|
|
184
|
-
if (!item)
|
|
185
|
-
continue;
|
|
186
|
-
const isSelected = i === this.selectedIndex;
|
|
187
|
-
const isCurrent = modelsAreEqual(this.currentModel, item.model);
|
|
188
|
-
let line = "";
|
|
189
|
-
if (isSelected) {
|
|
190
|
-
const prefix = theme.fg("accent", "→ ");
|
|
191
|
-
const modelText = `${item.id}`;
|
|
192
|
-
const providerBadge = theme.fg("muted", `[${item.provider}]`);
|
|
193
|
-
const checkmark = isCurrent ? theme.fg("success", " ✓") : "";
|
|
194
|
-
line = `${prefix + theme.fg("accent", modelText)} ${providerBadge}${checkmark}`;
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
const modelText = ` ${item.id}`;
|
|
198
|
-
const providerBadge = theme.fg("muted", `[${item.provider}]`);
|
|
199
|
-
const checkmark = isCurrent ? theme.fg("success", " ✓") : "";
|
|
200
|
-
line = `${modelText} ${providerBadge}${checkmark}`;
|
|
201
|
-
}
|
|
202
|
-
this.listContainer.addChild(new Text(line, 0, 0));
|
|
203
|
-
}
|
|
204
|
-
// Add scroll indicator if needed
|
|
205
|
-
if (startIndex > 0 || endIndex < this.filteredModels.length) {
|
|
206
|
-
const scrollInfo = theme.fg("muted", ` (${this.selectedIndex + 1}/${this.filteredModels.length})`);
|
|
207
|
-
this.listContainer.addChild(new Text(scrollInfo, 0, 0));
|
|
208
|
-
}
|
|
209
|
-
// Show error message or "no results" if empty
|
|
210
|
-
if (this.errorMessage) {
|
|
211
|
-
// Show error in red
|
|
212
|
-
const errorLines = this.errorMessage.split("\n");
|
|
213
|
-
for (const line of errorLines) {
|
|
214
|
-
this.listContainer.addChild(new Text(theme.fg("error", line), 0, 0));
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
else if (this.filteredModels.length === 0) {
|
|
218
|
-
this.listContainer.addChild(new Text(theme.fg("muted", " No matching models"), 0, 0));
|
|
219
|
-
}
|
|
220
|
-
else {
|
|
221
|
-
const selected = this.filteredModels[this.selectedIndex];
|
|
222
|
-
this.listContainer.addChild(new Spacer(1));
|
|
223
|
-
this.listContainer.addChild(new Text(theme.fg("muted", ` Model Name: ${selected.model.name}`), 0, 0));
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
handleInput(keyData) {
|
|
227
|
-
const kb = getKeybindings();
|
|
228
|
-
if (kb.matches(keyData, "tui.input.tab")) {
|
|
229
|
-
if (this.scopedModelItems.length > 0) {
|
|
230
|
-
const nextScope = this.scope === "all" ? "scoped" : "all";
|
|
231
|
-
this.setScope(nextScope);
|
|
232
|
-
if (this.scopeHintText) {
|
|
233
|
-
this.scopeHintText.setText(this.getScopeHintText());
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
// Up arrow - wrap to bottom when at top
|
|
239
|
-
if (kb.matches(keyData, "tui.select.up")) {
|
|
240
|
-
if (this.filteredModels.length === 0)
|
|
241
|
-
return;
|
|
242
|
-
this.selectedIndex = this.selectedIndex === 0 ? this.filteredModels.length - 1 : this.selectedIndex - 1;
|
|
243
|
-
this.updateList();
|
|
244
|
-
}
|
|
245
|
-
// Down arrow - wrap to top when at bottom
|
|
246
|
-
else if (kb.matches(keyData, "tui.select.down")) {
|
|
247
|
-
if (this.filteredModels.length === 0)
|
|
248
|
-
return;
|
|
249
|
-
this.selectedIndex = this.selectedIndex === this.filteredModels.length - 1 ? 0 : this.selectedIndex + 1;
|
|
250
|
-
this.updateList();
|
|
251
|
-
}
|
|
252
|
-
// Enter
|
|
253
|
-
else if (kb.matches(keyData, "tui.select.confirm")) {
|
|
254
|
-
const selectedModel = this.filteredModels[this.selectedIndex];
|
|
255
|
-
if (selectedModel) {
|
|
256
|
-
this.handleSelect(selectedModel.model);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
// Escape or Ctrl+C
|
|
260
|
-
else if (kb.matches(keyData, "tui.select.cancel")) {
|
|
261
|
-
this.onCancelCallback();
|
|
262
|
-
}
|
|
263
|
-
// Pass everything else to search input
|
|
264
|
-
else {
|
|
265
|
-
this.searchInput.handleInput(keyData);
|
|
266
|
-
this.filterModels(this.searchInput.getValue());
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
handleSelect(model) {
|
|
270
|
-
// Save as new default
|
|
271
|
-
this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
|
|
272
|
-
this.onSelectCallback(model);
|
|
273
|
-
}
|
|
274
|
-
getSearchInput() {
|
|
275
|
-
return this.searchInput;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
4
|
+
export { buildSelectRows, formatTokenCount, ModelHubComponent, ModelHubComponent as ModelSelectorComponent, } from "./model-hub.js";
|
|
278
5
|
//# sourceMappingURL=model-selector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/model-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EACN,SAAS,EAET,WAAW,EACX,cAAc,EACd,KAAK,EACL,MAAM,EACN,IAAI,GAEJ,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAehD;;GAEG;AACH,MAAM,OAAO,sBAAuB,SAAQ,SAAS;IAC5C,WAAW,CAAQ;IAE3B,iFAAiF;IACzE,QAAQ,GAAG,KAAK,CAAC;IACzB,IAAI,OAAO,GAAY;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC;IAAA,CACrB;IACD,IAAI,OAAO,CAAC,KAAc,EAAE;QAC3B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,WAAW,CAAC,OAAO,GAAG,KAAK,CAAC;IAAA,CACjC;IACO,aAAa,CAAY;IACzB,SAAS,GAAgB,EAAE,CAAC;IAC5B,gBAAgB,GAAgB,EAAE,CAAC;IACnC,YAAY,GAAgB,EAAE,CAAC;IAC/B,cAAc,GAAgB,EAAE,CAAC;IACjC,aAAa,GAAW,CAAC,CAAC;IAC1B,YAAY,CAAc;IAC1B,eAAe,CAAkB;IACjC,aAAa,CAAgB;IAC7B,gBAAgB,CAA8B;IAC9C,gBAAgB,CAAa;IAC7B,YAAY,CAAU;IACtB,GAAG,CAAM;IACT,YAAY,CAAiC;IAC7C,KAAK,GAAe,KAAK,CAAC;IAC1B,SAAS,CAAQ;IACjB,aAAa,CAAQ;IAE7B,YACC,GAAQ,EACR,YAAoC,EACpC,eAAgC,EAChC,aAA4B,EAC5B,YAA4C,EAC5C,QAAqC,EACrC,QAAoB,EACpB,kBAA2B,EAC1B;QACD,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;QACxD,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC;QACjC,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC;QAEjC,iBAAiB;QACjB,IAAI,CAAC,QAAQ,CAAC,IAAI,aAAa,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7B,iCAAiC;QACjC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACrD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9B,IAAI,CAAC,aAAa,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC7D,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACP,MAAM,QAAQ,GAAG,6EAA6E,CAAC;YAC/F,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7B,sBAAsB;QACtB,IAAI,CAAC,WAAW,GAAG,IAAI,KAAK,EAAE,CAAC;QAC/B,IAAI,kBAAkB,EAAE,CAAC;YACxB,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG,GAAG,EAAE,CAAC;YACjC,wDAAwD;YACxD,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC7C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,CAAC;YAClE,CAAC;QAAA,CACD,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAEhC,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7B,wBAAwB;QACxB,IAAI,CAAC,aAAa,GAAG,IAAI,SAAS,EAAE,CAAC;QACrC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAElC,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7B,oBAAoB;QACpB,IAAI,CAAC,QAAQ,CAAC,IAAI,aAAa,EAAE,CAAC,CAAC;QAEnC,oCAAoC;QACpC,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YAC5B,IAAI,kBAAkB,EAAE,CAAC;gBACxB,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC;YACvC,CAAC;iBAAM,CAAC;gBACP,IAAI,CAAC,UAAU,EAAE,CAAC;YACnB,CAAC;YACD,4CAA4C;YAC5C,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAAA,CACzB,CAAC,CAAC;IAAA,CACH;IAEO,KAAK,CAAC,UAAU,GAAkB;QACzC,IAAI,MAAmB,CAAC;QAExB,gDAAgD;QAChD,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;QAE7B,+BAA+B;QAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;QAChD,IAAI,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;QAC/B,CAAC;QAED,gFAAgF;QAChF,IAAI,CAAC;YACJ,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;YAChE,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,KAAiB,EAAE,EAAE,CAAC,CAAC;gBACpD,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,KAAK;aACL,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;YAC3B,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;YACvB,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;YACzB,IAAI,CAAC,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3E,OAAO;QACR,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;YACrD,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClF,OAAO,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QAAA,CAC5D,CAAC,CAAC;QACH,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC1D,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ;YAC/B,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE;YACnB,KAAK,EAAE,MAAM,CAAC,KAAK;SACnB,CAAC,CAAC,CAAC;QACJ,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;QACrF,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,YAAY,CAAC;QACxC,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5G,IAAI,CAAC,aAAa;YACjB,YAAY,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAAA,CAC9G;IAEO,UAAU,CAAC,MAAmB,EAAe;QACpD,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;QAC3B,8CAA8C;QAC9C,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACrB,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YAC9D,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YAC9D,IAAI,UAAU,IAAI,CAAC,UAAU;gBAAE,OAAO,CAAC,CAAC,CAAC;YACzC,IAAI,CAAC,UAAU,IAAI,UAAU;gBAAE,OAAO,CAAC,CAAC;YACxC,OAAO,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAAA,CAC5C,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAAA,CACd;IAEO,YAAY,GAAW;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC5F,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACxG,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,UAAU,EAAE,CAAC;IAAA,CAC3F;IAEO,gBAAgB,GAAW;QAClC,OAAO,OAAO,CAAC,eAAe,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAAA,CAC9E;IAEO,QAAQ,CAAC,KAAiB,EAAQ;QACzC,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK;YAAE,OAAO;QACjC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;QACrF,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1G,IAAI,CAAC,aAAa,GAAG,YAAY,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/C,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QAC7C,CAAC;IAAA,CACD;IAEO,YAAY,CAAC,KAAa,EAAQ;QACzC,IAAI,CAAC,cAAc,GAAG,KAAK;YAC1B,CAAC,CAAC,WAAW,CACX,IAAI,CAAC,YAAY,EACjB,KAAK,EACL,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,IAAI,QAAQ,IAAI,QAAQ,IAAI,EAAE,IAAI,QAAQ,IAAI,EAAE,EAAE,CAC7E;YACF,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC;QACrB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QAC/F,IAAI,CAAC,UAAU,EAAE,CAAC;IAAA,CAClB;IAEO,UAAU,GAAS;QAC1B,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAE3B,MAAM,UAAU,GAAG,EAAE,CAAC;QACtB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAC1B,CAAC,EACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,UAAU,CAAC,CAClG,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,UAAU,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAE/E,wCAAwC;QACxC,KAAK,IAAI,CAAC,GAAG,UAAU,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI;gBAAE,SAAS;YAEpB,MAAM,UAAU,GAAG,CAAC,KAAK,IAAI,CAAC,aAAa,CAAC;YAC5C,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YAEhE,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,IAAI,UAAU,EAAE,CAAC;gBAChB,MAAM,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAI,CAAC,CAAC;gBACxC,MAAM,SAAS,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;gBAC/B,MAAM,aAAa,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;gBAC9D,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,MAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7D,IAAI,GAAG,GAAG,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,aAAa,GAAG,SAAS,EAAE,CAAC;YACjF,CAAC;iBAAM,CAAC;gBACP,MAAM,SAAS,GAAG,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC;gBACjC,MAAM,aAAa,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;gBAC9D,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,MAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7D,IAAI,GAAG,GAAG,SAAS,IAAI,aAAa,GAAG,SAAS,EAAE,CAAC;YACpD,CAAC;YAED,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC;QAED,iCAAiC;QACjC,IAAI,UAAU,GAAG,CAAC,IAAI,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC;YAC7D,MAAM,UAAU,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;YACpG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;QAED,8CAA8C;QAC9C,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,oBAAoB;YACpB,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjD,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;gBAC/B,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACtE,CAAC;QACF,CAAC;aAAM,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,sBAAsB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACxF,CAAC;aAAM,CAAC;YACP,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACzD,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACxG,CAAC;IAAA,CACD;IAED,WAAW,CAAC,OAAe,EAAQ;QAClC,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;QAC5B,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,EAAE,CAAC;YAC1C,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtC,MAAM,SAAS,GAAe,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;gBACtE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACzB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;oBACxB,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;gBACrD,CAAC;YACF,CAAC;YACD,OAAO;QACR,CAAC;QACD,wCAAwC;QACxC,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,EAAE,CAAC;YAC1C,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAC7C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;YACxG,IAAI,CAAC,UAAU,EAAE,CAAC;QACnB,CAAC;QACD,0CAA0C;aACrC,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,iBAAiB,CAAC,EAAE,CAAC;YACjD,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAC7C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,KAAK,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;YACxG,IAAI,CAAC,UAAU,EAAE,CAAC;QACnB,CAAC;QACD,QAAQ;aACH,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,oBAAoB,CAAC,EAAE,CAAC;YACpD,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC9D,IAAI,aAAa,EAAE,CAAC;gBACnB,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YACxC,CAAC;QACF,CAAC;QACD,mBAAmB;aACd,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,mBAAmB,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACzB,CAAC;QACD,uCAAuC;aAClC,CAAC;YACL,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YACtC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;QAChD,CAAC;IAAA,CACD;IAEO,YAAY,CAAC,KAAiB,EAAQ;QAC7C,sBAAsB;QACtB,IAAI,CAAC,eAAe,CAAC,0BAA0B,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAAA,CAC7B;IAED,cAAc,GAAU;QACvB,OAAO,IAAI,CAAC,WAAW,CAAC;IAAA,CACxB;CACD","sourcesContent":["import { type Model, modelsAreEqual } from \"@openeryc/pi-ai\";\nimport {\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tInput,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@openeryc/pi-tui\";\nimport type { ModelRegistry } from \"../../../core/model-registry.ts\";\nimport type { SettingsManager } from \"../../../core/settings-manager.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyHint } from \"./keybinding-hints.ts\";\n\ninterface ModelItem {\n\tprovider: string;\n\tid: string;\n\tmodel: Model<any>;\n}\n\ninterface ScopedModelItem {\n\tmodel: Model<any>;\n\tthinkingLevel?: string;\n}\n\ntype ModelScope = \"all\" | \"scoped\";\n\n/**\n * Component that renders a model selector with search\n */\nexport class ModelSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: Input;\n\n\t// Focusable implementation - propagate to searchInput for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\tprivate listContainer: Container;\n\tprivate allModels: ModelItem[] = [];\n\tprivate scopedModelItems: ModelItem[] = [];\n\tprivate activeModels: ModelItem[] = [];\n\tprivate filteredModels: ModelItem[] = [];\n\tprivate selectedIndex: number = 0;\n\tprivate currentModel?: Model<any>;\n\tprivate settingsManager: SettingsManager;\n\tprivate modelRegistry: ModelRegistry;\n\tprivate onSelectCallback: (model: Model<any>) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate errorMessage?: string;\n\tprivate tui: TUI;\n\tprivate scopedModels: ReadonlyArray<ScopedModelItem>;\n\tprivate scope: ModelScope = \"all\";\n\tprivate scopeText?: Text;\n\tprivate scopeHintText?: Text;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tcurrentModel: Model<any> | undefined,\n\t\tsettingsManager: SettingsManager,\n\t\tmodelRegistry: ModelRegistry,\n\t\tscopedModels: ReadonlyArray<ScopedModelItem>,\n\t\tonSelect: (model: Model<any>) => void,\n\t\tonCancel: () => void,\n\t\tinitialSearchInput?: string,\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.currentModel = currentModel;\n\t\tthis.settingsManager = settingsManager;\n\t\tthis.modelRegistry = modelRegistry;\n\t\tthis.scopedModels = scopedModels;\n\t\tthis.scope = scopedModels.length > 0 ? \"scoped\" : \"all\";\n\t\tthis.onSelectCallback = onSelect;\n\t\tthis.onCancelCallback = onCancel;\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add hint about model filtering\n\t\tif (scopedModels.length > 0) {\n\t\t\tthis.scopeText = new Text(this.getScopeText(), 0, 0);\n\t\t\tthis.addChild(this.scopeText);\n\t\t\tthis.scopeHintText = new Text(this.getScopeHintText(), 0, 0);\n\t\t\tthis.addChild(this.scopeHintText);\n\t\t} else {\n\t\t\tconst hintText = \"Only showing models from configured providers. Use /login to add providers.\";\n\t\t\tthis.addChild(new Text(theme.fg(\"warning\", hintText), 0, 0));\n\t\t}\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create search input\n\t\tthis.searchInput = new Input();\n\t\tif (initialSearchInput) {\n\t\t\tthis.searchInput.setValue(initialSearchInput);\n\t\t}\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\t// Enter on search input selects the first filtered item\n\t\t\tif (this.filteredModels[this.selectedIndex]) {\n\t\t\t\tthis.handleSelect(this.filteredModels[this.selectedIndex].model);\n\t\t\t}\n\t\t};\n\t\tthis.addChild(this.searchInput);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create list container\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Load models and do initial render\n\t\tthis.loadModels().then(() => {\n\t\t\tif (initialSearchInput) {\n\t\t\t\tthis.filterModels(initialSearchInput);\n\t\t\t} else {\n\t\t\t\tthis.updateList();\n\t\t\t}\n\t\t\t// Request re-render after models are loaded\n\t\t\tthis.tui.requestRender();\n\t\t});\n\t}\n\n\tprivate async loadModels(): Promise<void> {\n\t\tlet models: ModelItem[];\n\n\t\t// Refresh to pick up any changes to models.json\n\t\tthis.modelRegistry.refresh();\n\n\t\t// Check for models.json errors\n\t\tconst loadError = this.modelRegistry.getError();\n\t\tif (loadError) {\n\t\t\tthis.errorMessage = loadError;\n\t\t}\n\n\t\t// Load available models (built-in models still work even if models.json failed)\n\t\ttry {\n\t\t\tconst availableModels = await this.modelRegistry.getAvailable();\n\t\t\tmodels = availableModels.map((model: Model<any>) => ({\n\t\t\t\tprovider: model.provider,\n\t\t\t\tid: model.id,\n\t\t\t\tmodel,\n\t\t\t}));\n\t\t} catch (error) {\n\t\t\tthis.allModels = [];\n\t\t\tthis.scopedModelItems = [];\n\t\t\tthis.activeModels = [];\n\t\t\tthis.filteredModels = [];\n\t\t\tthis.errorMessage = error instanceof Error ? error.message : String(error);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.allModels = this.sortModels(models);\n\t\tthis.scopedModels = this.scopedModels.map((scoped) => {\n\t\t\tconst refreshed = this.modelRegistry.find(scoped.model.provider, scoped.model.id);\n\t\t\treturn refreshed ? { ...scoped, model: refreshed } : scoped;\n\t\t});\n\t\tthis.scopedModelItems = this.scopedModels.map((scoped) => ({\n\t\t\tprovider: scoped.model.provider,\n\t\t\tid: scoped.model.id,\n\t\t\tmodel: scoped.model,\n\t\t}));\n\t\tthis.activeModels = this.scope === \"scoped\" ? this.scopedModelItems : this.allModels;\n\t\tthis.filteredModels = this.activeModels;\n\t\tconst currentIndex = this.filteredModels.findIndex((item) => modelsAreEqual(this.currentModel, item.model));\n\t\tthis.selectedIndex =\n\t\t\tcurrentIndex >= 0 ? currentIndex : Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));\n\t}\n\n\tprivate sortModels(models: ModelItem[]): ModelItem[] {\n\t\tconst sorted = [...models];\n\t\t// Sort: current model first, then by provider\n\t\tsorted.sort((a, b) => {\n\t\t\tconst aIsCurrent = modelsAreEqual(this.currentModel, a.model);\n\t\t\tconst bIsCurrent = modelsAreEqual(this.currentModel, b.model);\n\t\t\tif (aIsCurrent && !bIsCurrent) return -1;\n\t\t\tif (!aIsCurrent && bIsCurrent) return 1;\n\t\t\treturn a.provider.localeCompare(b.provider);\n\t\t});\n\t\treturn sorted;\n\t}\n\n\tprivate getScopeText(): string {\n\t\tconst allText = this.scope === \"all\" ? theme.fg(\"accent\", \"all\") : theme.fg(\"muted\", \"all\");\n\t\tconst scopedText = this.scope === \"scoped\" ? theme.fg(\"accent\", \"scoped\") : theme.fg(\"muted\", \"scoped\");\n\t\treturn `${theme.fg(\"muted\", \"Scope: \")}${allText}${theme.fg(\"muted\", \" | \")}${scopedText}`;\n\t}\n\n\tprivate getScopeHintText(): string {\n\t\treturn keyHint(\"tui.input.tab\", \"scope\") + theme.fg(\"muted\", \" (all/scoped)\");\n\t}\n\n\tprivate setScope(scope: ModelScope): void {\n\t\tif (this.scope === scope) return;\n\t\tthis.scope = scope;\n\t\tthis.activeModels = this.scope === \"scoped\" ? this.scopedModelItems : this.allModels;\n\t\tconst currentIndex = this.activeModels.findIndex((item) => modelsAreEqual(this.currentModel, item.model));\n\t\tthis.selectedIndex = currentIndex >= 0 ? currentIndex : 0;\n\t\tthis.filterModels(this.searchInput.getValue());\n\t\tif (this.scopeText) {\n\t\t\tthis.scopeText.setText(this.getScopeText());\n\t\t}\n\t}\n\n\tprivate filterModels(query: string): void {\n\t\tthis.filteredModels = query\n\t\t\t? fuzzyFilter(\n\t\t\t\t\tthis.activeModels,\n\t\t\t\t\tquery,\n\t\t\t\t\t({ id, provider }) => `${id} ${provider} ${provider}/${id} ${provider} ${id}`,\n\t\t\t\t)\n\t\t\t: this.activeModels;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));\n\t\tthis.updateList();\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tconst maxVisible = 10;\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(maxVisible / 2), this.filteredModels.length - maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredModels.length);\n\n\t\t// Show visible slice of filtered models\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = this.filteredModels[i];\n\t\t\tif (!item) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst isCurrent = modelsAreEqual(this.currentModel, item.model);\n\n\t\t\tlet line = \"\";\n\t\t\tif (isSelected) {\n\t\t\t\tconst prefix = theme.fg(\"accent\", \"→ \");\n\t\t\t\tconst modelText = `${item.id}`;\n\t\t\t\tconst providerBadge = theme.fg(\"muted\", `[${item.provider}]`);\n\t\t\t\tconst checkmark = isCurrent ? theme.fg(\"success\", \" ✓\") : \"\";\n\t\t\t\tline = `${prefix + theme.fg(\"accent\", modelText)} ${providerBadge}${checkmark}`;\n\t\t\t} else {\n\t\t\t\tconst modelText = ` ${item.id}`;\n\t\t\t\tconst providerBadge = theme.fg(\"muted\", `[${item.provider}]`);\n\t\t\t\tconst checkmark = isCurrent ? theme.fg(\"success\", \" ✓\") : \"\";\n\t\t\t\tline = `${modelText} ${providerBadge}${checkmark}`;\n\t\t\t}\n\n\t\t\tthis.listContainer.addChild(new Text(line, 0, 0));\n\t\t}\n\n\t\t// Add scroll indicator if needed\n\t\tif (startIndex > 0 || endIndex < this.filteredModels.length) {\n\t\t\tconst scrollInfo = theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredModels.length})`);\n\t\t\tthis.listContainer.addChild(new Text(scrollInfo, 0, 0));\n\t\t}\n\n\t\t// Show error message or \"no results\" if empty\n\t\tif (this.errorMessage) {\n\t\t\t// Show error in red\n\t\t\tconst errorLines = this.errorMessage.split(\"\\n\");\n\t\t\tfor (const line of errorLines) {\n\t\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"error\", line), 0, 0));\n\t\t\t}\n\t\t} else if (this.filteredModels.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No matching models\"), 0, 0));\n\t\t} else {\n\t\t\tconst selected = this.filteredModels[this.selectedIndex];\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", ` Model Name: ${selected.model.name}`), 0, 0));\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (kb.matches(keyData, \"tui.input.tab\")) {\n\t\t\tif (this.scopedModelItems.length > 0) {\n\t\t\t\tconst nextScope: ModelScope = this.scope === \"all\" ? \"scoped\" : \"all\";\n\t\t\t\tthis.setScope(nextScope);\n\t\t\t\tif (this.scopeHintText) {\n\t\t\t\t\tthis.scopeHintText.setText(this.getScopeHintText());\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\t// Up arrow - wrap to bottom when at top\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.filteredModels.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.filteredModels.length - 1 : this.selectedIndex - 1;\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Down arrow - wrap to top when at bottom\n\t\telse if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.filteredModels.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.filteredModels.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Enter\n\t\telse if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tconst selectedModel = this.filteredModels[this.selectedIndex];\n\t\t\tif (selectedModel) {\n\t\t\t\tthis.handleSelect(selectedModel.model);\n\t\t\t}\n\t\t}\n\t\t// Escape or Ctrl+C\n\t\telse if (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t}\n\t\t// Pass everything else to search input\n\t\telse {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filterModels(this.searchInput.getValue());\n\t\t}\n\t}\n\n\tprivate handleSelect(model: Model<any>): void {\n\t\t// Save as new default\n\t\tthis.settingsManager.setDefaultModelAndProvider(model.provider, model.id);\n\t\tthis.onSelectCallback(model);\n\t}\n\n\tgetSearchInput(): Input {\n\t\treturn this.searchInput;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"model-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/model-selector.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACN,eAAe,EACf,gBAAgB,EAEhB,iBAAiB,EACjB,iBAAiB,IAAI,sBAAsB,GAE3C,MAAM,gBAAgB,CAAC","sourcesContent":["/**\n * Back-compat re-export. Prefer importing ModelHubComponent from model-hub.ts.\n */\nexport {\n\tbuildSelectRows,\n\tformatTokenCount,\n\ttype ModelHubCallbacks,\n\tModelHubComponent,\n\tModelHubComponent as ModelSelectorComponent,\n\ttype ModelHubTab,\n} from \"./model-hub.ts\";\n"]}
|
|
@@ -347,8 +347,9 @@ export declare class InteractiveMode {
|
|
|
347
347
|
private getModelCandidates;
|
|
348
348
|
private updateAvailableProviderCount;
|
|
349
349
|
private maybeWarnAboutAnthropicSubscriptionAuth;
|
|
350
|
-
private
|
|
351
|
-
private
|
|
350
|
+
private resolveEnabledModelIds;
|
|
351
|
+
private applyCycleEnabledIds;
|
|
352
|
+
private showModelHub;
|
|
352
353
|
private showUserMessageSelector;
|
|
353
354
|
private handleCloneCommand;
|
|
354
355
|
private showTreeSelector;
|
|
@@ -363,6 +364,7 @@ export declare class InteractiveMode {
|
|
|
363
364
|
private showBedrockSetupDialog;
|
|
364
365
|
private showApiKeyLoginDialog;
|
|
365
366
|
private showOpenAICompatibleLoginDialog;
|
|
367
|
+
private showCustomProviderWizard;
|
|
366
368
|
private showOAuthLoginSelect;
|
|
367
369
|
private showLoginDialog;
|
|
368
370
|
private handleReloadCommand;
|