gsd-pi 2.25.0 → 2.26.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/README.md +11 -2
- package/dist/headless.js +24 -4
- package/dist/resources/extensions/async-jobs/index.ts +9 -1
- package/dist/resources/extensions/bg-shell/index.ts +3 -2
- package/dist/resources/extensions/gsd/auto-recovery.ts +7 -4
- package/dist/resources/extensions/gsd/auto-worktree.ts +14 -3
- package/dist/resources/extensions/gsd/auto.ts +81 -12
- package/dist/resources/extensions/gsd/doctor-proactive.ts +7 -6
- package/dist/resources/extensions/gsd/doctor.ts +24 -1
- package/dist/resources/extensions/gsd/files.ts +13 -2
- package/dist/resources/extensions/gsd/guided-flow.ts +19 -9
- package/dist/resources/extensions/gsd/index.ts +48 -7
- package/dist/resources/extensions/gsd/migrate/writer.ts +39 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.ts +122 -4
- package/dist/resources/extensions/gsd/preferences.ts +2 -1
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
- package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/dist/resources/extensions/gsd/prompts/queue.md +2 -2
- package/dist/resources/extensions/gsd/roadmap-slices.ts +45 -1
- package/dist/resources/extensions/gsd/state.ts +17 -6
- package/dist/resources/extensions/gsd/tests/derive-state.test.ts +70 -0
- package/dist/resources/extensions/gsd/tests/doctor-proactive.test.ts +23 -3
- package/dist/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +13 -7
- package/dist/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +171 -0
- package/dist/resources/extensions/gsd/tests/validate-milestone.test.ts +8 -4
- package/dist/resources/extensions/gsd/types.ts +2 -0
- package/dist/resources/extensions/search-the-web/native-search.ts +4 -0
- package/dist/resources/extensions/shared/path-display.ts +19 -0
- package/package.json +1 -6
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +25 -0
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/src/providers/anthropic.ts +27 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +32 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/keybindings.js +1 -1
- package/packages/pi-coding-agent/dist/core/keybindings.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +12 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.js +7 -0
- package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +8 -3
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
- package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +2 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +5 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +41 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +301 -62
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +63 -30
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/path-display.test.d.ts +8 -0
- package/packages/pi-coding-agent/dist/tests/path-display.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/path-display.test.js +60 -0
- package/packages/pi-coding-agent/dist/tests/path-display.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/utils/clipboard-image.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/utils/clipboard-image.js +32 -6
- package/packages/pi-coding-agent/dist/utils/clipboard-image.js.map +1 -1
- package/packages/pi-coding-agent/dist/utils/path-display.d.ts +34 -0
- package/packages/pi-coding-agent/dist/utils/path-display.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/utils/path-display.js +36 -0
- package/packages/pi-coding-agent/dist/utils/path-display.js.map +1 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +36 -0
- package/packages/pi-coding-agent/src/core/keybindings.ts +1 -1
- package/packages/pi-coding-agent/src/core/lsp/client.ts +11 -1
- package/packages/pi-coding-agent/src/core/lsp/index.ts +7 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +17 -1
- package/packages/pi-coding-agent/src/core/settings-manager.ts +11 -0
- package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +2 -1
- package/packages/pi-coding-agent/src/index.ts +15 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +347 -62
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +40 -4
- package/packages/pi-coding-agent/src/tests/path-display.test.ts +85 -0
- package/packages/pi-coding-agent/src/utils/clipboard-image.ts +33 -6
- package/packages/pi-coding-agent/src/utils/path-display.ts +36 -0
- package/src/resources/extensions/async-jobs/index.ts +9 -1
- package/src/resources/extensions/bg-shell/index.ts +3 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +7 -4
- package/src/resources/extensions/gsd/auto-worktree.ts +14 -3
- package/src/resources/extensions/gsd/auto.ts +81 -12
- package/src/resources/extensions/gsd/doctor-proactive.ts +7 -6
- package/src/resources/extensions/gsd/doctor.ts +24 -1
- package/src/resources/extensions/gsd/files.ts +13 -2
- package/src/resources/extensions/gsd/guided-flow.ts +19 -9
- package/src/resources/extensions/gsd/index.ts +48 -7
- package/src/resources/extensions/gsd/migrate/writer.ts +39 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +122 -4
- package/src/resources/extensions/gsd/preferences.ts +2 -1
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
- package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/src/resources/extensions/gsd/prompts/queue.md +2 -2
- package/src/resources/extensions/gsd/roadmap-slices.ts +45 -1
- package/src/resources/extensions/gsd/state.ts +17 -6
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +23 -3
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +13 -7
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +171 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +8 -4
- package/src/resources/extensions/gsd/types.ts +2 -0
- package/src/resources/extensions/search-the-web/native-search.ts +4 -0
- package/src/resources/extensions/shared/path-display.ts +19 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Core session management\n\n// Config paths\nexport { getAgentDir, VERSION } from \"./config.js\";\nexport {\n\tAgentSession,\n\ttype AgentSessionConfig,\n\ttype AgentSessionEvent,\n\ttype AgentSessionEventListener,\n\ttype ModelCycleResult,\n\ttype ParsedSkillBlock,\n\ttype PromptOptions,\n\tparseSkillBlock,\n\ttype SessionStats,\n} from \"./core/agent-session.js\";\n// Auth and model registry\nexport {\n\ttype ApiKeyCredential,\n\ttype AuthCredential,\n\tAuthStorage,\n\ttype AuthStorageBackend,\n\tFileAuthStorageBackend,\n\tInMemoryAuthStorageBackend,\n\ttype OAuthCredential,\n} from \"./core/auth-storage.js\";\n// Compaction\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryResult,\n\ttype CollectEntriesResult,\n\ttype CompactionResult,\n\ttype CutPointResult,\n\tcalculateContextTokens,\n\tcollectEntriesForBranchSummary,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateTokens,\n\ttype FileOperations,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\ttype GenerateBranchSummaryOptions,\n\tgenerateBranchSummary,\n\tgenerateSummary,\n\tgetLastAssistantUsage,\n\tprepareBranchEntries,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./core/compaction/index.js\";\nexport { createEventBus, type EventBus, type EventBusController } from \"./core/event-bus.js\";\n// Extension system\nexport type {\n\tAgentEndEvent,\n\tAgentStartEvent,\n\tAgentToolResult,\n\tAgentToolUpdateCallback,\n\tAppAction,\n\tBashToolCallEvent,\n\tBeforeAgentStartEvent,\n\tBeforeProviderRequestEvent,\n\tBeforeProviderRequestEventResult,\n\tCompactOptions,\n\tContextEvent,\n\tContextUsage,\n\tCustomToolCallEvent,\n\tEditToolCallEvent,\n\tExecOptions,\n\tExecResult,\n\tExtension,\n\tExtensionActions,\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionCommandContextActions,\n\tExtensionContext,\n\tExtensionContextActions,\n\tExtensionError,\n\tExtensionEvent,\n\tExtensionFactory,\n\tExtensionFlag,\n\tExtensionHandler,\n\tExtensionRuntime,\n\tExtensionShortcut,\n\tExtensionUIContext,\n\tExtensionUIDialogOptions,\n\tExtensionWidgetOptions,\n\tFindToolCallEvent,\n\tGrepToolCallEvent,\n\tInputEvent,\n\tInputEventResult,\n\tInputSource,\n\tKeybindingsManager,\n\tLoadExtensionsResult,\n\tLsToolCallEvent,\n\tMessageRenderer,\n\tMessageRenderOptions,\n\tProviderConfig,\n\tProviderModelConfig,\n\tReadToolCallEvent,\n\tRegisteredCommand,\n\tRegisteredTool,\n\tSessionBeforeCompactEvent,\n\tSessionBeforeForkEvent,\n\tSessionBeforeSwitchEvent,\n\tSessionBeforeTreeEvent,\n\tSessionCompactEvent,\n\tSessionForkEvent,\n\tSessionShutdownEvent,\n\tSessionStartEvent,\n\tSessionSwitchEvent,\n\tSessionTreeEvent,\n\tSlashCommandInfo,\n\tSlashCommandLocation,\n\tSlashCommandSource,\n\tTerminalInputHandler,\n\tToolCallEvent,\n\tToolDefinition,\n\tToolInfo,\n\tToolRenderResultOptions,\n\tToolResultEvent,\n\tTurnEndEvent,\n\tTurnStartEvent,\n\tUserBashEvent,\n\tUserBashEventResult,\n\tWidgetPlacement,\n\tWriteToolCallEvent,\n} from \"./core/extensions/index.js\";\nexport {\n\tcreateExtensionRuntime,\n\tdiscoverAndLoadExtensions,\n\tExtensionRunner,\n\tisBashToolResult,\n\tisEditToolResult,\n\tisFindToolResult,\n\tisGrepToolResult,\n\tisLsToolResult,\n\tisReadToolResult,\n\tisToolCallEventType,\n\tisWriteToolResult,\n\twrapRegisteredTool,\n\twrapRegisteredTools,\n\twrapToolsWithExtensions,\n\twrapToolWithExtensions,\n} from \"./core/extensions/index.js\";\n// Footer data provider (git branch + extension statuses - data not otherwise available to extensions)\nexport type { ReadonlyFooterDataProvider } from \"./core/footer-data-provider.js\";\nexport { convertToLlm } from \"./core/messages.js\";\nexport { ModelDiscoveryCache } from \"./core/discovery-cache.js\";\nexport type { DiscoveredModel, DiscoveryResult, ProviderDiscoveryAdapter } from \"./core/model-discovery.js\";\nexport { getDiscoverableProviders, getDiscoveryAdapter } from \"./core/model-discovery.js\";\nexport { ModelRegistry } from \"./core/model-registry.js\";\nexport { ModelsJsonWriter } from \"./core/models-json-writer.js\";\nexport type {\n\tPackageManager,\n\tPathMetadata,\n\tProgressCallback,\n\tProgressEvent,\n\tResolvedPaths,\n\tResolvedResource,\n} from \"./core/package-manager.js\";\nexport { DefaultPackageManager } from \"./core/package-manager.js\";\nexport type { ResourceCollision, ResourceDiagnostic, ResourceLoader } from \"./core/resource-loader.js\";\nexport { DefaultResourceLoader } from \"./core/resource-loader.js\";\n// SDK for programmatic usage\nexport {\n\ttype CreateAgentSessionOptions,\n\ttype CreateAgentSessionResult,\n\t// Factory\n\tcreateAgentSession,\n\tcreateBashTool,\n\t// Tool factories (for custom cwd)\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\ttype PromptTemplate,\n\t// Pre-built tools (use process.cwd())\n\treadOnlyTools,\n} from \"./core/sdk.js\";\nexport {\n\ttype BranchSummaryEntry,\n\tbuildSessionContext,\n\ttype CompactionEntry,\n\tCURRENT_SESSION_VERSION,\n\ttype CustomEntry,\n\ttype CustomMessageEntry,\n\ttype FileEntry,\n\tgetLatestCompactionEntry,\n\ttype ModelChangeEntry,\n\tmigrateSessionEntries,\n\ttype NewSessionOptions,\n\tparseSessionEntries,\n\ttype SessionContext,\n\ttype SessionEntry,\n\ttype SessionEntryBase,\n\ttype SessionHeader,\n\ttype SessionInfo,\n\ttype SessionInfoEntry,\n\tSessionManager,\n\ttype SessionMessageEntry,\n\ttype ThinkingLevelChangeEntry,\n} from \"./core/session-manager.js\";\n// Blob and artifact storage\nexport { BlobStore, isBlobRef, parseBlobRef, externalizeImageData, resolveImageData } from \"./core/blob-store.js\";\nexport { ArtifactManager } from \"./core/artifact-manager.js\";\nexport {\n\ttype AsyncSettings,\n\ttype CompactionSettings,\n\ttype ImageSettings,\n\ttype MemorySettings,\n\ttype PackageSource,\n\ttype RetrySettings,\n\tSettingsManager,\n\ttype TaskIsolationSettings,\n} from \"./core/settings-manager.js\";\n// Skills\nexport {\n\tformatSkillsForPrompt,\n\ttype LoadSkillsFromDirOptions,\n\ttype LoadSkillsResult,\n\tloadSkills,\n\tloadSkillsFromDir,\n\ttype Skill,\n\ttype SkillFrontmatter,\n} from \"./core/skills.js\";\n// Tools\nexport {\n\ttype BashInterceptorRule,\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\ttype BashToolDetails,\n\ttype BashToolInput,\n\ttype BashToolOptions,\n\tbashTool,\n\trewriteBackgroundCommand,\n\tcheckBashInterception,\n\ttype CompiledInterceptor,\n\tcompileInterceptor,\n\tDEFAULT_BASH_INTERCEPTOR_RULES,\n\tcodingTools,\n\tDEFAULT_MAX_BYTES,\n\tDEFAULT_MAX_LINES,\n\ttype EditOperations,\n\ttype EditToolDetails,\n\ttype EditToolInput,\n\ttype EditToolOptions,\n\teditTool,\n\ttype FindOperations,\n\ttype FindToolDetails,\n\ttype FindToolInput,\n\ttype FindToolOptions,\n\tfindTool,\n\tformatSize,\n\ttype GrepOperations,\n\ttype GrepToolDetails,\n\ttype GrepToolInput,\n\ttype GrepToolOptions,\n\tgrepTool,\n\ttype LsOperations,\n\ttype LsToolDetails,\n\ttype LsToolInput,\n\ttype LsToolOptions,\n\tlsTool,\n\ttype ReadOperations,\n\ttype ReadToolDetails,\n\ttype ReadToolInput,\n\ttype ReadToolOptions,\n\treadTool,\n\ttype ToolsOptions,\n\ttype TruncationOptions,\n\ttype TruncationResult,\n\ttruncateHead,\n\ttruncateLine,\n\ttruncateTail,\n\ttype WriteOperations,\n\ttype WriteToolInput,\n\ttype WriteToolOptions,\n\twriteTool,\n} from \"./core/tools/index.js\";\n// Main entry point\nexport { main } from \"./main.js\";\n// Run modes for programmatic SDK usage\nexport {\n\tInteractiveMode,\n\ttype InteractiveModeOptions,\n\ttype PrintModeOptions,\n\trunPrintMode,\n\trunRpcMode,\n} from \"./modes/index.js\";\n// UI components for extensions\nexport {\n\tArminComponent,\n\tAssistantMessageComponent,\n\tappKey,\n\tappKeyHint,\n\tBashExecutionComponent,\n\tBorderedLoader,\n\tBranchSummaryMessageComponent,\n\tCompactionSummaryMessageComponent,\n\tCustomEditor,\n\tCustomMessageComponent,\n\tDynamicBorder,\n\tExtensionEditorComponent,\n\tExtensionInputComponent,\n\tExtensionSelectorComponent,\n\teditorKey,\n\tFooterComponent,\n\tkeyHint,\n\tLoginDialogComponent,\n\tModelSelectorComponent,\n\tOAuthSelectorComponent,\n\tProviderManagerComponent,\n\ttype RenderDiffOptions,\n\trawKeyHint,\n\trenderDiff,\n\tSessionSelectorComponent,\n\ttype SettingsCallbacks,\n\ttype SettingsConfig,\n\tSettingsSelectorComponent,\n\tShowImagesSelectorComponent,\n\tSkillInvocationMessageComponent,\n\tThemeSelectorComponent,\n\tThinkingSelectorComponent,\n\tToolExecutionComponent,\n\ttype ToolExecutionOptions,\n\tTreeSelectorComponent,\n\ttruncateToVisualLines,\n\tUserMessageComponent,\n\tUserMessageSelectorComponent,\n\ttype VisualTruncateResult,\n} from \"./modes/interactive/components/index.js\";\n// Theme utilities for custom tools and extensions\nexport {\n\tgetLanguageFromPath,\n\tgetMarkdownTheme,\n\tgetSelectListTheme,\n\tgetSettingsListTheme,\n\thighlightCode,\n\tinitTheme,\n\tTheme,\n\ttype ThemeColor,\n} from \"./modes/interactive/theme/theme.js\";\n// Clipboard utilities\nexport { copyToClipboard } from \"./utils/clipboard.js\";\nexport { parseFrontmatter, stripFrontmatter } from \"./utils/frontmatter.js\";\n// Shell utilities\nexport { getShellConfig, sanitizeCommand } from \"./utils/shell.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Core session management\n\n// Config paths\nexport { getAgentDir, VERSION } from \"./config.js\";\nexport {\n\tAgentSession,\n\ttype AgentSessionConfig,\n\ttype AgentSessionEvent,\n\ttype AgentSessionEventListener,\n\ttype ModelCycleResult,\n\ttype ParsedSkillBlock,\n\ttype PromptOptions,\n\tparseSkillBlock,\n\ttype SessionStats,\n} from \"./core/agent-session.js\";\n// Auth and model registry\nexport {\n\ttype ApiKeyCredential,\n\ttype AuthCredential,\n\tAuthStorage,\n\ttype AuthStorageBackend,\n\tFileAuthStorageBackend,\n\tInMemoryAuthStorageBackend,\n\ttype OAuthCredential,\n} from \"./core/auth-storage.js\";\n// Compaction\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryResult,\n\ttype CollectEntriesResult,\n\ttype CompactionResult,\n\ttype CutPointResult,\n\tcalculateContextTokens,\n\tcollectEntriesForBranchSummary,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateTokens,\n\ttype FileOperations,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\ttype GenerateBranchSummaryOptions,\n\tgenerateBranchSummary,\n\tgenerateSummary,\n\tgetLastAssistantUsage,\n\tprepareBranchEntries,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./core/compaction/index.js\";\nexport { createEventBus, type EventBus, type EventBusController } from \"./core/event-bus.js\";\n// Extension system\nexport type {\n\tAgentEndEvent,\n\tAgentStartEvent,\n\tAgentToolResult,\n\tAgentToolUpdateCallback,\n\tAppAction,\n\tBashToolCallEvent,\n\tBeforeAgentStartEvent,\n\tBeforeProviderRequestEvent,\n\tBeforeProviderRequestEventResult,\n\tCompactOptions,\n\tContextEvent,\n\tContextUsage,\n\tCustomToolCallEvent,\n\tEditToolCallEvent,\n\tExecOptions,\n\tExecResult,\n\tExtension,\n\tExtensionActions,\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionCommandContextActions,\n\tExtensionContext,\n\tExtensionContextActions,\n\tExtensionError,\n\tExtensionEvent,\n\tExtensionFactory,\n\tExtensionFlag,\n\tExtensionHandler,\n\tExtensionRuntime,\n\tExtensionShortcut,\n\tExtensionUIContext,\n\tExtensionUIDialogOptions,\n\tExtensionWidgetOptions,\n\tFindToolCallEvent,\n\tGrepToolCallEvent,\n\tInputEvent,\n\tInputEventResult,\n\tInputSource,\n\tKeybindingsManager,\n\tLoadExtensionsResult,\n\tLsToolCallEvent,\n\tMessageRenderer,\n\tMessageRenderOptions,\n\tProviderConfig,\n\tProviderModelConfig,\n\tReadToolCallEvent,\n\tRegisteredCommand,\n\tRegisteredTool,\n\tSessionBeforeCompactEvent,\n\tSessionBeforeForkEvent,\n\tSessionBeforeSwitchEvent,\n\tSessionBeforeTreeEvent,\n\tSessionCompactEvent,\n\tSessionForkEvent,\n\tSessionShutdownEvent,\n\tSessionStartEvent,\n\tSessionSwitchEvent,\n\tSessionTreeEvent,\n\tSlashCommandInfo,\n\tSlashCommandLocation,\n\tSlashCommandSource,\n\tTerminalInputHandler,\n\tToolCallEvent,\n\tToolDefinition,\n\tToolInfo,\n\tToolRenderResultOptions,\n\tToolResultEvent,\n\tTurnEndEvent,\n\tTurnStartEvent,\n\tUserBashEvent,\n\tUserBashEventResult,\n\tWidgetPlacement,\n\tWriteToolCallEvent,\n} from \"./core/extensions/index.js\";\nexport {\n\tcreateExtensionRuntime,\n\tdiscoverAndLoadExtensions,\n\tExtensionRunner,\n\tisBashToolResult,\n\tisEditToolResult,\n\tisFindToolResult,\n\tisGrepToolResult,\n\tisLsToolResult,\n\tisReadToolResult,\n\tisToolCallEventType,\n\tisWriteToolResult,\n\twrapRegisteredTool,\n\twrapRegisteredTools,\n\twrapToolsWithExtensions,\n\twrapToolWithExtensions,\n} from \"./core/extensions/index.js\";\n// Footer data provider (git branch + extension statuses - data not otherwise available to extensions)\nexport type { ReadonlyFooterDataProvider } from \"./core/footer-data-provider.js\";\nexport { convertToLlm } from \"./core/messages.js\";\nexport { ModelDiscoveryCache } from \"./core/discovery-cache.js\";\nexport type { DiscoveredModel, DiscoveryResult, ProviderDiscoveryAdapter } from \"./core/model-discovery.js\";\nexport { getDiscoverableProviders, getDiscoveryAdapter } from \"./core/model-discovery.js\";\nexport { ModelRegistry } from \"./core/model-registry.js\";\nexport { ModelsJsonWriter } from \"./core/models-json-writer.js\";\nexport type {\n\tPackageManager,\n\tPathMetadata,\n\tProgressCallback,\n\tProgressEvent,\n\tResolvedPaths,\n\tResolvedResource,\n} from \"./core/package-manager.js\";\nexport { DefaultPackageManager } from \"./core/package-manager.js\";\nexport type { ResourceCollision, ResourceDiagnostic, ResourceLoader } from \"./core/resource-loader.js\";\nexport { DefaultResourceLoader } from \"./core/resource-loader.js\";\n// SDK for programmatic usage\nexport {\n\ttype CreateAgentSessionOptions,\n\ttype CreateAgentSessionResult,\n\t// Factory\n\tcreateAgentSession,\n\tcreateBashTool,\n\t// Tool factories (for custom cwd)\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\ttype PromptTemplate,\n\t// Pre-built tools (use process.cwd())\n\treadOnlyTools,\n} from \"./core/sdk.js\";\nexport {\n\ttype BranchSummaryEntry,\n\tbuildSessionContext,\n\ttype CompactionEntry,\n\tCURRENT_SESSION_VERSION,\n\ttype CustomEntry,\n\ttype CustomMessageEntry,\n\ttype FileEntry,\n\tgetLatestCompactionEntry,\n\ttype ModelChangeEntry,\n\tmigrateSessionEntries,\n\ttype NewSessionOptions,\n\tparseSessionEntries,\n\ttype SessionContext,\n\ttype SessionEntry,\n\ttype SessionEntryBase,\n\ttype SessionHeader,\n\ttype SessionInfo,\n\ttype SessionInfoEntry,\n\tSessionManager,\n\ttype SessionMessageEntry,\n\ttype ThinkingLevelChangeEntry,\n} from \"./core/session-manager.js\";\n// Blob and artifact storage\nexport { BlobStore, isBlobRef, parseBlobRef, externalizeImageData, resolveImageData } from \"./core/blob-store.js\";\nexport { ArtifactManager } from \"./core/artifact-manager.js\";\nexport {\n\ttype AsyncSettings,\n\ttype CompactionSettings,\n\ttype ImageSettings,\n\ttype MemorySettings,\n\ttype PackageSource,\n\ttype RetrySettings,\n\tSettingsManager,\n\ttype TaskIsolationSettings,\n} from \"./core/settings-manager.js\";\n// Skills\nexport {\n\tformatSkillsForPrompt,\n\ttype LoadSkillsFromDirOptions,\n\ttype LoadSkillsResult,\n\tloadSkills,\n\tloadSkillsFromDir,\n\ttype Skill,\n\ttype SkillFrontmatter,\n} from \"./core/skills.js\";\n// Tools\nexport {\n\ttype BashInterceptorRule,\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\ttype BashToolDetails,\n\ttype BashToolInput,\n\ttype BashToolOptions,\n\tbashTool,\n\trewriteBackgroundCommand,\n\tcheckBashInterception,\n\ttype CompiledInterceptor,\n\tcompileInterceptor,\n\tDEFAULT_BASH_INTERCEPTOR_RULES,\n\tcodingTools,\n\tDEFAULT_MAX_BYTES,\n\tDEFAULT_MAX_LINES,\n\ttype EditOperations,\n\ttype EditToolDetails,\n\ttype EditToolInput,\n\ttype EditToolOptions,\n\teditTool,\n\ttype FindOperations,\n\ttype FindToolDetails,\n\ttype FindToolInput,\n\ttype FindToolOptions,\n\tfindTool,\n\tformatSize,\n\ttype GrepOperations,\n\ttype GrepToolDetails,\n\ttype GrepToolInput,\n\ttype GrepToolOptions,\n\tgrepTool,\n\ttype LsOperations,\n\ttype LsToolDetails,\n\ttype LsToolInput,\n\ttype LsToolOptions,\n\tlsTool,\n\ttype ReadOperations,\n\ttype ReadToolDetails,\n\ttype ReadToolInput,\n\ttype ReadToolOptions,\n\treadTool,\n\ttype ToolsOptions,\n\ttype TruncationOptions,\n\ttype TruncationResult,\n\ttruncateHead,\n\ttruncateLine,\n\ttruncateTail,\n\ttype WriteOperations,\n\ttype WriteToolInput,\n\ttype WriteToolOptions,\n\twriteTool,\n\t// Hashline edit mode tools\n\thashlineEditTool,\n\thashlineReadTool,\n\thashlineCodingTools,\n\tcreateHashlineEditTool,\n\tcreateHashlineReadTool,\n\tcreateHashlineCodingTools,\n\ttype HashlineEditInput,\n\ttype HashlineEditToolDetails,\n\ttype HashlineEditToolOptions,\n\ttype HashlineReadToolDetails,\n\ttype HashlineReadToolInput,\n\ttype HashlineReadToolOptions,\n} from \"./core/tools/index.js\";\n// Main entry point\nexport { main } from \"./main.js\";\n// Run modes for programmatic SDK usage\nexport {\n\tInteractiveMode,\n\ttype InteractiveModeOptions,\n\ttype PrintModeOptions,\n\trunPrintMode,\n\trunRpcMode,\n} from \"./modes/index.js\";\n// UI components for extensions\nexport {\n\tArminComponent,\n\tAssistantMessageComponent,\n\tappKey,\n\tappKeyHint,\n\tBashExecutionComponent,\n\tBorderedLoader,\n\tBranchSummaryMessageComponent,\n\tCompactionSummaryMessageComponent,\n\tCustomEditor,\n\tCustomMessageComponent,\n\tDynamicBorder,\n\tExtensionEditorComponent,\n\tExtensionInputComponent,\n\tExtensionSelectorComponent,\n\teditorKey,\n\tFooterComponent,\n\tkeyHint,\n\tLoginDialogComponent,\n\tModelSelectorComponent,\n\tOAuthSelectorComponent,\n\tProviderManagerComponent,\n\ttype RenderDiffOptions,\n\trawKeyHint,\n\trenderDiff,\n\tSessionSelectorComponent,\n\ttype SettingsCallbacks,\n\ttype SettingsConfig,\n\tSettingsSelectorComponent,\n\tShowImagesSelectorComponent,\n\tSkillInvocationMessageComponent,\n\tThemeSelectorComponent,\n\tThinkingSelectorComponent,\n\tToolExecutionComponent,\n\ttype ToolExecutionOptions,\n\tTreeSelectorComponent,\n\ttruncateToVisualLines,\n\tUserMessageComponent,\n\tUserMessageSelectorComponent,\n\ttype VisualTruncateResult,\n} from \"./modes/interactive/components/index.js\";\n// Theme utilities for custom tools and extensions\nexport {\n\tgetLanguageFromPath,\n\tgetMarkdownTheme,\n\tgetSelectListTheme,\n\tgetSettingsListTheme,\n\thighlightCode,\n\tinitTheme,\n\tTheme,\n\ttype ThemeColor,\n} from \"./modes/interactive/theme/theme.js\";\n// Clipboard utilities\nexport { copyToClipboard } from \"./utils/clipboard.js\";\nexport { parseFrontmatter, stripFrontmatter } from \"./utils/frontmatter.js\";\n// Shell utilities\nexport { getShellConfig, sanitizeCommand } from \"./utils/shell.js\";\n// Cross-platform path display\nexport { toPosixPath } from \"./utils/path-display.js\";\n"]}
|
|
@@ -7,7 +7,12 @@ interface ScopedModelItem {
|
|
|
7
7
|
thinkingLevel?: string;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
* Component that renders a model selector with search
|
|
10
|
+
* Component that renders a grouped model selector with search.
|
|
11
|
+
*
|
|
12
|
+
* Browsing (no search): models are grouped under provider headers.
|
|
13
|
+
* - Current model's provider is shown first; remaining providers sorted alphabetically.
|
|
14
|
+
* - Arrow keys navigate all rows; headers are skipped during selection.
|
|
15
|
+
* Searching: reverts to a flat fuzzy-filtered list (same as before), with [provider] badges.
|
|
11
16
|
*/
|
|
12
17
|
export declare class ModelSelectorComponent extends Container implements Focusable {
|
|
13
18
|
private searchInput;
|
|
@@ -18,8 +23,12 @@ export declare class ModelSelectorComponent extends Container implements Focusab
|
|
|
18
23
|
private allModels;
|
|
19
24
|
private scopedModelItems;
|
|
20
25
|
private activeModels;
|
|
26
|
+
private groupedRows;
|
|
27
|
+
private modelRowIndices;
|
|
28
|
+
private selectedGroupIndex;
|
|
21
29
|
private filteredModels;
|
|
22
|
-
private
|
|
30
|
+
private selectedFlatIndex;
|
|
31
|
+
private isSearching;
|
|
23
32
|
private currentModel?;
|
|
24
33
|
private settingsManager;
|
|
25
34
|
private modelRegistry;
|
|
@@ -33,13 +42,42 @@ export declare class ModelSelectorComponent extends Container implements Focusab
|
|
|
33
42
|
private scopeHintText?;
|
|
34
43
|
constructor(tui: TUI, currentModel: Model<any> | undefined, settingsManager: SettingsManager, modelRegistry: ModelRegistry, scopedModels: ReadonlyArray<ScopedModelItem>, onSelect: (model: Model<any>) => void, onCancel: () => void, initialSearchInput?: string);
|
|
35
44
|
private loadModels;
|
|
36
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Sort models within each provider: current model first, then by name desc.
|
|
47
|
+
* Provider ordering is handled separately in buildGroupedRows().
|
|
48
|
+
*/
|
|
49
|
+
private sortModelsWithinProvider;
|
|
50
|
+
/**
|
|
51
|
+
* Build the grouped rows array for browse mode.
|
|
52
|
+
* Current model's provider comes first; remaining providers sorted alphabetically.
|
|
53
|
+
*/
|
|
54
|
+
private buildGroupedRows;
|
|
55
|
+
/**
|
|
56
|
+
* Move selectedGroupIndex to point at the current model (or first model).
|
|
57
|
+
*/
|
|
58
|
+
private jumpToCurrentModel;
|
|
59
|
+
/**
|
|
60
|
+
* Get the currently selected model from grouped or flat state.
|
|
61
|
+
*/
|
|
62
|
+
private getSelectedModel;
|
|
37
63
|
private getScopeText;
|
|
38
64
|
private getScopeHintText;
|
|
39
65
|
private setScope;
|
|
40
66
|
private filterModels;
|
|
41
67
|
private updateList;
|
|
68
|
+
/** Flat fuzzy-search results, same as original behaviour */
|
|
69
|
+
private renderFlatList;
|
|
70
|
+
/**
|
|
71
|
+
* Grouped browse view: provider headers + model rows, windowed around selection.
|
|
72
|
+
* Shows enough rows to fill ~10 visible lines; headers count as one line each.
|
|
73
|
+
*/
|
|
74
|
+
private renderGroupedList;
|
|
75
|
+
private modelDetailLine;
|
|
42
76
|
handleInput(keyData: string): void;
|
|
77
|
+
/** Move selection up, skipping headers in grouped mode */
|
|
78
|
+
private moveUp;
|
|
79
|
+
/** Move selection down, skipping headers in grouped mode */
|
|
80
|
+
private moveDown;
|
|
43
81
|
private handleSelect;
|
|
44
82
|
getSearchInput(): Input;
|
|
45
83
|
}
|
|
@@ -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,YAAY,CAAC;AACxD,OAAO,EACN,SAAS,EACT,KAAK,SAAS,EAGd,KAAK,EAGL,KAAK,GAAG,EACR,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAuBzE,UAAU,eAAe;IACxB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;
|
|
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,YAAY,CAAC;AACxD,OAAO,EACN,SAAS,EACT,KAAK,SAAS,EAGd,KAAK,EAGL,KAAK,GAAG,EACR,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAuBzE,UAAU,eAAe;IACxB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAWD;;;;;;;GAOG;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;IAGvC,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,kBAAkB,CAAa;IAGvC,OAAO,CAAC,cAAc,CAAmB;IACzC,OAAO,CAAC,iBAAiB,CAAa;IAEtC,OAAO,CAAC,WAAW,CAAkB;IACrC,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;gBAG5B,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;YAwEd,UAAU;IA2CxB;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAehC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAoCxB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAmB1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,QAAQ;IAmBhB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,UAAU;IAkBlB,4DAA4D;IAC5D,OAAO,CAAC,cAAc;IAsDtB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAsEzB,OAAO,CAAC,eAAe;IAYvB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAiElC,0DAA0D;IAC1D,OAAO,CAAC,MAAM;IA2Bd,4DAA4D;IAC5D,OAAO,CAAC,QAAQ;IA2BhB,OAAO,CAAC,YAAY;IAMpB,cAAc,IAAI,KAAK;CAGvB"}
|
|
@@ -15,7 +15,12 @@ function formatTokenCount(count) {
|
|
|
15
15
|
return count.toString();
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* Component that renders a model selector with search
|
|
18
|
+
* Component that renders a grouped model selector with search.
|
|
19
|
+
*
|
|
20
|
+
* Browsing (no search): models are grouped under provider headers.
|
|
21
|
+
* - Current model's provider is shown first; remaining providers sorted alphabetically.
|
|
22
|
+
* - Arrow keys navigate all rows; headers are skipped during selection.
|
|
23
|
+
* Searching: reverts to a flat fuzzy-filtered list (same as before), with [provider] badges.
|
|
19
24
|
*/
|
|
20
25
|
export class ModelSelectorComponent extends Container {
|
|
21
26
|
get focused() {
|
|
@@ -32,8 +37,14 @@ export class ModelSelectorComponent extends Container {
|
|
|
32
37
|
this.allModels = [];
|
|
33
38
|
this.scopedModelItems = [];
|
|
34
39
|
this.activeModels = [];
|
|
40
|
+
// Grouped (browse) state
|
|
41
|
+
this.groupedRows = [];
|
|
42
|
+
this.modelRowIndices = []; // indices into groupedRows that are "model" kind
|
|
43
|
+
this.selectedGroupIndex = 0; // index into groupedRows (can be model or header)
|
|
44
|
+
// Search (flat) state
|
|
35
45
|
this.filteredModels = [];
|
|
36
|
-
this.
|
|
46
|
+
this.selectedFlatIndex = 0;
|
|
47
|
+
this.isSearching = false;
|
|
37
48
|
this.scope = "all";
|
|
38
49
|
this.tui = tui;
|
|
39
50
|
this.currentModel = currentModel;
|
|
@@ -64,9 +75,15 @@ export class ModelSelectorComponent extends Container {
|
|
|
64
75
|
this.searchInput.setValue(initialSearchInput);
|
|
65
76
|
}
|
|
66
77
|
this.searchInput.onSubmit = () => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
78
|
+
if (this.isSearching) {
|
|
79
|
+
if (this.filteredModels[this.selectedFlatIndex]) {
|
|
80
|
+
this.handleSelect(this.filteredModels[this.selectedFlatIndex].model);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
const model = this.getSelectedModel();
|
|
85
|
+
if (model)
|
|
86
|
+
this.handleSelect(model);
|
|
70
87
|
}
|
|
71
88
|
};
|
|
72
89
|
this.addChild(this.searchInput);
|
|
@@ -80,9 +97,12 @@ export class ModelSelectorComponent extends Container {
|
|
|
80
97
|
// Load models and do initial render
|
|
81
98
|
this.loadModels().then(() => {
|
|
82
99
|
if (initialSearchInput) {
|
|
100
|
+
this.isSearching = true;
|
|
83
101
|
this.filterModels(initialSearchInput);
|
|
84
102
|
}
|
|
85
103
|
else {
|
|
104
|
+
this.buildGroupedRows();
|
|
105
|
+
this.jumpToCurrentModel();
|
|
86
106
|
this.updateList();
|
|
87
107
|
}
|
|
88
108
|
// Request re-render after models are loaded
|
|
@@ -112,22 +132,26 @@ export class ModelSelectorComponent extends Container {
|
|
|
112
132
|
this.scopedModelItems = [];
|
|
113
133
|
this.activeModels = [];
|
|
114
134
|
this.filteredModels = [];
|
|
135
|
+
this.groupedRows = [];
|
|
136
|
+
this.modelRowIndices = [];
|
|
115
137
|
this.errorMessage = error instanceof Error ? error.message : String(error);
|
|
116
138
|
return;
|
|
117
139
|
}
|
|
118
|
-
this.allModels = this.
|
|
119
|
-
this.scopedModelItems = this.
|
|
140
|
+
this.allModels = this.sortModelsWithinProvider(models);
|
|
141
|
+
this.scopedModelItems = this.sortModelsWithinProvider(this.scopedModels.map((scoped) => ({
|
|
120
142
|
provider: scoped.model.provider,
|
|
121
143
|
id: scoped.model.id,
|
|
122
144
|
model: scoped.model,
|
|
123
145
|
})));
|
|
124
146
|
this.activeModels = this.scope === "scoped" ? this.scopedModelItems : this.allModels;
|
|
125
147
|
this.filteredModels = this.activeModels;
|
|
126
|
-
this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));
|
|
127
148
|
}
|
|
128
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Sort models within each provider: current model first, then by name desc.
|
|
151
|
+
* Provider ordering is handled separately in buildGroupedRows().
|
|
152
|
+
*/
|
|
153
|
+
sortModelsWithinProvider(models) {
|
|
129
154
|
const sorted = [...models];
|
|
130
|
-
// Sort: current model first, then by name descending (newest first), then by provider
|
|
131
155
|
sorted.sort((a, b) => {
|
|
132
156
|
const aIsCurrent = modelsAreEqual(this.currentModel, a.model);
|
|
133
157
|
const bIsCurrent = modelsAreEqual(this.currentModel, b.model);
|
|
@@ -135,7 +159,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
135
159
|
return -1;
|
|
136
160
|
if (!aIsCurrent && bIsCurrent)
|
|
137
161
|
return 1;
|
|
138
|
-
//
|
|
162
|
+
// Within provider: newest/largest model name first
|
|
139
163
|
const nameCmp = b.model.name.localeCompare(a.model.name);
|
|
140
164
|
if (nameCmp !== 0)
|
|
141
165
|
return nameCmp;
|
|
@@ -143,6 +167,74 @@ export class ModelSelectorComponent extends Container {
|
|
|
143
167
|
});
|
|
144
168
|
return sorted;
|
|
145
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Build the grouped rows array for browse mode.
|
|
172
|
+
* Current model's provider comes first; remaining providers sorted alphabetically.
|
|
173
|
+
*/
|
|
174
|
+
buildGroupedRows() {
|
|
175
|
+
// Group models by provider
|
|
176
|
+
const byProvider = new Map();
|
|
177
|
+
for (const item of this.activeModels) {
|
|
178
|
+
let group = byProvider.get(item.provider);
|
|
179
|
+
if (!group) {
|
|
180
|
+
group = [];
|
|
181
|
+
byProvider.set(item.provider, group);
|
|
182
|
+
}
|
|
183
|
+
group.push(item);
|
|
184
|
+
}
|
|
185
|
+
// Determine provider order: current model's provider first, rest alphabetically
|
|
186
|
+
const currentProvider = this.currentModel?.provider;
|
|
187
|
+
const providers = Array.from(byProvider.keys()).sort((a, b) => {
|
|
188
|
+
if (a === currentProvider)
|
|
189
|
+
return -1;
|
|
190
|
+
if (b === currentProvider)
|
|
191
|
+
return 1;
|
|
192
|
+
return a.localeCompare(b);
|
|
193
|
+
});
|
|
194
|
+
const rows = [];
|
|
195
|
+
const modelIndices = [];
|
|
196
|
+
for (const provider of providers) {
|
|
197
|
+
const items = byProvider.get(provider);
|
|
198
|
+
rows.push({ kind: "header", provider, count: items.length });
|
|
199
|
+
for (const item of items) {
|
|
200
|
+
modelIndices.push(rows.length);
|
|
201
|
+
rows.push({ kind: "model", item });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
this.groupedRows = rows;
|
|
205
|
+
this.modelRowIndices = modelIndices;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Move selectedGroupIndex to point at the current model (or first model).
|
|
209
|
+
*/
|
|
210
|
+
jumpToCurrentModel() {
|
|
211
|
+
if (this.groupedRows.length === 0) {
|
|
212
|
+
this.selectedGroupIndex = 0;
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
// Find the current model in grouped rows
|
|
216
|
+
for (let i = 0; i < this.groupedRows.length; i++) {
|
|
217
|
+
const row = this.groupedRows[i];
|
|
218
|
+
if (row.kind === "model" && modelsAreEqual(this.currentModel, row.item.model)) {
|
|
219
|
+
this.selectedGroupIndex = i;
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// Fall back to first model row
|
|
224
|
+
if (this.modelRowIndices.length > 0) {
|
|
225
|
+
this.selectedGroupIndex = this.modelRowIndices[0];
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Get the currently selected model from grouped or flat state.
|
|
230
|
+
*/
|
|
231
|
+
getSelectedModel() {
|
|
232
|
+
if (this.isSearching) {
|
|
233
|
+
return this.filteredModels[this.selectedFlatIndex]?.model;
|
|
234
|
+
}
|
|
235
|
+
const row = this.groupedRows[this.selectedGroupIndex];
|
|
236
|
+
return row?.kind === "model" ? row.item.model : undefined;
|
|
237
|
+
}
|
|
146
238
|
getScopeText() {
|
|
147
239
|
const allText = this.scope === "all" ? theme.fg("accent", "all") : theme.fg("muted", "all");
|
|
148
240
|
const scopedText = this.scope === "scoped" ? theme.fg("accent", "scoped") : theme.fg("muted", "scoped");
|
|
@@ -156,8 +248,15 @@ export class ModelSelectorComponent extends Container {
|
|
|
156
248
|
return;
|
|
157
249
|
this.scope = scope;
|
|
158
250
|
this.activeModels = this.scope === "scoped" ? this.scopedModelItems : this.allModels;
|
|
159
|
-
this.
|
|
160
|
-
|
|
251
|
+
if (this.isSearching) {
|
|
252
|
+
this.selectedFlatIndex = 0;
|
|
253
|
+
this.filterModels(this.searchInput.getValue());
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
this.buildGroupedRows();
|
|
257
|
+
this.jumpToCurrentModel();
|
|
258
|
+
this.updateList();
|
|
259
|
+
}
|
|
161
260
|
if (this.scopeText) {
|
|
162
261
|
this.scopeText.setText(this.getScopeText());
|
|
163
262
|
}
|
|
@@ -166,26 +265,45 @@ export class ModelSelectorComponent extends Container {
|
|
|
166
265
|
this.filteredModels = query
|
|
167
266
|
? fuzzyFilter(this.activeModels, query, ({ id, provider }) => `${id} ${provider}`)
|
|
168
267
|
: this.activeModels;
|
|
169
|
-
this.
|
|
268
|
+
this.selectedFlatIndex = Math.min(this.selectedFlatIndex, Math.max(0, this.filteredModels.length - 1));
|
|
170
269
|
this.updateList();
|
|
171
270
|
}
|
|
172
271
|
updateList() {
|
|
173
272
|
this.listContainer.clear();
|
|
273
|
+
if (this.errorMessage) {
|
|
274
|
+
const errorLines = this.errorMessage.split("\n");
|
|
275
|
+
for (const line of errorLines) {
|
|
276
|
+
this.listContainer.addChild(new Text(theme.fg("error", line), 0, 0));
|
|
277
|
+
}
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (this.isSearching) {
|
|
281
|
+
this.renderFlatList();
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
this.renderGroupedList();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/** Flat fuzzy-search results, same as original behaviour */
|
|
288
|
+
renderFlatList() {
|
|
174
289
|
const maxVisible = 10;
|
|
175
|
-
|
|
290
|
+
if (this.filteredModels.length === 0) {
|
|
291
|
+
this.listContainer.addChild(new Text(theme.fg("muted", " No matching models"), 0, 0));
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
const startIndex = Math.max(0, Math.min(this.selectedFlatIndex - Math.floor(maxVisible / 2), this.filteredModels.length - maxVisible));
|
|
176
295
|
const endIndex = Math.min(startIndex + maxVisible, this.filteredModels.length);
|
|
177
|
-
// Show visible slice of filtered models
|
|
178
296
|
for (let i = startIndex; i < endIndex; i++) {
|
|
179
297
|
const item = this.filteredModels[i];
|
|
180
298
|
if (!item)
|
|
181
299
|
continue;
|
|
182
|
-
const isSelected = i === this.
|
|
300
|
+
const isSelected = i === this.selectedFlatIndex;
|
|
183
301
|
const isCurrent = modelsAreEqual(this.currentModel, item.model);
|
|
184
302
|
const ctx = formatTokenCount(item.model.contextWindow);
|
|
185
303
|
const ctxBadge = theme.fg("muted", `${ctx}`);
|
|
186
304
|
const providerBadge = theme.fg("muted", `[${item.provider}]`);
|
|
187
305
|
const checkmark = isCurrent ? theme.fg("success", " ✓") : "";
|
|
188
|
-
let line
|
|
306
|
+
let line;
|
|
189
307
|
if (isSelected) {
|
|
190
308
|
const prefix = theme.fg("accent", "→ ");
|
|
191
309
|
line = `${prefix}${theme.fg("accent", item.id)} ${ctxBadge} ${providerBadge}${checkmark}`;
|
|
@@ -195,40 +313,87 @@ export class ModelSelectorComponent extends Container {
|
|
|
195
313
|
}
|
|
196
314
|
this.listContainer.addChild(new Text(line, 0, 0));
|
|
197
315
|
}
|
|
198
|
-
// Add scroll indicator if needed
|
|
199
316
|
if (startIndex > 0 || endIndex < this.filteredModels.length) {
|
|
200
|
-
|
|
201
|
-
this.listContainer.addChild(new Text(scrollInfo, 0, 0));
|
|
317
|
+
this.listContainer.addChild(new Text(theme.fg("muted", ` (${this.selectedFlatIndex + 1}/${this.filteredModels.length})`), 0, 0));
|
|
202
318
|
}
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
this.listContainer.addChild(new Text(theme.fg("error", line), 0, 0));
|
|
209
|
-
}
|
|
319
|
+
// Detail line for selected model
|
|
320
|
+
const selected = this.filteredModels[this.selectedFlatIndex];
|
|
321
|
+
if (selected) {
|
|
322
|
+
this.listContainer.addChild(new Spacer(1));
|
|
323
|
+
this.listContainer.addChild(new Text(theme.fg("muted", ` ${this.modelDetailLine(selected.model)}`), 0, 0));
|
|
210
324
|
}
|
|
211
|
-
|
|
212
|
-
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Grouped browse view: provider headers + model rows, windowed around selection.
|
|
328
|
+
* Shows enough rows to fill ~10 visible lines; headers count as one line each.
|
|
329
|
+
*/
|
|
330
|
+
renderGroupedList() {
|
|
331
|
+
const maxVisible = 12;
|
|
332
|
+
if (this.groupedRows.length === 0) {
|
|
333
|
+
this.listContainer.addChild(new Text(theme.fg("muted", " No models available"), 0, 0));
|
|
334
|
+
return;
|
|
213
335
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
336
|
+
// Window around selectedGroupIndex
|
|
337
|
+
const startIndex = Math.max(0, Math.min(this.selectedGroupIndex - Math.floor(maxVisible / 2), this.groupedRows.length - maxVisible));
|
|
338
|
+
const endIndex = Math.min(startIndex + maxVisible, this.groupedRows.length);
|
|
339
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
340
|
+
const row = this.groupedRows[i];
|
|
341
|
+
if (!row)
|
|
342
|
+
continue;
|
|
343
|
+
if (row.kind === "header") {
|
|
344
|
+
// Provider group header — always unselectable
|
|
345
|
+
const providerLabel = theme.fg("borderAccent", row.provider);
|
|
346
|
+
const count = theme.fg("muted", ` (${row.count})`);
|
|
347
|
+
// Add blank line before header if not the very first visible row
|
|
348
|
+
if (i > startIndex) {
|
|
349
|
+
this.listContainer.addChild(new Text("", 0, 0));
|
|
350
|
+
}
|
|
351
|
+
this.listContainer.addChild(new Text(` ${providerLabel}${count}`, 0, 0));
|
|
227
352
|
}
|
|
353
|
+
else {
|
|
354
|
+
// Model row
|
|
355
|
+
const isSelected = i === this.selectedGroupIndex;
|
|
356
|
+
const isCurrent = modelsAreEqual(this.currentModel, row.item.model);
|
|
357
|
+
const ctx = formatTokenCount(row.item.model.contextWindow);
|
|
358
|
+
const ctxBadge = theme.fg("muted", ` ${ctx}`);
|
|
359
|
+
const checkmark = isCurrent ? theme.fg("success", " ✓") : "";
|
|
360
|
+
let line;
|
|
361
|
+
if (isSelected) {
|
|
362
|
+
line = ` ${theme.fg("accent", "→")} ${theme.fg("accent", row.item.id)}${ctxBadge}${checkmark}`;
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
line = ` ${row.item.id}${ctxBadge}${checkmark}`;
|
|
366
|
+
}
|
|
367
|
+
this.listContainer.addChild(new Text(line, 0, 0));
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// Scroll indicator
|
|
371
|
+
if (startIndex > 0 || endIndex < this.groupedRows.length) {
|
|
372
|
+
const modelPos = this.modelRowIndices.indexOf(this.selectedGroupIndex) + 1;
|
|
373
|
+
const totalModels = this.modelRowIndices.length;
|
|
374
|
+
this.listContainer.addChild(new Text(theme.fg("muted", ` (${modelPos}/${totalModels})`), 0, 0));
|
|
228
375
|
}
|
|
376
|
+
// Detail line for selected model
|
|
377
|
+
const selectedModel = this.getSelectedModel();
|
|
378
|
+
if (selectedModel) {
|
|
379
|
+
this.listContainer.addChild(new Spacer(1));
|
|
380
|
+
this.listContainer.addChild(new Text(theme.fg("muted", ` ${this.modelDetailLine(selectedModel)}`), 0, 0));
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
modelDetailLine(m) {
|
|
384
|
+
return [
|
|
385
|
+
m.name,
|
|
386
|
+
`ctx: ${formatTokenCount(m.contextWindow)}`,
|
|
387
|
+
`out: ${formatTokenCount(m.maxTokens)}`,
|
|
388
|
+
m.reasoning ? "thinking" : "",
|
|
389
|
+
m.input.includes("image") ? "vision" : "",
|
|
390
|
+
]
|
|
391
|
+
.filter(Boolean)
|
|
392
|
+
.join(" · ");
|
|
229
393
|
}
|
|
230
394
|
handleInput(keyData) {
|
|
231
395
|
const kb = getEditorKeybindings();
|
|
396
|
+
// Tab: scope toggle
|
|
232
397
|
if (kb.matches(keyData, "tab")) {
|
|
233
398
|
if (this.scopedModelItems.length > 0) {
|
|
234
399
|
const nextScope = this.scope === "all" ? "scoped" : "all";
|
|
@@ -239,36 +404,110 @@ export class ModelSelectorComponent extends Container {
|
|
|
239
404
|
}
|
|
240
405
|
return;
|
|
241
406
|
}
|
|
242
|
-
//
|
|
407
|
+
// Navigation keys
|
|
243
408
|
if (kb.matches(keyData, "selectUp")) {
|
|
409
|
+
this.moveUp();
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (kb.matches(keyData, "selectDown")) {
|
|
413
|
+
this.moveDown();
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
// Confirm
|
|
417
|
+
if (kb.matches(keyData, "selectConfirm")) {
|
|
418
|
+
const model = this.getSelectedModel();
|
|
419
|
+
if (model)
|
|
420
|
+
this.handleSelect(model);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
// Cancel
|
|
424
|
+
if (kb.matches(keyData, "selectCancel")) {
|
|
425
|
+
this.onCancelCallback();
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
// Everything else: feed to search input
|
|
429
|
+
const prevQuery = this.searchInput.getValue();
|
|
430
|
+
this.searchInput.handleInput(keyData);
|
|
431
|
+
const newQuery = this.searchInput.getValue();
|
|
432
|
+
if (newQuery !== prevQuery) {
|
|
433
|
+
const entering = !prevQuery && !!newQuery;
|
|
434
|
+
const leaving = !!prevQuery && !newQuery;
|
|
435
|
+
if (entering) {
|
|
436
|
+
// Entering search mode: remember current model position
|
|
437
|
+
this.isSearching = true;
|
|
438
|
+
this.selectedFlatIndex = 0;
|
|
439
|
+
}
|
|
440
|
+
else if (leaving) {
|
|
441
|
+
// Leaving search mode: return to grouped view, restore position
|
|
442
|
+
this.isSearching = false;
|
|
443
|
+
this.buildGroupedRows();
|
|
444
|
+
this.jumpToCurrentModel();
|
|
445
|
+
}
|
|
446
|
+
if (this.isSearching) {
|
|
447
|
+
this.filterModels(newQuery);
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
this.updateList();
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
/** Move selection up, skipping headers in grouped mode */
|
|
455
|
+
moveUp() {
|
|
456
|
+
if (this.isSearching) {
|
|
244
457
|
if (this.filteredModels.length === 0)
|
|
245
458
|
return;
|
|
246
|
-
this.
|
|
459
|
+
this.selectedFlatIndex =
|
|
460
|
+
this.selectedFlatIndex === 0
|
|
461
|
+
? this.filteredModels.length - 1
|
|
462
|
+
: this.selectedFlatIndex - 1;
|
|
247
463
|
this.updateList();
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
if (this.groupedRows.length === 0)
|
|
467
|
+
return;
|
|
468
|
+
let next = this.selectedGroupIndex - 1;
|
|
469
|
+
// Wrap
|
|
470
|
+
if (next < 0)
|
|
471
|
+
next = this.groupedRows.length - 1;
|
|
472
|
+
// Skip headers
|
|
473
|
+
while (next > 0 && this.groupedRows[next]?.kind === "header") {
|
|
474
|
+
next--;
|
|
248
475
|
}
|
|
249
|
-
//
|
|
250
|
-
|
|
476
|
+
// If landed on header at 0, wrap to bottom
|
|
477
|
+
if (this.groupedRows[next]?.kind === "header") {
|
|
478
|
+
next = this.groupedRows.length - 1;
|
|
479
|
+
}
|
|
480
|
+
this.selectedGroupIndex = next;
|
|
481
|
+
this.updateList();
|
|
482
|
+
}
|
|
483
|
+
/** Move selection down, skipping headers in grouped mode */
|
|
484
|
+
moveDown() {
|
|
485
|
+
if (this.isSearching) {
|
|
251
486
|
if (this.filteredModels.length === 0)
|
|
252
487
|
return;
|
|
253
|
-
this.
|
|
488
|
+
this.selectedFlatIndex =
|
|
489
|
+
this.selectedFlatIndex === this.filteredModels.length - 1
|
|
490
|
+
? 0
|
|
491
|
+
: this.selectedFlatIndex + 1;
|
|
254
492
|
this.updateList();
|
|
493
|
+
return;
|
|
255
494
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
this.onCancelCallback();
|
|
495
|
+
if (this.groupedRows.length === 0)
|
|
496
|
+
return;
|
|
497
|
+
let next = this.selectedGroupIndex + 1;
|
|
498
|
+
// Wrap
|
|
499
|
+
if (next >= this.groupedRows.length)
|
|
500
|
+
next = 0;
|
|
501
|
+
// Skip headers
|
|
502
|
+
while (next < this.groupedRows.length - 1 && this.groupedRows[next]?.kind === "header") {
|
|
503
|
+
next++;
|
|
266
504
|
}
|
|
267
|
-
//
|
|
268
|
-
|
|
269
|
-
this.
|
|
270
|
-
this.filterModels(this.searchInput.getValue());
|
|
505
|
+
// If landed on header at end, wrap to first model
|
|
506
|
+
if (this.groupedRows[next]?.kind === "header") {
|
|
507
|
+
next = this.modelRowIndices[0] ?? 0;
|
|
271
508
|
}
|
|
509
|
+
this.selectedGroupIndex = next;
|
|
510
|
+
this.updateList();
|
|
272
511
|
}
|
|
273
512
|
handleSelect(model) {
|
|
274
513
|
// Save as new default
|