@within-7/minto 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Tool.js +7 -0
- package/dist/Tool.js.map +2 -2
- package/dist/commands/agents/AgentsCommand.js +1 -1
- package/dist/commands/agents/AgentsCommand.js.map +2 -2
- package/dist/commands/agents/constants.js +2 -2
- package/dist/commands/agents/constants.js.map +2 -2
- package/dist/commands/clear.js +4 -3
- package/dist/commands/clear.js.map +2 -2
- package/dist/commands/compact.js +2 -2
- package/dist/commands/compact.js.map +1 -1
- package/dist/commands/context.js +3 -1
- package/dist/commands/context.js.map +2 -2
- package/dist/commands/login.js +128 -0
- package/dist/commands/login.js.map +7 -0
- package/dist/commands/memory.js +33 -82
- package/dist/commands/memory.js.map +2 -2
- package/dist/commands/quit.js +3 -1
- package/dist/commands/quit.js.map +2 -2
- package/dist/commands/resume.js +39 -239
- package/dist/commands/resume.js.map +2 -2
- package/dist/commands/tasks.js +1 -1
- package/dist/commands/tasks.js.map +2 -2
- package/dist/commands/terminalSetup.js +6 -2
- package/dist/commands/terminalSetup.js.map +2 -2
- package/dist/commands.js +2 -0
- package/dist/commands.js.map +2 -2
- package/dist/components/AgentDetailView.js +126 -0
- package/dist/components/AgentDetailView.js.map +7 -0
- package/dist/components/AgentThinkingBlock.js +1 -1
- package/dist/components/AgentThinkingBlock.js.map +2 -2
- package/dist/components/AgentViewBanner.js +22 -0
- package/dist/components/AgentViewBanner.js.map +7 -0
- package/dist/components/HeaderBar.js +1 -1
- package/dist/components/HeaderBar.js.map +2 -2
- package/dist/components/Help.js +8 -1
- package/dist/components/Help.js.map +2 -2
- package/dist/components/HotkeyHelpPanel.js +26 -8
- package/dist/components/HotkeyHelpPanel.js.map +2 -2
- package/dist/components/IdleNotificationBar.js +10 -0
- package/dist/components/IdleNotificationBar.js.map +7 -0
- package/dist/components/ModelSelector/ModelSelector.js +55 -20
- package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
- package/dist/components/PromptInput.js +186 -115
- package/dist/components/PromptInput.js.map +2 -2
- package/dist/components/RewindPanel.js +272 -0
- package/dist/components/RewindPanel.js.map +7 -0
- package/dist/components/Spinner.js +10 -21
- package/dist/components/Spinner.js.map +2 -2
- package/dist/components/StreamingTextPreview.js +29 -0
- package/dist/components/StreamingTextPreview.js.map +7 -0
- package/dist/components/SubagentBlock.js +3 -2
- package/dist/components/SubagentBlock.js.map +2 -2
- package/dist/components/SubagentProgress.js +4 -4
- package/dist/components/SubagentProgress.js.map +2 -2
- package/dist/components/TabbedListView/SearchInput.js +1 -1
- package/dist/components/TabbedListView/SearchInput.js.map +2 -2
- package/dist/components/TabbedListView/TabbedListView.js +87 -41
- package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
- package/dist/components/TaskCard.js +4 -4
- package/dist/components/TaskCard.js.map +2 -2
- package/dist/components/TeamMemberPanel.js +107 -0
- package/dist/components/TeamMemberPanel.js.map +7 -0
- package/dist/components/ThinkingSelector.js +84 -0
- package/dist/components/ThinkingSelector.js.map +7 -0
- package/dist/components/TitledDivider.js +26 -0
- package/dist/components/TitledDivider.js.map +7 -0
- package/dist/components/TodoPanel.js +31 -30
- package/dist/components/TodoPanel.js.map +2 -2
- package/dist/components/TokenWarning.js +28 -7
- package/dist/components/TokenWarning.js.map +2 -2
- package/dist/components/messages/AssistantTextMessage.js +5 -2
- package/dist/components/messages/AssistantTextMessage.js.map +2 -2
- package/dist/components/messages/AssistantToolUseMessage.js +9 -1
- package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
- package/dist/components/messages/DefaultToolResultFallback.js +11 -0
- package/dist/components/messages/DefaultToolResultFallback.js.map +7 -0
- package/dist/components/messages/ParallelTasksGroupView.js +14 -6
- package/dist/components/messages/ParallelTasksGroupView.js.map +2 -2
- package/dist/components/messages/TaskInModuleView.js +27 -27
- package/dist/components/messages/TaskInModuleView.js.map +2 -2
- package/dist/components/messages/UserGuidanceMessage.js +26 -0
- package/dist/components/messages/UserGuidanceMessage.js.map +7 -0
- package/dist/components/messages/UserPromptMessage.js +2 -1
- package/dist/components/messages/UserPromptMessage.js.map +2 -2
- package/dist/components/messages/UserTeamNotificationMessage.js +91 -0
- package/dist/components/messages/UserTeamNotificationMessage.js.map +7 -0
- package/dist/components/messages/UserTextMessage.js +8 -0
- package/dist/components/messages/UserTextMessage.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js +4 -2
- package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js +18 -1
- package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +12 -1
- package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js.map +2 -2
- package/dist/components/permissions/PermissionRequest.js +4 -0
- package/dist/components/permissions/PermissionRequest.js.map +2 -2
- package/dist/components/permissions/PlanApprovalRequest.js +164 -0
- package/dist/components/permissions/PlanApprovalRequest.js.map +7 -0
- package/dist/constants/agentTeams.js +17 -0
- package/dist/constants/agentTeams.js.map +7 -0
- package/dist/constants/macros.js +2 -1
- package/dist/constants/macros.js.map +2 -2
- package/dist/constants/prompts/agentPrompt.js +1 -0
- package/dist/constants/prompts/agentPrompt.js.map +2 -2
- package/dist/constants/prompts/autoMemory.js +39 -0
- package/dist/constants/prompts/autoMemory.js.map +7 -0
- package/dist/constants/prompts/codeConventions.js +1 -13
- package/dist/constants/prompts/codeConventions.js.map +2 -2
- package/dist/constants/prompts/doingTasks.js +21 -2
- package/dist/constants/prompts/doingTasks.js.map +2 -2
- package/dist/constants/prompts/envInfo.js +6 -7
- package/dist/constants/prompts/envInfo.js.map +2 -2
- package/dist/constants/prompts/index.js +27 -5
- package/dist/constants/prompts/index.js.map +2 -2
- package/dist/constants/prompts/taskManagement.js +2 -43
- package/dist/constants/prompts/taskManagement.js.map +2 -2
- package/dist/constants/prompts/teamOverlays.js +50 -0
- package/dist/constants/prompts/teamOverlays.js.map +7 -0
- package/dist/constants/prompts/toneAndStyle.js +4 -29
- package/dist/constants/prompts/toneAndStyle.js.map +2 -2
- package/dist/constants/prompts/toolUsagePolicy.js +7 -22
- package/dist/constants/prompts/toolUsagePolicy.js.map +2 -2
- package/dist/constants/toolInputExamples.js +2 -2
- package/dist/constants/toolInputExamples.js.map +2 -2
- package/dist/context.js +39 -6
- package/dist/context.js.map +2 -2
- package/dist/core/backupManager.js +1 -1
- package/dist/core/backupManager.js.map +2 -2
- package/dist/core/permissions/rules/planModeRule.js +1 -1
- package/dist/core/permissions/rules/planModeRule.js.map +1 -1
- package/dist/core/permissions/rules/safeModeRule.js +1 -1
- package/dist/core/permissions/rules/safeModeRule.js.map +1 -1
- package/dist/engine/AgentEngine.js +902 -0
- package/dist/engine/AgentEngine.js.map +7 -0
- package/dist/engine/EngineRegistry.js +89 -0
- package/dist/engine/EngineRegistry.js.map +7 -0
- package/dist/engine/foregroundAdapter.js +191 -0
- package/dist/engine/foregroundAdapter.js.map +7 -0
- package/dist/engine/index.js +15 -0
- package/dist/engine/index.js.map +7 -0
- package/dist/engine/types.js +1 -0
- package/dist/engine/types.js.map +7 -0
- package/dist/entrypoints/cli.js +410 -79
- package/dist/entrypoints/cli.js.map +3 -3
- package/dist/hooks/useAgentEngine.js +129 -0
- package/dist/hooks/useAgentEngine.js.map +7 -0
- package/dist/hooks/useAgentTokenStats.js +0 -16
- package/dist/hooks/useAgentTokenStats.js.map +2 -2
- package/dist/hooks/useCanUseTool.js +47 -2
- package/dist/hooks/useCanUseTool.js.map +2 -2
- package/dist/hooks/useDeferredLoading.js +4 -1
- package/dist/hooks/useDeferredLoading.js.map +2 -2
- package/dist/hooks/useIdleNotifications.js +66 -0
- package/dist/hooks/useIdleNotifications.js.map +7 -0
- package/dist/hooks/useSessionTracking.js +9 -7
- package/dist/hooks/useSessionTracking.js.map +2 -2
- package/dist/hooks/useTeamMembers.js +51 -0
- package/dist/hooks/useTeamMembers.js.map +7 -0
- package/dist/i18n/locales/en.js +77 -12
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.js +77 -12
- package/dist/i18n/locales/zh-CN.js.map +2 -2
- package/dist/i18n/types.js.map +1 -1
- package/dist/messages.js.map +2 -2
- package/dist/permissions.js +113 -7
- package/dist/permissions.js.map +2 -2
- package/dist/query.js +135 -37
- package/dist/query.js.map +2 -2
- package/dist/screens/REPL.js +504 -361
- package/dist/screens/REPL.js.map +3 -3
- package/dist/screens/ResumeConversation.js +199 -14
- package/dist/screens/ResumeConversation.js.map +2 -2
- package/dist/services/adapters/base.js.map +1 -1
- package/dist/services/agentTeams/backends/headless.js +108 -0
- package/dist/services/agentTeams/backends/headless.js.map +7 -0
- package/dist/services/agentTeams/backends/inProcess.js +102 -0
- package/dist/services/agentTeams/backends/inProcess.js.map +7 -0
- package/dist/services/agentTeams/backends/resolver.js +18 -0
- package/dist/services/agentTeams/backends/resolver.js.map +7 -0
- package/dist/services/agentTeams/backends/tmux.js +168 -0
- package/dist/services/agentTeams/backends/tmux.js.map +7 -0
- package/dist/services/agentTeams/backends/types.js +1 -0
- package/dist/services/agentTeams/backends/types.js.map +7 -0
- package/dist/services/agentTeams/heartbeat.js +88 -0
- package/dist/services/agentTeams/heartbeat.js.map +7 -0
- package/dist/services/agentTeams/index.js +42 -2
- package/dist/services/agentTeams/index.js.map +2 -2
- package/dist/services/agentTeams/injectionChannel.js +105 -0
- package/dist/services/agentTeams/injectionChannel.js.map +7 -0
- package/dist/services/agentTeams/mailbox.js +410 -30
- package/dist/services/agentTeams/mailbox.js.map +2 -2
- package/dist/services/agentTeams/messageFormatter.js +80 -0
- package/dist/services/agentTeams/messageFormatter.js.map +7 -0
- package/dist/services/agentTeams/permissionDelegation.js +71 -0
- package/dist/services/agentTeams/permissionDelegation.js.map +7 -0
- package/dist/services/agentTeams/teamEvents.js +45 -0
- package/dist/services/agentTeams/teamEvents.js.map +7 -0
- package/dist/services/agentTeams/teamManager.js +251 -34
- package/dist/services/agentTeams/teamManager.js.map +2 -2
- package/dist/services/agentTeams/teamTaskStore.js +290 -61
- package/dist/services/agentTeams/teamTaskStore.js.map +2 -2
- package/dist/services/agentTeams/teammateSpawner.js +99 -18
- package/dist/services/agentTeams/teammateSpawner.js.map +2 -2
- package/dist/services/hookExecutor.js +51 -8
- package/dist/services/hookExecutor.js.map +2 -2
- package/dist/services/llm/anthropicProvider.js +56 -59
- package/dist/services/llm/anthropicProvider.js.map +2 -2
- package/dist/services/llm/dispatch.js +24 -5
- package/dist/services/llm/dispatch.js.map +2 -2
- package/dist/services/llm/openaiProvider.js +115 -136
- package/dist/services/llm/openaiProvider.js.map +3 -3
- package/dist/services/llm/types.js +89 -15
- package/dist/services/llm/types.js.map +2 -2
- package/dist/services/mcpClient.js +80 -4
- package/dist/services/mcpClient.js.map +2 -2
- package/dist/services/mintoAuth.js +299 -0
- package/dist/services/mintoAuth.js.map +7 -0
- package/dist/services/oauth.js +3 -3
- package/dist/services/oauth.js.map +2 -2
- package/dist/services/openai.js +91 -20
- package/dist/services/openai.js.map +2 -2
- package/dist/services/plugins/pluginRuntime.js +11 -5
- package/dist/services/plugins/pluginRuntime.js.map +2 -2
- package/dist/services/plugins/pluginValidation.js +4 -2
- package/dist/services/plugins/pluginValidation.js.map +2 -2
- package/dist/services/sandbox/sandboxController.js +11 -3
- package/dist/services/sandbox/sandboxController.js.map +2 -2
- package/dist/services/sessionMemoryInjector.js +77 -0
- package/dist/services/sessionMemoryInjector.js.map +7 -0
- package/dist/services/systemReminder.js +130 -8
- package/dist/services/systemReminder.js.map +2 -2
- package/dist/services/taskStore.js +199 -8
- package/dist/services/taskStore.js.map +3 -3
- package/dist/services/topicDetector.js +169 -0
- package/dist/services/topicDetector.js.map +7 -0
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +0 -13
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +2 -2
- package/dist/tools/BashTool/BashTool.js +51 -28
- package/dist/tools/BashTool/BashTool.js.map +2 -2
- package/dist/tools/BashTool/prompt.js +95 -118
- package/dist/tools/BashTool/prompt.js.map +2 -2
- package/dist/tools/BashTool/utils.js +39 -1
- package/dist/tools/BashTool/utils.js.map +2 -2
- package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js +121 -0
- package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js.map +7 -0
- package/dist/tools/EnterWorktreeTool/prompt.js +22 -0
- package/dist/tools/EnterWorktreeTool/prompt.js.map +7 -0
- package/dist/tools/FileEditTool/FileEditTool.js +9 -4
- package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
- package/dist/tools/FileEditTool/prompt.js +3 -7
- package/dist/tools/FileEditTool/prompt.js.map +2 -2
- package/dist/tools/FileReadTool/FileReadTool.js +125 -3
- package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
- package/dist/tools/FileReadTool/prompt.js +1 -2
- package/dist/tools/FileReadTool/prompt.js.map +2 -2
- package/dist/tools/FileWriteTool/prompt.js +3 -5
- package/dist/tools/FileWriteTool/prompt.js.map +2 -2
- package/dist/tools/GlobTool/GlobTool.js +3 -2
- package/dist/tools/GlobTool/GlobTool.js.map +2 -2
- package/dist/tools/GrepTool/GrepTool.js +16 -5
- package/dist/tools/GrepTool/GrepTool.js.map +2 -2
- package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +2 -2
- package/dist/tools/MCPSearchTool/MCPSearchTool.js +172 -0
- package/dist/tools/MCPSearchTool/MCPSearchTool.js.map +7 -0
- package/dist/tools/MCPSearchTool/prompt.js +77 -0
- package/dist/tools/MCPSearchTool/prompt.js.map +7 -0
- package/dist/tools/MultiEditTool/prompt.js +4 -7
- package/dist/tools/MultiEditTool/prompt.js.map +2 -2
- package/dist/tools/PlanModeTool/EnterPlanModeTool.js +12 -8
- package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +2 -2
- package/dist/tools/PlanModeTool/ExitPlanModeTool.js +54 -1
- package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +2 -2
- package/dist/tools/PlanModeTool/prompt.js +23 -74
- package/dist/tools/PlanModeTool/prompt.js.map +2 -2
- package/dist/tools/SendMessageTool/SendMessageTool.js +341 -0
- package/dist/tools/SendMessageTool/SendMessageTool.js.map +7 -0
- package/dist/tools/SendMessageTool/prompt.js +44 -0
- package/dist/tools/SendMessageTool/prompt.js.map +7 -0
- package/dist/tools/TaskCreateTool/prompt.js +15 -4
- package/dist/tools/TaskCreateTool/prompt.js.map +2 -2
- package/dist/tools/TaskListTool/prompt.js +18 -3
- package/dist/tools/TaskListTool/prompt.js.map +2 -2
- package/dist/tools/TaskOutputTool/prompt.js +4 -3
- package/dist/tools/TaskOutputTool/prompt.js.map +2 -2
- package/dist/tools/TaskTool/TaskTool.js +762 -98
- package/dist/tools/TaskTool/TaskTool.js.map +3 -3
- package/dist/tools/TaskTool/constants.js +8 -2
- package/dist/tools/TaskTool/constants.js.map +2 -2
- package/dist/tools/TaskTool/prompt.js +74 -70
- package/dist/tools/TaskTool/prompt.js.map +2 -2
- package/dist/tools/TaskUpdateTool/TaskUpdateTool.js +15 -1
- package/dist/tools/TaskUpdateTool/TaskUpdateTool.js.map +2 -2
- package/dist/tools/TeamCreateTool/TeamCreateTool.js +129 -0
- package/dist/tools/TeamCreateTool/TeamCreateTool.js.map +7 -0
- package/dist/tools/TeamCreateTool/prompt.js +58 -0
- package/dist/tools/TeamCreateTool/prompt.js.map +7 -0
- package/dist/tools/TeamDeleteTool/TeamDeleteTool.js +151 -0
- package/dist/tools/TeamDeleteTool/TeamDeleteTool.js.map +7 -0
- package/dist/tools/TeamDeleteTool/prompt.js +16 -0
- package/dist/tools/TeamDeleteTool/prompt.js.map +7 -0
- package/dist/tools/URLFetcherTool/URLFetcherTool.js +106 -15
- package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +2 -2
- package/dist/tools/URLFetcherTool/prompt.js +3 -2
- package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
- package/dist/tools/WebSearchTool/WebSearchTool.js +2 -1
- package/dist/tools/WebSearchTool/WebSearchTool.js.map +2 -2
- package/dist/tools/WebSearchTool/prompt.js +5 -4
- package/dist/tools/WebSearchTool/prompt.js.map +2 -2
- package/dist/tools.js +100 -20
- package/dist/tools.js.map +2 -2
- package/dist/types/PermissionMode.js +35 -6
- package/dist/types/PermissionMode.js.map +2 -2
- package/dist/types/hooks.js +2 -0
- package/dist/types/hooks.js.map +2 -2
- package/dist/types/plugin.js +2 -0
- package/dist/types/plugin.js.map +3 -3
- package/dist/utils/CircuitBreaker.js +15 -9
- package/dist/utils/CircuitBreaker.js.map +2 -2
- package/dist/utils/agentLoader.js +249 -112
- package/dist/utils/agentLoader.js.map +2 -2
- package/dist/utils/animationManager.js +40 -3
- package/dist/utils/animationManager.js.map +2 -2
- package/dist/utils/ask.js +7 -6
- package/dist/utils/ask.js.map +2 -2
- package/dist/utils/atomicWrite.js +23 -0
- package/dist/utils/atomicWrite.js.map +7 -0
- package/dist/utils/autoCompactCore.js +73 -56
- package/dist/utils/autoCompactCore.js.map +2 -2
- package/dist/utils/autoMemoryPaths.js +89 -0
- package/dist/utils/autoMemoryPaths.js.map +7 -0
- package/dist/utils/config.js +63 -38
- package/dist/utils/config.js.map +2 -2
- package/dist/utils/configSchema.js +13 -8
- package/dist/utils/configSchema.js.map +2 -2
- package/dist/utils/credentials/index.js +14 -0
- package/dist/utils/credentials/index.js.map +2 -2
- package/dist/utils/dualPath.js +24 -0
- package/dist/utils/dualPath.js.map +7 -0
- package/dist/utils/exit.js +66 -7
- package/dist/utils/exit.js.map +2 -2
- package/dist/utils/externalEditor.js +155 -0
- package/dist/utils/externalEditor.js.map +7 -0
- package/dist/utils/fileLock.js +67 -0
- package/dist/utils/fileLock.js.map +7 -0
- package/dist/utils/format.js +24 -14
- package/dist/utils/format.js.map +2 -2
- package/dist/utils/globalErrorHandler.js +5 -96
- package/dist/utils/globalErrorHandler.js.map +3 -3
- package/dist/utils/groupHandlers/parallelTasksHandler.js +5 -3
- package/dist/utils/groupHandlers/parallelTasksHandler.js.map +2 -2
- package/dist/utils/groupHandlers/taskHandler.js +2 -2
- package/dist/utils/groupHandlers/taskHandler.js.map +2 -2
- package/dist/utils/hookManager.js +64 -6
- package/dist/utils/hookManager.js.map +2 -2
- package/dist/utils/log.js +6 -2
- package/dist/utils/log.js.map +2 -2
- package/dist/utils/markdown.js +237 -19
- package/dist/utils/markdown.js.map +2 -2
- package/dist/utils/messageContextManager.js +18 -5
- package/dist/utils/messageContextManager.js.map +2 -2
- package/dist/utils/messageGroupManager.js +1 -1
- package/dist/utils/messageGroupManager.js.map +2 -2
- package/dist/utils/messages.js +104 -46
- package/dist/utils/messages.js.map +2 -2
- package/dist/utils/model.js +2 -2
- package/dist/utils/model.js.map +2 -2
- package/dist/utils/pasteCache.js +8 -4
- package/dist/utils/pasteCache.js.map +2 -2
- package/dist/utils/pluginLoader.js +18 -0
- package/dist/utils/pluginLoader.js.map +2 -2
- package/dist/utils/secureKeyStorage.js +36 -7
- package/dist/utils/secureKeyStorage.js.map +2 -2
- package/dist/utils/simpleMode.js +7 -0
- package/dist/utils/simpleMode.js.map +7 -0
- package/dist/utils/streamingState.js +11 -1
- package/dist/utils/streamingState.js.map +2 -2
- package/dist/utils/taskDisplayUtils.js +2 -1
- package/dist/utils/taskDisplayUtils.js.map +2 -2
- package/dist/utils/teamConfig.js +2 -2
- package/dist/utils/teamConfig.js.map +2 -2
- package/dist/utils/thinking.js +6 -2
- package/dist/utils/thinking.js.map +3 -3
- package/dist/utils/tokenProgress.js +55 -0
- package/dist/utils/tokenProgress.js.map +7 -0
- package/dist/utils/toolRiskClassification.js +26 -17
- package/dist/utils/toolRiskClassification.js.map +2 -2
- package/dist/utils/tooling/toolError.js +12 -0
- package/dist/utils/tooling/toolError.js.map +7 -0
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/package.json +10 -8
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/ModelSelector/ModelSelector.tsx"],
|
|
4
|
-
"sourcesContent": ["import React, { useState, useEffect, useCallback } from 'react'\nimport { Text, useInput } from 'ink'\nimport { getModelManager } from '@utils/model'\nimport { useExitOnCtrlCD } from '@hooks/useExitOnCtrlCD'\nimport {\n getGlobalConfig,\n saveGlobalConfig,\n ProviderType,\n ModelPointerType,\n ModelProfile,\n setAllPointersToModel,\n setModelPointer,\n} from '@utils/config'\nimport models, { providers } from '@constants/models'\nimport OpenAI from 'openai'\nimport { fetchAnthropicModels, verifyApiKey } from '@services/claude'\nimport { fetchCustomModels, getModelFeatures } from '@services/openai'\nimport {\n testGPT5Connection,\n validateGPT5Config,\n} from '@services/gpt5ConnectionTest'\nimport { SEMANTIC_COLORS } from '@constants/colors'\nimport { isOpenAICompatibleProvider } from '@constants/providers'\nimport { getEffectiveCapabilities } from '@constants/providerRegistry'\nimport { t } from '@i18n'\n\n// Brand-consistent components\nimport { SimpleSelector } from '@components/SimpleSelector/SimpleSelector'\nimport { InfoPanel } from '@components/InfoPanel/InfoPanel'\nimport type { SelectorItem } from '@components/SimpleSelector/types'\nimport type { InfoSection, InfoPanelAction } from '@components/InfoPanel/types'\nimport { BrandTextInput } from './BrandTextInput'\n\n// Import from local modules\nimport {\n CONTEXT_LENGTH_OPTIONS,\n DEFAULT_CONTEXT_LENGTH,\n MAX_TOKENS_OPTIONS,\n DEFAULT_MAX_TOKENS,\n} from './constants'\nimport type {\n ModelInfo,\n ScreenType,\n ReasoningEffortOption,\n AnthropicProviderType,\n ConnectionTestResult,\n} from './types'\n\ntype Props = {\n onDone: () => void\n abortController?: AbortController\n targetPointer?: ModelPointerType\n isOnboarding?: boolean\n onCancel?: () => void\n skipModelType?: boolean\n editingModel?: ModelProfile\n}\n\nexport function ModelSelector({\n onDone: onDoneProp,\n abortController,\n targetPointer,\n isOnboarding = false,\n onCancel,\n skipModelType = false,\n editingModel,\n}: Props): React.ReactNode {\n const config = getGlobalConfig()\n const onDone = onDoneProp\n // Initialize the exit hook for Ctrl+C/D\n useExitOnCtrlCD(() => process.exit(0))\n\n // Edit mode starts directly at testAndSave; add mode starts at provider\n const isEditMode = !!editingModel\n\n // Screen navigation stack\n const [screenStack, setScreenStack] = useState<\n Array<\n | 'provider'\n | 'anthropicSubMenu'\n | 'apiKey'\n | 'resourceName'\n | 'baseUrl'\n | 'model'\n | 'modelInput'\n | 'modelParams'\n | 'contextLength'\n | 'testAndSave'\n >\n >([isEditMode ? 'testAndSave' : 'provider'])\n\n // Current screen is always the last item in the stack\n const currentScreen = screenStack[screenStack.length - 1]\n\n // Function to navigate to a new screen\n const navigateTo = (\n screen:\n | 'provider'\n | 'anthropicSubMenu'\n | 'apiKey'\n | 'resourceName'\n | 'baseUrl'\n | 'model'\n | 'modelInput'\n | 'modelParams'\n | 'contextLength'\n | 'testAndSave',\n ) => {\n setScreenStack(prev => [...prev, screen])\n }\n\n // Function to go back to the previous screen\n const goBack = () => {\n if (screenStack.length > 1) {\n // Remove the current screen from the stack\n setScreenStack(prev => prev.slice(0, -1))\n } else {\n // If we're at the first screen, call onDone to exit\n onDone()\n }\n }\n\n // State for model configuration (initialized from editingModel in edit mode)\n const [selectedProvider, setSelectedProvider] = useState<ProviderType>(\n editingModel?.provider ?? config.primaryProvider ?? 'anthropic',\n )\n\n // State for Anthropic provider sub-menu\n const [anthropicProviderType, setAnthropicProviderType] = useState<\n 'official' | 'bigdream' | 'opendev' | 'custom'\n >('official')\n const [selectedModel, setSelectedModel] = useState<string>(\n editingModel?.modelName ?? '',\n )\n const [apiKey, setApiKey] = useState<string>(editingModel?.apiKey ?? '')\n\n // New state for model parameters\n const [maxTokens, setMaxTokens] = useState<string>(\n editingModel?.maxTokens?.toString() ??\n config.maxTokens?.toString() ??\n DEFAULT_MAX_TOKENS.toString(),\n )\n const [maxTokensMode, setMaxTokensMode] = useState<'preset' | 'custom'>(\n 'preset',\n )\n const [selectedMaxTokensPreset, setSelectedMaxTokensPreset] =\n useState<number>(config.maxTokens || DEFAULT_MAX_TOKENS)\n const [reasoningEffort, setReasoningEffort] = useState<ReasoningEffortOption>(\n (editingModel?.reasoningEffort as ReasoningEffortOption) ?? 'medium',\n )\n const [supportsReasoningEffort, setSupportsReasoningEffort] =\n useState<boolean>(!!editingModel?.reasoningEffort)\n\n // Context length state (use default instead of legacy config)\n const [contextLength, setContextLength] = useState<number>(\n editingModel?.contextLength ?? DEFAULT_CONTEXT_LENGTH,\n )\n\n // Form focus state\n const [activeFieldIndex, setActiveFieldIndex] = useState(0)\n const [maxTokensCursorOffset, setMaxTokensCursorOffset] = useState<number>(0)\n\n // UI state\n\n // Search and model loading state\n const [availableModels, setAvailableModels] = useState<ModelInfo[]>([])\n const [isLoadingModels, setIsLoadingModels] = useState(false)\n const [modelLoadError, setModelLoadError] = useState<string | null>(null)\n const [modelSearchQuery, setModelSearchQuery] = useState<string>('')\n const [modelSearchCursorOffset, setModelSearchCursorOffset] =\n useState<number>(0)\n const [cursorOffset, setCursorOffset] = useState<number>(0)\n const [apiKeyEdited, setApiKeyEdited] = useState<boolean>(isEditMode)\n\n // Retry logic state\n const [fetchRetryCount, setFetchRetryCount] = useState<number>(0)\n const [isRetrying, setIsRetrying] = useState<boolean>(false)\n\n // Connection test state\n const [isTestingConnection, setIsTestingConnection] = useState<boolean>(false)\n const [connectionTestResult, setConnectionTestResult] = useState<{\n success: boolean\n message: string\n endpoint?: string\n details?: string\n } | null>(null)\n\n // Validation error state for duplicate model detection\n const [validationError, setValidationError] = useState<string | null>(null)\n\n // Track whether model was manually entered (needs contextLength screen)\n const [isManualModelEntry, setIsManualModelEntry] = useState<boolean>(false)\n\n // State for Azure-specific configuration\n const [resourceName, setResourceName] = useState<string>('')\n const [resourceNameCursorOffset, setResourceNameCursorOffset] =\n useState<number>(0)\n const [customModelName, setCustomModelName] = useState<string>('')\n const [customModelNameCursorOffset, setCustomModelNameCursorOffset] =\n useState<number>(0)\n\n // State for Ollama-specific configuration\n const [ollamaBaseUrl, setOllamaBaseUrl] = useState<string>(\n 'http://localhost:11434/v1',\n )\n const [ollamaBaseUrlCursorOffset, setOllamaBaseUrlCursorOffset] =\n useState<number>(0)\n\n // State for custom OpenAI-compatible API configuration\n const [customBaseUrl, setCustomBaseUrl] = useState<string>('')\n const [customBaseUrlCursorOffset, setCustomBaseUrlCursorOffset] =\n useState<number>(0)\n\n // State for provider base URL configuration (used for all providers)\n const [providerBaseUrl, setProviderBaseUrl] = useState<string>(\n editingModel?.baseURL ?? '',\n )\n const [providerBaseUrlCursorOffset, setProviderBaseUrlCursorOffset] =\n useState<number>(0)\n\n // Reasoning effort options\n const reasoningEffortOptions = [\n { label: 'Low - Faster responses, less thorough reasoning', value: 'low' },\n { label: 'Medium - Balanced speed and reasoning depth', value: 'medium' },\n {\n label: 'High - Slower responses, more thorough reasoning',\n value: 'high',\n },\n ]\n\n // Get available providers from models.ts, excluding community Claude providers (now in Anthropic sub-menu)\n const availableProviders = Object.keys(providers).filter(\n provider => provider !== 'bigdream' && provider !== 'opendev',\n )\n\n // Create provider options with nice labels\n const providerOptions = availableProviders.map(provider => {\n const modelCount = models[provider]?.length || 0\n const label = getProviderLabel(provider, modelCount)\n return {\n label,\n value: provider,\n }\n })\n\n useEffect(() => {\n if (!apiKeyEdited && selectedProvider) {\n if (process.env[selectedProvider.toUpperCase() + '_API_KEY']) {\n setApiKey(\n process.env[selectedProvider.toUpperCase() + '_API_KEY'] as string,\n )\n } else {\n setApiKey('')\n }\n }\n }, [selectedProvider, apiKey, apiKeyEdited])\n\n // Ensure contextLength is always set to a valid option when contextLength screen is displayed\n useEffect(() => {\n if (\n currentScreen === 'contextLength' &&\n !CONTEXT_LENGTH_OPTIONS.find(opt => opt.value === contextLength)\n ) {\n setContextLength(DEFAULT_CONTEXT_LENGTH)\n }\n }, [currentScreen, contextLength])\n\n // Auto-start connection test when entering testAndSave screen (add mode only)\n useEffect(() => {\n if (\n currentScreen === 'testAndSave' &&\n !isEditMode &&\n !isTestingConnection &&\n !connectionTestResult\n ) {\n handleConnectionTest()\n }\n }, [currentScreen])\n\n // Create a set of model names from our constants/models.ts for the current provider\n const ourModelNames = new Set(\n (models[selectedProvider as keyof typeof models] || []).map(\n (model: any) => model.model,\n ),\n )\n\n // Create model options from available models, filtered by search query\n const filteredModels = modelSearchQuery\n ? availableModels.filter(model =>\n model.model?.toLowerCase().includes(modelSearchQuery.toLowerCase()),\n )\n : availableModels\n\n // Sort models with priority for specific keywords\n const sortModelsByPriority = (models: ModelInfo[]) => {\n const priorityKeywords = [\n 'claude',\n 'kimi',\n 'deepseek',\n 'minimax',\n 'o3',\n 'gpt',\n 'qwen',\n ]\n\n return models.sort((a, b) => {\n // Add safety checks for undefined model names\n const aModelLower = a.model?.toLowerCase() || ''\n const bModelLower = b.model?.toLowerCase() || ''\n\n // Check if models contain priority keywords\n const aHasPriority = priorityKeywords.some(keyword =>\n aModelLower.includes(keyword),\n )\n const bHasPriority = priorityKeywords.some(keyword =>\n bModelLower.includes(keyword),\n )\n\n // If one has priority and the other doesn't, prioritize the one with keywords\n if (aHasPriority && !bHasPriority) return -1\n if (!aHasPriority && bHasPriority) return 1\n\n // If both have priority or neither has priority, sort alphabetically\n return a.model.localeCompare(b.model)\n })\n }\n\n const sortedFilteredModels = sortModelsByPriority(filteredModels)\n\n const modelOptions = sortedFilteredModels.map(model => {\n // Check if this model is in our constants/models.ts list\n const isInOurModels = ourModelNames.has(model.model)\n\n return {\n label: `${model.model}${getModelDetails(model)}`,\n value: model.model,\n }\n })\n\n function getModelDetails(model: ModelInfo): string {\n const details = []\n\n // Show context_length if available (Ollama models), otherwise max_tokens\n if (model.context_length) {\n details.push(`${formatNumber(model.context_length)} tokens`)\n } else if (model.max_tokens) {\n details.push(`${formatNumber(model.max_tokens)} tokens`)\n }\n\n if (model.supports_vision) {\n details.push('vision')\n }\n\n if (model.supports_function_calling) {\n details.push('tools')\n }\n\n return details.length > 0 ? ` (${details.join(', ')})` : ''\n }\n\n function formatNumber(num: number): string {\n if (num >= 1000000) {\n return `${(num / 1000000).toFixed(1)}M`\n } else if (num >= 1000) {\n return `${(num / 1000).toFixed(0)}K`\n }\n return num.toString()\n }\n\n function getProviderLabel(provider: string, modelCount: number): string {\n // Use provider names from the providers object if available\n if (providers[provider]) {\n return `${providers[provider].name} ${providers[provider].status === 'wip' ? '(WIP)' : ''} (${modelCount} models)`\n }\n return `${provider}`\n }\n\n function handleProviderSelection(provider: string) {\n const providerType = provider as ProviderType\n setSelectedProvider(providerType)\n\n if (provider === 'custom') {\n // For custom provider, save and exit\n saveConfiguration(providerType, selectedModel || '')\n onDone()\n } else if (provider === 'anthropic') {\n // For Anthropic provider, go to sub-menu to choose between official, community proxies, or custom\n navigateTo('anthropicSubMenu')\n } else {\n // For all other providers, go to base URL configuration first\n // Initialize with the default base URL for the provider\n const defaultBaseUrl = providers[providerType]?.baseURL || ''\n setProviderBaseUrl(defaultBaseUrl)\n navigateTo('baseUrl')\n }\n }\n\n // Local implementation of fetchAnthropicModels for UI\n async function fetchAnthropicModels(baseURL: string, apiKey: string) {\n try {\n const response = await fetch(`${baseURL}/v1/models`, {\n method: 'GET',\n headers: {\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n signal: AbortSignal.timeout(30_000),\n })\n\n if (!response.ok) {\n if (response.status === 401) {\n throw new Error(\n 'Invalid API key. Please check your API key and try again.',\n )\n } else if (response.status === 403) {\n throw new Error('API key does not have permission to access models.')\n } else if (response.status === 404) {\n throw new Error(\n 'API endpoint not found. This provider may not support model listing.',\n )\n } else if (response.status === 429) {\n throw new Error(\n 'Too many requests. Please wait a moment and try again.',\n )\n } else if (response.status >= 500) {\n throw new Error(\n 'API service is temporarily unavailable. Please try again later.',\n )\n } else {\n throw new Error(`Unable to connect to API (${response.status}).`)\n }\n }\n\n const data = await response.json()\n\n // Handle different response formats\n let models = []\n if (data && data.data && Array.isArray(data.data)) {\n models = data.data\n } else if (Array.isArray(data)) {\n models = data\n } else if (data && data.models && Array.isArray(data.models)) {\n models = data.models\n } else {\n throw new Error('API returned unexpected response format.')\n }\n\n return models\n } catch (error) {\n if (\n error instanceof Error &&\n (error.message.includes('API key') ||\n error.message.includes('API endpoint') ||\n error.message.includes('API service') ||\n error.message.includes('response format'))\n ) {\n throw error\n }\n\n if (error instanceof Error && error.message.includes('fetch')) {\n throw new Error(\n 'Unable to connect to the API. Please check the base URL and your internet connection.',\n )\n }\n\n throw new Error(\n 'Failed to fetch models from API. Please check your configuration and try again.',\n )\n }\n }\n\n // \u901A\u7528\u7684Anthropic\u517C\u5BB9\u6A21\u578B\u83B7\u53D6\u51FD\u6570\uFF0C\u5B9E\u73B0\u4E09\u5C42\u964D\u7EA7\u7B56\u7565\n async function fetchAnthropicCompatibleModelsWithFallback(\n baseURL: string,\n provider: string,\n apiKeyUrl: string,\n ) {\n let lastError: Error | null = null\n\n // \u7B2C\u4E00\u5C42\uFF1A\u5C1D\u8BD5\u4F7F\u7528 Anthropic \u98CE\u683C\u7684 API\n try {\n const models = await fetchAnthropicModels(baseURL, apiKey)\n return models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: provider,\n max_tokens: model.max_tokens || 8192,\n supports_vision: model.supports_vision || true,\n supports_function_calling: model.supports_function_calling || true,\n supports_reasoning_effort: false,\n }))\n } catch (error) {\n lastError = error as Error\n }\n\n // \u7B2C\u4E8C\u5C42\uFF1A\u5C1D\u8BD5\u4F7F\u7528 OpenAI \u98CE\u683C\u7684 API\n try {\n const models = await fetchCustomModels(baseURL, apiKey)\n return models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: provider,\n max_tokens: model.max_tokens || 8192,\n supports_vision: model.supports_vision || false,\n supports_function_calling: model.supports_function_calling || true,\n supports_reasoning_effort: false,\n }))\n } catch (error) {\n lastError = error as Error\n }\n\n // \u7B2C\u4E09\u5C42\uFF1A\u629B\u51FA\u9519\u8BEF\uFF0C\u89E6\u53D1\u624B\u52A8\u8F93\u5165\u6A21\u5F0F\n let errorMessage = `Failed to fetch ${provider} models using both Anthropic and OpenAI API formats`\n\n if (lastError) {\n errorMessage = lastError.message\n }\n\n // \u6DFB\u52A0\u6709\u7528\u7684\u5EFA\u8BAE\n if (errorMessage.includes('API key')) {\n errorMessage += `\\n\\n\uD83D\uDCA1 Tip: Get your API key from ${apiKeyUrl}`\n } else if (errorMessage.includes('permission')) {\n errorMessage += `\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the ${provider} API`\n } else if (errorMessage.includes('connection')) {\n errorMessage += '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw new Error(errorMessage)\n }\n\n // \u7EDF\u4E00\u5904\u7406\u6240\u6709Anthropic\u517C\u5BB9\u63D0\u4F9B\u5546\u7684\u6A21\u578B\u83B7\u53D6\n async function fetchAnthropicCompatibleProviderModels() {\n // \u6839\u636EanthropicProviderType\u786E\u5B9A\u9ED8\u8BA4baseURL\u548CAPI key\u83B7\u53D6\u5730\u5740\n let defaultBaseURL: string\n let apiKeyUrl: string\n let actualProvider: string\n\n switch (anthropicProviderType) {\n case 'official':\n defaultBaseURL = 'https://api.anthropic.com'\n apiKeyUrl = 'https://console.anthropic.com/settings/keys'\n actualProvider = 'anthropic'\n break\n case 'bigdream':\n defaultBaseURL = 'https://api-key.info'\n apiKeyUrl = 'https://api-key.info/register?aff=MSl4'\n actualProvider = 'bigdream'\n break\n case 'opendev':\n defaultBaseURL = 'https://api.openai-next.com'\n apiKeyUrl = 'https://api.openai-next.com/register/?aff_code=4xo7'\n actualProvider = 'opendev'\n break\n case 'custom':\n defaultBaseURL = providerBaseUrl\n apiKeyUrl = 'your custom API provider'\n actualProvider = 'anthropic'\n break\n default:\n throw new Error(\n `Unsupported Anthropic provider type: ${anthropicProviderType}`,\n )\n }\n\n const baseURL =\n anthropicProviderType === 'custom'\n ? providerBaseUrl\n : providerBaseUrl || defaultBaseURL\n return await fetchAnthropicCompatibleModelsWithFallback(\n baseURL,\n actualProvider,\n apiKeyUrl,\n )\n }\n\n // Remove duplicate function definitions - using unified fetchAnthropicCompatibleProviderModels instead\n\n async function fetchKimiModels() {\n try {\n const baseURL = providerBaseUrl || 'https://api.moonshot.cn/v1'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const kimiModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'kimi',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false, // Default to false, could be enhanced\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return kimiModels\n } catch (error) {\n let errorMessage = 'Failed to fetch Kimi models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n // Add helpful suggestions based on error type\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://platform.moonshot.cn/console/api-keys'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the Kimi API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchDeepSeekModels() {\n try {\n const baseURL = providerBaseUrl || 'https://api.deepseek.com'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const deepseekModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'deepseek',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false, // Default to false, could be enhanced\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return deepseekModels\n } catch (error) {\n let errorMessage = 'Failed to fetch DeepSeek models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n // Add helpful suggestions based on error type\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://platform.deepseek.com/api_keys'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the DeepSeek API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchSiliconFlowModels() {\n try {\n const baseURL = providerBaseUrl || 'https://api.siliconflow.cn/v1'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const siliconflowModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'siliconflow',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false, // Default to false, could be enhanced\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return siliconflowModels\n } catch (error) {\n let errorMessage = 'Failed to fetch SiliconFlow models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n // Add helpful suggestions based on error type\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://cloud.siliconflow.cn/i/oJWsm6io'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the SiliconFlow API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchQwenModels() {\n try {\n const baseURL =\n providerBaseUrl || 'https://dashscope.aliyuncs.com/compatible-mode/v1'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const qwenModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'qwen',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false,\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return qwenModels\n } catch (error) {\n let errorMessage = 'Failed to fetch Qwen models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://bailian.console.aliyun.com/?tab=model#/api-key'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the Qwen API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchGLMModels() {\n try {\n const baseURL = providerBaseUrl || 'https://open.bigmodel.cn/api/paas/v4'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const glmModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'glm',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false,\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return glmModels\n } catch (error) {\n let errorMessage = 'Failed to fetch GLM models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://open.bigmodel.cn (API Keys section)'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the GLM API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchMinimaxModels() {\n try {\n const baseURL = providerBaseUrl || 'https://api.minimaxi.com/v1'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const minimaxModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'minimax',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false,\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return minimaxModels\n } catch (error) {\n let errorMessage = 'Failed to fetch MiniMax models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://www.minimax.io/platform/user-center/basic-information'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the MiniMax API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchBaiduQianfanModels() {\n try {\n const baseURL = providerBaseUrl || 'https://qianfan.baidubce.com/v2'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const baiduModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'baidu-qianfan',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false,\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return baiduModels\n } catch (error) {\n let errorMessage = 'Failed to fetch Baidu Qianfan models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://console.bce.baidu.com/iam/#/iam/accesslist'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the Baidu Qianfan API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchCustomOpenAIModels() {\n try {\n const models = await fetchCustomModels(customBaseUrl, apiKey)\n\n const customModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'custom-openai',\n max_tokens: model.max_tokens || 4096,\n supports_vision: false, // Default to false, could be enhanced\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return customModels\n } catch (error) {\n let errorMessage = 'Failed to fetch custom API models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n // Add helpful suggestions based on error type\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check that your API key is valid for this endpoint'\n } else if (errorMessage.includes('endpoint not found')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure the base URL ends with /v1 and supports OpenAI-compatible API'\n } else if (errorMessage.includes('connect')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Verify the base URL is correct and accessible'\n } else if (errorMessage.includes('response format')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: This API may not be fully OpenAI-compatible'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchGeminiModels() {\n try {\n const response = await fetch(\n `https://generativelanguage.googleapis.com/v1beta/models?key=${apiKey}`,\n { signal: AbortSignal.timeout(30_000) },\n )\n\n if (!response.ok) {\n const errorData = await response.json()\n throw new Error(\n errorData.error?.message || `API error: ${response.status}`,\n )\n }\n\n const { models } = await response.json()\n\n const geminiModels = models\n .filter((model: any) =>\n model.supportedGenerationMethods.includes('generateContent'),\n )\n .map((model: any) => ({\n model: model.name.replace('models/', ''),\n provider: 'gemini',\n max_tokens: model.outputTokenLimit,\n supports_vision:\n model.supportedGenerationMethods.includes('generateContent'),\n supports_function_calling:\n model.supportedGenerationMethods.includes('generateContent'),\n }))\n\n return geminiModels\n } catch (error) {\n setModelLoadError(\n error instanceof Error ? error.message : 'Unknown error',\n )\n throw error\n }\n }\n\n async function fetchOllamaModels() {\n try {\n const response = await fetch(`${ollamaBaseUrl}/models`, {\n signal: AbortSignal.timeout(30_000),\n })\n\n if (!response.ok) {\n throw new Error(`HTTP error ${response.status}: ${response.statusText}`)\n }\n\n const responseData = await response.json()\n\n // Properly handle Ollama API response format\n // Ollama API can return models in different formats based on version\n let models = []\n\n // Check if data field exists (newer Ollama versions)\n if (responseData.data && Array.isArray(responseData.data)) {\n models = responseData.data\n }\n // Check if models array is directly at the root (older Ollama versions)\n else if (Array.isArray(responseData.models)) {\n models = responseData.models\n }\n // If response is already an array\n else if (Array.isArray(responseData)) {\n models = responseData\n } else {\n throw new Error(\n 'Invalid response from Ollama API: missing models array',\n )\n }\n\n // Transform Ollama models to our format\n // Note: max_tokens here is for OUTPUT tokens, not context length\n const ollamaModels = models.map((model: any) => ({\n model:\n model.id ??\n model.name ??\n model.modelName ??\n (typeof model === 'string' ? model : ''),\n provider: 'ollama',\n max_tokens: DEFAULT_MAX_TOKENS, // Default output tokens (8K is reasonable)\n supports_vision: false,\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n // Filter out models with empty names\n const validModels = ollamaModels.filter(model => model.model)\n\n // Helper: normalize Ollama server root for /api/show (strip trailing /v1)\n const normalizeOllamaRoot = (url: string): string => {\n try {\n const u = new URL(url)\n let pathname = u.pathname.replace(/\\/+$|^$/, '')\n if (pathname.endsWith('/v1')) {\n pathname = pathname.slice(0, -3)\n }\n u.pathname = pathname\n return u.toString().replace(/\\/+$/, '')\n } catch {\n return url.replace(/\\/v1\\/?$/, '')\n }\n }\n\n // Helper: extract num_ctx/context_length from /api/show response\n const extractContextTokens = (data: any): number | null => {\n if (!data || typeof data !== 'object') return null\n\n // First check model_info for architecture-specific context_length fields\n // Example: qwen2.context_length, llama.context_length, etc.\n if (data.model_info && typeof data.model_info === 'object') {\n const modelInfo = data.model_info\n for (const key of Object.keys(modelInfo)) {\n if (\n key.endsWith('.context_length') ||\n key.endsWith('_context_length')\n ) {\n const val = modelInfo[key]\n if (typeof val === 'number' && isFinite(val) && val > 0) {\n return val\n }\n }\n }\n }\n\n // Fallback to other common fields\n const candidates = [\n (data as any)?.parameters?.num_ctx,\n (data as any)?.model_info?.num_ctx,\n (data as any)?.config?.num_ctx,\n (data as any)?.details?.context_length,\n (data as any)?.context_length,\n (data as any)?.num_ctx,\n (data as any)?.max_tokens,\n (data as any)?.max_new_tokens,\n ].filter((v: any) => typeof v === 'number' && isFinite(v) && v > 0)\n if (candidates.length > 0) {\n return Math.max(...candidates)\n }\n\n // parameters may be a string like \"num_ctx=4096 ...\"\n if (typeof (data as any)?.parameters === 'string') {\n const m = (data as any).parameters.match(/num_ctx\\s*[:=]\\s*(\\d+)/i)\n if (m) {\n const n = parseInt(m[1], 10)\n if (Number.isFinite(n) && n > 0) return n\n }\n }\n return null\n }\n\n // Enrich each model via /api/show to get accurate context length\n // Store context length separately from max_tokens (output limit)\n const ollamaRoot = normalizeOllamaRoot(ollamaBaseUrl)\n const enrichedModels = await Promise.all(\n validModels.map(async (m: any) => {\n try {\n const showResp = await fetch(`${ollamaRoot}/api/show`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name: m.model }),\n signal: AbortSignal.timeout(30_000),\n })\n if (showResp.ok) {\n const showData = await showResp.json()\n const ctx = extractContextTokens(showData)\n if (typeof ctx === 'number' && isFinite(ctx) && ctx > 0) {\n // Store context_length separately, don't override max_tokens\n return { ...m, context_length: ctx }\n }\n }\n // Fallback to default if missing\n return m\n } catch {\n return m\n }\n }),\n )\n\n setAvailableModels(enrichedModels)\n\n // Only navigate if we have models\n if (enrichedModels.length > 0) {\n navigateTo('model')\n } else {\n setModelLoadError('No models found in your Ollama installation')\n }\n\n return enrichedModels\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n\n if (errorMessage.includes('fetch')) {\n setModelLoadError(\n `Could not connect to Ollama server at ${ollamaBaseUrl}. Make sure Ollama is running and the URL is correct.`,\n )\n } else {\n setModelLoadError(`Error loading Ollama models: ${errorMessage}`)\n }\n\n return []\n }\n }\n\n async function fetchModelsWithRetry() {\n const MAX_RETRIES = 2\n let lastError: Error | null = null\n\n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n setFetchRetryCount(attempt)\n setIsRetrying(attempt > 1)\n\n if (attempt > 1) {\n // Show retry message\n setModelLoadError(\n `Attempt ${attempt}/${MAX_RETRIES}: Retrying model discovery...`,\n )\n // Wait 1 second before retrying\n await new Promise(resolve => setTimeout(resolve, 1000))\n }\n\n try {\n const models = await fetchModels()\n // Success! Reset retry state and return models\n setFetchRetryCount(0)\n setIsRetrying(false)\n setModelLoadError(null)\n return models\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error))\n\n if (attempt === MAX_RETRIES) {\n // Final attempt failed, break to handle fallback\n break\n }\n }\n }\n\n // All retries failed, handle fallback to manual input\n setIsRetrying(false)\n const errorMessage = lastError?.message || 'Unknown error'\n\n // Check if provider supports manual input fallback\n const supportsManualInput = [\n 'anthropic',\n 'kimi',\n 'deepseek',\n 'siliconflow',\n 'qwen',\n 'glm',\n 'minimax',\n 'baidu-qianfan',\n 'custom-openai',\n ].includes(selectedProvider)\n\n if (supportsManualInput) {\n setModelLoadError(\n `Failed to auto-discover models after ${MAX_RETRIES} attempts: ${errorMessage}\\n\\n\u26A1 Automatically switching to manual model configuration...`,\n )\n\n // Automatically switch to manual input after 2 seconds\n setTimeout(() => {\n setModelLoadError(null)\n navigateTo('modelInput')\n }, 2000)\n } else {\n setModelLoadError(\n `Failed to load models after ${MAX_RETRIES} attempts: ${errorMessage}`,\n )\n }\n\n return []\n }\n\n async function fetchModels() {\n setIsLoadingModels(true)\n setModelLoadError(null)\n\n try {\n // For Anthropic provider (including official and community proxies via sub-menu), use the same logic\n if (selectedProvider === 'anthropic') {\n const anthropicModels = await fetchAnthropicCompatibleProviderModels()\n setAvailableModels(anthropicModels)\n navigateTo('model')\n return anthropicModels\n }\n\n // For custom OpenAI-compatible APIs, use the fetchCustomOpenAIModels function\n if (selectedProvider === 'custom-openai') {\n const customModels = await fetchCustomOpenAIModels()\n setAvailableModels(customModels)\n navigateTo('model')\n return customModels\n }\n\n // For Gemini, use the separate fetchGeminiModels function\n if (selectedProvider === 'gemini') {\n const geminiModels = await fetchGeminiModels()\n setAvailableModels(geminiModels)\n navigateTo('model')\n return geminiModels\n }\n\n // For Kimi, use the fetchKimiModels function\n if (selectedProvider === 'kimi') {\n const kimiModels = await fetchKimiModels()\n setAvailableModels(kimiModels)\n navigateTo('model')\n return kimiModels\n }\n\n // For DeepSeek, use the fetchDeepSeekModels function\n if (selectedProvider === 'deepseek') {\n const deepseekModels = await fetchDeepSeekModels()\n setAvailableModels(deepseekModels)\n navigateTo('model')\n return deepseekModels\n }\n\n // For SiliconFlow, use the fetchSiliconFlowModels function\n if (selectedProvider === 'siliconflow') {\n const siliconflowModels = await fetchSiliconFlowModels()\n setAvailableModels(siliconflowModels)\n navigateTo('model')\n return siliconflowModels\n }\n\n // For Qwen, use the fetchQwenModels function\n if (selectedProvider === 'qwen') {\n const qwenModels = await fetchQwenModels()\n setAvailableModels(qwenModels)\n navigateTo('model')\n return qwenModels\n }\n\n // For GLM, use the fetchGLMModels function\n if (selectedProvider === 'glm') {\n const glmModels = await fetchGLMModels()\n setAvailableModels(glmModels)\n navigateTo('model')\n return glmModels\n }\n\n // For Baidu Qianfan, use the fetchBaiduQianfanModels function\n if (selectedProvider === 'baidu-qianfan') {\n const baiduModels = await fetchBaiduQianfanModels()\n setAvailableModels(baiduModels)\n navigateTo('model')\n return baiduModels\n }\n\n // For Azure, skip model fetching and go directly to model input\n if (selectedProvider === 'azure') {\n navigateTo('modelInput')\n return []\n }\n\n // For all other providers, use the OpenAI client\n let baseURL = providerBaseUrl || providers[selectedProvider]?.baseURL\n\n // For custom-openai provider, use the custom base URL\n if (selectedProvider === 'custom-openai') {\n baseURL = customBaseUrl\n }\n\n const openai = new OpenAI({\n apiKey: apiKey || 'dummy-key-for-ollama', // Ollama doesn't need a real key\n baseURL: baseURL,\n dangerouslyAllowBrowser: true,\n })\n\n // Fetch the models\n const response = await openai.models.list()\n\n // Transform the response into our ModelInfo format\n const fetchedModels = []\n for (const model of response.data) {\n const modelName =\n (model as any).modelName ||\n (model as any).id ||\n (model as any).name ||\n (model as any).model ||\n 'unknown'\n const modelInfo = models[selectedProvider as keyof typeof models]?.find(\n m => m.model === modelName,\n )\n fetchedModels.push({\n model: modelName,\n provider: selectedProvider,\n max_tokens: modelInfo?.max_output_tokens,\n supports_vision: modelInfo?.supports_vision || false,\n supports_function_calling:\n modelInfo?.supports_function_calling || false,\n supports_reasoning_effort:\n modelInfo?.supports_reasoning_effort || false,\n })\n }\n\n setAvailableModels(fetchedModels)\n\n // Navigate to model selection screen if models were loaded successfully\n navigateTo('model')\n\n return fetchedModels\n } catch (error) {\n // Re-throw the error so that fetchModelsWithRetry can handle it properly\n throw error\n } finally {\n setIsLoadingModels(false)\n }\n }\n\n function handleApiKeySubmit(key: string) {\n setApiKey(key)\n\n // In edit mode, return to edit summary after changing API key\n if (isEditMode) {\n goBack()\n return\n }\n\n // For Azure, go to resource name input next\n if (selectedProvider === 'azure') {\n navigateTo('resourceName')\n return\n }\n\n // Fetch models with the provided API key\n fetchModelsWithRetry().catch(() => {\n // The retry logic in fetchModelsWithRetry already handles the error display\n // This catch is just to prevent unhandled promise rejection\n })\n }\n\n function handleResourceNameSubmit(name: string) {\n setResourceName(name)\n navigateTo('modelInput')\n }\n\n function handleOllamaBaseUrlSubmit(url: string) {\n setOllamaBaseUrl(url)\n setIsLoadingModels(true)\n setModelLoadError(null)\n\n // Use the dedicated Ollama model fetch function\n fetchOllamaModels().finally(() => {\n setIsLoadingModels(false)\n })\n }\n\n function handleCustomBaseUrlSubmit(url: string) {\n // Automatically remove trailing slash from baseURL\n const cleanUrl = url.replace(/\\/+$/, '')\n setCustomBaseUrl(cleanUrl)\n setProviderBaseUrl(cleanUrl)\n\n // In edit mode, return to edit summary\n if (isEditMode) {\n goBack()\n return\n }\n\n // After setting custom base URL, go to API key input\n navigateTo('apiKey')\n }\n\n function handleProviderBaseUrlSubmit(url: string) {\n // Automatically remove trailing slash from baseURL\n const cleanUrl = url.replace(/\\/+$/, '')\n setProviderBaseUrl(cleanUrl)\n\n // In edit mode, return to edit summary\n if (isEditMode) {\n goBack()\n return\n }\n\n // For Ollama, handle differently - it tries to fetch models immediately\n if (selectedProvider === 'ollama') {\n setOllamaBaseUrl(cleanUrl)\n setIsLoadingModels(true)\n setModelLoadError(null)\n\n // Use the dedicated Ollama model fetch function\n fetchOllamaModels().finally(() => {\n setIsLoadingModels(false)\n })\n } else {\n // For all other providers, go to API key input next\n navigateTo('apiKey')\n }\n }\n\n function handleAnthropicProviderSelection(\n providerType: 'official' | 'bigdream' | 'custom',\n ) {\n setAnthropicProviderType(providerType)\n\n if (providerType === 'custom') {\n // For custom Anthropic provider, go to base URL configuration\n setProviderBaseUrl('')\n navigateTo('baseUrl')\n } else {\n // For official/community proxy providers, set default base URL and go to API key\n const defaultUrls = {\n official: 'https://api.anthropic.com',\n bigdream: 'https://api-key.info',\n opendev: 'https://api.openai-next.com',\n }\n setProviderBaseUrl(defaultUrls[providerType])\n navigateTo('apiKey')\n }\n }\n\n function handleCustomModelSubmit(model: string) {\n setCustomModelName(model)\n setSelectedModel(model)\n setIsManualModelEntry(true)\n\n // No model info available, so set default values\n setSupportsReasoningEffort(false)\n setReasoningEffort(null)\n\n // Use default max tokens for manually entered models\n setMaxTokensMode('preset')\n setSelectedMaxTokensPreset(DEFAULT_MAX_TOKENS)\n setMaxTokens(DEFAULT_MAX_TOKENS.toString())\n setMaxTokensCursorOffset(DEFAULT_MAX_TOKENS.toString().length)\n\n // Go to model parameters screen\n navigateTo('modelParams')\n // Reset active field index\n setActiveFieldIndex(0)\n }\n\n function handleModelSelection(model: string) {\n setSelectedModel(model)\n setIsManualModelEntry(false)\n\n // Check if the selected model supports reasoning_effort\n const modelInfo = availableModels.find(m => m.model === model)\n setSupportsReasoningEffort(modelInfo?.supports_reasoning_effort || false)\n\n if (!modelInfo?.supports_reasoning_effort) {\n setReasoningEffort(null)\n }\n\n // Set context length if available (from Ollama /api/show)\n if (modelInfo?.context_length) {\n setContextLength(modelInfo.context_length)\n } else {\n setContextLength(DEFAULT_CONTEXT_LENGTH)\n }\n\n // Set max tokens based on model info or default\n // Note: max_tokens is for OUTPUT, not context window\n if (modelInfo?.max_tokens) {\n const modelMaxTokens = modelInfo.max_tokens\n // Check if the model's max tokens matches any of our presets\n const matchingPreset = MAX_TOKENS_OPTIONS.find(\n option => option.value === modelMaxTokens,\n )\n\n if (matchingPreset) {\n setMaxTokensMode('preset')\n setSelectedMaxTokensPreset(modelMaxTokens)\n setMaxTokens(modelMaxTokens.toString())\n } else {\n setMaxTokensMode('custom')\n setMaxTokens(modelMaxTokens.toString())\n }\n setMaxTokensCursorOffset(modelMaxTokens.toString().length)\n } else {\n // No model-specific max tokens, use default\n setMaxTokensMode('preset')\n setSelectedMaxTokensPreset(DEFAULT_MAX_TOKENS)\n setMaxTokens(DEFAULT_MAX_TOKENS.toString())\n setMaxTokensCursorOffset(DEFAULT_MAX_TOKENS.toString().length)\n }\n\n // Go to model parameters screen\n navigateTo('modelParams')\n // Reset active field index\n setActiveFieldIndex(0)\n }\n\n const handleModelParamsSubmit = () => {\n // Values are already in state, no need to extract from form\n\n // In edit mode, return to edit summary\n if (isEditMode) {\n goBack()\n return\n }\n\n // Smart skip: when model was selected from API list with known context_length,\n // skip the contextLength selection screen and go directly to testAndSave\n if (!isManualModelEntry) {\n const modelInfo = availableModels.find(m => m.model === selectedModel)\n if (modelInfo?.context_length || modelInfo?.max_input_tokens) {\n // Context length was already set in handleModelSelection\n navigateTo('testAndSave')\n return\n }\n }\n\n // For manual model entry or unknown context length, show contextLength screen\n if (!CONTEXT_LENGTH_OPTIONS.find(opt => opt.value === contextLength)) {\n setContextLength(DEFAULT_CONTEXT_LENGTH)\n }\n navigateTo('contextLength')\n }\n\n async function testConnection(): Promise<{\n success: boolean\n message: string\n endpoint?: string\n details?: string\n }> {\n setIsTestingConnection(true)\n setConnectionTestResult(null)\n\n try {\n // Determine the base URL to test\n let testBaseURL =\n providerBaseUrl || providers[selectedProvider]?.baseURL || ''\n\n if (selectedProvider === 'azure') {\n testBaseURL = `https://${resourceName}.openai.azure.com/openai/deployments/${selectedModel}`\n } else if (selectedProvider === 'custom-openai') {\n testBaseURL = customBaseUrl\n }\n\n // For OpenAI-compatible providers, try multiple endpoints in order of preference\n if (isOpenAICompatibleProvider(selectedProvider)) {\n // \uD83D\uDD25 Use specialized GPT-5 connection test for GPT-5 models\n const isGPT5 = selectedModel?.toLowerCase().includes('gpt-5')\n\n if (isGPT5) {\n // Validate configuration first\n const configValidation = validateGPT5Config({\n model: selectedModel,\n apiKey: apiKey,\n baseURL: testBaseURL,\n maxTokens: parseInt(maxTokens) || 8192,\n provider: selectedProvider,\n })\n\n if (!configValidation.valid) {\n return {\n success: false,\n message: '\u274C GPT-5 configuration validation failed',\n details: configValidation.errors.join('\\n'),\n }\n }\n\n // Use specialized GPT-5 test service\n const gpt5Result = await testGPT5Connection({\n model: selectedModel,\n apiKey: apiKey,\n baseURL: testBaseURL,\n maxTokens: parseInt(maxTokens) || 8192,\n provider: selectedProvider,\n })\n\n return gpt5Result\n }\n\n // For non-GPT-5 OpenAI-compatible models, use existing logic\n const endpointsToTry = []\n\n if (selectedProvider === 'minimax') {\n endpointsToTry.push(\n {\n path: '/text/chatcompletion_v2',\n name: 'MiniMax v2 (recommended)',\n },\n { path: '/chat/completions', name: 'Standard OpenAI' },\n )\n } else {\n endpointsToTry.push({\n path: '/chat/completions',\n name: 'Standard OpenAI',\n })\n }\n\n let lastError = null\n for (const endpoint of endpointsToTry) {\n try {\n const testResult = await testChatEndpoint(\n testBaseURL,\n endpoint.path,\n endpoint.name,\n )\n\n if (testResult.success) {\n return testResult\n }\n lastError = testResult\n } catch (error) {\n lastError = {\n success: false,\n message: `Failed to test ${endpoint.name}`,\n endpoint: endpoint.path,\n details: error instanceof Error ? error.message : String(error),\n }\n }\n }\n\n return (\n lastError || {\n success: false,\n message: 'All endpoints failed',\n details: 'No endpoints could be reached',\n }\n )\n } else {\n // For non-OpenAI providers (like Anthropic, Gemini), use different test approach\n return await testProviderSpecificEndpoint(testBaseURL)\n }\n } catch (error) {\n return {\n success: false,\n message: 'Connection test failed',\n details: error instanceof Error ? error.message : String(error),\n }\n } finally {\n setIsTestingConnection(false)\n }\n }\n\n async function testChatEndpoint(\n baseURL: string,\n endpointPath: string,\n endpointName: string,\n ): Promise<{\n success: boolean\n message: string\n endpoint?: string\n details?: string\n }> {\n const testURL = `${baseURL.replace(/\\/+$/, '')}${endpointPath}`\n\n // Create a test message that expects a specific response\n const testPayload: any = {\n model: selectedModel,\n messages: [\n {\n role: 'user',\n content:\n 'Please respond with exactly \"YES\" (in capital letters) to confirm this connection is working.',\n },\n ],\n max_tokens: Math.max(parseInt(maxTokens) || 8192, 8192), // Ensure minimum 8192 tokens for connection test\n temperature: 0,\n stream: false,\n }\n\n // Apply provider/model-aware parameter normalization\n if (selectedModel && selectedProvider) {\n const caps = getEffectiveCapabilities(selectedProvider, selectedModel)\n\n // Fix max tokens field name\n if (caps.maxTokensField !== 'max_tokens' && testPayload.max_tokens) {\n testPayload[caps.maxTokensField] = testPayload.max_tokens\n delete testPayload.max_tokens\n }\n\n // Fix temperature: omit for reasoning models, clamp for limited providers\n if (caps.temperatureRange === 'omit') {\n delete testPayload.temperature\n } else if (typeof caps.temperatureRange === 'object') {\n testPayload.temperature = Math.min(\n testPayload.temperature,\n caps.temperatureRange.max,\n )\n }\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n\n // Add authorization headers\n if (selectedProvider === 'azure') {\n headers['api-key'] = apiKey\n } else {\n headers['Authorization'] = `Bearer ${apiKey}`\n }\n\n try {\n const response = await fetch(testURL, {\n method: 'POST',\n headers,\n body: JSON.stringify(testPayload),\n signal: AbortSignal.timeout(30_000),\n })\n\n if (response.ok) {\n const data = await response.json()\n\n // Check if we got a valid response with content\n let responseContent = ''\n\n if (data.choices && data.choices.length > 0) {\n responseContent = data.choices[0]?.message?.content || ''\n } else if (data.reply) {\n // Handle MiniMax format\n responseContent = data.reply\n } else if (data.output) {\n // Handle other formats\n responseContent = data.output?.text || data.output || ''\n }\n\n // Check if response contains \"YES\" (case insensitive)\n const containsYes = responseContent.toLowerCase().includes('yes')\n\n if (containsYes) {\n return {\n success: true,\n message: `\u2705 Connection test passed with ${endpointName}`,\n endpoint: endpointPath,\n details: `Model responded correctly: \"${responseContent.trim()}\"`,\n }\n } else {\n return {\n success: false,\n message: `\u26A0\uFE0F ${endpointName} connected but model response unexpected`,\n endpoint: endpointPath,\n details: `Expected \"YES\" but got: \"${responseContent.trim() || '(empty response)'}\"`,\n }\n }\n } else {\n const errorData = await response.json().catch(() => null)\n const errorMessage =\n errorData?.error?.message || errorData?.message || response.statusText\n\n return {\n success: false,\n message: `\u274C ${endpointName} failed (${response.status})`,\n endpoint: endpointPath,\n details: `Error: ${errorMessage}`,\n }\n }\n } catch (error) {\n return {\n success: false,\n message: `\u274C ${endpointName} connection failed`,\n endpoint: endpointPath,\n details: error instanceof Error ? error.message : String(error),\n }\n }\n }\n\n async function testResponsesEndpoint(\n baseURL: string,\n endpointPath: string,\n endpointName: string,\n ): Promise<{\n success: boolean\n message: string\n endpoint?: string\n details?: string\n }> {\n const testURL = `${baseURL.replace(/\\/+$/, '')}${endpointPath}`\n\n // \uD83D\uDD27 Enhanced GPT-5 Responses API test payload\n const testPayload: any = {\n model: selectedModel,\n input: [\n {\n role: 'user',\n content:\n 'Please respond with exactly \"YES\" (in capital letters) to confirm this connection is working.',\n },\n ],\n max_completion_tokens: Math.max(parseInt(maxTokens) || 8192, 8192),\n temperature: 1, // GPT-5 only supports temperature=1\n // \uD83D\uDE80 Add reasoning configuration for better GPT-5 performance\n reasoning: {\n effort: 'low', // Fast response for connection test\n },\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n }\n\n try {\n const response = await fetch(testURL, {\n method: 'POST',\n headers,\n body: JSON.stringify(testPayload),\n signal: AbortSignal.timeout(30_000),\n })\n\n if (response.ok) {\n const data = await response.json()\n\n // Extract content from Responses API format\n let responseContent = ''\n\n if (data.output_text) {\n responseContent = data.output_text\n } else if (data.output) {\n responseContent =\n typeof data.output === 'string'\n ? data.output\n : data.output.text || ''\n }\n\n // Check if response contains \"YES\" (case insensitive)\n const containsYes = responseContent.toLowerCase().includes('yes')\n\n if (containsYes) {\n return {\n success: true,\n message: `\u2705 Connection test passed with ${endpointName}`,\n endpoint: endpointPath,\n details: `GPT-5 responded correctly via Responses API: \"${responseContent.trim()}\"`,\n }\n } else {\n return {\n success: false,\n message: `\u26A0\uFE0F ${endpointName} connected but model response unexpected`,\n endpoint: endpointPath,\n details: `Expected \"YES\" but got: \"${responseContent.trim() || '(empty response)'}\"`,\n }\n }\n } else {\n // \uD83D\uDD27 Enhanced error handling with detailed debugging\n const errorData = await response.json().catch(() => null)\n const errorMessage =\n errorData?.error?.message || errorData?.message || response.statusText\n\n // Provide specific guidance for common GPT-5 errors\n let details = `Responses API Error: ${errorMessage}`\n if (response.status === 400 && errorMessage.includes('max_tokens')) {\n details +=\n '\\n\uD83D\uDD27 Note: This appears to be a parameter compatibility issue. The fallback to Chat Completions should handle this.'\n } else if (response.status === 404) {\n details +=\n '\\n\uD83D\uDD27 Note: Responses API endpoint may not be available for this model or provider.'\n } else if (response.status === 401) {\n details += '\\n\uD83D\uDD27 Note: API key authentication failed.'\n }\n\n return {\n success: false,\n message: `\u274C ${endpointName} failed (${response.status})`,\n endpoint: endpointPath,\n details: details,\n }\n }\n } catch (error) {\n return {\n success: false,\n message: `\u274C ${endpointName} connection failed`,\n endpoint: endpointPath,\n details: error instanceof Error ? error.message : String(error),\n }\n }\n }\n\n async function testProviderSpecificEndpoint(baseURL: string): Promise<{\n success: boolean\n message: string\n endpoint?: string\n details?: string\n }> {\n // For Anthropic and Anthropic-compatible providers, use the official SDK for testing\n if (selectedProvider === 'anthropic' || selectedProvider === 'bigdream') {\n try {\n // Determine the baseURL for testing\n let testBaseURL: string | undefined = undefined\n if (selectedProvider === 'bigdream') {\n testBaseURL = baseURL || 'https://api-key.info'\n } else if (selectedProvider === 'anthropic') {\n // For anthropic, use user-provided baseURL if available, otherwise undefined (official API)\n testBaseURL =\n baseURL && baseURL !== 'https://api.anthropic.com'\n ? baseURL\n : undefined\n }\n\n // Use the verifyApiKey function which uses the official Anthropic SDK\n const isValid = await verifyApiKey(\n apiKey,\n testBaseURL,\n selectedProvider,\n )\n\n if (isValid) {\n return {\n success: true,\n message: `\u2705 ${selectedProvider} connection test passed`,\n endpoint: '/messages',\n details: 'API key verified using official Anthropic SDK',\n }\n } else {\n return {\n success: false,\n message: `\u274C ${selectedProvider} API key verification failed`,\n endpoint: '/messages',\n details:\n 'Invalid API key. Please check your API key and try again.',\n }\n }\n } catch (error) {\n return {\n success: false,\n message: `\u274C ${selectedProvider} connection failed`,\n endpoint: '/messages',\n details: error instanceof Error ? error.message : String(error),\n }\n }\n }\n\n // For other providers, return a placeholder success (we can extend this later)\n return {\n success: true,\n message: `\u2705 Configuration saved for ${selectedProvider}`,\n details: 'Provider-specific testing not implemented yet',\n }\n }\n\n async function handleConnectionTest() {\n const result = await testConnection()\n setConnectionTestResult(result)\n }\n\n const handleContextLengthSubmit = () => {\n // Context length value is already in state\n if (isEditMode) {\n goBack()\n return\n }\n navigateTo('testAndSave')\n }\n\n async function saveConfiguration(\n provider: ProviderType,\n model: string,\n ): Promise<string | null> {\n let baseURL = providerBaseUrl || providers[provider]?.baseURL || ''\n let actualProvider = provider\n\n // For Anthropic provider, determine the actual provider based on sub-menu selection\n if (provider === 'anthropic') {\n switch (anthropicProviderType) {\n case 'official':\n actualProvider = 'anthropic'\n baseURL = baseURL || 'https://api.anthropic.com'\n break\n case 'bigdream':\n actualProvider = 'bigdream'\n baseURL = baseURL || 'https://api-key.info'\n break\n case 'custom':\n actualProvider = 'anthropic' // Use anthropic for custom endpoints\n // baseURL is already set from user input\n break\n }\n }\n\n // For Azure, construct the baseURL using the resource name\n if (provider === 'azure') {\n baseURL = `https://${resourceName}.openai.azure.com/openai/deployments/${model}`\n }\n // For custom OpenAI-compatible API, use the custom base URL\n else if (provider === 'custom-openai') {\n baseURL = customBaseUrl\n }\n\n try {\n // Use ModelManager's addModel method for duplicate validation\n const modelManager = getModelManager()\n\n const modelConfig = {\n name: `${actualProvider} ${model}`,\n provider: actualProvider,\n modelName: model,\n baseURL: baseURL,\n apiKey: apiKey || '',\n maxTokens: parseInt(maxTokens) || DEFAULT_MAX_TOKENS,\n contextLength: contextLength || DEFAULT_CONTEXT_LENGTH,\n reasoningEffort,\n }\n\n // addModel method will throw error if duplicate exists\n return await modelManager.addModel(modelConfig)\n } catch (error) {\n // Validation failed - show error to user\n setValidationError(\n error instanceof Error ? error.message : 'Failed to add model',\n )\n return null\n }\n }\n\n async function handleConfirmation() {\n // Clear any previous validation errors\n setValidationError(null)\n\n if (isEditMode && editingModel) {\n // Edit mode: update existing model\n try {\n const modelManager = getModelManager()\n modelManager.updateModel(editingModel.modelName, {\n baseURL: providerBaseUrl || editingModel.baseURL,\n apiKey: apiKey || editingModel.apiKey,\n maxTokens: parseInt(maxTokens) || editingModel.maxTokens,\n contextLength: contextLength || editingModel.contextLength,\n reasoningEffort,\n })\n onDone()\n } catch (error) {\n setValidationError(\n error instanceof Error ? error.message : 'Failed to update model',\n )\n }\n return\n }\n\n // Add mode: save the configuration and exit\n const modelId = await saveConfiguration(selectedProvider, selectedModel)\n\n // If validation failed (modelId is null), don't proceed\n if (!modelId) {\n return // Error is already set in saveConfiguration\n }\n\n // Handle model pointer assignment for new system\n if (modelId && (isOnboarding || targetPointer)) {\n if (isOnboarding) {\n // First-time setup: set all pointers to this model\n setAllPointersToModel(modelId)\n } else if (targetPointer) {\n // Specific pointer configuration: only set target pointer\n setModelPointer(targetPointer, modelId)\n }\n }\n\n onDone()\n }\n\n // Handle back navigation based on current screen\n const handleBack = () => {\n if (currentScreen === 'provider') {\n // If we're at the first screen, exit\n if (onCancel) {\n onCancel()\n } else {\n onDone()\n }\n } else {\n // When going back from testAndSave, reset test state\n if (currentScreen === 'testAndSave') {\n setConnectionTestResult(null)\n setIsTestingConnection(false)\n setValidationError(null)\n }\n // When going back to modelParams, reset activeFieldIndex to the last\n // chooseable field so the auto-submit doesn't immediately re-navigate forward\n const prevScreen = screenStack[screenStack.length - 2]\n if (prevScreen === 'modelParams') {\n const formFields = getFormFieldsForModelParams()\n const submitIndex = formFields.findIndex(f => f.name === 'submit')\n setActiveFieldIndex(Math.max(0, submitIndex - 1))\n }\n // Remove the current screen from the stack\n setScreenStack(prev => prev.slice(0, -1))\n }\n }\n\n // Esc is now handled per-screen by SimpleSelector/InfoPanel/BrandTextInput onClose/useInput\n\n // Handle cursor offset changes\n function handleCursorOffsetChange(offset: number) {\n setCursorOffset(offset)\n }\n\n // Handle API key changes\n function handleApiKeyChange(value: string) {\n setApiKeyEdited(true)\n setApiKey(value)\n }\n\n // Handle model search query changes\n function handleModelSearchChange(value: string) {\n setModelSearchQuery(value)\n // Update cursor position to end of text when typing\n setModelSearchCursorOffset(value.length)\n }\n\n // Handle model search cursor offset changes\n function handleModelSearchCursorOffsetChange(offset: number) {\n setModelSearchCursorOffset(offset)\n }\n\n // Screens using SimpleSelector/InfoPanel handle their own input.\n // This useInput handles text input screens (apiKey, baseUrl, resourceName, modelInput)\n // and Esc for those screens.\n const textScreens = ['apiKey', 'baseUrl', 'resourceName', 'modelInput']\n useInput((input, key) => {\n if (!textScreens.includes(currentScreen)) return\n\n // Esc goes back on text input screens\n if (key.escape) {\n handleBack()\n return\n }\n\n // Handle API key submission on Enter\n if (currentScreen === 'apiKey' && key.return) {\n if (apiKey) {\n handleApiKeySubmit(apiKey)\n }\n return\n }\n\n if (currentScreen === 'apiKey' && key.tab) {\n // For providers that support manual model input, skip to manual model input\n if (\n selectedProvider === 'anthropic' ||\n selectedProvider === 'kimi' ||\n selectedProvider === 'deepseek' ||\n selectedProvider === 'qwen' ||\n selectedProvider === 'glm' ||\n selectedProvider === 'minimax' ||\n selectedProvider === 'baidu-qianfan' ||\n selectedProvider === 'siliconflow' ||\n selectedProvider === 'custom-openai'\n ) {\n navigateTo('modelInput')\n return\n }\n\n // For other providers, try to fetch models without API key\n fetchModelsWithRetry().catch(() => {\n // Retry logic in fetchModelsWithRetry already handles error display\n })\n return\n }\n\n // Handle Resource Name submission on Enter\n if (currentScreen === 'resourceName' && key.return) {\n if (resourceName) {\n handleResourceNameSubmit(resourceName)\n }\n return\n }\n\n // Handle Base URL submission on Enter\n if (currentScreen === 'baseUrl' && key.return) {\n if (selectedProvider === 'custom-openai') {\n handleCustomBaseUrlSubmit(customBaseUrl)\n } else {\n handleProviderBaseUrlSubmit(providerBaseUrl)\n }\n return\n }\n\n // Handle Custom Model Name submission on Enter\n if (currentScreen === 'modelInput' && key.return) {\n if (customModelName) {\n handleCustomModelSubmit(customModelName)\n }\n return\n }\n })\n\n // Helper function to get form fields for model params\n function getFormFieldsForModelParams() {\n return [\n {\n name: 'maxTokens',\n label: 'Maximum Tokens',\n description: 'Select the maximum number of tokens to generate.',\n value: parseInt(maxTokens),\n component: 'select',\n options: MAX_TOKENS_OPTIONS.map(option => ({\n label: option.label,\n value: option.value.toString(),\n })),\n defaultValue: maxTokens,\n },\n ...(supportsReasoningEffort\n ? [\n {\n name: 'reasoningEffort',\n label: 'Reasoning Effort',\n description: 'Controls reasoning depth for complex problems.',\n value: reasoningEffort,\n component: 'select',\n },\n ]\n : []),\n {\n name: 'submit',\n label: 'Continue \u2192',\n component: 'button',\n },\n ]\n }\n\n // Render API Key Input Screen\n if (currentScreen === 'apiKey') {\n const providerLabel = getProviderLabel(selectedProvider, 0).split(' (')[0]\n\n // Build provider-specific API key hint\n const apiKeyUrls: Record<string, string> = {\n kimi: 'https://platform.moonshot.cn/console/api-keys',\n deepseek: 'https://platform.deepseek.com/api_keys',\n siliconflow: 'https://cloud.siliconflow.cn/i/oJWsm6io',\n qwen: 'https://bailian.console.aliyun.com/?tab=model#/api-key',\n glm: 'https://open.bigmodel.cn (API Keys section)',\n minimax: 'https://www.minimax.io/platform/user-center/basic-information',\n 'baidu-qianfan': 'https://console.bce.baidu.com/iam/#/iam/accesslist',\n openai: 'https://platform.openai.com/api-keys',\n }\n\n let apiKeyUrl = apiKeyUrls[selectedProvider] || ''\n if (selectedProvider === 'anthropic') {\n apiKeyUrl =\n anthropicProviderType === 'official'\n ? 'https://console.anthropic.com/settings/keys'\n : anthropicProviderType === 'bigdream'\n ? 'https://api-key.info/register?aff=MSl4'\n : anthropicProviderType === 'opendev'\n ? 'https://api.openai-next.com/register/?aff_code=4xo7'\n : 'your custom API provider'\n }\n\n const supportsManualInput =\n selectedProvider === 'anthropic' ||\n selectedProvider === 'kimi' ||\n selectedProvider === 'deepseek' ||\n selectedProvider === 'qwen' ||\n selectedProvider === 'glm' ||\n selectedProvider === 'minimax' ||\n selectedProvider === 'baidu-qianfan' ||\n selectedProvider === 'siliconflow' ||\n selectedProvider === 'custom-openai'\n\n const tabHintText = supportsManualInput\n ? t('modelSelector.apiKeyTabHintManual')\n : t('modelSelector.apiKeyTabHintSkip')\n\n const apiKeyHint = apiKeyUrl ? (\n <Text color={SEMANTIC_COLORS.dim}>\n Get your API key from:{' '}\n <Text color={SEMANTIC_COLORS.info}>{apiKeyUrl}</Text>\n </Text>\n ) : undefined\n\n return (\n <BrandTextInput\n title={`${t('modelSelector.apiKeyTitle')} \u2014 ${providerLabel}`}\n description={t('modelSelector.apiKeyDesc')}\n placeholder=\"sk-...\"\n value={apiKey}\n onChange={handleApiKeyChange}\n onSubmit={handleApiKeySubmit}\n mask=\"*\"\n error={modelLoadError ? `Error: ${modelLoadError}` : null}\n isLoading={isLoadingModels}\n loadingText=\"Loading available models...\"\n hint={apiKeyHint}\n footerHint={`Enter continue \u00B7 Tab ${tabHintText} \u00B7 Esc back`}\n cursorOffset={cursorOffset}\n onChangeCursorOffset={handleCursorOffsetChange}\n />\n )\n }\n\n // Render Model Selection Screen\n if (currentScreen === 'model') {\n const providerLabel = getProviderLabel(\n selectedProvider,\n availableModels.length,\n ).split(' (')[0]\n\n // Convert modelOptions to SelectorItem[] for SimpleSelector\n // modelOptions already has search filtering applied\n const modelSelectorItems: SelectorItem[] = modelOptions.map(opt => ({\n id: opt.value,\n label: opt.label,\n }))\n\n const subtitle =\n modelOptions.length > 0\n ? `${modelOptions.length}/${availableModels.length} models`\n : availableModels.length > 0\n ? t('modelSelector.noModelsMatch')\n : t('modelSelector.noModelsAvailable')\n\n return (\n <SimpleSelector\n title={`${t('modelSelector.modelSelectionTitle')} \u2014 ${providerLabel}`}\n subtitle={subtitle}\n items={modelSelectorItems}\n onSelect={item => handleModelSelection(item.id)}\n onClose={handleBack}\n />\n )\n }\n\n if (currentScreen === 'modelParams') {\n // Sequential SimpleSelector: first maxTokens, then reasoningEffort (if applicable), then submit\n const formFields = getFormFieldsForModelParams()\n const currentField = formFields[activeFieldIndex]\n\n if (currentField?.name === 'maxTokens') {\n const maxTokensItems: SelectorItem[] = MAX_TOKENS_OPTIONS.map(opt => ({\n id: opt.value.toString(),\n label: opt.label,\n isCurrent: opt.value === parseInt(maxTokens),\n }))\n\n return (\n <SimpleSelector\n title={`${t('modelSelector.modelParamsTitle')} \u2014 ${t('modelSelector.maxTokens')}`}\n subtitle={selectedModel}\n items={maxTokensItems}\n onSelect={item => {\n const numValue = parseInt(item.id)\n setMaxTokens(numValue.toString())\n setSelectedMaxTokensPreset(numValue)\n setMaxTokensCursorOffset(numValue.toString().length)\n setActiveFieldIndex(activeFieldIndex + 1)\n }}\n onClose={handleBack}\n />\n )\n }\n\n if (currentField?.name === 'reasoningEffort') {\n const effortItems: SelectorItem[] = reasoningEffortOptions.map(opt => ({\n id: opt.value,\n label: opt.label,\n isCurrent: opt.value === reasoningEffort,\n }))\n\n return (\n <SimpleSelector\n title={`${t('modelSelector.modelParamsTitle')} \u2014 ${t('modelSelector.reasoningEffort')}`}\n subtitle={selectedModel}\n items={effortItems}\n onSelect={item => {\n setReasoningEffort(item.id as ReasoningEffortOption)\n setActiveFieldIndex(activeFieldIndex + 1)\n }}\n onClose={() => {\n // Go back to maxTokens within modelParams, not exit modelParams\n setActiveFieldIndex(0)\n }}\n />\n )\n }\n\n // If on submit field or past all fields, auto-submit\n handleModelParamsSubmit()\n return null\n }\n\n // Render Resource Name Input Screen\n if (currentScreen === 'resourceName') {\n return (\n <BrandTextInput\n title={t('modelSelector.resourceNameTitle')}\n description={t('modelSelector.resourceNameDesc')}\n placeholder=\"myazureresource\"\n value={resourceName}\n onChange={setResourceName}\n onSubmit={handleResourceNameSubmit}\n footerHint={t('modelSelector.footerEnterContinue')}\n cursorOffset={resourceNameCursorOffset}\n onChangeCursorOffset={setResourceNameCursorOffset}\n />\n )\n }\n\n // Render Base URL Input Screen (for all providers)\n if (currentScreen === 'baseUrl') {\n const isCustomOpenAI = selectedProvider === 'custom-openai'\n\n if (isCustomOpenAI) {\n return (\n <BrandTextInput\n title={t('modelSelector.customApiTitle')}\n description={t('modelSelector.customApiDesc')}\n placeholder=\"https://api.example.com/v1\"\n value={customBaseUrl}\n onChange={setCustomBaseUrl}\n onSubmit={handleCustomBaseUrlSubmit}\n isLoading={isLoadingModels}\n loadingText=\"Connecting...\"\n error={modelLoadError ? `Error: ${modelLoadError}` : null}\n footerHint={t('modelSelector.footerEnterContinue')}\n cursorOffset={customBaseUrlCursorOffset}\n onChangeCursorOffset={setCustomBaseUrlCursorOffset}\n />\n )\n }\n\n const providerName = providers[selectedProvider]?.name || selectedProvider\n const defaultUrl = providers[selectedProvider]?.baseURL || ''\n const desc =\n selectedProvider === 'ollama'\n ? t('modelSelector.baseUrlOllamaDesc')\n : `${t('modelSelector.baseUrlDesc')} You can modify this URL or press Enter to use the default.`\n\n return (\n <BrandTextInput\n title={`${t('modelSelector.baseUrlTitle')} \u2014 ${providerName}`}\n description={desc}\n placeholder={defaultUrl}\n value={providerBaseUrl}\n onChange={setProviderBaseUrl}\n onSubmit={handleProviderBaseUrlSubmit}\n isLoading={isLoadingModels}\n loadingText={\n selectedProvider === 'ollama'\n ? 'Connecting to Ollama server...'\n : `Connecting to ${providerName}...`\n }\n error={modelLoadError ? `Error: ${modelLoadError}` : null}\n footerHint={t('modelSelector.footerEnterContinue')}\n cursorOffset={providerBaseUrlCursorOffset}\n onChangeCursorOffset={setProviderBaseUrlCursorOffset}\n />\n )\n }\n\n // Render Custom Model Input Screen\n if (currentScreen === 'modelInput') {\n // Provider-specific model name config\n const modelInputConfig: Record<\n string,\n { title: string; placeholder: string; examples: string }\n > = {\n azure: {\n title: 'Azure Model Setup',\n placeholder: 'gpt-4',\n examples: 'e.g. \"gpt-4\", \"gpt-35-turbo\"',\n },\n anthropic: {\n title: 'Claude Model Setup',\n placeholder: 'claude-3-5-sonnet-latest',\n examples: 'e.g. \"claude-3-5-sonnet-latest\", \"claude-3-5-haiku-latest\"',\n },\n bigdream: {\n title: 'BigDream Model Setup',\n placeholder: 'claude-3-5-sonnet-latest',\n examples: 'e.g. \"claude-3-5-sonnet-latest\", \"claude-3-5-haiku-latest\"',\n },\n kimi: {\n title: 'Kimi Model Setup',\n placeholder: 'kimi-k2-0711-preview',\n examples: 'e.g. \"kimi-k2-0711-preview\"',\n },\n deepseek: {\n title: 'DeepSeek Model Setup',\n placeholder: 'deepseek-chat',\n examples: 'e.g. \"deepseek-chat\", \"deepseek-coder\", \"deepseek-reasoner\"',\n },\n siliconflow: {\n title: 'SiliconFlow Model Setup',\n placeholder: 'Qwen/Qwen2.5-72B-Instruct',\n examples: 'e.g. \"Qwen/Qwen2.5-72B-Instruct\"',\n },\n qwen: {\n title: 'Qwen Model Setup',\n placeholder: 'qwen-plus',\n examples: 'e.g. \"qwen-plus\", \"qwen-turbo\", \"qwen-max\"',\n },\n glm: {\n title: 'GLM Model Setup',\n placeholder: 'glm-4',\n examples: 'e.g. \"glm-4\", \"glm-4v\", \"glm-3-turbo\"',\n },\n minimax: {\n title: 'MiniMax Model Setup',\n placeholder: 'abab6.5s-chat',\n examples: 'e.g. \"abab6.5s-chat\", \"abab6.5g-chat\"',\n },\n 'baidu-qianfan': {\n title: 'Baidu Qianfan Model Setup',\n placeholder: 'ERNIE-4.0-8K',\n examples: 'e.g. \"ERNIE-4.0-8K\", \"ERNIE-3.5-8K\"',\n },\n 'custom-openai': {\n title: 'Custom API Model Setup',\n placeholder: 'model-name',\n examples: 'Enter the exact model name supported by your API endpoint.',\n },\n }\n\n const cfg = modelInputConfig[selectedProvider] || {\n title: t('modelSelector.modelInputTitle'),\n placeholder: 'gpt-4',\n examples: 'e.g. \"gpt-4\", \"gpt-3.5-turbo\"',\n }\n\n return (\n <BrandTextInput\n title={cfg.title}\n description={cfg.examples}\n placeholder={cfg.placeholder}\n value={customModelName}\n onChange={setCustomModelName}\n onSubmit={handleCustomModelSubmit}\n footerHint={t('modelSelector.footerEnterContinue')}\n cursorOffset={customModelNameCursorOffset}\n onChangeCursorOffset={setCustomModelNameCursorOffset}\n />\n )\n }\n\n // Render Context Length Selection Screen\n if (currentScreen === 'contextLength') {\n const contextItems: SelectorItem[] = CONTEXT_LENGTH_OPTIONS.map(opt => ({\n id: opt.value.toString(),\n label:\n opt.value === DEFAULT_CONTEXT_LENGTH\n ? `${opt.label} (${t('modelSelector.recommended')})`\n : opt.label,\n isCurrent: opt.value === contextLength,\n }))\n\n return (\n <SimpleSelector\n title={t('modelSelector.contextLengthTitle')}\n subtitle={t('modelSelector.contextLengthDesc')}\n items={contextItems}\n onSelect={item => {\n setContextLength(parseInt(item.id))\n handleContextLengthSubmit()\n }}\n onClose={handleBack}\n />\n )\n }\n\n // Render Test & Save Screen (merged connectionTest + confirmation)\n if (currentScreen === 'testAndSave') {\n const providerDisplayName = getProviderLabel(selectedProvider, 0).split(\n ' (',\n )[0]\n const showsApiKey = selectedProvider !== 'ollama'\n const contextLengthLabel =\n CONTEXT_LENGTH_OPTIONS.find(opt => opt.value === contextLength)?.label ||\n `${contextLength.toLocaleString()} tokens`\n\n // \u2500\u2500\u2500 Edit mode: SimpleSelector with editable fields \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (isEditMode) {\n const editItems: SelectorItem[] = []\n\n // Editable fields\n if (showsApiKey) {\n editItems.push({\n id: '__edit_apiKey__',\n label: 'API Key',\n description: apiKey ? `****${apiKey.slice(-4)}` : '(not set)',\n category: t('modelSelector.testAndSaveDesc'),\n })\n }\n\n // Show base URL for providers that use it\n if (\n selectedProvider === 'custom-openai' ||\n providerBaseUrl !== providers[selectedProvider]?.baseURL\n ) {\n editItems.push({\n id: '__edit_baseUrl__',\n label: 'Base URL',\n description: providerBaseUrl || customBaseUrl || '(not set)',\n category: t('modelSelector.testAndSaveDesc'),\n })\n }\n\n editItems.push({\n id: '__edit_modelParams__',\n label: 'Max Tokens',\n description: maxTokens,\n category: t('modelSelector.testAndSaveDesc'),\n })\n editItems.push({\n id: '__edit_contextLength__',\n label: 'Context Length',\n description: contextLengthLabel,\n category: t('modelSelector.testAndSaveDesc'),\n })\n\n // Connection test status (non-editable, info only)\n if (connectionTestResult) {\n editItems.push({\n id: '__test_status__',\n label: 'Connection',\n description: connectionTestResult.message,\n statusIcon: connectionTestResult.success ? '\\u2713' : '\\u2715',\n statusColor: connectionTestResult.success\n ? SEMANTIC_COLORS.success\n : SEMANTIC_COLORS.error,\n category: t('modelSelector.testAndSaveDesc'),\n })\n }\n\n // Action items\n editItems.push({\n id: '__save__',\n label: t('modelSelector.confirmationSave'),\n category: t('commands.model.actionsCategory'),\n statusIcon: '\\u2713',\n statusColor: SEMANTIC_COLORS.success,\n })\n editItems.push({\n id: '__test__',\n label: t('modelSelector.connectionTestRetry'),\n category: t('commands.model.actionsCategory'),\n })\n\n const editTitle = t('commands.model.editTitle').replace(\n '{model}',\n editingModel?.name ?? selectedModel,\n )\n\n const editOverlay = isTestingConnection\n ? {\n type: 'loading' as const,\n message: t('modelSelector.autoTesting'),\n }\n : validationError\n ? { type: 'error' as const, message: validationError }\n : null\n\n return (\n <SimpleSelector\n title={editTitle}\n items={editItems}\n groupByCategory={true}\n onSelect={item => {\n if (item.id === '__edit_apiKey__') {\n navigateTo('apiKey')\n } else if (item.id === '__edit_baseUrl__') {\n navigateTo('baseUrl')\n } else if (item.id === '__edit_modelParams__') {\n setActiveFieldIndex(0)\n navigateTo('modelParams')\n } else if (item.id === '__edit_contextLength__') {\n navigateTo('contextLength')\n } else if (item.id === '__save__') {\n handleConfirmation().catch(error => {\n setValidationError(\n error instanceof Error\n ? error.message\n : 'Unexpected error occurred',\n )\n })\n } else if (item.id === '__test__') {\n setConnectionTestResult(null)\n handleConnectionTest()\n }\n // __test_status__ is info-only, no action\n }}\n onClose={handleBack}\n statusOverlay={editOverlay}\n />\n )\n }\n\n // \u2500\u2500\u2500 Add mode: InfoPanel with auto-test \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const configItems: { label: string; value: string; valueColor?: string }[] =\n [\n { label: 'Provider', value: providerDisplayName },\n ...(selectedProvider === 'azure'\n ? [{ label: 'Resource Name', value: resourceName }]\n : []),\n ...(selectedProvider === 'ollama'\n ? [{ label: 'Server URL', value: ollamaBaseUrl }]\n : []),\n ...(selectedProvider === 'custom-openai'\n ? [{ label: 'API Base URL', value: customBaseUrl }]\n : []),\n { label: 'Model', value: selectedModel },\n ...(apiKey && showsApiKey\n ? [{ label: 'API Key', value: `****${apiKey.slice(-4)}` }]\n : []),\n ...(maxTokens ? [{ label: 'Max Tokens', value: maxTokens }] : []),\n { label: 'Context Length', value: contextLengthLabel },\n ...(supportsReasoningEffort\n ? [{ label: 'Reasoning Effort', value: reasoningEffort }]\n : []),\n ]\n\n // Add connection test status to config items\n if (connectionTestResult) {\n configItems.push({\n label: 'Connection',\n value: connectionTestResult.message,\n valueColor: connectionTestResult.success\n ? SEMANTIC_COLORS.success\n : SEMANTIC_COLORS.error,\n })\n if (connectionTestResult.details && !connectionTestResult.success) {\n configItems.push({\n label: 'Details',\n value: connectionTestResult.details,\n })\n }\n }\n\n const testAndSaveSections: InfoSection[] = [\n {\n title: t('modelSelector.testAndSaveDesc'),\n items: configItems,\n },\n ]\n\n // Add validation error section if present\n if (validationError) {\n testAndSaveSections.unshift({\n title: t('modelSelector.configError'),\n items: [\n {\n label: 'Error',\n value: validationError,\n valueColor: SEMANTIC_COLORS.error,\n },\n ],\n })\n }\n\n // Build actions based on test state\n const testAndSaveActions: InfoPanelAction[] = []\n if (connectionTestResult?.success) {\n testAndSaveActions.push({\n key: 'return',\n keyLabel: 'Enter',\n description: t('modelSelector.confirmationSave'),\n onPress: () => {\n handleConfirmation().catch(error => {\n setValidationError(\n error instanceof Error\n ? error.message\n : 'Unexpected error occurred',\n )\n })\n },\n })\n } else if (connectionTestResult && !connectionTestResult.success) {\n testAndSaveActions.push({\n key: 'return',\n keyLabel: 'Enter',\n description: t('modelSelector.connectionTestRetry'),\n onPress: () => {\n setConnectionTestResult(null)\n handleConnectionTest()\n },\n })\n testAndSaveActions.push({\n key: 's',\n keyLabel: 's',\n description: t('modelSelector.saveAnyway'),\n onPress: () => {\n handleConfirmation().catch(error => {\n setValidationError(\n error instanceof Error\n ? error.message\n : 'Unexpected error occurred',\n )\n })\n },\n })\n }\n\n const testAndSaveOverlay = isTestingConnection\n ? {\n type: 'loading' as const,\n message: t('modelSelector.autoTesting'),\n }\n : null\n\n return (\n <InfoPanel\n title={t('modelSelector.testAndSaveTitle')}\n sections={testAndSaveSections}\n actions={testAndSaveActions}\n onClose={handleBack}\n statusOverlay={testAndSaveOverlay}\n />\n )\n }\n\n // Render Anthropic Sub-Menu Selection Screen\n if (currentScreen === 'anthropicSubMenu') {\n const anthropicItems: SelectorItem[] = [\n {\n id: 'official',\n label: t('modelSelector.anthropicOfficial'),\n description: t('modelSelector.anthropicOfficialDesc'),\n },\n {\n id: 'bigdream',\n label: t('modelSelector.anthropicBigdream'),\n description: t('modelSelector.anthropicBigdreamDesc'),\n },\n {\n id: 'opendev',\n label: t('modelSelector.anthropicOpendev'),\n description: t('modelSelector.anthropicOpendevDesc'),\n },\n {\n id: 'custom',\n label: t('modelSelector.anthropicCustom'),\n description: t('modelSelector.anthropicCustomDesc'),\n },\n ]\n\n return (\n <SimpleSelector\n title={t('modelSelector.anthropicSubMenu')}\n subtitle={t('modelSelector.anthropicSubMenuDesc')}\n items={anthropicItems}\n onSelect={item =>\n handleAnthropicProviderSelection(\n item.id as 'official' | 'bigdream' | 'custom',\n )\n }\n onClose={handleBack}\n />\n )\n }\n\n // Render Provider Selection Screen\n const providerSelectorItems: SelectorItem[] = providerOptions.map(opt => ({\n id: opt.value,\n label: opt.label,\n }))\n\n return (\n <SimpleSelector\n title={t('modelSelector.providerSelection')}\n subtitle={t('modelSelector.providerSelectionDesc')}\n items={providerSelectorItems}\n onSelect={item => handleProviderSelection(item.id)}\n onClose={() => {\n if (onCancel) {\n onCancel()\n } else {\n onDone()\n }\n }}\n />\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import React, { useState, useEffect, useCallback, useRef } from 'react'\nimport { Text, useInput } from 'ink'\nimport { getModelManager } from '@utils/model'\nimport { useExitOnCtrlCD } from '@hooks/useExitOnCtrlCD'\nimport {\n getGlobalConfig,\n saveGlobalConfig,\n ProviderType,\n ModelPointerType,\n ModelProfile,\n setAllPointersToModel,\n setModelPointer,\n resolveApiKey,\n} from '@utils/config'\nimport models, { providers } from '@constants/models'\nimport OpenAI from 'openai'\nimport { fetchAnthropicModels, verifyApiKey } from '@services/claude'\nimport { fetchCustomModels, getModelFeatures } from '@services/openai'\nimport {\n testGPT5Connection,\n validateGPT5Config,\n} from '@services/gpt5ConnectionTest'\nimport { SEMANTIC_COLORS } from '@constants/colors'\nimport { isOpenAICompatibleProvider } from '@constants/providers'\nimport { getEffectiveCapabilities } from '@constants/providerRegistry'\nimport { t } from '@i18n'\n\n// Brand-consistent components\nimport { SimpleSelector } from '@components/SimpleSelector/SimpleSelector'\nimport { InfoPanel } from '@components/InfoPanel/InfoPanel'\nimport type { SelectorItem } from '@components/SimpleSelector/types'\nimport type { InfoSection, InfoPanelAction } from '@components/InfoPanel/types'\nimport { BrandTextInput } from './BrandTextInput'\n\n// Import from local modules\nimport {\n CONTEXT_LENGTH_OPTIONS,\n DEFAULT_CONTEXT_LENGTH,\n MAX_TOKENS_OPTIONS,\n DEFAULT_MAX_TOKENS,\n} from './constants'\nimport type {\n ModelInfo,\n ScreenType,\n ReasoningEffortOption,\n AnthropicProviderType,\n ConnectionTestResult,\n} from './types'\n\ntype Props = {\n onDone: () => void\n abortController?: AbortController\n targetPointer?: ModelPointerType\n isOnboarding?: boolean\n onCancel?: () => void\n skipModelType?: boolean\n editingModel?: ModelProfile\n}\n\nexport function ModelSelector({\n onDone: onDoneProp,\n abortController,\n targetPointer,\n isOnboarding = false,\n onCancel,\n skipModelType = false,\n editingModel,\n}: Props): React.ReactNode {\n const config = getGlobalConfig()\n const onDone = onDoneProp\n // Initialize the exit hook for Ctrl+C/D\n useExitOnCtrlCD(() => process.exit(0))\n\n // Edit mode starts directly at testAndSave; add mode starts at provider\n const isEditMode = !!editingModel\n\n // Screen navigation stack\n const [screenStack, setScreenStack] = useState<\n Array<\n | 'provider'\n | 'anthropicSubMenu'\n | 'apiKey'\n | 'resourceName'\n | 'baseUrl'\n | 'model'\n | 'modelInput'\n | 'modelParams'\n | 'contextLength'\n | 'testAndSave'\n >\n >([isEditMode ? 'testAndSave' : 'provider'])\n\n // Current screen is always the last item in the stack\n const currentScreen = screenStack[screenStack.length - 1]\n\n // Ref to track current screen for async navigation guards\n const currentScreenRef = useRef(currentScreen)\n currentScreenRef.current = currentScreen\n\n // Ref to track pending setTimeout IDs for cleanup on back-navigation\n const pendingTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n // Function to navigate to a new screen\n const navigateTo = (\n screen:\n | 'provider'\n | 'anthropicSubMenu'\n | 'apiKey'\n | 'resourceName'\n | 'baseUrl'\n | 'model'\n | 'modelInput'\n | 'modelParams'\n | 'contextLength'\n | 'testAndSave',\n ) => {\n setScreenStack(prev => [...prev, screen])\n }\n\n // Guarded navigateTo for async contexts: only navigates if still on the expected screen\n const navigateToIfStillOn = (\n expectedScreen: typeof currentScreen,\n targetScreen: typeof currentScreen,\n ) => {\n if (currentScreenRef.current === expectedScreen) {\n navigateTo(targetScreen)\n }\n }\n\n // Function to go back to the previous screen\n const goBack = () => {\n if (screenStack.length > 1) {\n // Remove the current screen from the stack\n setScreenStack(prev => prev.slice(0, -1))\n } else {\n // If we're at the first screen, call onDone to exit\n onDone()\n }\n }\n\n // State for model configuration (initialized from editingModel in edit mode)\n const [selectedProvider, setSelectedProvider] = useState<ProviderType>(\n editingModel?.provider ?? config.primaryProvider ?? 'anthropic',\n )\n\n // State for Anthropic provider sub-menu\n const [anthropicProviderType, setAnthropicProviderType] = useState<\n 'official' | 'bigdream' | 'opendev' | 'custom'\n >('official')\n const [selectedModel, setSelectedModel] = useState<string>(\n editingModel?.modelName ?? '',\n )\n const [apiKey, setApiKey] = useState<string>(editingModel?.apiKey ?? '')\n\n // New state for model parameters\n const [maxTokens, setMaxTokens] = useState<string>(\n editingModel?.maxTokens?.toString() ??\n config.maxTokens?.toString() ??\n DEFAULT_MAX_TOKENS.toString(),\n )\n const [maxTokensMode, setMaxTokensMode] = useState<'preset' | 'custom'>(\n 'preset',\n )\n const [selectedMaxTokensPreset, setSelectedMaxTokensPreset] =\n useState<number>(config.maxTokens || DEFAULT_MAX_TOKENS)\n const [reasoningEffort, setReasoningEffort] = useState<ReasoningEffortOption>(\n (editingModel?.reasoningEffort as ReasoningEffortOption) ?? 'medium',\n )\n const [supportsReasoningEffort, setSupportsReasoningEffort] =\n useState<boolean>(!!editingModel?.reasoningEffort)\n\n // Context length state (use default instead of legacy config)\n const [contextLength, setContextLength] = useState<number>(\n editingModel?.contextLength ?? DEFAULT_CONTEXT_LENGTH,\n )\n\n // Form focus state\n const [activeFieldIndex, setActiveFieldIndex] = useState(0)\n const [maxTokensCursorOffset, setMaxTokensCursorOffset] = useState<number>(0)\n\n // UI state\n\n // Search and model loading state\n const [availableModels, setAvailableModels] = useState<ModelInfo[]>([])\n const [isLoadingModels, setIsLoadingModels] = useState(false)\n const [modelLoadError, setModelLoadError] = useState<string | null>(null)\n const [modelSearchQuery, setModelSearchQuery] = useState<string>('')\n const [modelSearchCursorOffset, setModelSearchCursorOffset] =\n useState<number>(0)\n const [cursorOffset, setCursorOffset] = useState<number>(0)\n const [apiKeyEdited, setApiKeyEdited] = useState<boolean>(isEditMode)\n\n // Track original encrypted reference to preserve on save when user doesn't change the key\n const [originalEncryptedRef, setOriginalEncryptedRef] = useState<\n string | null\n >(editingModel?.apiKey?.startsWith('encrypted:') ? editingModel.apiKey : null)\n const [apiKeyUserModified, setApiKeyUserModified] = useState(false)\n\n // Resolve encrypted API key references (encrypted:keyName \u2192 actual key)\n useEffect(() => {\n if (editingModel?.apiKey?.startsWith('encrypted:')) {\n resolveApiKey(editingModel).then(resolved => {\n if (resolved) setApiKey(resolved)\n })\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n // Retry logic state\n const [fetchRetryCount, setFetchRetryCount] = useState<number>(0)\n const [isRetrying, setIsRetrying] = useState<boolean>(false)\n\n // Connection test state\n const [isTestingConnection, setIsTestingConnection] = useState<boolean>(false)\n const [connectionTestResult, setConnectionTestResult] = useState<{\n success: boolean\n message: string\n endpoint?: string\n details?: string\n } | null>(null)\n\n // Validation error state for duplicate model detection\n const [validationError, setValidationError] = useState<string | null>(null)\n\n // Track whether model was manually entered (needs contextLength screen)\n const [isManualModelEntry, setIsManualModelEntry] = useState<boolean>(false)\n\n // State for Azure-specific configuration\n const [resourceName, setResourceName] = useState<string>('')\n const [resourceNameCursorOffset, setResourceNameCursorOffset] =\n useState<number>(0)\n const [customModelName, setCustomModelName] = useState<string>('')\n const [customModelNameCursorOffset, setCustomModelNameCursorOffset] =\n useState<number>(0)\n\n // State for Ollama-specific configuration\n const [ollamaBaseUrl, setOllamaBaseUrl] = useState<string>(\n 'http://localhost:11434/v1',\n )\n const [ollamaBaseUrlCursorOffset, setOllamaBaseUrlCursorOffset] =\n useState<number>(0)\n\n // State for custom OpenAI-compatible API configuration\n const [customBaseUrl, setCustomBaseUrl] = useState<string>(\n editingModel?.provider === 'custom-openai'\n ? (editingModel?.baseURL ?? '')\n : '',\n )\n const [customBaseUrlCursorOffset, setCustomBaseUrlCursorOffset] =\n useState<number>(0)\n\n // State for provider base URL configuration (used for all providers)\n const [providerBaseUrl, setProviderBaseUrl] = useState<string>(\n editingModel?.baseURL ?? '',\n )\n const [providerBaseUrlCursorOffset, setProviderBaseUrlCursorOffset] =\n useState<number>(0)\n\n // Reasoning effort options\n const reasoningEffortOptions = [\n { label: 'Low - Faster responses, less thorough reasoning', value: 'low' },\n { label: 'Medium - Balanced speed and reasoning depth', value: 'medium' },\n {\n label: 'High - Slower responses, more thorough reasoning',\n value: 'high',\n },\n ]\n\n // Get available providers from models.ts, excluding community Claude providers (now in Anthropic sub-menu)\n const availableProviders = Object.keys(providers).filter(\n provider => provider !== 'bigdream' && provider !== 'opendev',\n )\n\n // Create provider options with nice labels\n const providerOptions = availableProviders.map(provider => {\n const modelCount = models[provider]?.length || 0\n const label = getProviderLabel(provider, modelCount)\n return {\n label,\n value: provider,\n }\n })\n\n useEffect(() => {\n if (!apiKeyEdited && selectedProvider) {\n if (process.env[selectedProvider.toUpperCase() + '_API_KEY']) {\n setApiKey(\n process.env[selectedProvider.toUpperCase() + '_API_KEY'] as string,\n )\n } else {\n setApiKey('')\n }\n }\n }, [selectedProvider, apiKey, apiKeyEdited])\n\n // Ensure contextLength is always set to a valid option when contextLength screen is displayed\n useEffect(() => {\n if (\n currentScreen === 'contextLength' &&\n !CONTEXT_LENGTH_OPTIONS.find(opt => opt.value === contextLength)\n ) {\n setContextLength(DEFAULT_CONTEXT_LENGTH)\n }\n }, [currentScreen, contextLength])\n\n // Auto-start connection test when entering testAndSave screen (add mode only)\n useEffect(() => {\n if (\n currentScreen === 'testAndSave' &&\n !isEditMode &&\n !isTestingConnection &&\n !connectionTestResult\n ) {\n handleConnectionTest()\n }\n }, [currentScreen])\n\n // Create a set of model names from our constants/models.ts for the current provider\n const ourModelNames = new Set(\n (models[selectedProvider as keyof typeof models] || []).map(\n (model: any) => model.model,\n ),\n )\n\n // Create model options from available models, filtered by search query\n const filteredModels = modelSearchQuery\n ? availableModels.filter(model =>\n model.model?.toLowerCase().includes(modelSearchQuery.toLowerCase()),\n )\n : availableModels\n\n // Sort models with priority for specific keywords\n const sortModelsByPriority = (models: ModelInfo[]) => {\n const priorityKeywords = [\n 'claude',\n 'kimi',\n 'deepseek',\n 'minimax',\n 'o3',\n 'gpt',\n 'qwen',\n ]\n\n return models.sort((a, b) => {\n // Add safety checks for undefined model names\n const aModelLower = a.model?.toLowerCase() || ''\n const bModelLower = b.model?.toLowerCase() || ''\n\n // Check if models contain priority keywords\n const aHasPriority = priorityKeywords.some(keyword =>\n aModelLower.includes(keyword),\n )\n const bHasPriority = priorityKeywords.some(keyword =>\n bModelLower.includes(keyword),\n )\n\n // If one has priority and the other doesn't, prioritize the one with keywords\n if (aHasPriority && !bHasPriority) return -1\n if (!aHasPriority && bHasPriority) return 1\n\n // If both have priority or neither has priority, sort alphabetically\n return a.model.localeCompare(b.model)\n })\n }\n\n const sortedFilteredModels = sortModelsByPriority(filteredModels)\n\n const modelOptions = sortedFilteredModels.map(model => {\n // Check if this model is in our constants/models.ts list\n const isInOurModels = ourModelNames.has(model.model)\n\n return {\n label: `${model.model}${getModelDetails(model)}`,\n value: model.model,\n }\n })\n\n function getModelDetails(model: ModelInfo): string {\n const details = []\n\n // Show context_length if available (Ollama models), otherwise max_tokens\n if (model.context_length) {\n details.push(`${formatNumber(model.context_length)} tokens`)\n } else if (model.max_tokens) {\n details.push(`${formatNumber(model.max_tokens)} tokens`)\n }\n\n if (model.supports_vision) {\n details.push('vision')\n }\n\n if (model.supports_function_calling) {\n details.push('tools')\n }\n\n return details.length > 0 ? ` (${details.join(', ')})` : ''\n }\n\n function formatNumber(num: number): string {\n if (num >= 1000000) {\n return `${(num / 1000000).toFixed(1)}M`\n } else if (num >= 1000) {\n return `${(num / 1000).toFixed(0)}K`\n }\n return num.toString()\n }\n\n function getProviderLabel(provider: string, modelCount: number): string {\n // Use provider names from the providers object if available\n if (providers[provider]) {\n return `${providers[provider].name} ${providers[provider].status === 'wip' ? '(WIP)' : ''} (${modelCount} models)`\n }\n return `${provider}`\n }\n\n function handleProviderSelection(provider: string) {\n const providerType = provider as ProviderType\n setSelectedProvider(providerType)\n\n if (provider === 'custom') {\n // For custom provider, save and exit\n saveConfiguration(providerType, selectedModel || '')\n onDone()\n } else if (provider === 'anthropic') {\n // For Anthropic provider, go to sub-menu to choose between official, community proxies, or custom\n navigateTo('anthropicSubMenu')\n } else {\n // For all other providers, go to base URL configuration first\n // Initialize with the default base URL for the provider\n const defaultBaseUrl = providers[providerType]?.baseURL || ''\n setProviderBaseUrl(defaultBaseUrl)\n navigateTo('baseUrl')\n }\n }\n\n // Local implementation of fetchAnthropicModels for UI\n async function fetchAnthropicModels(baseURL: string, apiKey: string) {\n try {\n const response = await fetch(`${baseURL}/v1/models`, {\n method: 'GET',\n headers: {\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n signal: AbortSignal.timeout(30_000),\n })\n\n if (!response.ok) {\n if (response.status === 401) {\n throw new Error(\n 'Invalid API key. Please check your API key and try again.',\n )\n } else if (response.status === 403) {\n throw new Error('API key does not have permission to access models.')\n } else if (response.status === 404) {\n throw new Error(\n 'API endpoint not found. This provider may not support model listing.',\n )\n } else if (response.status === 429) {\n throw new Error(\n 'Too many requests. Please wait a moment and try again.',\n )\n } else if (response.status >= 500) {\n throw new Error(\n 'API service is temporarily unavailable. Please try again later.',\n )\n } else {\n throw new Error(`Unable to connect to API (${response.status}).`)\n }\n }\n\n const data = await response.json()\n\n // Handle different response formats\n let models = []\n if (data && data.data && Array.isArray(data.data)) {\n models = data.data\n } else if (Array.isArray(data)) {\n models = data\n } else if (data && data.models && Array.isArray(data.models)) {\n models = data.models\n } else {\n throw new Error('API returned unexpected response format.')\n }\n\n return models\n } catch (error) {\n if (\n error instanceof Error &&\n (error.message.includes('API key') ||\n error.message.includes('API endpoint') ||\n error.message.includes('API service') ||\n error.message.includes('response format'))\n ) {\n throw error\n }\n\n if (error instanceof Error && error.message.includes('fetch')) {\n throw new Error(\n 'Unable to connect to the API. Please check the base URL and your internet connection.',\n )\n }\n\n throw new Error(\n 'Failed to fetch models from API. Please check your configuration and try again.',\n )\n }\n }\n\n // \u901A\u7528\u7684Anthropic\u517C\u5BB9\u6A21\u578B\u83B7\u53D6\u51FD\u6570\uFF0C\u5B9E\u73B0\u4E09\u5C42\u964D\u7EA7\u7B56\u7565\n async function fetchAnthropicCompatibleModelsWithFallback(\n baseURL: string,\n provider: string,\n apiKeyUrl: string,\n ) {\n let lastError: Error | null = null\n\n // \u7B2C\u4E00\u5C42\uFF1A\u5C1D\u8BD5\u4F7F\u7528 Anthropic \u98CE\u683C\u7684 API\n try {\n const models = await fetchAnthropicModels(baseURL, apiKey)\n return models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: provider,\n max_tokens: model.max_tokens || 8192,\n supports_vision: model.supports_vision || true,\n supports_function_calling: model.supports_function_calling || true,\n supports_reasoning_effort: false,\n }))\n } catch (error) {\n lastError = error as Error\n }\n\n // \u7B2C\u4E8C\u5C42\uFF1A\u5C1D\u8BD5\u4F7F\u7528 OpenAI \u98CE\u683C\u7684 API\n try {\n const models = await fetchCustomModels(baseURL, apiKey)\n return models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: provider,\n max_tokens: model.max_tokens || 8192,\n supports_vision: model.supports_vision || false,\n supports_function_calling: model.supports_function_calling || true,\n supports_reasoning_effort: false,\n }))\n } catch (error) {\n lastError = error as Error\n }\n\n // \u7B2C\u4E09\u5C42\uFF1A\u629B\u51FA\u9519\u8BEF\uFF0C\u89E6\u53D1\u624B\u52A8\u8F93\u5165\u6A21\u5F0F\n let errorMessage = `Failed to fetch ${provider} models using both Anthropic and OpenAI API formats`\n\n if (lastError) {\n errorMessage = lastError.message\n }\n\n // \u6DFB\u52A0\u6709\u7528\u7684\u5EFA\u8BAE\n if (errorMessage.includes('API key')) {\n errorMessage += `\\n\\n\uD83D\uDCA1 Tip: Get your API key from ${apiKeyUrl}`\n } else if (errorMessage.includes('permission')) {\n errorMessage += `\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the ${provider} API`\n } else if (errorMessage.includes('connection')) {\n errorMessage += '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw new Error(errorMessage)\n }\n\n // \u7EDF\u4E00\u5904\u7406\u6240\u6709Anthropic\u517C\u5BB9\u63D0\u4F9B\u5546\u7684\u6A21\u578B\u83B7\u53D6\n async function fetchAnthropicCompatibleProviderModels() {\n // \u6839\u636EanthropicProviderType\u786E\u5B9A\u9ED8\u8BA4baseURL\u548CAPI key\u83B7\u53D6\u5730\u5740\n let defaultBaseURL: string\n let apiKeyUrl: string\n let actualProvider: string\n\n switch (anthropicProviderType) {\n case 'official':\n defaultBaseURL = 'https://api.anthropic.com'\n apiKeyUrl = 'https://console.anthropic.com/settings/keys'\n actualProvider = 'anthropic'\n break\n case 'bigdream':\n defaultBaseURL = 'https://api-key.info'\n apiKeyUrl = 'https://api-key.info/register?aff=MSl4'\n actualProvider = 'bigdream'\n break\n case 'opendev':\n defaultBaseURL = 'https://api.openai-next.com'\n apiKeyUrl = 'https://api.openai-next.com/register/?aff_code=4xo7'\n actualProvider = 'opendev'\n break\n case 'custom':\n defaultBaseURL = providerBaseUrl\n apiKeyUrl = 'your custom API provider'\n actualProvider = 'anthropic'\n break\n default:\n throw new Error(\n `Unsupported Anthropic provider type: ${anthropicProviderType}`,\n )\n }\n\n const baseURL =\n anthropicProviderType === 'custom'\n ? providerBaseUrl\n : providerBaseUrl || defaultBaseURL\n return await fetchAnthropicCompatibleModelsWithFallback(\n baseURL,\n actualProvider,\n apiKeyUrl,\n )\n }\n\n // Remove duplicate function definitions - using unified fetchAnthropicCompatibleProviderModels instead\n\n async function fetchKimiModels() {\n try {\n const baseURL = providerBaseUrl || 'https://api.moonshot.cn/v1'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const kimiModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'kimi',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false, // Default to false, could be enhanced\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return kimiModels\n } catch (error) {\n let errorMessage = 'Failed to fetch Kimi models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n // Add helpful suggestions based on error type\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://platform.moonshot.cn/console/api-keys'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the Kimi API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchDeepSeekModels() {\n try {\n const baseURL = providerBaseUrl || 'https://api.deepseek.com'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const deepseekModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'deepseek',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false, // Default to false, could be enhanced\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return deepseekModels\n } catch (error) {\n let errorMessage = 'Failed to fetch DeepSeek models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n // Add helpful suggestions based on error type\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://platform.deepseek.com/api_keys'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the DeepSeek API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchSiliconFlowModels() {\n try {\n const baseURL = providerBaseUrl || 'https://api.siliconflow.cn/v1'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const siliconflowModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'siliconflow',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false, // Default to false, could be enhanced\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return siliconflowModels\n } catch (error) {\n let errorMessage = 'Failed to fetch SiliconFlow models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n // Add helpful suggestions based on error type\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://cloud.siliconflow.cn/i/oJWsm6io'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the SiliconFlow API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchQwenModels() {\n try {\n const baseURL =\n providerBaseUrl || 'https://dashscope.aliyuncs.com/compatible-mode/v1'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const qwenModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'qwen',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false,\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return qwenModels\n } catch (error) {\n let errorMessage = 'Failed to fetch Qwen models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://bailian.console.aliyun.com/?tab=model#/api-key'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the Qwen API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchGLMModels() {\n try {\n const baseURL = providerBaseUrl || 'https://open.bigmodel.cn/api/paas/v4'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const glmModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'glm',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false,\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return glmModels\n } catch (error) {\n let errorMessage = 'Failed to fetch GLM models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://open.bigmodel.cn (API Keys section)'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the GLM API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchMinimaxModels() {\n try {\n const baseURL = providerBaseUrl || 'https://api.minimaxi.com/v1'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const minimaxModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'minimax',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false,\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return minimaxModels\n } catch (error) {\n let errorMessage = 'Failed to fetch MiniMax models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://www.minimax.io/platform/user-center/basic-information'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the MiniMax API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchBaiduQianfanModels() {\n try {\n const baseURL = providerBaseUrl || 'https://qianfan.baidubce.com/v2'\n const models = await fetchCustomModels(baseURL, apiKey)\n\n const baiduModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'baidu-qianfan',\n max_tokens: model.max_tokens || 8192,\n supports_vision: false,\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return baiduModels\n } catch (error) {\n let errorMessage = 'Failed to fetch Baidu Qianfan models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Get your API key from https://console.bce.baidu.com/iam/#/iam/accesslist'\n } else if (errorMessage.includes('permission')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure your API key has access to the Baidu Qianfan API'\n } else if (errorMessage.includes('connection')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check your internet connection and try again'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchCustomOpenAIModels() {\n try {\n const models = await fetchCustomModels(customBaseUrl, apiKey)\n\n const customModels = models.map((model: any) => ({\n model:\n model.modelName || model.id || model.name || model.model || 'unknown',\n provider: 'custom-openai',\n max_tokens: model.max_tokens || 4096,\n supports_vision: false, // Default to false, could be enhanced\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n return customModels\n } catch (error) {\n let errorMessage = 'Failed to fetch custom API models'\n\n if (error instanceof Error) {\n errorMessage = error.message\n }\n\n // Add helpful suggestions based on error type\n if (errorMessage.includes('API key')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Check that your API key is valid for this endpoint'\n } else if (errorMessage.includes('endpoint not found')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Make sure the base URL ends with /v1 and supports OpenAI-compatible API'\n } else if (errorMessage.includes('connect')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: Verify the base URL is correct and accessible'\n } else if (errorMessage.includes('response format')) {\n errorMessage +=\n '\\n\\n\uD83D\uDCA1 Tip: This API may not be fully OpenAI-compatible'\n }\n\n setModelLoadError(errorMessage)\n throw error\n }\n }\n\n async function fetchGeminiModels() {\n try {\n const response = await fetch(\n `https://generativelanguage.googleapis.com/v1beta/models?key=${apiKey}`,\n { signal: AbortSignal.timeout(30_000) },\n )\n\n if (!response.ok) {\n const errorData = await response.json()\n throw new Error(\n errorData.error?.message || `API error: ${response.status}`,\n )\n }\n\n const { models } = await response.json()\n\n const geminiModels = models\n .filter((model: any) =>\n model.supportedGenerationMethods.includes('generateContent'),\n )\n .map((model: any) => ({\n model: model.name.replace('models/', ''),\n provider: 'gemini',\n max_tokens: model.outputTokenLimit,\n supports_vision:\n model.supportedGenerationMethods.includes('generateContent'),\n supports_function_calling:\n model.supportedGenerationMethods.includes('generateContent'),\n }))\n\n return geminiModels\n } catch (error) {\n setModelLoadError(\n error instanceof Error ? error.message : 'Unknown error',\n )\n throw error\n }\n }\n\n async function fetchOllamaModels() {\n try {\n const response = await fetch(`${ollamaBaseUrl}/models`, {\n signal: AbortSignal.timeout(30_000),\n })\n\n if (!response.ok) {\n throw new Error(`HTTP error ${response.status}: ${response.statusText}`)\n }\n\n const responseData = await response.json()\n\n // Properly handle Ollama API response format\n // Ollama API can return models in different formats based on version\n let models = []\n\n // Check if data field exists (newer Ollama versions)\n if (responseData.data && Array.isArray(responseData.data)) {\n models = responseData.data\n }\n // Check if models array is directly at the root (older Ollama versions)\n else if (Array.isArray(responseData.models)) {\n models = responseData.models\n }\n // If response is already an array\n else if (Array.isArray(responseData)) {\n models = responseData\n } else {\n throw new Error(\n 'Invalid response from Ollama API: missing models array',\n )\n }\n\n // Transform Ollama models to our format\n // Note: max_tokens here is for OUTPUT tokens, not context length\n const ollamaModels = models.map((model: any) => ({\n model:\n model.id ??\n model.name ??\n model.modelName ??\n (typeof model === 'string' ? model : ''),\n provider: 'ollama',\n max_tokens: DEFAULT_MAX_TOKENS, // Default output tokens (8K is reasonable)\n supports_vision: false,\n supports_function_calling: true,\n supports_reasoning_effort: false,\n }))\n\n // Filter out models with empty names\n const validModels = ollamaModels.filter(model => model.model)\n\n // Helper: normalize Ollama server root for /api/show (strip trailing /v1)\n const normalizeOllamaRoot = (url: string): string => {\n try {\n const u = new URL(url)\n let pathname = u.pathname.replace(/\\/+$|^$/, '')\n if (pathname.endsWith('/v1')) {\n pathname = pathname.slice(0, -3)\n }\n u.pathname = pathname\n return u.toString().replace(/\\/+$/, '')\n } catch {\n return url.replace(/\\/v1\\/?$/, '')\n }\n }\n\n // Helper: extract num_ctx/context_length from /api/show response\n const extractContextTokens = (data: any): number | null => {\n if (!data || typeof data !== 'object') return null\n\n // First check model_info for architecture-specific context_length fields\n // Example: qwen2.context_length, llama.context_length, etc.\n if (data.model_info && typeof data.model_info === 'object') {\n const modelInfo = data.model_info\n for (const key of Object.keys(modelInfo)) {\n if (\n key.endsWith('.context_length') ||\n key.endsWith('_context_length')\n ) {\n const val = modelInfo[key]\n if (typeof val === 'number' && isFinite(val) && val > 0) {\n return val\n }\n }\n }\n }\n\n // Fallback to other common fields\n const candidates = [\n (data as any)?.parameters?.num_ctx,\n (data as any)?.model_info?.num_ctx,\n (data as any)?.config?.num_ctx,\n (data as any)?.details?.context_length,\n (data as any)?.context_length,\n (data as any)?.num_ctx,\n (data as any)?.max_tokens,\n (data as any)?.max_new_tokens,\n ].filter((v: any) => typeof v === 'number' && isFinite(v) && v > 0)\n if (candidates.length > 0) {\n return Math.max(...candidates)\n }\n\n // parameters may be a string like \"num_ctx=4096 ...\"\n if (typeof (data as any)?.parameters === 'string') {\n const m = (data as any).parameters.match(/num_ctx\\s*[:=]\\s*(\\d+)/i)\n if (m) {\n const n = parseInt(m[1], 10)\n if (Number.isFinite(n) && n > 0) return n\n }\n }\n return null\n }\n\n // Enrich each model via /api/show to get accurate context length\n // Store context length separately from max_tokens (output limit)\n const ollamaRoot = normalizeOllamaRoot(ollamaBaseUrl)\n const enrichedModels = await Promise.all(\n validModels.map(async (m: any) => {\n try {\n const showResp = await fetch(`${ollamaRoot}/api/show`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name: m.model }),\n signal: AbortSignal.timeout(30_000),\n })\n if (showResp.ok) {\n const showData = await showResp.json()\n const ctx = extractContextTokens(showData)\n if (typeof ctx === 'number' && isFinite(ctx) && ctx > 0) {\n // Store context_length separately, don't override max_tokens\n return { ...m, context_length: ctx }\n }\n }\n // Fallback to default if missing\n return m\n } catch {\n return m\n }\n }),\n )\n\n setAvailableModels(enrichedModels)\n\n // Only navigate if we have models and user hasn't navigated away\n if (enrichedModels.length > 0) {\n navigateToIfStillOn('baseUrl', 'model')\n } else {\n setModelLoadError('No models found in your Ollama installation')\n }\n\n return enrichedModels\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n\n if (errorMessage.includes('fetch')) {\n setModelLoadError(\n `Could not connect to Ollama server at ${ollamaBaseUrl}. Make sure Ollama is running and the URL is correct.`,\n )\n } else {\n setModelLoadError(`Error loading Ollama models: ${errorMessage}`)\n }\n\n return []\n }\n }\n\n async function fetchModelsWithRetry() {\n const MAX_RETRIES = 2\n let lastError: Error | null = null\n\n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n setFetchRetryCount(attempt)\n setIsRetrying(attempt > 1)\n\n if (attempt > 1) {\n // Show retry message\n setModelLoadError(\n `Attempt ${attempt}/${MAX_RETRIES}: Retrying model discovery...`,\n )\n // Wait 1 second before retrying\n await new Promise(resolve => setTimeout(resolve, 1000))\n }\n\n try {\n const models = await fetchModels()\n // Success! Reset retry state and return models\n setFetchRetryCount(0)\n setIsRetrying(false)\n setModelLoadError(null)\n return models\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error))\n\n if (attempt === MAX_RETRIES) {\n // Final attempt failed, break to handle fallback\n break\n }\n }\n }\n\n // All retries failed, handle fallback to manual input\n setIsRetrying(false)\n const errorMessage = lastError?.message || 'Unknown error'\n\n // Check if provider supports manual input fallback\n const supportsManualInput = [\n 'anthropic',\n 'kimi',\n 'deepseek',\n 'siliconflow',\n 'qwen',\n 'glm',\n 'minimax',\n 'baidu-qianfan',\n 'custom-openai',\n ].includes(selectedProvider)\n\n if (supportsManualInput) {\n setModelLoadError(\n `Failed to auto-discover models after ${MAX_RETRIES} attempts: ${errorMessage}\\n\\n\u26A1 Automatically switching to manual model configuration...`,\n )\n\n // Automatically switch to manual input after 2 seconds\n // Store timer ID so handleBack can cancel it if user navigates away\n pendingTimerRef.current = setTimeout(() => {\n pendingTimerRef.current = null\n setModelLoadError(null)\n navigateToIfStillOn('apiKey', 'modelInput')\n }, 2000)\n } else {\n setModelLoadError(\n `Failed to load models after ${MAX_RETRIES} attempts: ${errorMessage}`,\n )\n }\n\n return []\n }\n\n async function fetchModels() {\n // Capture the screen we're on when fetch starts, so async callbacks\n // only navigate if the user hasn't pressed ESC in the meantime.\n const originScreen = currentScreenRef.current\n setIsLoadingModels(true)\n setModelLoadError(null)\n\n try {\n // For Anthropic provider (including official and community proxies via sub-menu), use the same logic\n if (selectedProvider === 'anthropic') {\n const anthropicModels = await fetchAnthropicCompatibleProviderModels()\n setAvailableModels(anthropicModels)\n navigateToIfStillOn(originScreen, 'model')\n return anthropicModels\n }\n\n // For custom OpenAI-compatible APIs, use the fetchCustomOpenAIModels function\n if (selectedProvider === 'custom-openai') {\n const customModels = await fetchCustomOpenAIModels()\n setAvailableModels(customModels)\n navigateToIfStillOn(originScreen, 'model')\n return customModels\n }\n\n // For Gemini, use the separate fetchGeminiModels function\n if (selectedProvider === 'gemini') {\n const geminiModels = await fetchGeminiModels()\n setAvailableModels(geminiModels)\n navigateToIfStillOn(originScreen, 'model')\n return geminiModels\n }\n\n // For Kimi, use the fetchKimiModels function\n if (selectedProvider === 'kimi') {\n const kimiModels = await fetchKimiModels()\n setAvailableModels(kimiModels)\n navigateToIfStillOn(originScreen, 'model')\n return kimiModels\n }\n\n // For DeepSeek, use the fetchDeepSeekModels function\n if (selectedProvider === 'deepseek') {\n const deepseekModels = await fetchDeepSeekModels()\n setAvailableModels(deepseekModels)\n navigateToIfStillOn(originScreen, 'model')\n return deepseekModels\n }\n\n // For SiliconFlow, use the fetchSiliconFlowModels function\n if (selectedProvider === 'siliconflow') {\n const siliconflowModels = await fetchSiliconFlowModels()\n setAvailableModels(siliconflowModels)\n navigateToIfStillOn(originScreen, 'model')\n return siliconflowModels\n }\n\n // For Qwen, use the fetchQwenModels function\n if (selectedProvider === 'qwen') {\n const qwenModels = await fetchQwenModels()\n setAvailableModels(qwenModels)\n navigateToIfStillOn(originScreen, 'model')\n return qwenModels\n }\n\n // For GLM, use the fetchGLMModels function\n if (selectedProvider === 'glm') {\n const glmModels = await fetchGLMModels()\n setAvailableModels(glmModels)\n navigateToIfStillOn(originScreen, 'model')\n return glmModels\n }\n\n // For Baidu Qianfan, use the fetchBaiduQianfanModels function\n if (selectedProvider === 'baidu-qianfan') {\n const baiduModels = await fetchBaiduQianfanModels()\n setAvailableModels(baiduModels)\n navigateToIfStillOn(originScreen, 'model')\n return baiduModels\n }\n\n // For Azure, skip model fetching and go directly to model input\n if (selectedProvider === 'azure') {\n navigateToIfStillOn(originScreen, 'modelInput')\n return []\n }\n\n // For all other providers, use the OpenAI client\n let baseURL = providerBaseUrl || providers[selectedProvider]?.baseURL\n\n // For custom-openai provider, use the custom base URL\n if (selectedProvider === 'custom-openai') {\n baseURL = customBaseUrl\n }\n\n const openai = new OpenAI({\n apiKey: apiKey || 'dummy-key-for-ollama', // Ollama doesn't need a real key\n baseURL: baseURL,\n dangerouslyAllowBrowser: true,\n })\n\n // Fetch the models\n const response = await openai.models.list()\n\n // Transform the response into our ModelInfo format\n const fetchedModels = []\n for (const model of response.data) {\n const modelName =\n (model as any).modelName ||\n (model as any).id ||\n (model as any).name ||\n (model as any).model ||\n 'unknown'\n const modelInfo = models[selectedProvider as keyof typeof models]?.find(\n m => m.model === modelName,\n )\n fetchedModels.push({\n model: modelName,\n provider: selectedProvider,\n max_tokens: modelInfo?.max_output_tokens,\n supports_vision: modelInfo?.supports_vision || false,\n supports_function_calling:\n modelInfo?.supports_function_calling || false,\n supports_reasoning_effort:\n modelInfo?.supports_reasoning_effort || false,\n })\n }\n\n setAvailableModels(fetchedModels)\n\n // Navigate to model selection screen if models were loaded successfully\n // and user hasn't navigated away during the async fetch\n navigateToIfStillOn(originScreen, 'model')\n\n return fetchedModels\n } catch (error) {\n // Re-throw the error so that fetchModelsWithRetry can handle it properly\n throw error\n } finally {\n setIsLoadingModels(false)\n }\n }\n\n function handleApiKeySubmit(key: string) {\n setApiKey(key)\n\n // In edit mode, return to edit summary after changing API key\n if (isEditMode) {\n goBack()\n return\n }\n\n // For Azure, go to resource name input next\n if (selectedProvider === 'azure') {\n navigateTo('resourceName')\n return\n }\n\n // Fetch models with the provided API key\n fetchModelsWithRetry().catch(() => {\n // The retry logic in fetchModelsWithRetry already handles the error display\n // This catch is just to prevent unhandled promise rejection\n })\n }\n\n function handleResourceNameSubmit(name: string) {\n setResourceName(name)\n navigateTo('modelInput')\n }\n\n function handleOllamaBaseUrlSubmit(url: string) {\n setOllamaBaseUrl(url)\n setIsLoadingModels(true)\n setModelLoadError(null)\n\n // Use the dedicated Ollama model fetch function\n fetchOllamaModels().finally(() => {\n setIsLoadingModels(false)\n })\n }\n\n function handleCustomBaseUrlSubmit(url: string) {\n // Automatically remove trailing slash from baseURL\n const cleanUrl = url.replace(/\\/+$/, '')\n setCustomBaseUrl(cleanUrl)\n setProviderBaseUrl(cleanUrl)\n\n // In edit mode, return to edit summary\n if (isEditMode) {\n goBack()\n return\n }\n\n // After setting custom base URL, go to API key input\n navigateTo('apiKey')\n }\n\n function handleProviderBaseUrlSubmit(url: string) {\n // Automatically remove trailing slash from baseURL\n const cleanUrl = url.replace(/\\/+$/, '')\n setProviderBaseUrl(cleanUrl)\n\n // In edit mode, return to edit summary\n if (isEditMode) {\n goBack()\n return\n }\n\n // For Ollama, handle differently - it tries to fetch models immediately\n if (selectedProvider === 'ollama') {\n setOllamaBaseUrl(cleanUrl)\n setIsLoadingModels(true)\n setModelLoadError(null)\n\n // Use the dedicated Ollama model fetch function\n fetchOllamaModels().finally(() => {\n setIsLoadingModels(false)\n })\n } else {\n // For all other providers, go to API key input next\n navigateTo('apiKey')\n }\n }\n\n function handleAnthropicProviderSelection(\n providerType: 'official' | 'bigdream' | 'custom',\n ) {\n setAnthropicProviderType(providerType)\n\n if (providerType === 'custom') {\n // For custom Anthropic provider, go to base URL configuration\n setProviderBaseUrl('')\n navigateTo('baseUrl')\n } else {\n // For official/community proxy providers, set default base URL and go to API key\n const defaultUrls = {\n official: 'https://api.anthropic.com',\n bigdream: 'https://api-key.info',\n opendev: 'https://api.openai-next.com',\n }\n setProviderBaseUrl(defaultUrls[providerType])\n navigateTo('apiKey')\n }\n }\n\n function handleCustomModelSubmit(model: string) {\n setCustomModelName(model)\n setSelectedModel(model)\n setIsManualModelEntry(true)\n\n // No model info available, so set default values\n setSupportsReasoningEffort(false)\n setReasoningEffort(null)\n\n // Use default max tokens for manually entered models\n setMaxTokensMode('preset')\n setSelectedMaxTokensPreset(DEFAULT_MAX_TOKENS)\n setMaxTokens(DEFAULT_MAX_TOKENS.toString())\n setMaxTokensCursorOffset(DEFAULT_MAX_TOKENS.toString().length)\n\n // Go to model parameters screen\n navigateTo('modelParams')\n // Reset active field index\n setActiveFieldIndex(0)\n }\n\n function handleModelSelection(model: string) {\n setSelectedModel(model)\n setIsManualModelEntry(false)\n\n // Check if the selected model supports reasoning_effort\n const modelInfo = availableModels.find(m => m.model === model)\n setSupportsReasoningEffort(modelInfo?.supports_reasoning_effort || false)\n\n if (!modelInfo?.supports_reasoning_effort) {\n setReasoningEffort(null)\n }\n\n // Set context length if available (from Ollama /api/show)\n if (modelInfo?.context_length) {\n setContextLength(modelInfo.context_length)\n } else {\n setContextLength(DEFAULT_CONTEXT_LENGTH)\n }\n\n // Set max tokens based on model info or default\n // Note: max_tokens is for OUTPUT, not context window\n if (modelInfo?.max_tokens) {\n const modelMaxTokens = modelInfo.max_tokens\n // Check if the model's max tokens matches any of our presets\n const matchingPreset = MAX_TOKENS_OPTIONS.find(\n option => option.value === modelMaxTokens,\n )\n\n if (matchingPreset) {\n setMaxTokensMode('preset')\n setSelectedMaxTokensPreset(modelMaxTokens)\n setMaxTokens(modelMaxTokens.toString())\n } else {\n setMaxTokensMode('custom')\n setMaxTokens(modelMaxTokens.toString())\n }\n setMaxTokensCursorOffset(modelMaxTokens.toString().length)\n } else {\n // No model-specific max tokens, use default\n setMaxTokensMode('preset')\n setSelectedMaxTokensPreset(DEFAULT_MAX_TOKENS)\n setMaxTokens(DEFAULT_MAX_TOKENS.toString())\n setMaxTokensCursorOffset(DEFAULT_MAX_TOKENS.toString().length)\n }\n\n // Go to model parameters screen\n navigateTo('modelParams')\n // Reset active field index\n setActiveFieldIndex(0)\n }\n\n const handleModelParamsSubmit = () => {\n // Values are already in state, no need to extract from form\n\n // In edit mode, return to edit summary\n if (isEditMode) {\n goBack()\n return\n }\n\n // Smart skip: when model was selected from API list with known context_length,\n // skip the contextLength selection screen and go directly to testAndSave\n if (!isManualModelEntry) {\n const modelInfo = availableModels.find(m => m.model === selectedModel)\n if (modelInfo?.context_length || modelInfo?.max_input_tokens) {\n // Context length was already set in handleModelSelection\n navigateTo('testAndSave')\n return\n }\n }\n\n // For manual model entry or unknown context length, show contextLength screen\n if (!CONTEXT_LENGTH_OPTIONS.find(opt => opt.value === contextLength)) {\n setContextLength(DEFAULT_CONTEXT_LENGTH)\n }\n navigateTo('contextLength')\n }\n\n async function testConnection(): Promise<{\n success: boolean\n message: string\n endpoint?: string\n details?: string\n }> {\n setIsTestingConnection(true)\n setConnectionTestResult(null)\n\n try {\n // Determine the base URL to test\n let testBaseURL =\n providerBaseUrl || providers[selectedProvider]?.baseURL || ''\n\n if (selectedProvider === 'azure') {\n testBaseURL = `https://${resourceName}.openai.azure.com/openai/deployments/${selectedModel}`\n } else if (selectedProvider === 'custom-openai') {\n testBaseURL = customBaseUrl\n }\n\n // For OpenAI-compatible providers, try multiple endpoints in order of preference\n if (isOpenAICompatibleProvider(selectedProvider)) {\n // \uD83D\uDD25 Use specialized GPT-5 connection test for GPT-5 models\n const isGPT5 = selectedModel?.toLowerCase().includes('gpt-5')\n\n if (isGPT5) {\n // Validate configuration first\n const configValidation = validateGPT5Config({\n model: selectedModel,\n apiKey: apiKey,\n baseURL: testBaseURL,\n maxTokens: parseInt(maxTokens) || 8192,\n provider: selectedProvider,\n })\n\n if (!configValidation.valid) {\n return {\n success: false,\n message: '\u274C GPT-5 configuration validation failed',\n details: configValidation.errors.join('\\n'),\n }\n }\n\n // Use specialized GPT-5 test service\n const gpt5Result = await testGPT5Connection({\n model: selectedModel,\n apiKey: apiKey,\n baseURL: testBaseURL,\n maxTokens: parseInt(maxTokens) || 8192,\n provider: selectedProvider,\n })\n\n return gpt5Result\n }\n\n // For non-GPT-5 OpenAI-compatible models, use existing logic\n const endpointsToTry = []\n\n if (selectedProvider === 'minimax') {\n endpointsToTry.push(\n {\n path: '/text/chatcompletion_v2',\n name: 'MiniMax v2 (recommended)',\n },\n { path: '/chat/completions', name: 'Standard OpenAI' },\n )\n } else {\n endpointsToTry.push({\n path: '/chat/completions',\n name: 'Standard OpenAI',\n })\n }\n\n let lastError = null\n for (const endpoint of endpointsToTry) {\n try {\n const testResult = await testChatEndpoint(\n testBaseURL,\n endpoint.path,\n endpoint.name,\n )\n\n if (testResult.success) {\n return testResult\n }\n lastError = testResult\n } catch (error) {\n lastError = {\n success: false,\n message: `Failed to test ${endpoint.name}`,\n endpoint: endpoint.path,\n details: error instanceof Error ? error.message : String(error),\n }\n }\n }\n\n return (\n lastError || {\n success: false,\n message: 'All endpoints failed',\n details: 'No endpoints could be reached',\n }\n )\n } else {\n // For non-OpenAI providers (like Anthropic, Gemini), use different test approach\n return await testProviderSpecificEndpoint(testBaseURL)\n }\n } catch (error) {\n return {\n success: false,\n message: 'Connection test failed',\n details: error instanceof Error ? error.message : String(error),\n }\n } finally {\n setIsTestingConnection(false)\n }\n }\n\n async function testChatEndpoint(\n baseURL: string,\n endpointPath: string,\n endpointName: string,\n ): Promise<{\n success: boolean\n message: string\n endpoint?: string\n details?: string\n }> {\n const testURL = `${baseURL.replace(/\\/+$/, '')}${endpointPath}`\n\n // Create a test message that expects a specific response\n const testPayload: any = {\n model: selectedModel,\n messages: [\n {\n role: 'user',\n content:\n 'Please respond with exactly \"YES\" (in capital letters) to confirm this connection is working.',\n },\n ],\n max_tokens: Math.max(parseInt(maxTokens) || 8192, 8192), // Ensure minimum 8192 tokens for connection test\n temperature: 0,\n stream: false,\n }\n\n // Apply provider/model-aware parameter normalization\n if (selectedModel && selectedProvider) {\n const caps = getEffectiveCapabilities(selectedProvider, selectedModel)\n\n // Fix max tokens field name\n if (caps.maxTokensField !== 'max_tokens' && testPayload.max_tokens) {\n testPayload[caps.maxTokensField] = testPayload.max_tokens\n delete testPayload.max_tokens\n }\n\n // Fix temperature: omit for reasoning models, clamp for limited providers\n if (caps.temperatureRange === 'omit') {\n delete testPayload.temperature\n } else if (typeof caps.temperatureRange === 'object') {\n testPayload.temperature = Math.min(\n testPayload.temperature,\n caps.temperatureRange.max,\n )\n }\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n\n // Add authorization headers\n if (selectedProvider === 'azure') {\n headers['api-key'] = apiKey\n } else {\n headers['Authorization'] = `Bearer ${apiKey}`\n }\n\n try {\n const response = await fetch(testURL, {\n method: 'POST',\n headers,\n body: JSON.stringify(testPayload),\n signal: AbortSignal.timeout(30_000),\n })\n\n if (response.ok) {\n const data = await response.json()\n\n // Check if we got a valid response with content\n let responseContent = ''\n\n if (data.choices && data.choices.length > 0) {\n responseContent = data.choices[0]?.message?.content || ''\n } else if (data.reply) {\n // Handle MiniMax format\n responseContent = data.reply\n } else if (data.output) {\n // Handle other formats\n responseContent = data.output?.text || data.output || ''\n }\n\n // Check if response contains \"YES\" (case insensitive)\n const containsYes = responseContent.toLowerCase().includes('yes')\n\n if (containsYes) {\n return {\n success: true,\n message: `\u2705 Connection test passed with ${endpointName}`,\n endpoint: endpointPath,\n details: `Model responded correctly: \"${responseContent.trim()}\"`,\n }\n } else {\n return {\n success: false,\n message: `\u26A0\uFE0F ${endpointName} connected but model response unexpected`,\n endpoint: endpointPath,\n details: `Expected \"YES\" but got: \"${responseContent.trim() || '(empty response)'}\"`,\n }\n }\n } else {\n const errorData = await response.json().catch(() => null)\n const errorMessage =\n errorData?.error?.message || errorData?.message || response.statusText\n\n return {\n success: false,\n message: `\u274C ${endpointName} failed (${response.status})`,\n endpoint: endpointPath,\n details: `Error: ${errorMessage}`,\n }\n }\n } catch (error) {\n return {\n success: false,\n message: `\u274C ${endpointName} connection failed`,\n endpoint: endpointPath,\n details: error instanceof Error ? error.message : String(error),\n }\n }\n }\n\n async function testResponsesEndpoint(\n baseURL: string,\n endpointPath: string,\n endpointName: string,\n ): Promise<{\n success: boolean\n message: string\n endpoint?: string\n details?: string\n }> {\n const testURL = `${baseURL.replace(/\\/+$/, '')}${endpointPath}`\n\n // \uD83D\uDD27 Enhanced GPT-5 Responses API test payload\n const testPayload: any = {\n model: selectedModel,\n input: [\n {\n role: 'user',\n content:\n 'Please respond with exactly \"YES\" (in capital letters) to confirm this connection is working.',\n },\n ],\n max_completion_tokens: Math.max(parseInt(maxTokens) || 8192, 8192),\n temperature: 1, // GPT-5 only supports temperature=1\n // \uD83D\uDE80 Add reasoning configuration for better GPT-5 performance\n reasoning: {\n effort: 'low', // Fast response for connection test\n },\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n }\n\n try {\n const response = await fetch(testURL, {\n method: 'POST',\n headers,\n body: JSON.stringify(testPayload),\n signal: AbortSignal.timeout(30_000),\n })\n\n if (response.ok) {\n const data = await response.json()\n\n // Extract content from Responses API format\n let responseContent = ''\n\n if (data.output_text) {\n responseContent = data.output_text\n } else if (data.output) {\n responseContent =\n typeof data.output === 'string'\n ? data.output\n : data.output.text || ''\n }\n\n // Check if response contains \"YES\" (case insensitive)\n const containsYes = responseContent.toLowerCase().includes('yes')\n\n if (containsYes) {\n return {\n success: true,\n message: `\u2705 Connection test passed with ${endpointName}`,\n endpoint: endpointPath,\n details: `GPT-5 responded correctly via Responses API: \"${responseContent.trim()}\"`,\n }\n } else {\n return {\n success: false,\n message: `\u26A0\uFE0F ${endpointName} connected but model response unexpected`,\n endpoint: endpointPath,\n details: `Expected \"YES\" but got: \"${responseContent.trim() || '(empty response)'}\"`,\n }\n }\n } else {\n // \uD83D\uDD27 Enhanced error handling with detailed debugging\n const errorData = await response.json().catch(() => null)\n const errorMessage =\n errorData?.error?.message || errorData?.message || response.statusText\n\n // Provide specific guidance for common GPT-5 errors\n let details = `Responses API Error: ${errorMessage}`\n if (response.status === 400 && errorMessage.includes('max_tokens')) {\n details +=\n '\\n\uD83D\uDD27 Note: This appears to be a parameter compatibility issue. The fallback to Chat Completions should handle this.'\n } else if (response.status === 404) {\n details +=\n '\\n\uD83D\uDD27 Note: Responses API endpoint may not be available for this model or provider.'\n } else if (response.status === 401) {\n details += '\\n\uD83D\uDD27 Note: API key authentication failed.'\n }\n\n return {\n success: false,\n message: `\u274C ${endpointName} failed (${response.status})`,\n endpoint: endpointPath,\n details: details,\n }\n }\n } catch (error) {\n return {\n success: false,\n message: `\u274C ${endpointName} connection failed`,\n endpoint: endpointPath,\n details: error instanceof Error ? error.message : String(error),\n }\n }\n }\n\n async function testProviderSpecificEndpoint(baseURL: string): Promise<{\n success: boolean\n message: string\n endpoint?: string\n details?: string\n }> {\n // For Anthropic and Anthropic-compatible providers, use the official SDK for testing\n if (selectedProvider === 'anthropic' || selectedProvider === 'bigdream') {\n try {\n // Determine the baseURL for testing\n let testBaseURL: string | undefined = undefined\n if (selectedProvider === 'bigdream') {\n testBaseURL = baseURL || 'https://api-key.info'\n } else if (selectedProvider === 'anthropic') {\n // For anthropic, use user-provided baseURL if available, otherwise undefined (official API)\n testBaseURL =\n baseURL && baseURL !== 'https://api.anthropic.com'\n ? baseURL\n : undefined\n }\n\n // Use the verifyApiKey function which uses the official Anthropic SDK\n const isValid = await verifyApiKey(\n apiKey,\n testBaseURL,\n selectedProvider,\n )\n\n if (isValid) {\n return {\n success: true,\n message: `\u2705 ${selectedProvider} connection test passed`,\n endpoint: '/messages',\n details: 'API key verified using official Anthropic SDK',\n }\n } else {\n return {\n success: false,\n message: `\u274C ${selectedProvider} API key verification failed`,\n endpoint: '/messages',\n details:\n 'Invalid API key. Please check your API key and try again.',\n }\n }\n } catch (error) {\n return {\n success: false,\n message: `\u274C ${selectedProvider} connection failed`,\n endpoint: '/messages',\n details: error instanceof Error ? error.message : String(error),\n }\n }\n }\n\n // For other providers, return a placeholder success (we can extend this later)\n return {\n success: true,\n message: `\u2705 Configuration saved for ${selectedProvider}`,\n details: 'Provider-specific testing not implemented yet',\n }\n }\n\n async function handleConnectionTest() {\n const result = await testConnection()\n setConnectionTestResult(result)\n }\n\n const handleContextLengthSubmit = () => {\n // Context length value is already in state\n if (isEditMode) {\n goBack()\n return\n }\n navigateTo('testAndSave')\n }\n\n async function saveConfiguration(\n provider: ProviderType,\n model: string,\n ): Promise<string | null> {\n let baseURL = providerBaseUrl || providers[provider]?.baseURL || ''\n let actualProvider = provider\n\n // For Anthropic provider, determine the actual provider based on sub-menu selection\n if (provider === 'anthropic') {\n switch (anthropicProviderType) {\n case 'official':\n actualProvider = 'anthropic'\n baseURL = baseURL || 'https://api.anthropic.com'\n break\n case 'bigdream':\n actualProvider = 'bigdream'\n baseURL = baseURL || 'https://api-key.info'\n break\n case 'custom':\n actualProvider = 'anthropic' // Use anthropic for custom endpoints\n // baseURL is already set from user input\n break\n }\n }\n\n // For Azure, construct the baseURL using the resource name\n if (provider === 'azure') {\n baseURL = `https://${resourceName}.openai.azure.com/openai/deployments/${model}`\n }\n // For custom OpenAI-compatible API, use the custom base URL\n else if (provider === 'custom-openai') {\n baseURL = customBaseUrl\n }\n\n try {\n // Use ModelManager's addModel method for duplicate validation\n const modelManager = getModelManager()\n\n const modelConfig = {\n name: `${actualProvider} ${model}`,\n provider: actualProvider,\n modelName: model,\n baseURL: baseURL,\n apiKey: apiKey || '',\n maxTokens: parseInt(maxTokens) || DEFAULT_MAX_TOKENS,\n contextLength: contextLength || DEFAULT_CONTEXT_LENGTH,\n reasoningEffort,\n }\n\n // addModel method will throw error if duplicate exists\n return await modelManager.addModel(modelConfig)\n } catch (error) {\n // Validation failed - show error to user\n setValidationError(\n error instanceof Error ? error.message : 'Failed to add model',\n )\n return null\n }\n }\n\n async function handleConfirmation() {\n // Clear any previous validation errors\n setValidationError(null)\n\n if (isEditMode && editingModel) {\n // Edit mode: update existing model\n try {\n const modelManager = getModelManager()\n // Preserve encrypted: reference if user didn't manually change the key\n const saveApiKey =\n !apiKeyUserModified && originalEncryptedRef\n ? originalEncryptedRef\n : apiKey || editingModel.apiKey\n modelManager.updateModel(editingModel.modelName, {\n baseURL: providerBaseUrl || editingModel.baseURL,\n apiKey: saveApiKey,\n maxTokens: parseInt(maxTokens) || editingModel.maxTokens,\n contextLength: contextLength || editingModel.contextLength,\n reasoningEffort,\n })\n onDone()\n } catch (error) {\n setValidationError(\n error instanceof Error ? error.message : 'Failed to update model',\n )\n }\n return\n }\n\n // Add mode: save the configuration and exit\n const modelId = await saveConfiguration(selectedProvider, selectedModel)\n\n // If validation failed (modelId is null), don't proceed\n if (!modelId) {\n return // Error is already set in saveConfiguration\n }\n\n // Handle model pointer assignment for new system\n if (modelId && (isOnboarding || targetPointer)) {\n if (isOnboarding) {\n // First-time setup: set all pointers to this model\n setAllPointersToModel(modelId)\n } else if (targetPointer) {\n // Specific pointer configuration: only set target pointer\n setModelPointer(targetPointer, modelId)\n }\n }\n\n onDone()\n }\n\n // Handle back navigation based on current screen\n const handleBack = () => {\n // Clear any pending async navigation timers to prevent stale navigations\n if (pendingTimerRef.current) {\n clearTimeout(pendingTimerRef.current)\n pendingTimerRef.current = null\n }\n\n if (screenStack.length <= 1) {\n // At the root screen (provider in add mode, testAndSave in edit mode), exit\n if (onCancel) {\n onCancel()\n } else {\n onDone()\n }\n } else {\n // When going back from testAndSave, reset test state\n if (currentScreen === 'testAndSave') {\n setConnectionTestResult(null)\n setIsTestingConnection(false)\n setValidationError(null)\n }\n // When going back to modelParams, reset activeFieldIndex to the last\n // chooseable field so the auto-submit doesn't immediately re-navigate forward\n const prevScreen = screenStack[screenStack.length - 2]\n if (prevScreen === 'modelParams') {\n const formFields = getFormFieldsForModelParams()\n const submitIndex = formFields.findIndex(f => f.name === 'submit')\n setActiveFieldIndex(Math.max(0, submitIndex - 1))\n }\n // Remove the current screen from the stack\n setScreenStack(prev => prev.slice(0, -1))\n }\n }\n\n // Esc is now handled per-screen by SimpleSelector/InfoPanel/BrandTextInput onClose/useInput\n\n // Handle cursor offset changes\n function handleCursorOffsetChange(offset: number) {\n setCursorOffset(offset)\n }\n\n // Handle API key changes\n function handleApiKeyChange(value: string) {\n setApiKeyEdited(true)\n setApiKeyUserModified(true)\n setApiKey(value)\n }\n\n // Handle model search query changes\n function handleModelSearchChange(value: string) {\n setModelSearchQuery(value)\n // Update cursor position to end of text when typing\n setModelSearchCursorOffset(value.length)\n }\n\n // Handle model search cursor offset changes\n function handleModelSearchCursorOffsetChange(offset: number) {\n setModelSearchCursorOffset(offset)\n }\n\n // Screens using SimpleSelector/InfoPanel handle their own input.\n // This useInput handles text input screens (apiKey, baseUrl, resourceName, modelInput)\n // and Esc for those screens.\n const textScreens = ['apiKey', 'baseUrl', 'resourceName', 'modelInput']\n useInput((input, key) => {\n if (!textScreens.includes(currentScreen)) return\n\n // Esc goes back on text input screens\n if (key.escape) {\n handleBack()\n return\n }\n\n // Handle API key submission on Enter\n if (currentScreen === 'apiKey' && key.return) {\n if (apiKey) {\n handleApiKeySubmit(apiKey)\n }\n return\n }\n\n if (currentScreen === 'apiKey' && key.tab) {\n // For providers that support manual model input, skip to manual model input\n if (\n selectedProvider === 'anthropic' ||\n selectedProvider === 'kimi' ||\n selectedProvider === 'deepseek' ||\n selectedProvider === 'qwen' ||\n selectedProvider === 'glm' ||\n selectedProvider === 'minimax' ||\n selectedProvider === 'baidu-qianfan' ||\n selectedProvider === 'siliconflow' ||\n selectedProvider === 'custom-openai'\n ) {\n navigateTo('modelInput')\n return\n }\n\n // For other providers, try to fetch models without API key\n fetchModelsWithRetry().catch(() => {\n // Retry logic in fetchModelsWithRetry already handles error display\n })\n return\n }\n\n // Handle Resource Name submission on Enter\n if (currentScreen === 'resourceName' && key.return) {\n if (resourceName) {\n handleResourceNameSubmit(resourceName)\n }\n return\n }\n\n // Handle Base URL submission on Enter\n if (currentScreen === 'baseUrl' && key.return) {\n if (selectedProvider === 'custom-openai') {\n handleCustomBaseUrlSubmit(customBaseUrl)\n } else {\n handleProviderBaseUrlSubmit(providerBaseUrl)\n }\n return\n }\n\n // Handle Custom Model Name submission on Enter\n if (currentScreen === 'modelInput' && key.return) {\n if (customModelName) {\n handleCustomModelSubmit(customModelName)\n }\n return\n }\n })\n\n // Effect-based auto-submit for modelParams when activeFieldIndex reaches submit\n // (must be before any early returns in the render section to satisfy React hooks rules)\n useEffect(() => {\n if (currentScreen !== 'modelParams') return\n const formFields = getFormFieldsForModelParams()\n const currentField = formFields[activeFieldIndex]\n if (!currentField || currentField.name === 'submit') {\n handleModelParamsSubmit()\n }\n }, [currentScreen, activeFieldIndex]) // eslint-disable-line react-hooks/exhaustive-deps\n\n // Helper function to get form fields for model params\n function getFormFieldsForModelParams() {\n return [\n {\n name: 'maxTokens',\n label: 'Maximum Tokens',\n description: 'Select the maximum number of tokens to generate.',\n value: parseInt(maxTokens),\n component: 'select',\n options: MAX_TOKENS_OPTIONS.map(option => ({\n label: option.label,\n value: option.value.toString(),\n })),\n defaultValue: maxTokens,\n },\n ...(supportsReasoningEffort\n ? [\n {\n name: 'reasoningEffort',\n label: 'Reasoning Effort',\n description: 'Controls reasoning depth for complex problems.',\n value: reasoningEffort,\n component: 'select',\n },\n ]\n : []),\n {\n name: 'submit',\n label: 'Continue \u2192',\n component: 'button',\n },\n ]\n }\n\n // Render API Key Input Screen\n if (currentScreen === 'apiKey') {\n const providerLabel = getProviderLabel(selectedProvider, 0).split(' (')[0]\n\n // Build provider-specific API key hint\n const apiKeyUrls: Record<string, string> = {\n kimi: 'https://platform.moonshot.cn/console/api-keys',\n deepseek: 'https://platform.deepseek.com/api_keys',\n siliconflow: 'https://cloud.siliconflow.cn/i/oJWsm6io',\n qwen: 'https://bailian.console.aliyun.com/?tab=model#/api-key',\n glm: 'https://open.bigmodel.cn (API Keys section)',\n minimax: 'https://www.minimax.io/platform/user-center/basic-information',\n 'baidu-qianfan': 'https://console.bce.baidu.com/iam/#/iam/accesslist',\n openai: 'https://platform.openai.com/api-keys',\n }\n\n let apiKeyUrl = apiKeyUrls[selectedProvider] || ''\n if (selectedProvider === 'anthropic') {\n apiKeyUrl =\n anthropicProviderType === 'official'\n ? 'https://console.anthropic.com/settings/keys'\n : anthropicProviderType === 'bigdream'\n ? 'https://api-key.info/register?aff=MSl4'\n : anthropicProviderType === 'opendev'\n ? 'https://api.openai-next.com/register/?aff_code=4xo7'\n : 'your custom API provider'\n }\n\n const supportsManualInput =\n selectedProvider === 'anthropic' ||\n selectedProvider === 'kimi' ||\n selectedProvider === 'deepseek' ||\n selectedProvider === 'qwen' ||\n selectedProvider === 'glm' ||\n selectedProvider === 'minimax' ||\n selectedProvider === 'baidu-qianfan' ||\n selectedProvider === 'siliconflow' ||\n selectedProvider === 'custom-openai'\n\n const tabHintText = supportsManualInput\n ? t('modelSelector.apiKeyTabHintManual')\n : t('modelSelector.apiKeyTabHintSkip')\n\n const apiKeyHint = apiKeyUrl ? (\n <Text color={SEMANTIC_COLORS.dim}>\n Get your API key from:{' '}\n <Text color={SEMANTIC_COLORS.info}>{apiKeyUrl}</Text>\n </Text>\n ) : undefined\n\n return (\n <BrandTextInput\n title={`${t('modelSelector.apiKeyTitle')} \u2014 ${providerLabel}`}\n description={t('modelSelector.apiKeyDesc')}\n placeholder=\"sk-...\"\n value={apiKey}\n onChange={handleApiKeyChange}\n onSubmit={handleApiKeySubmit}\n mask=\"*\"\n error={modelLoadError ? `Error: ${modelLoadError}` : null}\n isLoading={isLoadingModels}\n loadingText=\"Loading available models...\"\n hint={apiKeyHint}\n footerHint={`Enter continue \u00B7 Tab ${tabHintText} \u00B7 Esc back`}\n cursorOffset={cursorOffset}\n onChangeCursorOffset={handleCursorOffsetChange}\n />\n )\n }\n\n // Render Model Selection Screen\n if (currentScreen === 'model') {\n const providerLabel = getProviderLabel(\n selectedProvider,\n availableModels.length,\n ).split(' (')[0]\n\n // Convert modelOptions to SelectorItem[] for SimpleSelector\n // modelOptions already has search filtering applied\n const modelSelectorItems: SelectorItem[] = modelOptions.map(opt => ({\n id: opt.value,\n label: opt.label,\n }))\n\n const subtitle =\n modelOptions.length > 0\n ? `${modelOptions.length}/${availableModels.length} models`\n : availableModels.length > 0\n ? t('modelSelector.noModelsMatch')\n : t('modelSelector.noModelsAvailable')\n\n return (\n <SimpleSelector\n title={`${t('modelSelector.modelSelectionTitle')} \u2014 ${providerLabel}`}\n subtitle={subtitle}\n items={modelSelectorItems}\n onSelect={item => handleModelSelection(item.id)}\n onClose={handleBack}\n />\n )\n }\n\n if (currentScreen === 'modelParams') {\n // Sequential SimpleSelector: first maxTokens, then reasoningEffort (if applicable), then submit\n const formFields = getFormFieldsForModelParams()\n const currentField = formFields[activeFieldIndex]\n\n if (currentField?.name === 'maxTokens') {\n const maxTokensItems: SelectorItem[] = MAX_TOKENS_OPTIONS.map(opt => ({\n id: opt.value.toString(),\n label: opt.label,\n isCurrent: opt.value === parseInt(maxTokens),\n }))\n\n return (\n <SimpleSelector\n title={`${t('modelSelector.modelParamsTitle')} \u2014 ${t('modelSelector.maxTokens')}`}\n subtitle={selectedModel}\n items={maxTokensItems}\n onSelect={item => {\n const numValue = parseInt(item.id)\n setMaxTokens(numValue.toString())\n setSelectedMaxTokensPreset(numValue)\n setMaxTokensCursorOffset(numValue.toString().length)\n setActiveFieldIndex(activeFieldIndex + 1)\n }}\n onClose={handleBack}\n />\n )\n }\n\n if (currentField?.name === 'reasoningEffort') {\n const effortItems: SelectorItem[] = reasoningEffortOptions.map(opt => ({\n id: opt.value,\n label: opt.label,\n isCurrent: opt.value === reasoningEffort,\n }))\n\n return (\n <SimpleSelector\n title={`${t('modelSelector.modelParamsTitle')} \u2014 ${t('modelSelector.reasoningEffort')}`}\n subtitle={selectedModel}\n items={effortItems}\n onSelect={item => {\n setReasoningEffort(item.id as ReasoningEffortOption)\n setActiveFieldIndex(activeFieldIndex + 1)\n }}\n onClose={() => {\n // Go back to maxTokens within modelParams, not exit modelParams\n setActiveFieldIndex(0)\n }}\n />\n )\n }\n\n // If on submit field or past all fields, auto-submit via effect\n // (the useEffect that triggers handleModelParamsSubmit is declared above, before the render section)\n return null\n }\n\n // Render Resource Name Input Screen\n if (currentScreen === 'resourceName') {\n return (\n <BrandTextInput\n title={t('modelSelector.resourceNameTitle')}\n description={t('modelSelector.resourceNameDesc')}\n placeholder=\"myazureresource\"\n value={resourceName}\n onChange={setResourceName}\n onSubmit={handleResourceNameSubmit}\n footerHint={t('modelSelector.footerEnterContinue')}\n cursorOffset={resourceNameCursorOffset}\n onChangeCursorOffset={setResourceNameCursorOffset}\n />\n )\n }\n\n // Render Base URL Input Screen (for all providers)\n if (currentScreen === 'baseUrl') {\n const isCustomOpenAI = selectedProvider === 'custom-openai'\n\n if (isCustomOpenAI) {\n return (\n <BrandTextInput\n title={t('modelSelector.customApiTitle')}\n description={t('modelSelector.customApiDesc')}\n placeholder=\"https://api.example.com/v1\"\n value={customBaseUrl}\n onChange={setCustomBaseUrl}\n onSubmit={handleCustomBaseUrlSubmit}\n isLoading={isLoadingModels}\n loadingText=\"Connecting...\"\n error={modelLoadError ? `Error: ${modelLoadError}` : null}\n footerHint={t('modelSelector.footerEnterContinue')}\n cursorOffset={customBaseUrlCursorOffset}\n onChangeCursorOffset={setCustomBaseUrlCursorOffset}\n />\n )\n }\n\n const providerName = providers[selectedProvider]?.name || selectedProvider\n const defaultUrl = providers[selectedProvider]?.baseURL || ''\n const desc =\n selectedProvider === 'ollama'\n ? t('modelSelector.baseUrlOllamaDesc')\n : `${t('modelSelector.baseUrlDesc')} You can modify this URL or press Enter to use the default.`\n\n return (\n <BrandTextInput\n title={`${t('modelSelector.baseUrlTitle')} \u2014 ${providerName}`}\n description={desc}\n placeholder={defaultUrl}\n value={providerBaseUrl}\n onChange={setProviderBaseUrl}\n onSubmit={handleProviderBaseUrlSubmit}\n isLoading={isLoadingModels}\n loadingText={\n selectedProvider === 'ollama'\n ? 'Connecting to Ollama server...'\n : `Connecting to ${providerName}...`\n }\n error={modelLoadError ? `Error: ${modelLoadError}` : null}\n footerHint={t('modelSelector.footerEnterContinue')}\n cursorOffset={providerBaseUrlCursorOffset}\n onChangeCursorOffset={setProviderBaseUrlCursorOffset}\n />\n )\n }\n\n // Render Custom Model Input Screen\n if (currentScreen === 'modelInput') {\n // Provider-specific model name config\n const modelInputConfig: Record<\n string,\n { title: string; placeholder: string; examples: string }\n > = {\n azure: {\n title: 'Azure Model Setup',\n placeholder: 'gpt-4',\n examples: 'e.g. \"gpt-4\", \"gpt-35-turbo\"',\n },\n anthropic: {\n title: 'Claude Model Setup',\n placeholder: 'claude-3-5-sonnet-latest',\n examples: 'e.g. \"claude-3-5-sonnet-latest\", \"claude-3-5-haiku-latest\"',\n },\n bigdream: {\n title: 'BigDream Model Setup',\n placeholder: 'claude-3-5-sonnet-latest',\n examples: 'e.g. \"claude-3-5-sonnet-latest\", \"claude-3-5-haiku-latest\"',\n },\n kimi: {\n title: 'Kimi Model Setup',\n placeholder: 'kimi-k2-0711-preview',\n examples: 'e.g. \"kimi-k2-0711-preview\"',\n },\n deepseek: {\n title: 'DeepSeek Model Setup',\n placeholder: 'deepseek-chat',\n examples: 'e.g. \"deepseek-chat\", \"deepseek-coder\", \"deepseek-reasoner\"',\n },\n siliconflow: {\n title: 'SiliconFlow Model Setup',\n placeholder: 'Qwen/Qwen2.5-72B-Instruct',\n examples: 'e.g. \"Qwen/Qwen2.5-72B-Instruct\"',\n },\n qwen: {\n title: 'Qwen Model Setup',\n placeholder: 'qwen-plus',\n examples: 'e.g. \"qwen-plus\", \"qwen-turbo\", \"qwen-max\"',\n },\n glm: {\n title: 'GLM Model Setup',\n placeholder: 'glm-4',\n examples: 'e.g. \"glm-4\", \"glm-4v\", \"glm-3-turbo\"',\n },\n minimax: {\n title: 'MiniMax Model Setup',\n placeholder: 'abab6.5s-chat',\n examples: 'e.g. \"abab6.5s-chat\", \"abab6.5g-chat\"',\n },\n 'baidu-qianfan': {\n title: 'Baidu Qianfan Model Setup',\n placeholder: 'ERNIE-4.0-8K',\n examples: 'e.g. \"ERNIE-4.0-8K\", \"ERNIE-3.5-8K\"',\n },\n 'custom-openai': {\n title: 'Custom API Model Setup',\n placeholder: 'model-name',\n examples: 'Enter the exact model name supported by your API endpoint.',\n },\n }\n\n const cfg = modelInputConfig[selectedProvider] || {\n title: t('modelSelector.modelInputTitle'),\n placeholder: 'gpt-4',\n examples: 'e.g. \"gpt-4\", \"gpt-3.5-turbo\"',\n }\n\n return (\n <BrandTextInput\n title={cfg.title}\n description={cfg.examples}\n placeholder={cfg.placeholder}\n value={customModelName}\n onChange={setCustomModelName}\n onSubmit={handleCustomModelSubmit}\n footerHint={t('modelSelector.footerEnterContinue')}\n cursorOffset={customModelNameCursorOffset}\n onChangeCursorOffset={setCustomModelNameCursorOffset}\n />\n )\n }\n\n // Render Context Length Selection Screen\n if (currentScreen === 'contextLength') {\n const contextItems: SelectorItem[] = CONTEXT_LENGTH_OPTIONS.map(opt => ({\n id: opt.value.toString(),\n label:\n opt.value === DEFAULT_CONTEXT_LENGTH\n ? `${opt.label} (${t('modelSelector.recommended')})`\n : opt.label,\n isCurrent: opt.value === contextLength,\n }))\n\n return (\n <SimpleSelector\n title={t('modelSelector.contextLengthTitle')}\n subtitle={t('modelSelector.contextLengthDesc')}\n items={contextItems}\n onSelect={item => {\n setContextLength(parseInt(item.id))\n handleContextLengthSubmit()\n }}\n onClose={handleBack}\n />\n )\n }\n\n // Render Test & Save Screen (merged connectionTest + confirmation)\n if (currentScreen === 'testAndSave') {\n const providerDisplayName = getProviderLabel(selectedProvider, 0).split(\n ' (',\n )[0]\n const showsApiKey = selectedProvider !== 'ollama'\n const contextLengthLabel =\n CONTEXT_LENGTH_OPTIONS.find(opt => opt.value === contextLength)?.label ||\n `${contextLength.toLocaleString()} tokens`\n\n // \u2500\u2500\u2500 Edit mode: SimpleSelector with editable fields \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (isEditMode) {\n const editItems: SelectorItem[] = []\n\n // Editable fields\n if (showsApiKey) {\n editItems.push({\n id: '__edit_apiKey__',\n label: 'API Key',\n description: apiKey ? `****${apiKey.slice(-4)}` : '(not set)',\n category: t('modelSelector.testAndSaveDesc'),\n })\n }\n\n // Show base URL for providers that use it\n if (\n selectedProvider === 'custom-openai' ||\n providerBaseUrl !== providers[selectedProvider]?.baseURL\n ) {\n editItems.push({\n id: '__edit_baseUrl__',\n label: 'Base URL',\n description: providerBaseUrl || customBaseUrl || '(not set)',\n category: t('modelSelector.testAndSaveDesc'),\n })\n }\n\n editItems.push({\n id: '__edit_modelParams__',\n label: 'Max Tokens',\n description: maxTokens,\n category: t('modelSelector.testAndSaveDesc'),\n })\n editItems.push({\n id: '__edit_contextLength__',\n label: 'Context Length',\n description: contextLengthLabel,\n category: t('modelSelector.testAndSaveDesc'),\n })\n\n // Connection test status (non-editable, info only)\n if (connectionTestResult) {\n editItems.push({\n id: '__test_status__',\n label: 'Connection',\n description: connectionTestResult.message,\n statusIcon: connectionTestResult.success ? '\\u2713' : '\\u2715',\n statusColor: connectionTestResult.success\n ? SEMANTIC_COLORS.success\n : SEMANTIC_COLORS.error,\n category: t('modelSelector.testAndSaveDesc'),\n })\n }\n\n // Action items\n editItems.push({\n id: '__save__',\n label: t('modelSelector.confirmationSave'),\n category: t('commands.model.actionsCategory'),\n statusIcon: '\\u2713',\n statusColor: SEMANTIC_COLORS.success,\n })\n editItems.push({\n id: '__test__',\n label: t('modelSelector.connectionTestRetry'),\n category: t('commands.model.actionsCategory'),\n })\n\n const editTitle = t('commands.model.editTitle').replace(\n '{model}',\n editingModel?.name ?? selectedModel,\n )\n\n const editOverlay = isTestingConnection\n ? {\n type: 'loading' as const,\n message: t('modelSelector.autoTesting'),\n }\n : validationError\n ? { type: 'error' as const, message: validationError }\n : null\n\n return (\n <SimpleSelector\n title={editTitle}\n items={editItems}\n groupByCategory={true}\n onSelect={item => {\n if (item.id === '__edit_apiKey__') {\n navigateTo('apiKey')\n } else if (item.id === '__edit_baseUrl__') {\n navigateTo('baseUrl')\n } else if (item.id === '__edit_modelParams__') {\n setActiveFieldIndex(0)\n navigateTo('modelParams')\n } else if (item.id === '__edit_contextLength__') {\n navigateTo('contextLength')\n } else if (item.id === '__save__') {\n handleConfirmation().catch(error => {\n setValidationError(\n error instanceof Error\n ? error.message\n : 'Unexpected error occurred',\n )\n })\n } else if (item.id === '__test__') {\n setConnectionTestResult(null)\n handleConnectionTest()\n }\n // __test_status__ is info-only, no action\n }}\n onClose={handleBack}\n statusOverlay={editOverlay}\n />\n )\n }\n\n // \u2500\u2500\u2500 Add mode: InfoPanel with auto-test \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const configItems: { label: string; value: string; valueColor?: string }[] =\n [\n { label: 'Provider', value: providerDisplayName },\n ...(selectedProvider === 'azure'\n ? [{ label: 'Resource Name', value: resourceName }]\n : []),\n ...(selectedProvider === 'ollama'\n ? [{ label: 'Server URL', value: ollamaBaseUrl }]\n : []),\n ...(selectedProvider === 'custom-openai'\n ? [{ label: 'API Base URL', value: customBaseUrl }]\n : []),\n { label: 'Model', value: selectedModel },\n ...(apiKey && showsApiKey\n ? [{ label: 'API Key', value: `****${apiKey.slice(-4)}` }]\n : []),\n ...(maxTokens ? [{ label: 'Max Tokens', value: maxTokens }] : []),\n { label: 'Context Length', value: contextLengthLabel },\n ...(supportsReasoningEffort\n ? [{ label: 'Reasoning Effort', value: reasoningEffort }]\n : []),\n ]\n\n // Add connection test status to config items\n if (connectionTestResult) {\n configItems.push({\n label: 'Connection',\n value: connectionTestResult.message,\n valueColor: connectionTestResult.success\n ? SEMANTIC_COLORS.success\n : SEMANTIC_COLORS.error,\n })\n if (connectionTestResult.details && !connectionTestResult.success) {\n configItems.push({\n label: 'Details',\n value: connectionTestResult.details,\n })\n }\n }\n\n const testAndSaveSections: InfoSection[] = [\n {\n title: t('modelSelector.testAndSaveDesc'),\n items: configItems,\n },\n ]\n\n // Add validation error section if present\n if (validationError) {\n testAndSaveSections.unshift({\n title: t('modelSelector.configError'),\n items: [\n {\n label: 'Error',\n value: validationError,\n valueColor: SEMANTIC_COLORS.error,\n },\n ],\n })\n }\n\n // Build actions based on test state\n const testAndSaveActions: InfoPanelAction[] = []\n if (connectionTestResult?.success) {\n testAndSaveActions.push({\n key: 'return',\n keyLabel: 'Enter',\n description: t('modelSelector.confirmationSave'),\n onPress: () => {\n handleConfirmation().catch(error => {\n setValidationError(\n error instanceof Error\n ? error.message\n : 'Unexpected error occurred',\n )\n })\n },\n })\n } else if (connectionTestResult && !connectionTestResult.success) {\n testAndSaveActions.push({\n key: 'return',\n keyLabel: 'Enter',\n description: t('modelSelector.connectionTestRetry'),\n onPress: () => {\n setConnectionTestResult(null)\n handleConnectionTest()\n },\n })\n testAndSaveActions.push({\n key: 's',\n keyLabel: 's',\n description: t('modelSelector.saveAnyway'),\n onPress: () => {\n handleConfirmation().catch(error => {\n setValidationError(\n error instanceof Error\n ? error.message\n : 'Unexpected error occurred',\n )\n })\n },\n })\n }\n\n const testAndSaveOverlay = isTestingConnection\n ? {\n type: 'loading' as const,\n message: t('modelSelector.autoTesting'),\n }\n : null\n\n return (\n <InfoPanel\n title={t('modelSelector.testAndSaveTitle')}\n sections={testAndSaveSections}\n actions={testAndSaveActions}\n onClose={handleBack}\n statusOverlay={testAndSaveOverlay}\n />\n )\n }\n\n // Render Anthropic Sub-Menu Selection Screen\n if (currentScreen === 'anthropicSubMenu') {\n const anthropicItems: SelectorItem[] = [\n {\n id: 'official',\n label: t('modelSelector.anthropicOfficial'),\n description: t('modelSelector.anthropicOfficialDesc'),\n },\n {\n id: 'bigdream',\n label: t('modelSelector.anthropicBigdream'),\n description: t('modelSelector.anthropicBigdreamDesc'),\n },\n {\n id: 'opendev',\n label: t('modelSelector.anthropicOpendev'),\n description: t('modelSelector.anthropicOpendevDesc'),\n },\n {\n id: 'custom',\n label: t('modelSelector.anthropicCustom'),\n description: t('modelSelector.anthropicCustomDesc'),\n },\n ]\n\n return (\n <SimpleSelector\n title={t('modelSelector.anthropicSubMenu')}\n subtitle={t('modelSelector.anthropicSubMenuDesc')}\n items={anthropicItems}\n onSelect={item =>\n handleAnthropicProviderSelection(\n item.id as 'official' | 'bigdream' | 'custom',\n )\n }\n onClose={handleBack}\n />\n )\n }\n\n // Render Provider Selection Screen\n const providerSelectorItems: SelectorItem[] = providerOptions.map(opt => ({\n id: opt.value,\n label: opt.label,\n }))\n\n return (\n <SimpleSelector\n title={t('modelSelector.providerSelection')}\n subtitle={t('modelSelector.providerSelectionDesc')}\n items={providerSelectorItems}\n onSelect={item => handleProviderSelection(item.id)}\n onClose={() => {\n if (onCancel) {\n onCancel()\n } else {\n onDone()\n }\n }}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["models", "fetchAnthropicModels", "apiKey"]
|
|
7
7
|
}
|