@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/services/openai.ts"],
|
|
4
|
-
"sourcesContent": ["import { OpenAI } from 'openai'\nimport { getGlobalConfig } from '@utils/config'\nimport { ProxyAgent, fetch, Response } from 'undici'\nimport { setSessionState, getSessionState } from '@utils/sessionState'\nimport {\n debug as debugLogger,\n getCurrentRequest,\n logAPIError,\n} from '@utils/debugLogger'\nimport { logError } from '@utils/log'\nimport {\n abortableDelay,\n getRetryDelay as sharedGetRetryDelay,\n} from '@utils/async'\nimport {\n formatErrorForUser,\n ErrorCategory,\n UserFriendlyError,\n} from '@utils/userFriendlyError'\nimport { isOpenAICompatibleProvider } from '@constants/providers'\nimport { getEffectiveCapabilities } from '@constants/providerRegistry'\n\n/**\n * Calculate retry delay \u2014 delegates to shared utility\n */\nfunction getRetryDelay(attempt: number): number {\n return sharedGetRetryDelay(attempt)\n}\n\nenum ModelErrorType {\n MaxLength = '1024',\n MaxCompletionTokens = 'max_completion_tokens',\n TemperatureRestriction = 'temperature_restriction',\n StreamOptions = 'stream_options',\n Citations = 'citations',\n RateLimit = 'rate_limit',\n}\n\nfunction getModelErrorKey(\n baseURL: string,\n model: string,\n type: ModelErrorType,\n): string {\n return `${baseURL}:${model}:${type}`\n}\n\nfunction hasModelError(\n baseURL: string,\n model: string,\n type: ModelErrorType,\n): boolean {\n return !!getSessionState('modelErrors')[\n getModelErrorKey(baseURL, model, type)\n ]\n}\n\nfunction setModelError(\n baseURL: string,\n model: string,\n type: ModelErrorType,\n error: string,\n) {\n setSessionState('modelErrors', {\n [getModelErrorKey(baseURL, model, type)]: error,\n })\n}\n\n// More flexible error detection system\ntype ErrorDetector = (errMsg: string) => boolean\ntype ErrorFixer = (\n opts: OpenAI.ChatCompletionCreateParams,\n) => Promise<void> | void\ninterface ErrorHandler {\n type: ModelErrorType\n detect: ErrorDetector\n fix: ErrorFixer\n}\n\n// GPT-5 specific error handlers with enhanced detection patterns\nconst GPT5_ERROR_HANDLERS: ErrorHandler[] = [\n {\n type: ModelErrorType.MaxCompletionTokens,\n detect: errMsg => {\n const lowerMsg = errMsg.toLowerCase()\n return (\n // Exact OpenAI GPT-5 error message\n (lowerMsg.includes(\"unsupported parameter: 'max_tokens'\") &&\n lowerMsg.includes(\"'max_completion_tokens'\")) ||\n // Generic max_tokens error patterns\n (lowerMsg.includes('max_tokens') &&\n lowerMsg.includes('max_completion_tokens')) ||\n (lowerMsg.includes('max_tokens') &&\n lowerMsg.includes('not supported')) ||\n (lowerMsg.includes('max_tokens') &&\n lowerMsg.includes('use max_completion_tokens')) ||\n // Additional patterns for various providers\n (lowerMsg.includes('invalid parameter') &&\n lowerMsg.includes('max_tokens')) ||\n (lowerMsg.includes('parameter error') &&\n lowerMsg.includes('max_tokens'))\n )\n },\n fix: async opts => {\n debugLogger.info('GPT5_FIX', {\n action: 'convert_max_tokens',\n from: opts.max_tokens,\n })\n if ('max_tokens' in opts) {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n },\n },\n {\n type: ModelErrorType.TemperatureRestriction,\n detect: errMsg => {\n const lowerMsg = errMsg.toLowerCase()\n return (\n lowerMsg.includes('temperature') &&\n (lowerMsg.includes('only supports') ||\n lowerMsg.includes('must be 1') ||\n lowerMsg.includes('invalid temperature'))\n )\n },\n fix: async opts => {\n debugLogger.info('GPT5_FIX', {\n action: 'adjust_temperature',\n from: opts.temperature,\n to: 1,\n })\n opts.temperature = 1\n },\n },\n // Add more GPT-5 specific handlers as needed\n]\n\n// Standard error handlers\nconst ERROR_HANDLERS: ErrorHandler[] = [\n {\n type: ModelErrorType.MaxLength,\n detect: errMsg =>\n errMsg.includes('Expected a string with maximum length 1024'),\n fix: async opts => {\n const toolDescriptions = {}\n for (const tool of opts.tools || []) {\n if (tool.function.description.length <= 1024) continue\n let str = ''\n let remainder = ''\n for (let line of tool.function.description.split('\\n')) {\n if (str.length + line.length < 1024) {\n str += line + '\\n'\n } else {\n remainder += line + '\\n'\n }\n }\n\n tool.function.description = str\n toolDescriptions[tool.function.name] = remainder\n }\n if (Object.keys(toolDescriptions).length > 0) {\n let content = '<additional-tool-usage-instructions>\\n\\n'\n for (const [name, description] of Object.entries(toolDescriptions)) {\n content += `<${name}>\\n${description}\\n</${name}>\\n\\n`\n }\n content += '</additional-tool-usage-instructions>'\n\n for (let i = opts.messages.length - 1; i >= 0; i--) {\n if (opts.messages[i].role === 'system') {\n opts.messages.splice(i + 1, 0, {\n role: 'system',\n content,\n })\n break\n }\n }\n }\n },\n },\n {\n type: ModelErrorType.MaxCompletionTokens,\n detect: errMsg => errMsg.includes(\"Use 'max_completion_tokens'\"),\n fix: async opts => {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n },\n },\n {\n type: ModelErrorType.StreamOptions,\n detect: errMsg => errMsg.includes('stream_options'),\n fix: async opts => {\n delete opts.stream_options\n },\n },\n {\n type: ModelErrorType.Citations,\n detect: errMsg =>\n errMsg.includes('Extra inputs are not permitted') &&\n errMsg.includes('citations'),\n fix: async opts => {\n if (!opts.messages) return\n\n for (const message of opts.messages) {\n if (!message) continue\n\n if (Array.isArray(message.content)) {\n for (const item of message.content) {\n // Convert to unknown first to safely access properties\n if (item && typeof item === 'object') {\n const itemObj = item as unknown as Record<string, unknown>\n if ('citations' in itemObj) {\n delete itemObj.citations\n }\n }\n }\n } else if (message.content && typeof message.content === 'object') {\n // Convert to unknown first to safely access properties\n const contentObj = message.content as unknown as Record<\n string,\n unknown\n >\n if ('citations' in contentObj) {\n delete contentObj.citations\n }\n }\n }\n },\n },\n]\n\n// Model-specific feature flags - can be extended with more properties as needed\ninterface ModelFeatures {\n usesMaxCompletionTokens: boolean\n supportsResponsesAPI?: boolean\n requiresTemperatureOne?: boolean\n supportsVerbosityControl?: boolean\n supportsCustomTools?: boolean\n supportsAllowedTools?: boolean\n}\n\n// Map of model identifiers to their specific features\nconst MODEL_FEATURES: Record<string, ModelFeatures> = {\n // OpenAI thinking models\n o1: { usesMaxCompletionTokens: true },\n 'o1-preview': { usesMaxCompletionTokens: true },\n 'o1-mini': { usesMaxCompletionTokens: true },\n 'o1-pro': { usesMaxCompletionTokens: true },\n 'o3-mini': { usesMaxCompletionTokens: true },\n // GPT-5 models\n 'gpt-5': {\n usesMaxCompletionTokens: true,\n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n },\n 'gpt-5-mini': {\n usesMaxCompletionTokens: true,\n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n },\n 'gpt-5-nano': {\n usesMaxCompletionTokens: true,\n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n },\n 'gpt-5-chat-latest': {\n usesMaxCompletionTokens: true,\n supportsResponsesAPI: false, // Uses Chat Completions only\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n },\n}\n\n// Helper to get model features based on model ID/name\nfunction getModelFeatures(modelName: string): ModelFeatures {\n if (!modelName || typeof modelName !== 'string') {\n return { usesMaxCompletionTokens: false }\n }\n\n // Check for exact matches first (highest priority)\n if (MODEL_FEATURES[modelName]) {\n return MODEL_FEATURES[modelName]\n }\n\n // Simple GPT-5 detection: any model name containing 'gpt-5'\n if (modelName.toLowerCase().includes('gpt-5')) {\n return {\n usesMaxCompletionTokens: true,\n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n }\n }\n\n // Check for partial matches (e.g., other reasoning models)\n for (const [key, features] of Object.entries(MODEL_FEATURES)) {\n if (modelName.includes(key)) {\n return features\n }\n }\n\n // Default features for unknown models\n return { usesMaxCompletionTokens: false }\n}\n\n// Apply model-specific parameter transformations based on model features\nfunction applyModelSpecificTransformations(\n opts: OpenAI.ChatCompletionCreateParams,\n): void {\n if (!opts.model || typeof opts.model !== 'string') {\n return\n }\n\n const features = getModelFeatures(opts.model)\n const isGPT5 = opts.model.toLowerCase().includes('gpt-5')\n\n // \uD83D\uDD25 Enhanced GPT-5 Detection and Transformation\n if (isGPT5 || features.usesMaxCompletionTokens) {\n // Force max_completion_tokens for all GPT-5 models\n if ('max_tokens' in opts && !('max_completion_tokens' in opts)) {\n debugLogger.info('OPENAI_TRANSFORM', {\n action: 'max_tokens_to_completion',\n model: opts.model,\n value: opts.max_tokens,\n })\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n\n // Force temperature = 1 for GPT-5 models\n if (features.requiresTemperatureOne && 'temperature' in opts) {\n if (opts.temperature !== 1 && opts.temperature !== undefined) {\n debugLogger.info('OPENAI_TRANSFORM', {\n action: 'temperature_constraint',\n model: opts.model,\n from: opts.temperature,\n to: 1,\n })\n opts.temperature = 1\n }\n }\n\n // Remove unsupported parameters for GPT-5\n if (isGPT5) {\n // Remove parameters that may not be supported by GPT-5\n delete opts.frequency_penalty\n delete opts.presence_penalty\n delete opts.logit_bias\n delete opts.user\n\n // Add reasoning_effort if not present and model supports it\n if (!opts.reasoning_effort && features.supportsVerbosityControl) {\n opts.reasoning_effort = 'medium' // Default reasoning effort for coding tasks\n }\n }\n }\n\n // Apply transformations for non-GPT-5 models\n else {\n // Standard max_tokens to max_completion_tokens conversion for other reasoning models\n if (\n features.usesMaxCompletionTokens &&\n 'max_tokens' in opts &&\n !('max_completion_tokens' in opts)\n ) {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n }\n\n // Add more transformations here as needed\n}\n\n/**\n * Normalize request parameters based on provider capabilities from the registry.\n * This is a pre-request transform that ensures parameters are compatible with\n * the target provider and model.\n */\nexport function normalizeRequestParams(\n opts: OpenAI.ChatCompletionCreateParams,\n provider: string,\n): void {\n if (!opts.model || typeof opts.model !== 'string') {\n return\n }\n\n const caps = getEffectiveCapabilities(provider, opts.model)\n\n // 1. Normalize max tokens field name\n const correctField = caps.maxTokensField\n if (correctField === 'max_completion_tokens') {\n if ('max_tokens' in opts && !('max_completion_tokens' in opts)) {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n } else if (correctField === 'max_tokens') {\n if ('max_completion_tokens' in opts && !('max_tokens' in opts)) {\n opts.max_tokens = opts.max_completion_tokens\n delete opts.max_completion_tokens\n }\n }\n // max_output_tokens is only for Responses API, not Chat Completions\n\n // 2. Handle temperature based on provider/model capabilities\n if (caps.temperatureRange === 'omit') {\n // Model doesn't support temperature - remove it\n delete opts.temperature\n } else if ('temperature' in opts && opts.temperature !== undefined) {\n // Clamp temperature to provider's valid range\n const { min, max } = caps.temperatureRange\n opts.temperature = Math.max(min, Math.min(max, opts.temperature))\n }\n\n // 3. Downgrade tool_choice for providers that only support \"auto\"\n if (\n caps.supportsToolChoice === 'auto-only' &&\n opts.tool_choice &&\n typeof opts.tool_choice === 'object'\n ) {\n opts.tool_choice = 'auto'\n } else if (caps.supportsToolChoice === false) {\n delete opts.tool_choice\n }\n\n // 4. Limit stop sequences per provider capability\n if (\n caps.maxStopSequences !== null &&\n opts.stop &&\n Array.isArray(opts.stop) &&\n opts.stop.length > caps.maxStopSequences\n ) {\n opts.stop = opts.stop.slice(0, caps.maxStopSequences)\n }\n}\n\nasync function applyModelErrorFixes(\n opts: OpenAI.ChatCompletionCreateParams,\n baseURL: string,\n) {\n const isGPT5 = opts.model.startsWith('gpt-5')\n const handlers = isGPT5\n ? [...GPT5_ERROR_HANDLERS, ...ERROR_HANDLERS]\n : ERROR_HANDLERS\n\n for (const handler of handlers) {\n if (hasModelError(baseURL, opts.model, handler.type)) {\n await handler.fix(opts)\n return\n }\n }\n}\n\n// Helper function to try different endpoints for OpenAI-compatible providers\nasync function tryWithEndpointFallback(\n baseURL: string,\n opts: OpenAI.ChatCompletionCreateParams,\n headers: Record<string, string>,\n provider: string,\n proxy: any,\n signal?: AbortSignal, // \uD83D\uDD27 Add AbortSignal support\n): Promise<{ response: Response; endpoint: string }> {\n const endpointsToTry = []\n\n if (provider === 'minimax') {\n endpointsToTry.push('/text/chatcompletion_v2', '/chat/completions')\n } else {\n endpointsToTry.push('/chat/completions')\n }\n\n let lastError = null\n\n for (const endpoint of endpointsToTry) {\n try {\n const response = await fetch(`${baseURL}${endpoint}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(opts.stream ? { ...opts, stream: true } : opts),\n dispatcher: proxy,\n signal: signal, // \uD83D\uDD27 Connect AbortSignal to fetch call\n })\n\n // If successful, return immediately\n if (response.ok) {\n return { response, endpoint }\n }\n\n // If it's a 404, try the next endpoint\n if (response.status === 404 && endpointsToTry.length > 1) {\n debugLogger.info('OPENAI_ENDPOINT', {\n status: 404,\n endpoint,\n action: 'trying_next',\n })\n continue\n }\n\n // For other error codes, return this response (don't try fallback)\n return { response, endpoint }\n } catch (error) {\n lastError = error\n // Network errors might be temporary, try next endpoint\n if (endpointsToTry.indexOf(endpoint) < endpointsToTry.length - 1) {\n debugLogger.warn('OPENAI_ENDPOINT', {\n error: 'network_error',\n endpoint,\n action: 'trying_next',\n })\n continue\n }\n }\n }\n\n // If we get here, all endpoints failed\n throw lastError || new Error('All endpoints failed')\n}\n\n// Export shared utilities for GPT-5 compatibility\nexport {\n getGPT5CompletionWithProfile,\n getModelFeatures,\n applyModelSpecificTransformations,\n}\n\nexport async function getCompletionWithProfile(\n modelProfile: any,\n opts: OpenAI.ChatCompletionCreateParams,\n attempt: number = 0,\n maxAttempts: number = 10,\n signal?: AbortSignal, // \uD83D\uDD27 CRITICAL FIX: Add AbortSignal support\n): Promise<OpenAI.ChatCompletion | AsyncIterable<OpenAI.ChatCompletionChunk>> {\n if (attempt >= maxAttempts) {\n throw new Error('Max attempts reached')\n }\n\n const provider = modelProfile?.provider || 'anthropic'\n const baseURL = modelProfile?.baseURL\n const apiKey = modelProfile?.apiKey\n const proxy = getGlobalConfig().proxy\n ? new ProxyAgent(getGlobalConfig().proxy)\n : undefined\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n\n if (apiKey) {\n if (provider === 'azure') {\n headers['api-key'] = apiKey\n } else {\n headers['Authorization'] = `Bearer ${apiKey}`\n }\n }\n\n applyModelSpecificTransformations(opts)\n normalizeRequestParams(opts, provider)\n await applyModelErrorFixes(opts, baseURL || '')\n\n // \uD83D\uDD25 REAL-TIME API CALL DEBUG - \u4F7F\u7528\u5168\u5C40\u65E5\u5FD7\u7CFB\u7EDF\n debugLogger.api('OPENAI_API_CALL_START', {\n endpoint: baseURL || 'DEFAULT_OPENAI',\n model: opts.model,\n provider,\n apiKeyConfigured: !!apiKey,\n apiKeyPrefix: apiKey ? apiKey.substring(0, 8) : null,\n maxTokens: opts.max_tokens,\n temperature: opts.temperature,\n messageCount: opts.messages?.length || 0,\n streamMode: opts.stream,\n timestamp: new Date().toISOString(),\n modelProfileModelName: modelProfile?.modelName,\n modelProfileName: modelProfile?.name,\n })\n\n // Make sure all tool messages have string content\n opts.messages = opts.messages.map(msg => {\n if (msg.role === 'tool') {\n if (Array.isArray(msg.content)) {\n return {\n ...msg,\n content:\n msg.content\n .map(c => c.text || '')\n .filter(Boolean)\n .join('\\n\\n') || '(empty content)',\n }\n } else if (typeof msg.content !== 'string') {\n return {\n ...msg,\n content:\n typeof msg.content === 'undefined'\n ? '(empty content)'\n : JSON.stringify(msg.content),\n }\n }\n }\n return msg\n })\n\n // Define Azure-specific API endpoint with version\n const azureApiVersion = '2024-06-01'\n let endpoint = '/chat/completions'\n\n if (provider === 'azure') {\n endpoint = `/chat/completions?api-version=${azureApiVersion}`\n } else if (provider === 'minimax') {\n endpoint = '/text/chatcompletion_v2'\n }\n\n try {\n if (opts.stream) {\n let response: Response\n\n if (isOpenAICompatibleProvider(provider) && provider !== 'azure') {\n const result = await tryWithEndpointFallback(\n baseURL,\n opts,\n headers,\n provider,\n proxy,\n signal, // \uD83D\uDD27 Pass AbortSignal to endpoint fallback\n )\n response = result.response\n } else {\n response = await fetch(`${baseURL}${endpoint}`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ ...opts, stream: true }),\n dispatcher: proxy,\n signal: signal, // \uD83D\uDD27 CRITICAL FIX: Connect AbortSignal to fetch call\n })\n }\n\n if (!response.ok) {\n // \uD83D\uDD27 CRITICAL FIX: Check abort signal BEFORE showing retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n\n // \uD83D\uDD25 NEW: Parse error message to detect and handle specific API errors\n try {\n const errorData = await response.json()\n // Type guard for error data structure\n const hasError = (\n data: unknown,\n ): data is { error?: { message?: string }; message?: string } => {\n return typeof data === 'object' && data !== null\n }\n const errorMessage = hasError(errorData)\n ? errorData.error?.message ||\n errorData.message ||\n `HTTP ${response.status}`\n : `HTTP ${response.status}`\n\n // Check if this is a parameter error that we can fix\n const isGPT5 = opts.model.startsWith('gpt-5')\n const handlers = isGPT5\n ? [...GPT5_ERROR_HANDLERS, ...ERROR_HANDLERS]\n : ERROR_HANDLERS\n\n for (const handler of handlers) {\n if (handler.detect(errorMessage)) {\n debugLogger.info('OPENAI_ERROR_HANDLER', {\n type: handler.type,\n model: opts.model,\n error: errorMessage,\n })\n\n // Store this error for future requests\n setModelError(\n baseURL || '',\n opts.model,\n handler.type,\n errorMessage,\n )\n\n // Apply the fix and retry immediately\n await handler.fix(opts)\n debugLogger.info('OPENAI_ERROR_HANDLER', {\n action: 'fix_applied',\n type: handler.type,\n })\n\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal,\n )\n }\n }\n\n // If no specific handler found, log the error for debugging\n debugLogger.warn('OPENAI_UNHANDLED_ERROR', {\n status: response.status,\n error: errorMessage,\n })\n\n // Log API error using unified logger\n logAPIError({\n model: opts.model,\n endpoint: `${baseURL}${endpoint}`,\n status: response.status,\n error: errorMessage,\n request: opts,\n response: errorData,\n provider: provider,\n })\n } catch (parseError) {\n // If we can't parse the error, fall back to generic retry\n debugLogger.warn('OPENAI_PARSE_ERROR', { status: response.status })\n\n // Log parse error\n logAPIError({\n model: opts.model,\n endpoint: `${baseURL}${endpoint}`,\n status: response.status,\n error: `Could not parse error response: ${parseError.message}`,\n request: opts,\n response: { parseError: parseError.message },\n provider: provider,\n })\n }\n\n const delayMs = getRetryDelay(attempt)\n debugLogger.warn('API_RETRY', {\n status: response.status,\n delayMs,\n attempt: attempt + 1,\n maxAttempts,\n })\n try {\n await abortableDelay(delayMs, signal)\n } catch (error) {\n // If aborted during delay, throw the error to stop retrying\n if (error.message === 'Request was aborted') {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal, // \uD83D\uDD27 Pass AbortSignal to recursive call\n )\n }\n\n const stream = createStreamProcessor(response.body as any, signal)\n return stream\n }\n\n // Non-streaming request\n let response: Response\n\n if (isOpenAICompatibleProvider(provider) && provider !== 'azure') {\n const result = await tryWithEndpointFallback(\n baseURL,\n opts,\n headers,\n provider,\n proxy,\n signal, // \uD83D\uDD27 Pass AbortSignal to endpoint fallback\n )\n response = result.response\n } else {\n response = await fetch(`${baseURL}${endpoint}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(opts),\n dispatcher: proxy,\n signal: signal, // \uD83D\uDD27 CRITICAL FIX: Connect AbortSignal to non-streaming fetch call\n })\n }\n\n if (!response.ok) {\n // \uD83D\uDD27 CRITICAL FIX: Check abort signal BEFORE showing retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n\n // \uD83D\uDD25 NEW: Parse error message to detect and handle specific API errors\n try {\n const errorData = await response.json()\n // Type guard for error data structure\n const hasError = (\n data: unknown,\n ): data is { error?: { message?: string }; message?: string } => {\n return typeof data === 'object' && data !== null\n }\n const errorMessage = hasError(errorData)\n ? errorData.error?.message ||\n errorData.message ||\n `HTTP ${response.status}`\n : `HTTP ${response.status}`\n\n // Check if this is a parameter error that we can fix\n const isGPT5 = opts.model.startsWith('gpt-5')\n const handlers = isGPT5\n ? [...GPT5_ERROR_HANDLERS, ...ERROR_HANDLERS]\n : ERROR_HANDLERS\n\n for (const handler of handlers) {\n if (handler.detect(errorMessage)) {\n debugLogger.info('OPENAI_ERROR_HANDLER', {\n type: handler.type,\n model: opts.model,\n error: errorMessage,\n })\n\n // Store this error for future requests\n setModelError(baseURL || '', opts.model, handler.type, errorMessage)\n\n // Apply the fix and retry immediately\n await handler.fix(opts)\n debugLogger.info('OPENAI_ERROR_HANDLER', {\n action: 'fix_applied',\n type: handler.type,\n })\n\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal,\n )\n }\n }\n\n // If no specific handler found, log the error for debugging\n debugLogger.warn('OPENAI_UNHANDLED_ERROR', {\n status: response.status,\n error: errorMessage,\n })\n } catch (parseError) {\n // If we can't parse the error, fall back to generic retry\n debugLogger.warn('OPENAI_PARSE_ERROR', { status: response.status })\n }\n\n const delayMs = getRetryDelay(attempt)\n debugLogger.warn('API_RETRY', {\n status: response.status,\n delayMs,\n attempt: attempt + 1,\n maxAttempts,\n })\n try {\n await abortableDelay(delayMs, signal)\n } catch (error) {\n // If aborted during delay, throw the error to stop retrying\n if (error.message === 'Request was aborted') {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal, // \uD83D\uDD27 Pass AbortSignal to recursive call\n )\n }\n\n const responseData = (await response.json()) as OpenAI.ChatCompletion\n return responseData\n } catch (error) {\n // \uD83D\uDD27 CRITICAL FIX: Check abort signal BEFORE showing retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n\n if (attempt < maxAttempts) {\n // \uD83D\uDD27 Double-check abort status to avoid showing misleading retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n\n const delayMs = getRetryDelay(attempt)\n debugLogger.warn('API_RETRY', {\n error: 'network_error',\n delayMs,\n attempt: attempt + 1,\n maxAttempts,\n })\n try {\n await abortableDelay(delayMs, signal)\n } catch (error) {\n // If aborted during delay, throw the error to stop retrying\n if (error.message === 'Request was aborted') {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal, // \uD83D\uDD27 Pass AbortSignal to recursive call\n )\n }\n // Wrap network errors with user-friendly message\n throw new UserFriendlyError(error, {\n operation: 'API request',\n model: opts.model,\n endpoint: modelProfile.baseURL,\n })\n }\n}\n\nexport function createStreamProcessor(\n stream: any,\n signal?: AbortSignal,\n): AsyncGenerator<OpenAI.ChatCompletionChunk, void, unknown> {\n if (!stream) {\n throw new Error('Stream is null or undefined')\n }\n\n return (async function* () {\n const reader = stream.getReader()\n const decoder = new TextDecoder('utf-8')\n let buffer = ''\n\n try {\n while (true) {\n // Check for cancellation before attempting to read\n if (signal?.aborted) {\n break\n }\n\n let readResult\n try {\n readResult = await reader.read()\n } catch (e) {\n // If signal is aborted, this is user cancellation - exit silently\n if (signal?.aborted) {\n break\n }\n logError(e)\n break\n }\n\n const { done, value } = readResult\n if (done) {\n break\n }\n\n const chunk = decoder.decode(value, { stream: true })\n buffer += chunk\n\n let lineEnd = buffer.indexOf('\\n')\n while (lineEnd !== -1) {\n const line = buffer.substring(0, lineEnd).trim()\n buffer = buffer.substring(lineEnd + 1)\n\n if (line === 'data: [DONE]') {\n continue\n }\n\n if (line.startsWith('data: ')) {\n const data = line.slice(6).trim()\n if (!data) continue\n\n try {\n const parsed = JSON.parse(data) as OpenAI.ChatCompletionChunk\n yield parsed\n } catch (e) {\n debugLogger.warn('STREAM_PARSE_ERROR', {\n data: data.substring(0, 100),\n error: String(e),\n })\n }\n }\n\n lineEnd = buffer.indexOf('\\n')\n }\n }\n\n // Process any remaining data in the buffer\n if (buffer.trim()) {\n const lines = buffer.trim().split('\\n')\n for (const line of lines) {\n if (line.startsWith('data: ') && line !== 'data: [DONE]') {\n const data = line.slice(6).trim()\n if (!data) continue\n\n try {\n const parsed = JSON.parse(data) as OpenAI.ChatCompletionChunk\n yield parsed\n } catch (e) {\n debugLogger.warn('STREAM_PARSE_ERROR', {\n data: data.substring(0, 100),\n error: String(e),\n final: true,\n })\n }\n }\n }\n }\n } catch (e) {\n logError(e)\n } finally {\n try {\n reader.releaseLock()\n } catch (e) {\n // Silent - reader lock release failure is not critical\n }\n }\n })()\n}\n\nexport function streamCompletion(\n stream: any,\n signal?: AbortSignal,\n): AsyncGenerator<OpenAI.ChatCompletionChunk, void, unknown> {\n return createStreamProcessor(stream, signal)\n}\n\n/**\n * Call GPT-5 Responses API with proper parameter handling\n */\nexport async function callGPT5ResponsesAPI(\n modelProfile: any,\n opts: any, // Using 'any' for Responses API params which differ from ChatCompletionCreateParams\n signal?: AbortSignal,\n): Promise<any> {\n const baseURL = modelProfile?.baseURL || 'https://api.openai.com/v1'\n const apiKey = modelProfile?.apiKey\n const proxy = getGlobalConfig().proxy\n ? new ProxyAgent(getGlobalConfig().proxy)\n : undefined\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n }\n\n // \uD83D\uDD25 Enhanced Responses API Parameter Mapping for GPT-5\n const responsesParams: any = {\n model: opts.model,\n input: opts.messages, // Responses API uses 'input' instead of 'messages'\n }\n\n // \uD83D\uDD27 GPT-5 Token Configuration - Responses API uses max_output_tokens\n if (opts.max_completion_tokens) {\n responsesParams.max_output_tokens = opts.max_completion_tokens\n } else if (opts.max_tokens) {\n responsesParams.max_output_tokens = opts.max_tokens\n }\n\n // \uD83D\uDD27 GPT-5 Temperature Handling (only 1 or undefined)\n if (opts.temperature === 1) {\n responsesParams.temperature = 1\n }\n // Note: Do not pass temperature if it's not 1, GPT-5 will use default\n\n // \uD83D\uDD27 GPT-5 Reasoning Configuration\n const reasoningEffort = opts.reasoning_effort || 'medium'\n responsesParams.reasoning = {\n effort: reasoningEffort,\n // \uD83D\uDE80 Enable reasoning summaries for transparency in coding tasks\n generate_summary: true,\n }\n\n // \uD83D\uDD27 GPT-5 Tools Support\n if (opts.tools && opts.tools.length > 0) {\n responsesParams.tools = opts.tools\n\n // \uD83D\uDE80 GPT-5 Tool Choice Configuration\n if (opts.tool_choice) {\n responsesParams.tool_choice = opts.tool_choice\n }\n }\n\n // \uD83D\uDD27 GPT-5 System Instructions (separate from messages)\n const systemMessages = opts.messages.filter(msg => msg.role === 'system')\n const nonSystemMessages = opts.messages.filter(msg => msg.role !== 'system')\n\n if (systemMessages.length > 0) {\n responsesParams.instructions = systemMessages\n .map(msg => msg.content)\n .join('\\n\\n')\n responsesParams.input = nonSystemMessages\n }\n\n // Handle verbosity (if supported) - optimized for coding tasks\n const features = getModelFeatures(opts.model)\n if (features.supportsVerbosityControl) {\n // High verbosity for coding tasks to get detailed explanations and structured code\n // Based on GPT-5 best practices for agent-like coding environments\n responsesParams.text = {\n verbosity: 'high',\n }\n }\n\n // Apply GPT-5 coding optimizations\n if (opts.model.startsWith('gpt-5')) {\n // Set reasoning effort based on task complexity\n if (!responsesParams.reasoning) {\n responsesParams.reasoning = {\n effort: 'medium', // Balanced for most coding tasks\n }\n }\n\n // Add instructions parameter for coding-specific guidance\n if (!responsesParams.instructions) {\n responsesParams.instructions = `You are an expert programmer working in a terminal-based coding environment. Follow these guidelines:\n- Provide clear, concise code solutions\n- Use proper error handling and validation\n- Follow coding best practices and patterns\n- Explain complex logic when necessary\n- Focus on maintainable, readable code`\n }\n }\n\n try {\n const response = await fetch(`${baseURL}/responses`, {\n method: 'POST',\n headers,\n body: JSON.stringify(responsesParams),\n dispatcher: proxy,\n signal: signal,\n })\n\n if (!response.ok) {\n throw new Error(\n `GPT-5 Responses API error: ${response.status} ${response.statusText}`,\n )\n }\n\n const responseData = await response.json()\n\n // Convert Responses API response back to Chat Completion format for compatibility\n return convertResponsesAPIToChatCompletion(responseData)\n } catch (error) {\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n}\n\n/**\n * Convert Responses API response to Chat Completion format for compatibility\n * \uD83D\uDD25 Enhanced for GPT-5 with reasoning summary support\n */\nfunction convertResponsesAPIToChatCompletion(responsesData: any): any {\n // Extract content from Responses API format\n let outputText = responsesData.output_text || ''\n const usage = responsesData.usage || {}\n\n // \uD83D\uDE80 GPT-5 Reasoning Summary Integration\n // If reasoning summary is available, prepend it to the output for transparency\n if (responsesData.output && Array.isArray(responsesData.output)) {\n const reasoningItems = responsesData.output.filter(\n item => item.type === 'reasoning' && item.summary,\n )\n const messageItems = responsesData.output.filter(\n item => item.type === 'message',\n )\n\n if (reasoningItems.length > 0 && messageItems.length > 0) {\n const reasoningSummary = reasoningItems\n .map(item => item.summary?.map(s => s.text).join('\\n'))\n .filter(Boolean)\n .join('\\n\\n')\n\n const mainContent = messageItems\n .map(item => item.content?.map(c => c.text).join('\\n'))\n .filter(Boolean)\n .join('\\n\\n')\n\n if (reasoningSummary) {\n outputText = `**\uD83E\uDDE0 Reasoning Process:**\\n${reasoningSummary}\\n\\n**\uD83D\uDCDD Response:**\\n${mainContent}`\n } else {\n outputText = mainContent\n }\n }\n }\n\n return {\n id: responsesData.id || `chatcmpl-${Date.now()}`,\n object: 'chat.completion',\n created: Math.floor(Date.now() / 1000),\n model: responsesData.model || '',\n choices: [\n {\n index: 0,\n message: {\n role: 'assistant',\n content: outputText,\n // \uD83D\uDE80 Include reasoning metadata if available\n ...(responsesData.reasoning && {\n reasoning: {\n effort: responsesData.reasoning.effort,\n summary: responsesData.reasoning.summary,\n },\n }),\n },\n finish_reason: responsesData.status === 'completed' ? 'stop' : 'length',\n },\n ],\n usage: {\n prompt_tokens: usage.input_tokens || 0,\n completion_tokens: usage.output_tokens || 0,\n total_tokens: (usage.input_tokens || 0) + (usage.output_tokens || 0),\n // \uD83D\uDD27 GPT-5 Enhanced Usage Details\n prompt_tokens_details: {\n cached_tokens: usage.input_tokens_details?.cached_tokens || 0,\n },\n completion_tokens_details: {\n reasoning_tokens: usage.output_tokens_details?.reasoning_tokens || 0,\n },\n },\n }\n}\n\n/**\n * Enhanced getCompletionWithProfile that supports GPT-5 Responses API\n * \uD83D\uDD25 Optimized for both official OpenAI and third-party GPT-5 providers\n */\nasync function getGPT5CompletionWithProfile(\n modelProfile: any,\n opts: OpenAI.ChatCompletionCreateParams,\n attempt: number = 0,\n maxAttempts: number = 10,\n signal?: AbortSignal,\n): Promise<OpenAI.ChatCompletion | AsyncIterable<OpenAI.ChatCompletionChunk>> {\n const features = getModelFeatures(opts.model)\n const isOfficialOpenAI =\n !modelProfile.baseURL || modelProfile.baseURL.includes('api.openai.com')\n\n // \uD83D\uDE80 Try Responses API for official OpenAI non-streaming requests\n if (features.supportsResponsesAPI && !opts.stream && isOfficialOpenAI) {\n try {\n debugLogger.api('ATTEMPTING_GPT5_RESPONSES_API', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n provider: modelProfile.provider,\n stream: opts.stream,\n requestId: getCurrentRequest()?.id,\n })\n\n const result = await callGPT5ResponsesAPI(modelProfile, opts, signal)\n\n debugLogger.api('GPT5_RESPONSES_API_SUCCESS', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n requestId: getCurrentRequest()?.id,\n })\n\n return result\n } catch (error) {\n debugLogger.api('GPT5_RESPONSES_API_FALLBACK', {\n model: opts.model,\n error: error.message,\n baseURL: modelProfile.baseURL || 'official',\n requestId: getCurrentRequest()?.id,\n })\n\n debugLogger.warn('GPT5_FALLBACK', {\n reason: 'responses_api_failed',\n error: error.message,\n })\n // Fall through to Chat Completions API\n }\n }\n\n // \uD83C\uDF10 Handle third-party GPT-5 providers with enhanced compatibility\n else if (!isOfficialOpenAI) {\n debugLogger.api('GPT5_THIRD_PARTY_PROVIDER', {\n model: opts.model,\n baseURL: modelProfile.baseURL,\n provider: modelProfile.provider,\n supportsResponsesAPI: features.supportsResponsesAPI,\n requestId: getCurrentRequest()?.id,\n })\n\n // \uD83D\uDD27 Apply enhanced parameter optimization for third-party providers\n debugLogger.info('GPT5_THIRD_PARTY', {\n provider: modelProfile.provider,\n baseURL: modelProfile.baseURL,\n })\n\n // Some third-party providers may need additional parameter adjustments\n if (modelProfile.provider === 'azure') {\n // Azure OpenAI specific adjustments\n delete opts.reasoning_effort // Azure may not support this yet\n } else if (modelProfile.provider === 'custom-openai') {\n // Generic OpenAI-compatible provider optimizations\n debugLogger.info('GPT5_CUSTOM_OPTIMIZATIONS', {\n provider: 'custom-openai',\n })\n }\n }\n\n // \uD83D\uDCE1 Handle streaming requests (Responses API doesn't support streaming yet)\n else if (opts.stream) {\n debugLogger.api('GPT5_STREAMING_MODE', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n reason: 'responses_api_no_streaming',\n requestId: getCurrentRequest()?.id,\n })\n\n debugLogger.info('GPT5_STREAMING', { reason: 'responses_api_no_streaming' })\n }\n\n // \uD83D\uDD27 Enhanced Chat Completions fallback with GPT-5 optimizations\n debugLogger.api('USING_CHAT_COMPLETIONS_FOR_GPT5', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n provider: modelProfile.provider,\n reason: isOfficialOpenAI ? 'streaming_or_fallback' : 'third_party_provider',\n requestId: getCurrentRequest()?.id,\n })\n\n return await getCompletionWithProfile(\n modelProfile,\n opts,\n attempt,\n maxAttempts,\n signal,\n )\n}\n\n/**\n * Fetch available models from custom OpenAI-compatible API\n */\nexport async function fetchCustomModels(\n baseURL: string,\n apiKey: string,\n): Promise<any[]> {\n try {\n // Check if baseURL already contains version number (e.g., v1, v2, etc.)\n const hasVersionNumber = /\\/v\\d+/.test(baseURL)\n const cleanBaseURL = baseURL.replace(/\\/+$/, '')\n const modelsURL = hasVersionNumber\n ? `${cleanBaseURL}/models`\n : `${cleanBaseURL}/v1/models`\n\n const response = await fetch(modelsURL, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n },\n signal: AbortSignal.timeout(30_000),\n })\n\n if (!response.ok) {\n // Provide user-friendly error messages based on status code\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(\n 'API key does not have permission to access models. Please check your API key permissions.',\n )\n } else if (response.status === 404) {\n throw new Error(\n 'API endpoint not found. Please check if the base URL is correct and supports the /models endpoint.',\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(\n `Unable to connect to API (${response.status}). Please check your base URL, API key, and internet connection.`,\n )\n }\n }\n\n const data = await response.json()\n\n // Type guards for different API response formats\n const hasDataArray = (obj: unknown): obj is { data: unknown[] } => {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n 'data' in obj &&\n Array.isArray((obj as any).data)\n )\n }\n\n const hasModelsArray = (obj: unknown): obj is { models: unknown[] } => {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n 'models' in obj &&\n Array.isArray((obj as any).models)\n )\n }\n\n // Validate response format and extract models array\n let models = []\n\n if (hasDataArray(data)) {\n // Standard OpenAI format: { data: [...] }\n models = data.data\n } else if (Array.isArray(data)) {\n // Direct array format\n models = data\n } else if (hasModelsArray(data)) {\n // Alternative format: { models: [...] }\n models = data.models\n } else {\n throw new Error(\n 'API returned unexpected response format. Expected an array of models or an object with a \"data\" or \"models\" array.',\n )\n }\n\n // Ensure we have an array and validate it contains model objects\n if (!Array.isArray(models)) {\n throw new Error('API response format error: models data is not an array.')\n }\n\n return models\n } catch (error) {\n // If it's already our custom error, pass it through\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 // For network errors or other issues\n logError(error)\n\n // Check if it's a network error\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 custom API. Please check your configuration and try again.',\n )\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { OpenAI } from 'openai'\nimport { getGlobalConfig, type ModelProfile } from '@utils/config'\nimport { ProxyAgent, fetch, Response } from 'undici'\nimport { setSessionState, getSessionState } from '@utils/sessionState'\nimport {\n debug as debugLogger,\n getCurrentRequest,\n logAPIError,\n} from '@utils/debugLogger'\nimport { logError } from '@utils/log'\nimport { setStreamingState } from '@utils/streamingState'\nimport {\n abortableDelay,\n getRetryDelay as sharedGetRetryDelay,\n} from '@utils/async'\nimport {\n formatErrorForUser,\n ErrorCategory,\n UserFriendlyError,\n} from '@utils/userFriendlyError'\nimport { isOpenAICompatibleProvider } from '@constants/providers'\nimport { getEffectiveCapabilities } from '@constants/providerRegistry'\nimport { resolveApiKey } from '@utils/config'\n\n/**\n * Resolve API key from a model profile, handling encrypted: references.\n * encrypted:keyName \u2192 looks up actual key from credential store\n * plain string \u2192 returns as-is\n */\nasync function resolveModelApiKey(\n modelProfile: ModelProfile | null | undefined,\n): Promise<string> {\n if (!modelProfile?.apiKey) return ''\n return (await resolveApiKey(modelProfile)) ?? modelProfile.apiKey\n}\n\n/**\n * Calculate retry delay \u2014 delegates to shared utility\n */\nfunction getRetryDelay(attempt: number): number {\n return sharedGetRetryDelay(attempt)\n}\n\nenum ModelErrorType {\n MaxLength = '1024',\n MaxCompletionTokens = 'max_completion_tokens',\n TemperatureRestriction = 'temperature_restriction',\n StreamOptions = 'stream_options',\n Citations = 'citations',\n RateLimit = 'rate_limit',\n UnsupportedParam = 'unsupported_param',\n}\n\nfunction getModelErrorKey(\n baseURL: string,\n model: string,\n type: ModelErrorType,\n): string {\n return `${baseURL}:${model}:${type}`\n}\n\nfunction hasModelError(\n baseURL: string,\n model: string,\n type: ModelErrorType,\n): boolean {\n return !!getSessionState('modelErrors')[\n getModelErrorKey(baseURL, model, type)\n ]\n}\n\nfunction setModelError(\n baseURL: string,\n model: string,\n type: ModelErrorType,\n error: string,\n) {\n setSessionState('modelErrors', {\n [getModelErrorKey(baseURL, model, type)]: error,\n })\n}\n\n// More flexible error detection system\ntype ErrorDetector = (errMsg: string) => boolean\ntype ErrorFixer = (\n opts: OpenAI.ChatCompletionCreateParams,\n) => Promise<void> | void\ninterface ErrorHandler {\n type: ModelErrorType\n detect: ErrorDetector\n fix: ErrorFixer\n}\n\n// GPT-5 specific error handlers with enhanced detection patterns\nconst GPT5_ERROR_HANDLERS: ErrorHandler[] = [\n {\n type: ModelErrorType.MaxCompletionTokens,\n detect: errMsg => {\n const lowerMsg = errMsg.toLowerCase()\n return (\n // Exact OpenAI GPT-5 error message\n (lowerMsg.includes(\"unsupported parameter: 'max_tokens'\") &&\n lowerMsg.includes(\"'max_completion_tokens'\")) ||\n // Generic max_tokens error patterns\n (lowerMsg.includes('max_tokens') &&\n lowerMsg.includes('max_completion_tokens')) ||\n (lowerMsg.includes('max_tokens') &&\n lowerMsg.includes('not supported')) ||\n (lowerMsg.includes('max_tokens') &&\n lowerMsg.includes('use max_completion_tokens')) ||\n // Additional patterns for various providers\n (lowerMsg.includes('invalid parameter') &&\n lowerMsg.includes('max_tokens')) ||\n (lowerMsg.includes('parameter error') &&\n lowerMsg.includes('max_tokens'))\n )\n },\n fix: async opts => {\n debugLogger.info('GPT5_FIX', {\n action: 'convert_max_tokens',\n from: opts.max_tokens,\n })\n if ('max_tokens' in opts) {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n },\n },\n {\n type: ModelErrorType.TemperatureRestriction,\n detect: errMsg => {\n const lowerMsg = errMsg.toLowerCase()\n return (\n lowerMsg.includes('temperature') &&\n (lowerMsg.includes('only supports') ||\n lowerMsg.includes('must be 1') ||\n lowerMsg.includes('invalid temperature'))\n )\n },\n fix: async opts => {\n debugLogger.info('GPT5_FIX', {\n action: 'adjust_temperature',\n from: opts.temperature,\n to: 1,\n })\n opts.temperature = 1\n },\n },\n // Add more GPT-5 specific handlers as needed\n]\n\n// Standard error handlers\nconst ERROR_HANDLERS: ErrorHandler[] = [\n {\n type: ModelErrorType.MaxLength,\n detect: errMsg =>\n errMsg.includes('Expected a string with maximum length 1024'),\n fix: async opts => {\n const toolDescriptions = {}\n for (const tool of opts.tools || []) {\n if (tool.function.description.length <= 1024) continue\n let str = ''\n let remainder = ''\n for (let line of tool.function.description.split('\\n')) {\n if (str.length + line.length < 1024) {\n str += line + '\\n'\n } else {\n remainder += line + '\\n'\n }\n }\n\n tool.function.description = str\n toolDescriptions[tool.function.name] = remainder\n }\n if (Object.keys(toolDescriptions).length > 0) {\n let content = '<additional-tool-usage-instructions>\\n\\n'\n for (const [name, description] of Object.entries(toolDescriptions)) {\n content += `<${name}>\\n${description}\\n</${name}>\\n\\n`\n }\n content += '</additional-tool-usage-instructions>'\n\n for (let i = opts.messages.length - 1; i >= 0; i--) {\n if (opts.messages[i].role === 'system') {\n opts.messages.splice(i + 1, 0, {\n role: 'system',\n content,\n })\n break\n }\n }\n }\n },\n },\n {\n type: ModelErrorType.MaxCompletionTokens,\n detect: errMsg => errMsg.includes(\"Use 'max_completion_tokens'\"),\n fix: async opts => {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n },\n },\n {\n type: ModelErrorType.StreamOptions,\n detect: errMsg => errMsg.includes('stream_options'),\n fix: async opts => {\n delete opts.stream_options\n },\n },\n {\n type: ModelErrorType.UnsupportedParam,\n detect: errMsg => {\n const lower = errMsg.toLowerCase()\n return (\n (lower.includes('unsupported') && lower.includes('reasoning_effort')) ||\n (lower.includes('does not support') &&\n lower.includes('reasoning_effort'))\n )\n },\n fix: async opts => {\n debugLogger.info('OPENAI_FIX', {\n action: 'remove_reasoning_effort',\n model: opts.model,\n })\n delete (opts as any).reasoning_effort\n },\n },\n {\n type: ModelErrorType.Citations,\n detect: errMsg =>\n errMsg.includes('Extra inputs are not permitted') &&\n errMsg.includes('citations'),\n fix: async opts => {\n if (!opts.messages) return\n\n for (const message of opts.messages) {\n if (!message) continue\n\n if (Array.isArray(message.content)) {\n for (const item of message.content) {\n // Convert to unknown first to safely access properties\n if (item && typeof item === 'object') {\n const itemObj = item as unknown as Record<string, unknown>\n if ('citations' in itemObj) {\n delete itemObj.citations\n }\n }\n }\n } else if (message.content && typeof message.content === 'object') {\n // Convert to unknown first to safely access properties\n const contentObj = message.content as unknown as Record<\n string,\n unknown\n >\n if ('citations' in contentObj) {\n delete contentObj.citations\n }\n }\n }\n },\n },\n]\n\n// Model-specific feature flags - can be extended with more properties as needed\ninterface ModelFeatures {\n usesMaxCompletionTokens: boolean\n supportsResponsesAPI?: boolean\n requiresTemperatureOne?: boolean\n supportsVerbosityControl?: boolean\n supportsCustomTools?: boolean\n supportsAllowedTools?: boolean\n}\n\n// Map of model identifiers to their specific features\nconst MODEL_FEATURES: Record<string, ModelFeatures> = {\n // OpenAI thinking models\n o1: { usesMaxCompletionTokens: true },\n 'o1-preview': { usesMaxCompletionTokens: true },\n 'o1-mini': { usesMaxCompletionTokens: true },\n 'o1-pro': { usesMaxCompletionTokens: true },\n 'o3-mini': { usesMaxCompletionTokens: true },\n // GPT-5 models\n 'gpt-5': {\n usesMaxCompletionTokens: true,\n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n },\n 'gpt-5-mini': {\n usesMaxCompletionTokens: true,\n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n },\n 'gpt-5-nano': {\n usesMaxCompletionTokens: true,\n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n },\n 'gpt-5-chat-latest': {\n usesMaxCompletionTokens: true,\n supportsResponsesAPI: false, // Uses Chat Completions only\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n },\n}\n\n// Helper to get model features based on model ID/name\nfunction getModelFeatures(modelName: string): ModelFeatures {\n if (!modelName || typeof modelName !== 'string') {\n return { usesMaxCompletionTokens: false }\n }\n\n // Check for exact matches first (highest priority)\n if (MODEL_FEATURES[modelName]) {\n return MODEL_FEATURES[modelName]\n }\n\n // Simple GPT-5 detection: any model name containing 'gpt-5'\n if (modelName.toLowerCase().includes('gpt-5')) {\n return {\n usesMaxCompletionTokens: true,\n supportsResponsesAPI: true,\n requiresTemperatureOne: true,\n supportsVerbosityControl: true,\n supportsCustomTools: true,\n supportsAllowedTools: true,\n }\n }\n\n // Check for partial matches (e.g., other reasoning models)\n for (const [key, features] of Object.entries(MODEL_FEATURES)) {\n if (modelName.includes(key)) {\n return features\n }\n }\n\n // Default features for unknown models\n return { usesMaxCompletionTokens: false }\n}\n\n// Apply model-specific parameter transformations based on model features\nfunction applyModelSpecificTransformations(\n opts: OpenAI.ChatCompletionCreateParams,\n): void {\n if (!opts.model || typeof opts.model !== 'string') {\n return\n }\n\n const features = getModelFeatures(opts.model)\n const isGPT5 = opts.model.toLowerCase().includes('gpt-5')\n\n // \uD83D\uDD25 Enhanced GPT-5 Detection and Transformation\n if (isGPT5 || features.usesMaxCompletionTokens) {\n // Force max_completion_tokens for all GPT-5 models\n if ('max_tokens' in opts && !('max_completion_tokens' in opts)) {\n debugLogger.info('OPENAI_TRANSFORM', {\n action: 'max_tokens_to_completion',\n model: opts.model,\n value: opts.max_tokens,\n })\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n\n // Force temperature = 1 for GPT-5 models\n if (features.requiresTemperatureOne && 'temperature' in opts) {\n if (opts.temperature !== 1 && opts.temperature !== undefined) {\n debugLogger.info('OPENAI_TRANSFORM', {\n action: 'temperature_constraint',\n model: opts.model,\n from: opts.temperature,\n to: 1,\n })\n opts.temperature = 1\n }\n }\n\n // Remove unsupported parameters for GPT-5\n if (isGPT5) {\n // Remove parameters that may not be supported by GPT-5\n delete opts.frequency_penalty\n delete opts.presence_penalty\n delete opts.logit_bias\n delete opts.user\n\n // Add reasoning_effort if not present and model supports it\n if (!opts.reasoning_effort && features.supportsVerbosityControl) {\n opts.reasoning_effort = 'medium' // Default reasoning effort for coding tasks\n }\n }\n }\n\n // Apply transformations for non-GPT-5 models\n else {\n // Standard max_tokens to max_completion_tokens conversion for other reasoning models\n if (\n features.usesMaxCompletionTokens &&\n 'max_tokens' in opts &&\n !('max_completion_tokens' in opts)\n ) {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n }\n\n // Add more transformations here as needed\n}\n\n/**\n * Normalize request parameters based on provider capabilities from the registry.\n * This is a pre-request transform that ensures parameters are compatible with\n * the target provider and model.\n */\nexport function normalizeRequestParams(\n opts: OpenAI.ChatCompletionCreateParams,\n provider: string,\n): void {\n if (!opts.model || typeof opts.model !== 'string') {\n return\n }\n\n const caps = getEffectiveCapabilities(provider, opts.model)\n\n // 1. Normalize max tokens field name\n const correctField = caps.maxTokensField\n if (correctField === 'max_completion_tokens') {\n if ('max_tokens' in opts && !('max_completion_tokens' in opts)) {\n opts.max_completion_tokens = opts.max_tokens\n delete opts.max_tokens\n }\n } else if (correctField === 'max_tokens') {\n if ('max_completion_tokens' in opts && !('max_tokens' in opts)) {\n opts.max_tokens = opts.max_completion_tokens\n delete opts.max_completion_tokens\n }\n }\n // max_output_tokens is only for Responses API, not Chat Completions\n\n // 2. Handle temperature based on provider/model capabilities\n if (caps.temperatureRange === 'omit') {\n // Model doesn't support temperature - remove it\n delete opts.temperature\n } else if ('temperature' in opts && opts.temperature !== undefined) {\n // Clamp temperature to provider's valid range\n const { min, max } = caps.temperatureRange\n opts.temperature = Math.max(min, Math.min(max, opts.temperature))\n }\n\n // 3. Downgrade tool_choice for providers that only support \"auto\"\n if (\n caps.supportsToolChoice === 'auto-only' &&\n opts.tool_choice &&\n typeof opts.tool_choice === 'object'\n ) {\n opts.tool_choice = 'auto'\n } else if (caps.supportsToolChoice === false) {\n delete opts.tool_choice\n }\n\n // 4. Limit stop sequences per provider capability\n if (\n caps.maxStopSequences !== null &&\n opts.stop &&\n Array.isArray(opts.stop) &&\n opts.stop.length > caps.maxStopSequences\n ) {\n opts.stop = opts.stop.slice(0, caps.maxStopSequences)\n }\n}\n\nasync function applyModelErrorFixes(\n opts: OpenAI.ChatCompletionCreateParams,\n baseURL: string,\n) {\n const isGPT5 = opts.model.startsWith('gpt-5')\n const handlers = isGPT5\n ? [...GPT5_ERROR_HANDLERS, ...ERROR_HANDLERS]\n : ERROR_HANDLERS\n\n for (const handler of handlers) {\n if (hasModelError(baseURL, opts.model, handler.type)) {\n await handler.fix(opts)\n return\n }\n }\n}\n\n// Helper function to try different endpoints for OpenAI-compatible providers\n/**\n * Default timeout for OpenAI-compatible API fetch calls (ms).\n * Prevents indefinite hangs when the backend doesn't respond.\n * Mirrors the Anthropic path's API_TIMEOUT_MS behavior.\n */\nconst API_FETCH_TIMEOUT_MS = parseInt(\n process.env.API_TIMEOUT_MS || String(120 * 1000),\n 10,\n)\n\n/**\n * Combine a user abort signal with a timeout signal.\n * The resulting signal aborts on EITHER user cancellation OR timeout.\n */\nfunction withFetchTimeout(signal?: AbortSignal): AbortSignal {\n const timeoutSignal = AbortSignal.timeout(API_FETCH_TIMEOUT_MS)\n if (!signal) return timeoutSignal\n return AbortSignal.any([signal, timeoutSignal])\n}\n\nasync function tryWithEndpointFallback(\n baseURL: string,\n opts: OpenAI.ChatCompletionCreateParams,\n headers: Record<string, string>,\n provider: string,\n proxy: any,\n signal?: AbortSignal,\n): Promise<{ response: Response; endpoint: string }> {\n const endpointsToTry = []\n\n if (provider === 'minimax') {\n endpointsToTry.push('/text/chatcompletion_v2', '/chat/completions')\n } else {\n endpointsToTry.push('/chat/completions')\n }\n\n let lastError = null\n const fetchSignal = withFetchTimeout(signal)\n\n for (const endpoint of endpointsToTry) {\n try {\n const response = await fetch(`${baseURL}${endpoint}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(opts.stream ? { ...opts, stream: true } : opts),\n dispatcher: proxy,\n signal: fetchSignal,\n })\n\n // If successful, return immediately\n if (response.ok) {\n return { response, endpoint }\n }\n\n // If it's a 404, try the next endpoint\n if (response.status === 404 && endpointsToTry.length > 1) {\n debugLogger.info('OPENAI_ENDPOINT', {\n status: 404,\n endpoint,\n action: 'trying_next',\n })\n continue\n }\n\n // For other error codes, return this response (don't try fallback)\n return { response, endpoint }\n } catch (error) {\n lastError = error\n // Network errors might be temporary, try next endpoint\n if (endpointsToTry.indexOf(endpoint) < endpointsToTry.length - 1) {\n debugLogger.warn('OPENAI_ENDPOINT', {\n error: 'network_error',\n endpoint,\n action: 'trying_next',\n })\n continue\n }\n }\n }\n\n // If we get here, all endpoints failed\n throw lastError || new Error('All endpoints failed')\n}\n\n// Export shared utilities for GPT-5 compatibility\nexport {\n getGPT5CompletionWithProfile,\n getModelFeatures,\n applyModelSpecificTransformations,\n}\n\nexport async function getCompletionWithProfile(\n modelProfile: ModelProfile,\n opts: OpenAI.ChatCompletionCreateParams,\n attempt: number = 0,\n maxAttempts: number = 5,\n signal?: AbortSignal, // \uD83D\uDD27 CRITICAL FIX: Add AbortSignal support\n): Promise<OpenAI.ChatCompletion | AsyncIterable<OpenAI.ChatCompletionChunk>> {\n if (attempt >= maxAttempts) {\n throw new Error('Max attempts reached')\n }\n\n const provider = modelProfile?.provider || 'anthropic'\n const baseURL = modelProfile?.baseURL\n const apiKey = await resolveModelApiKey(modelProfile)\n const proxy = getGlobalConfig().proxy\n ? new ProxyAgent(getGlobalConfig().proxy)\n : undefined\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n\n if (apiKey) {\n if (provider === 'azure') {\n headers['api-key'] = apiKey\n } else {\n headers['Authorization'] = `Bearer ${apiKey}`\n }\n }\n\n applyModelSpecificTransformations(opts)\n normalizeRequestParams(opts, provider)\n await applyModelErrorFixes(opts, baseURL || '')\n\n // \uD83D\uDD25 REAL-TIME API CALL DEBUG - \u4F7F\u7528\u5168\u5C40\u65E5\u5FD7\u7CFB\u7EDF\n debugLogger.api('OPENAI_API_CALL_START', {\n endpoint: baseURL || 'DEFAULT_OPENAI',\n model: opts.model,\n provider,\n apiKeyConfigured: !!apiKey,\n apiKeyPrefix: apiKey ? apiKey.substring(0, 4) + '...' : null,\n maxTokens: opts.max_tokens,\n temperature: opts.temperature,\n messageCount: opts.messages?.length || 0,\n streamMode: opts.stream,\n timestamp: new Date().toISOString(),\n modelProfileModelName: modelProfile?.modelName,\n modelProfileName: modelProfile?.name,\n })\n\n // Normalize messages for OpenAI-compatible models:\n // - Strip Anthropic-specific thinking/redacted_thinking blocks from assistant messages\n // - Ensure tool messages have string content\n opts.messages = opts.messages.map(msg => {\n if (msg.role === 'assistant' && Array.isArray(msg.content)) {\n const filtered = msg.content.filter(\n (block: any) =>\n block.type !== 'thinking' && block.type !== 'redacted_thinking',\n )\n if (filtered.length !== msg.content.length) {\n return {\n ...msg,\n content:\n filtered.length > 0 ? filtered : [{ type: 'text', text: '' }],\n }\n }\n }\n if (msg.role === 'tool') {\n if (Array.isArray(msg.content)) {\n return {\n ...msg,\n content:\n msg.content\n .map(c => c.text || '')\n .filter(Boolean)\n .join('\\n\\n') || '(empty content)',\n }\n } else if (typeof msg.content !== 'string') {\n return {\n ...msg,\n content:\n typeof msg.content === 'undefined'\n ? '(empty content)'\n : JSON.stringify(msg.content),\n }\n }\n }\n return msg\n })\n\n // Define Azure-specific API endpoint with version\n const azureApiVersion = '2024-06-01'\n let endpoint = '/chat/completions'\n\n if (provider === 'azure') {\n endpoint = `/chat/completions?api-version=${azureApiVersion}`\n } else if (provider === 'minimax') {\n endpoint = '/text/chatcompletion_v2'\n }\n\n try {\n if (opts.stream) {\n let response: Response\n\n if (isOpenAICompatibleProvider(provider) && provider !== 'azure') {\n const result = await tryWithEndpointFallback(\n baseURL,\n opts,\n headers,\n provider,\n proxy,\n signal, // \uD83D\uDD27 Pass AbortSignal to endpoint fallback\n )\n response = result.response\n } else {\n response = await fetch(`${baseURL}${endpoint}`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ ...opts, stream: true }),\n dispatcher: proxy,\n signal: withFetchTimeout(signal),\n })\n }\n\n if (!response.ok) {\n // \uD83D\uDD27 CRITICAL FIX: Check abort signal BEFORE showing retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n\n // \uD83D\uDD25 NEW: Parse error message to detect and handle specific API errors\n try {\n const errorData = await response.json()\n // Type guard for error data structure\n const hasError = (\n data: unknown,\n ): data is { error?: { message?: string }; message?: string } => {\n return typeof data === 'object' && data !== null\n }\n const errorMessage = hasError(errorData)\n ? errorData.error?.message ||\n errorData.message ||\n `HTTP ${response.status}`\n : `HTTP ${response.status}`\n\n // Check if this is a parameter error that we can fix\n const isGPT5 = opts.model.startsWith('gpt-5')\n const handlers = isGPT5\n ? [...GPT5_ERROR_HANDLERS, ...ERROR_HANDLERS]\n : ERROR_HANDLERS\n\n for (const handler of handlers) {\n if (handler.detect(errorMessage)) {\n debugLogger.info('OPENAI_ERROR_HANDLER', {\n type: handler.type,\n model: opts.model,\n error: errorMessage,\n })\n\n // Store this error for future requests\n setModelError(\n baseURL || '',\n opts.model,\n handler.type,\n errorMessage,\n )\n\n // Apply the fix and retry immediately\n await handler.fix(opts)\n debugLogger.info('OPENAI_ERROR_HANDLER', {\n action: 'fix_applied',\n type: handler.type,\n })\n\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal,\n )\n }\n }\n\n // If no specific handler found, log the error for debugging\n debugLogger.warn('OPENAI_UNHANDLED_ERROR', {\n status: response.status,\n error: errorMessage,\n })\n\n // Log API error using unified logger\n logAPIError({\n model: opts.model,\n endpoint: `${baseURL}${endpoint}`,\n status: response.status,\n error: errorMessage,\n request: opts,\n response: errorData,\n provider: provider,\n })\n } catch (parseError) {\n // If we can't parse the error, fall back to generic retry\n debugLogger.warn('OPENAI_PARSE_ERROR', { status: response.status })\n\n // Log parse error\n logAPIError({\n model: opts.model,\n endpoint: `${baseURL}${endpoint}`,\n status: response.status,\n error: `Could not parse error response: ${parseError.message}`,\n request: opts,\n response: { parseError: parseError.message },\n provider: provider,\n })\n }\n\n const delayMs = getRetryDelay(attempt)\n setStreamingState({\n phase: 'retrying',\n retryCount: attempt + 1,\n maxRetries: maxAttempts,\n errorName: `HTTP ${response.status}`,\n retryDelayMs: delayMs,\n })\n debugLogger.warn('API_RETRY', {\n status: response.status,\n delayMs,\n attempt: attempt + 1,\n maxAttempts,\n })\n try {\n await abortableDelay(delayMs, signal)\n } catch (error) {\n // If aborted during delay, throw the error to stop retrying\n if (error.message === 'Request was aborted') {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal, // \uD83D\uDD27 Pass AbortSignal to recursive call\n )\n }\n\n const stream = createStreamProcessor(response.body as any, signal)\n return stream\n }\n\n // Non-streaming request\n let response: Response\n\n if (isOpenAICompatibleProvider(provider) && provider !== 'azure') {\n const result = await tryWithEndpointFallback(\n baseURL,\n opts,\n headers,\n provider,\n proxy,\n signal, // \uD83D\uDD27 Pass AbortSignal to endpoint fallback\n )\n response = result.response\n } else {\n response = await fetch(`${baseURL}${endpoint}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(opts),\n dispatcher: proxy,\n signal: withFetchTimeout(signal),\n })\n }\n\n if (!response.ok) {\n // \uD83D\uDD27 CRITICAL FIX: Check abort signal BEFORE showing retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n\n // \uD83D\uDD25 NEW: Parse error message to detect and handle specific API errors\n try {\n const errorData = await response.json()\n // Type guard for error data structure\n const hasError = (\n data: unknown,\n ): data is { error?: { message?: string }; message?: string } => {\n return typeof data === 'object' && data !== null\n }\n const errorMessage = hasError(errorData)\n ? errorData.error?.message ||\n errorData.message ||\n `HTTP ${response.status}`\n : `HTTP ${response.status}`\n\n // Check if this is a parameter error that we can fix\n const isGPT5 = opts.model.startsWith('gpt-5')\n const handlers = isGPT5\n ? [...GPT5_ERROR_HANDLERS, ...ERROR_HANDLERS]\n : ERROR_HANDLERS\n\n for (const handler of handlers) {\n if (handler.detect(errorMessage)) {\n debugLogger.info('OPENAI_ERROR_HANDLER', {\n type: handler.type,\n model: opts.model,\n error: errorMessage,\n })\n\n // Store this error for future requests\n setModelError(baseURL || '', opts.model, handler.type, errorMessage)\n\n // Apply the fix and retry immediately\n await handler.fix(opts)\n debugLogger.info('OPENAI_ERROR_HANDLER', {\n action: 'fix_applied',\n type: handler.type,\n })\n\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal,\n )\n }\n }\n\n // If no specific handler found, log the error for debugging\n debugLogger.warn('OPENAI_UNHANDLED_ERROR', {\n status: response.status,\n error: errorMessage,\n })\n } catch (parseError) {\n // If we can't parse the error, fall back to generic retry\n debugLogger.warn('OPENAI_PARSE_ERROR', { status: response.status })\n }\n\n const delayMs = getRetryDelay(attempt)\n setStreamingState({\n phase: 'retrying',\n retryCount: attempt + 1,\n maxRetries: maxAttempts,\n errorName: `HTTP ${response.status}`,\n retryDelayMs: delayMs,\n })\n debugLogger.warn('API_RETRY', {\n status: response.status,\n delayMs,\n attempt: attempt + 1,\n maxAttempts,\n })\n try {\n await abortableDelay(delayMs, signal)\n } catch (error) {\n // If aborted during delay, throw the error to stop retrying\n if (error.message === 'Request was aborted') {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal, // \uD83D\uDD27 Pass AbortSignal to recursive call\n )\n }\n\n const responseData = (await response.json()) as OpenAI.ChatCompletion\n return responseData\n } catch (error) {\n // \uD83D\uDD27 CRITICAL FIX: Check abort signal BEFORE showing retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n\n if (attempt < maxAttempts) {\n // \uD83D\uDD27 Double-check abort status to avoid showing misleading retry message\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n\n const delayMs = getRetryDelay(attempt)\n setStreamingState({\n phase: 'retrying',\n retryCount: attempt + 1,\n maxRetries: maxAttempts,\n errorName:\n error instanceof Error ? error.message.slice(0, 30) : 'network error',\n retryDelayMs: delayMs,\n })\n debugLogger.warn('API_RETRY', {\n error: 'network_error',\n delayMs,\n attempt: attempt + 1,\n maxAttempts,\n })\n try {\n await abortableDelay(delayMs, signal)\n } catch (error) {\n // If aborted during delay, throw the error to stop retrying\n if (error.message === 'Request was aborted') {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n return getCompletionWithProfile(\n modelProfile,\n opts,\n attempt + 1,\n maxAttempts,\n signal, // \uD83D\uDD27 Pass AbortSignal to recursive call\n )\n }\n // Wrap network errors with user-friendly message\n throw new UserFriendlyError(error, {\n operation: 'API request',\n model: opts.model,\n endpoint: modelProfile.baseURL,\n })\n }\n}\n\n/**\n * Idle timeout for SSE stream reads (ms).\n * If no data arrives for this duration after the connection is open,\n * the stream is considered stalled and reading stops.\n * This protects against backends that accept connections but never send data.\n */\nconst STREAM_IDLE_TIMEOUT_MS = parseInt(\n process.env.STREAM_IDLE_TIMEOUT_MS || String(120 * 1000),\n 10,\n)\n\nexport function createStreamProcessor(\n stream: any,\n signal?: AbortSignal,\n): AsyncGenerator<OpenAI.ChatCompletionChunk, void, unknown> {\n if (!stream) {\n throw new Error('Stream is null or undefined')\n }\n\n return (async function* () {\n const reader = stream.getReader()\n const decoder = new TextDecoder('utf-8')\n let buffer = ''\n\n try {\n while (true) {\n // Check for cancellation before attempting to read\n if (signal?.aborted) {\n break\n }\n\n let readResult\n try {\n // Race reader.read() against an idle timeout to detect stalled streams.\n // Without this, a backend that sends 200 OK but never sends SSE data\n // would hang reader.read() indefinitely.\n readResult = await Promise.race([\n reader.read(),\n new Promise<never>((_, reject) => {\n const timer = setTimeout(\n () =>\n reject(\n new Error(\n `Stream idle timeout: no data received for ${STREAM_IDLE_TIMEOUT_MS / 1000}s`,\n ),\n ),\n STREAM_IDLE_TIMEOUT_MS,\n )\n // If the signal aborts, clear the timer to avoid leaking\n signal?.addEventListener('abort', () => clearTimeout(timer), {\n once: true,\n })\n }),\n ])\n } catch (e) {\n // If signal is aborted, this is user cancellation - exit silently\n if (signal?.aborted) {\n break\n }\n logError(e)\n break\n }\n\n const { done, value } = readResult\n if (done) {\n break\n }\n\n const chunk = decoder.decode(value, { stream: true })\n buffer += chunk\n\n let lineEnd = buffer.indexOf('\\n')\n while (lineEnd !== -1) {\n const line = buffer.substring(0, lineEnd).trim()\n buffer = buffer.substring(lineEnd + 1)\n\n if (line === 'data: [DONE]') {\n continue\n }\n\n if (line.startsWith('data: ')) {\n const data = line.slice(6).trim()\n if (!data) continue\n\n try {\n const parsed = JSON.parse(data) as OpenAI.ChatCompletionChunk\n yield parsed\n } catch (e) {\n debugLogger.warn('STREAM_PARSE_ERROR', {\n data: data.substring(0, 100),\n error: String(e),\n })\n }\n }\n\n lineEnd = buffer.indexOf('\\n')\n }\n }\n\n // Process any remaining data in the buffer\n if (buffer.trim()) {\n const lines = buffer.trim().split('\\n')\n for (const line of lines) {\n if (line.startsWith('data: ') && line !== 'data: [DONE]') {\n const data = line.slice(6).trim()\n if (!data) continue\n\n try {\n const parsed = JSON.parse(data) as OpenAI.ChatCompletionChunk\n yield parsed\n } catch (e) {\n debugLogger.warn('STREAM_PARSE_ERROR', {\n data: data.substring(0, 100),\n error: String(e),\n final: true,\n })\n }\n }\n }\n }\n } catch (e) {\n logError(e)\n } finally {\n try {\n reader.releaseLock()\n } catch (e) {\n // Silent - reader lock release failure is not critical\n }\n }\n })()\n}\n\nexport function streamCompletion(\n stream: any,\n signal?: AbortSignal,\n): AsyncGenerator<OpenAI.ChatCompletionChunk, void, unknown> {\n return createStreamProcessor(stream, signal)\n}\n\n/**\n * Call GPT-5 Responses API with proper parameter handling\n */\nexport async function callGPT5ResponsesAPI(\n modelProfile: ModelProfile,\n opts: any, // Using 'any' for Responses API params which differ from ChatCompletionCreateParams\n signal?: AbortSignal,\n): Promise<any> {\n const baseURL = modelProfile?.baseURL || 'https://api.openai.com/v1'\n const apiKey = await resolveModelApiKey(modelProfile)\n const proxy = getGlobalConfig().proxy\n ? new ProxyAgent(getGlobalConfig().proxy)\n : undefined\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n }\n\n // \uD83D\uDD25 Enhanced Responses API Parameter Mapping for GPT-5\n const responsesParams: any = {\n model: opts.model,\n input: opts.messages, // Responses API uses 'input' instead of 'messages'\n }\n\n // \uD83D\uDD27 GPT-5 Token Configuration - Responses API uses max_output_tokens\n if (opts.max_completion_tokens) {\n responsesParams.max_output_tokens = opts.max_completion_tokens\n } else if (opts.max_tokens) {\n responsesParams.max_output_tokens = opts.max_tokens\n }\n\n // \uD83D\uDD27 GPT-5 Temperature Handling (only 1 or undefined)\n if (opts.temperature === 1) {\n responsesParams.temperature = 1\n }\n // Note: Do not pass temperature if it's not 1, GPT-5 will use default\n\n // \uD83D\uDD27 GPT-5 Reasoning Configuration\n const reasoningEffort = opts.reasoning_effort || 'medium'\n responsesParams.reasoning = {\n effort: reasoningEffort,\n // \uD83D\uDE80 Enable reasoning summaries for transparency in coding tasks\n generate_summary: true,\n }\n\n // \uD83D\uDD27 GPT-5 Tools Support\n if (opts.tools && opts.tools.length > 0) {\n responsesParams.tools = opts.tools\n\n // \uD83D\uDE80 GPT-5 Tool Choice Configuration\n if (opts.tool_choice) {\n responsesParams.tool_choice = opts.tool_choice\n }\n }\n\n // \uD83D\uDD27 GPT-5 System Instructions (separate from messages)\n const systemMessages = opts.messages.filter(msg => msg.role === 'system')\n const nonSystemMessages = opts.messages.filter(msg => msg.role !== 'system')\n\n if (systemMessages.length > 0) {\n responsesParams.instructions = systemMessages\n .map(msg => msg.content)\n .join('\\n\\n')\n responsesParams.input = nonSystemMessages\n }\n\n // Handle verbosity (if supported) - optimized for coding tasks\n const features = getModelFeatures(opts.model)\n if (features.supportsVerbosityControl) {\n // High verbosity for coding tasks to get detailed explanations and structured code\n // Based on GPT-5 best practices for agent-like coding environments\n responsesParams.text = {\n verbosity: 'high',\n }\n }\n\n // Apply GPT-5 coding optimizations\n if (opts.model.startsWith('gpt-5')) {\n // Set reasoning effort based on task complexity\n if (!responsesParams.reasoning) {\n responsesParams.reasoning = {\n effort: 'medium', // Balanced for most coding tasks\n }\n }\n\n // No default instructions fallback \u2014 let the model use its default behavior\n // if no system messages provided. Injecting generic instructions could override\n // the real system prompt set by the caller.\n }\n\n try {\n const response = await fetch(`${baseURL}/responses`, {\n method: 'POST',\n headers,\n body: JSON.stringify(responsesParams),\n dispatcher: proxy,\n signal: signal,\n })\n\n if (!response.ok) {\n throw new Error(\n `GPT-5 Responses API error: ${response.status} ${response.statusText}`,\n )\n }\n\n const responseData = await response.json()\n\n // Convert Responses API response back to Chat Completion format for compatibility\n return convertResponsesAPIToChatCompletion(responseData)\n } catch (error) {\n if (signal?.aborted) {\n throw new Error('Request cancelled by user')\n }\n throw error\n }\n}\n\n/**\n * Convert Responses API response to Chat Completion format for compatibility\n * \uD83D\uDD25 Enhanced for GPT-5 with reasoning summary support\n */\nfunction convertResponsesAPIToChatCompletion(responsesData: any): any {\n // Extract content from Responses API format\n let outputText = responsesData.output_text || ''\n const usage = responsesData.usage || {}\n\n // \uD83D\uDE80 GPT-5 Reasoning Summary Integration\n // If reasoning summary is available, prepend it to the output for transparency\n if (responsesData.output && Array.isArray(responsesData.output)) {\n const reasoningItems = responsesData.output.filter(\n item => item.type === 'reasoning' && item.summary,\n )\n const messageItems = responsesData.output.filter(\n item => item.type === 'message',\n )\n\n if (reasoningItems.length > 0 && messageItems.length > 0) {\n const reasoningSummary = reasoningItems\n .map(item => item.summary?.map(s => s.text).join('\\n'))\n .filter(Boolean)\n .join('\\n\\n')\n\n const mainContent = messageItems\n .map(item => item.content?.map(c => c.text).join('\\n'))\n .filter(Boolean)\n .join('\\n\\n')\n\n if (reasoningSummary) {\n outputText = `**\uD83E\uDDE0 Reasoning Process:**\\n${reasoningSummary}\\n\\n**\uD83D\uDCDD Response:**\\n${mainContent}`\n } else {\n outputText = mainContent\n }\n }\n }\n\n return {\n id: responsesData.id || `chatcmpl-${Date.now()}`,\n object: 'chat.completion',\n created: Math.floor(Date.now() / 1000),\n model: responsesData.model || '',\n choices: [\n {\n index: 0,\n message: {\n role: 'assistant',\n content: outputText,\n // \uD83D\uDE80 Include reasoning metadata if available\n ...(responsesData.reasoning && {\n reasoning: {\n effort: responsesData.reasoning.effort,\n summary: responsesData.reasoning.summary,\n },\n }),\n },\n finish_reason: responsesData.status === 'completed' ? 'stop' : 'length',\n },\n ],\n usage: {\n prompt_tokens: usage.input_tokens || 0,\n completion_tokens: usage.output_tokens || 0,\n total_tokens: (usage.input_tokens || 0) + (usage.output_tokens || 0),\n // \uD83D\uDD27 GPT-5 Enhanced Usage Details\n prompt_tokens_details: {\n cached_tokens: usage.input_tokens_details?.cached_tokens || 0,\n },\n completion_tokens_details: {\n reasoning_tokens: usage.output_tokens_details?.reasoning_tokens || 0,\n },\n },\n }\n}\n\n/**\n * Enhanced getCompletionWithProfile that supports GPT-5 Responses API\n * \uD83D\uDD25 Optimized for both official OpenAI and third-party GPT-5 providers\n */\nasync function getGPT5CompletionWithProfile(\n modelProfile: ModelProfile,\n opts: OpenAI.ChatCompletionCreateParams,\n attempt: number = 0,\n maxAttempts: number = 5,\n signal?: AbortSignal,\n): Promise<OpenAI.ChatCompletion | AsyncIterable<OpenAI.ChatCompletionChunk>> {\n const features = getModelFeatures(opts.model)\n const isOfficialOpenAI =\n !modelProfile.baseURL || modelProfile.baseURL.includes('api.openai.com')\n\n // \uD83D\uDE80 Try Responses API for official OpenAI non-streaming requests\n if (features.supportsResponsesAPI && !opts.stream && isOfficialOpenAI) {\n try {\n debugLogger.api('ATTEMPTING_GPT5_RESPONSES_API', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n provider: modelProfile.provider,\n stream: opts.stream,\n requestId: getCurrentRequest()?.id,\n })\n\n const result = await callGPT5ResponsesAPI(modelProfile, opts, signal)\n\n debugLogger.api('GPT5_RESPONSES_API_SUCCESS', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n requestId: getCurrentRequest()?.id,\n })\n\n return result\n } catch (error) {\n debugLogger.api('GPT5_RESPONSES_API_FALLBACK', {\n model: opts.model,\n error: error.message,\n baseURL: modelProfile.baseURL || 'official',\n requestId: getCurrentRequest()?.id,\n })\n\n debugLogger.warn('GPT5_FALLBACK', {\n reason: 'responses_api_failed',\n error: error.message,\n })\n // Fall through to Chat Completions API\n }\n }\n\n // \uD83C\uDF10 Handle third-party GPT-5 providers with enhanced compatibility\n else if (!isOfficialOpenAI) {\n debugLogger.api('GPT5_THIRD_PARTY_PROVIDER', {\n model: opts.model,\n baseURL: modelProfile.baseURL,\n provider: modelProfile.provider,\n supportsResponsesAPI: features.supportsResponsesAPI,\n requestId: getCurrentRequest()?.id,\n })\n\n // \uD83D\uDD27 Apply enhanced parameter optimization for third-party providers\n debugLogger.info('GPT5_THIRD_PARTY', {\n provider: modelProfile.provider,\n baseURL: modelProfile.baseURL,\n })\n\n // Some third-party providers may need additional parameter adjustments\n if (modelProfile.provider === 'azure') {\n // Azure OpenAI specific adjustments\n delete opts.reasoning_effort // Azure may not support this yet\n } else if (modelProfile.provider === 'custom-openai') {\n // Generic OpenAI-compatible provider optimizations\n debugLogger.info('GPT5_CUSTOM_OPTIMIZATIONS', {\n provider: 'custom-openai',\n })\n }\n }\n\n // \uD83D\uDCE1 Handle streaming requests (Responses API doesn't support streaming yet)\n else if (opts.stream) {\n debugLogger.api('GPT5_STREAMING_MODE', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n reason: 'responses_api_no_streaming',\n requestId: getCurrentRequest()?.id,\n })\n\n debugLogger.info('GPT5_STREAMING', { reason: 'responses_api_no_streaming' })\n }\n\n // \uD83D\uDD27 Enhanced Chat Completions fallback with GPT-5 optimizations\n debugLogger.api('USING_CHAT_COMPLETIONS_FOR_GPT5', {\n model: opts.model,\n baseURL: modelProfile.baseURL || 'official',\n provider: modelProfile.provider,\n reason: isOfficialOpenAI ? 'streaming_or_fallback' : 'third_party_provider',\n requestId: getCurrentRequest()?.id,\n })\n\n return await getCompletionWithProfile(\n modelProfile,\n opts,\n attempt,\n maxAttempts,\n signal,\n )\n}\n\n/**\n * Fetch available models from custom OpenAI-compatible API\n */\nexport async function fetchCustomModels(\n baseURL: string,\n apiKey: string,\n): Promise<any[]> {\n try {\n // Check if baseURL already contains version number (e.g., v1, v2, etc.)\n const hasVersionNumber = /\\/v\\d+/.test(baseURL)\n const cleanBaseURL = baseURL.replace(/\\/+$/, '')\n const modelsURL = hasVersionNumber\n ? `${cleanBaseURL}/models`\n : `${cleanBaseURL}/v1/models`\n\n const response = await fetch(modelsURL, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n },\n signal: AbortSignal.timeout(30_000),\n })\n\n if (!response.ok) {\n // Provide user-friendly error messages based on status code\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(\n 'API key does not have permission to access models. Please check your API key permissions.',\n )\n } else if (response.status === 404) {\n throw new Error(\n 'API endpoint not found. Please check if the base URL is correct and supports the /models endpoint.',\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(\n `Unable to connect to API (${response.status}). Please check your base URL, API key, and internet connection.`,\n )\n }\n }\n\n const data = await response.json()\n\n // Type guards for different API response formats\n const hasDataArray = (obj: unknown): obj is { data: unknown[] } => {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n 'data' in obj &&\n Array.isArray((obj as any).data)\n )\n }\n\n const hasModelsArray = (obj: unknown): obj is { models: unknown[] } => {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n 'models' in obj &&\n Array.isArray((obj as any).models)\n )\n }\n\n // Validate response format and extract models array\n let models = []\n\n if (hasDataArray(data)) {\n // Standard OpenAI format: { data: [...] }\n models = data.data\n } else if (Array.isArray(data)) {\n // Direct array format\n models = data\n } else if (hasModelsArray(data)) {\n // Alternative format: { models: [...] }\n models = data.models\n } else {\n throw new Error(\n 'API returned unexpected response format. Expected an array of models or an object with a \"data\" or \"models\" array.',\n )\n }\n\n // Ensure we have an array and validate it contains model objects\n if (!Array.isArray(models)) {\n throw new Error('API response format error: models data is not an array.')\n }\n\n return models\n } catch (error) {\n // If it's already our custom error, pass it through\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 // For network errors or other issues\n logError(error)\n\n // Check if it's a network error\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 custom API. Please check your configuration and try again.',\n )\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["ModelErrorType", "response", "error"]
|
|
7
7
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { existsSync, readFileSync, statSync } from "fs";
|
|
2
2
|
import { homedir } from "os";
|
|
3
|
-
import { join, resolve } from "path";
|
|
3
|
+
import { join, resolve, relative, isAbsolute } from "path";
|
|
4
4
|
import { glob as globLib } from "glob";
|
|
5
5
|
import { getCwd } from "../../utils/state.js";
|
|
6
6
|
import {
|
|
7
7
|
setSessionPlugins,
|
|
8
8
|
getSessionPlugins
|
|
9
9
|
} from "../../utils/session/sessionPlugins.js";
|
|
10
|
-
import {
|
|
10
|
+
import { MinimalPluginManifestSchema } from "./pluginValidation.js";
|
|
11
11
|
function expandHome(input) {
|
|
12
12
|
const trimmed = input.trim();
|
|
13
13
|
if (trimmed === "~") return homedir();
|
|
@@ -90,6 +90,8 @@ function resolveManifestPaths(rootDir, value) {
|
|
|
90
90
|
for (const item of list) {
|
|
91
91
|
if (typeof item !== "string") continue;
|
|
92
92
|
const abs = resolve(rootDir, item);
|
|
93
|
+
const rel = relative(rootDir, abs);
|
|
94
|
+
if (rel.startsWith("..") || isAbsolute(rel)) continue;
|
|
93
95
|
dirs.push(...listIfDir(abs));
|
|
94
96
|
files.push(...fileIfExists(abs));
|
|
95
97
|
}
|
|
@@ -117,7 +119,7 @@ function loadPluginFromDir(rootDir) {
|
|
|
117
119
|
} catch (err) {
|
|
118
120
|
throw new Error(`Invalid JSON in ${manifestPath}: ${String(err)}`);
|
|
119
121
|
}
|
|
120
|
-
const parsed =
|
|
122
|
+
const parsed = MinimalPluginManifestSchema.safeParse(manifestJson);
|
|
121
123
|
if (!parsed.success) {
|
|
122
124
|
throw new Error(
|
|
123
125
|
`Invalid plugin manifest schema in ${manifestPath}: ${parsed.error.message}`
|
|
@@ -208,9 +210,13 @@ async function loadDefaultPlugins() {
|
|
|
208
210
|
const home = homedir();
|
|
209
211
|
const cwd = getCwd();
|
|
210
212
|
const pluginDirs = [
|
|
211
|
-
//
|
|
213
|
+
// CC legacy fallback (lowest priority)
|
|
214
|
+
join(home, ".claude", "plugins"),
|
|
215
|
+
// Project CC legacy fallback
|
|
216
|
+
join(cwd, ".claude", "plugins"),
|
|
217
|
+
// User minto (higher priority)
|
|
212
218
|
join(home, ".minto", "plugins"),
|
|
213
|
-
// Project
|
|
219
|
+
// Project minto (highest priority)
|
|
214
220
|
join(cwd, ".minto", "plugins")
|
|
215
221
|
].filter((dir) => existsSync(dir));
|
|
216
222
|
return configureSessionPlugins({ pluginDirs, baseDir: cwd });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/services/plugins/pluginRuntime.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Plugin Runtime\n *\n * Handles loading and managing plugins at runtime.\n * Compatible with Claude Code CLI plugin specification.\n */\n\nimport { existsSync, readFileSync, statSync } from 'fs'\nimport { homedir } from 'os'\nimport { join, resolve } from 'path'\nimport { z } from 'zod'\nimport { glob as globLib } from 'glob'\nimport { getCwd } from '@utils/state'\nimport {\n setSessionPlugins,\n getSessionPlugins,\n} from '@utils/session/sessionPlugins'\nimport type { SessionPlugin } from '@minto-types/plugin'\nimport {
|
|
5
|
-
"mappings": "AAOA,SAAS,YAAY,cAAc,gBAAgB;AACnD,SAAS,eAAe;AACxB,SAAS,MAAM,
|
|
4
|
+
"sourcesContent": ["/**\n * Plugin Runtime\n *\n * Handles loading and managing plugins at runtime.\n * Compatible with Claude Code CLI plugin specification.\n */\n\nimport { existsSync, readFileSync, statSync } from 'fs'\nimport { homedir } from 'os'\nimport { join, resolve, relative, isAbsolute } from 'path'\nimport { z } from 'zod'\nimport { glob as globLib } from 'glob'\nimport { getCwd } from '@utils/state'\nimport {\n setSessionPlugins,\n getSessionPlugins,\n} from '@utils/session/sessionPlugins'\nimport type { SessionPlugin } from '@minto-types/plugin'\nimport { MinimalPluginManifestSchema } from './pluginValidation'\n\n/**\n * Expand ~ to home directory\n */\nfunction expandHome(input: string): string {\n const trimmed = input.trim()\n if (trimmed === '~') return homedir()\n if (trimmed.startsWith('~/') || trimmed.startsWith('~\\\\')) {\n return join(homedir(), trimmed.slice(2))\n }\n return trimmed\n}\n\n/**\n * Check if a string looks like a glob pattern\n */\nfunction isLikelyGlob(value: string): boolean {\n return /[*?[\\]]/.test(value)\n}\n\n/**\n * Expand plugin directory inputs (handles globs and ~ expansion)\n */\nasync function expandPluginDirInputs(\n pluginDirs: string[],\n baseDir: string,\n): Promise<string[]> {\n const out: string[] = []\n\n for (const raw of pluginDirs) {\n const trimmed = String(raw ?? '').trim()\n if (!trimmed) continue\n\n const expanded = expandHome(trimmed)\n const abs = resolve(baseDir, expanded)\n\n if (isLikelyGlob(trimmed) || isLikelyGlob(expanded)) {\n const patternsToTry =\n expanded !== trimmed ? [expanded, trimmed] : [trimmed]\n let matched = false\n\n for (const pattern of patternsToTry) {\n try {\n const matches = await globLib(pattern, {\n cwd: baseDir,\n absolute: true,\n nodir: false,\n nocase: process.platform === 'win32',\n })\n\n const dirs = matches.filter(match => {\n try {\n return existsSync(match) && statSync(match).isDirectory()\n } catch {\n return false\n }\n })\n\n if (dirs.length > 0) {\n out.push(...dirs)\n matched = true\n break\n }\n } catch {\n // Ignore glob errors\n }\n }\n\n if (matched) continue\n }\n\n out.push(abs)\n }\n\n // Remove duplicates\n const seen = new Set<string>()\n const unique: string[] = []\n for (const item of out) {\n if (seen.has(item)) continue\n seen.add(item)\n unique.push(item)\n }\n\n return unique\n}\n\n/**\n * List directory if it exists and is a directory\n */\nfunction listIfDir(path: string): string[] {\n try {\n if (!existsSync(path)) return []\n if (!statSync(path).isDirectory()) return []\n return [path]\n } catch {\n return []\n }\n}\n\n/**\n * Return file path if it exists and is a file\n */\nfunction fileIfExists(path: string): string[] {\n try {\n if (!existsSync(path)) return []\n if (!statSync(path).isFile()) return []\n return [path]\n } catch {\n return []\n }\n}\n\n/**\n * Resolve manifest paths (handles string or array values)\n */\nfunction resolveManifestPaths(\n rootDir: string,\n value: unknown,\n): { dirs: string[]; files: string[] } {\n const dirs: string[] = []\n const files: string[] = []\n const list = Array.isArray(value) ? value : value ? [value] : []\n\n for (const item of list) {\n if (typeof item !== 'string') continue\n const abs = resolve(rootDir, item)\n // Boundary check: skip paths that escape the plugin root\n const rel = relative(rootDir, abs)\n if (rel.startsWith('..') || isAbsolute(rel)) continue\n dirs.push(...listIfDir(abs))\n files.push(...fileIfExists(abs))\n }\n\n return { dirs, files }\n}\n\n/**\n * Load a plugin from a directory\n *\n * Uses .minto-plugin directory structure or root plugin.json.\n */\nfunction loadPluginFromDir(rootDir: string): SessionPlugin {\n // Check for manifest in order of preference: .minto-plugin > .claude-plugin > root\n const mintoManifestPath = join(rootDir, '.minto-plugin', 'plugin.json')\n const claudeManifestPath = join(rootDir, '.claude-plugin', 'plugin.json')\n const rootManifestPath = join(rootDir, 'plugin.json')\n\n const manifestPath = existsSync(mintoManifestPath)\n ? mintoManifestPath\n : existsSync(claudeManifestPath)\n ? claudeManifestPath\n : existsSync(rootManifestPath)\n ? rootManifestPath\n : null\n\n if (!manifestPath) {\n throw new Error(\n `Plugin manifest not found (expected .minto-plugin/plugin.json or plugin.json)`,\n )\n }\n\n // Read manifest\n let manifestRaw: string\n try {\n manifestRaw = readFileSync(manifestPath, 'utf8')\n } catch (err) {\n throw new Error(`Failed to read ${manifestPath}: ${String(err)}`)\n }\n\n // Parse JSON\n let manifestJson: unknown\n try {\n manifestJson = JSON.parse(manifestRaw)\n } catch (err) {\n throw new Error(`Invalid JSON in ${manifestPath}: ${String(err)}`)\n }\n\n // Validate manifest\n const parsed = MinimalPluginManifestSchema.safeParse(manifestJson)\n if (!parsed.success) {\n throw new Error(\n `Invalid plugin manifest schema in ${manifestPath}: ${parsed.error.message}`,\n )\n }\n\n const name = parsed.data.name\n const manifestData = parsed.data as Record<string, unknown>\n\n // Resolve commands\n const manifestCommands = resolveManifestPaths(rootDir, manifestData.commands)\n const commandsDirs = [\n ...listIfDir(join(rootDir, 'commands')),\n ...manifestCommands.dirs,\n ...manifestCommands.files,\n ]\n\n // Resolve skills\n const skillsDirs = [\n ...listIfDir(join(rootDir, 'skills')),\n ...resolveManifestPaths(rootDir, manifestData.skills).dirs,\n ]\n\n // Resolve agents\n const manifestAgents = resolveManifestPaths(rootDir, manifestData.agents)\n const agentsDirs = [\n ...listIfDir(join(rootDir, 'agents')),\n ...manifestAgents.dirs,\n ...manifestAgents.files,\n ]\n\n // Resolve output styles\n const manifestOutputStyles = resolveManifestPaths(\n rootDir,\n manifestData.outputStyles,\n )\n const outputStylesDirs = [\n ...listIfDir(join(rootDir, 'output-styles')),\n ...manifestOutputStyles.dirs,\n ...manifestOutputStyles.files,\n ]\n\n // Resolve hooks\n const standardHook = fileIfExists(join(rootDir, 'hooks', 'hooks.json'))\n const hookFromManifest = resolveManifestPaths(\n rootDir,\n manifestData.hooks,\n ).files\n const hooksFiles = [...standardHook, ...hookFromManifest]\n\n // Resolve MCP config files\n const mcpConfigFiles = [\n ...fileIfExists(join(rootDir, '.mcp.json')),\n ...fileIfExists(join(rootDir, '.mcp.jsonc')),\n ...resolveManifestPaths(rootDir, manifestData.mcpServers).files,\n ]\n\n // Resolve LSP config files\n const lspConfigFiles = [\n ...fileIfExists(join(rootDir, '.lsp.json')),\n ...resolveManifestPaths(rootDir, manifestData.lspServers).files,\n ]\n\n return {\n name,\n rootDir,\n manifestPath,\n manifest: parsed.data,\n commandsDirs,\n skillsDirs,\n agentsDirs,\n hooksFiles,\n outputStylesDirs,\n mcpConfigFiles,\n lspConfigFiles,\n }\n}\n\n/**\n * Configure session plugins\n *\n * Loads plugins from the specified directories and sets them\n * as the current session plugins.\n */\nexport async function configureSessionPlugins(args: {\n pluginDirs: string[]\n baseDir?: string\n}): Promise<{ plugins: SessionPlugin[]; errors: string[] }> {\n const baseDir = args.baseDir ?? getCwd()\n const dirs = await expandPluginDirInputs(args.pluginDirs ?? [], baseDir)\n\n const plugins: SessionPlugin[] = []\n const errors: string[] = []\n\n for (const dir of dirs) {\n try {\n plugins.push(loadPluginFromDir(dir))\n } catch (err) {\n errors.push(err instanceof Error ? err.message : String(err))\n }\n }\n\n // Set the plugins\n setSessionPlugins(plugins)\n\n // Reload dependent services\n try {\n // Reload custom commands\n const { reloadCustomCommands } = await import('@services/customCommands')\n reloadCustomCommands()\n\n // Clear command cache\n const { getCommands } = await import('@commands')\n ;(getCommands as any).cache?.clear?.()\n\n // Clear MCP tools cache\n const { getClients, getMCPTools } = await import('@services/mcpClient')\n ;(getClients as any).cache?.clear?.()\n ;(getMCPTools as any).cache?.clear?.()\n } catch {\n // Ignore errors during reload - services may not be available\n }\n\n return { plugins, errors }\n}\n\n/**\n * Load plugins from default locations\n *\n * Searches for plugins in:\n * 1. User plugins directory (~/.minto/plugins)\n * 2. Project plugins directory (.minto/plugins)\n */\nexport async function loadDefaultPlugins(): Promise<{\n plugins: SessionPlugin[]\n errors: string[]\n}> {\n const home = homedir()\n const cwd = getCwd()\n\n const pluginDirs = [\n // CC legacy fallback (lowest priority)\n join(home, '.claude', 'plugins'),\n // Project CC legacy fallback\n join(cwd, '.claude', 'plugins'),\n // User minto (higher priority)\n join(home, '.minto', 'plugins'),\n // Project minto (highest priority)\n join(cwd, '.minto', 'plugins'),\n ].filter(dir => existsSync(dir))\n\n return configureSessionPlugins({ pluginDirs, baseDir: cwd })\n}\n\n/**\n * Get all currently loaded plugins\n */\nexport function getLoadedPlugins(): SessionPlugin[] {\n return getSessionPlugins()\n}\n\n/**\n * Check if any plugins are loaded\n */\nexport function hasLoadedPlugins(): boolean {\n return getSessionPlugins().length > 0\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -48,9 +48,10 @@ const LspServersConfigSchema = z.union([
|
|
|
48
48
|
})
|
|
49
49
|
)
|
|
50
50
|
]);
|
|
51
|
-
const
|
|
51
|
+
const MinimalPluginManifestSchema = z.object({
|
|
52
52
|
name: z.string().min(1)
|
|
53
53
|
}).passthrough();
|
|
54
|
+
const PluginManifestSchema = MinimalPluginManifestSchema;
|
|
54
55
|
const FullPluginManifestSchema = z.object({
|
|
55
56
|
// Required field
|
|
56
57
|
name: z.string().min(1).regex(
|
|
@@ -87,7 +88,7 @@ const FullPluginManifestSchema = z.object({
|
|
|
87
88
|
dependencies: z.record(z.string()).optional()
|
|
88
89
|
});
|
|
89
90
|
function validatePluginManifest(manifest) {
|
|
90
|
-
const result =
|
|
91
|
+
const result = MinimalPluginManifestSchema.safeParse(manifest);
|
|
91
92
|
if (result.success) {
|
|
92
93
|
return { success: true, data: result.data };
|
|
93
94
|
}
|
|
@@ -215,6 +216,7 @@ function isStrictlyValidManifest(data) {
|
|
|
215
216
|
}
|
|
216
217
|
export {
|
|
217
218
|
FullPluginManifestSchema,
|
|
219
|
+
MinimalPluginManifestSchema,
|
|
218
220
|
PluginManifestSchema,
|
|
219
221
|
isStrictlyValidManifest,
|
|
220
222
|
isValidManifest,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/services/plugins/pluginValidation.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Plugin Validation\n *\n * Validates plugin manifests and configurations.\n * Compatible with Claude Code CLI plugin specification.\n */\n\nimport { z } from 'zod'\nimport { existsSync, readFileSync, statSync } from 'fs'\nimport { join, resolve } from 'path'\n\n/**\n * Author schema (can be string or object)\n */\nconst AuthorSchema = z.union([\n z.string(),\n z.object({\n name: z.string().optional(),\n email: z.string().email().optional(),\n url: z.string().url().optional(),\n }),\n])\n\n/**\n * Hooks configuration schema\n */\nconst HooksConfigSchema = z.union([\n z.string(),\n z.array(z.string()),\n z.record(\n z.object({\n command: z.string().optional(),\n script: z.string().optional(),\n timeout: z.number().optional(),\n blocking: z.boolean().optional(),\n }),\n ),\n])\n\n/**\n * MCP Servers configuration schema\n */\nconst McpServersConfigSchema = z.union([\n z.string(),\n z.array(z.string()),\n z.record(\n z.object({\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string()).optional(),\n type: z.enum(['stdio', 'http', 'sse']).optional(),\n url: z.string().optional(),\n headers: z.record(z.string()).optional(),\n timeout: z.number().optional(),\n }),\n ),\n])\n\n/**\n * LSP Servers configuration schema (Claude Code CLI specific)\n */\nconst LspServersConfigSchema = z.union([\n z.string(),\n z.array(z.string()),\n z.record(\n z.object({\n command: z.string(),\n args: z.array(z.string()).optional(),\n rootPath: z.string().optional(),\n filePatterns: z.array(z.string()).optional(),\n }),\n ),\n])\n\n/**\n * Minimal plugin manifest schema for loading\n * More permissive than full schema to allow partial manifests\n */\nexport const PluginManifestSchema = z\n .object({\n name: z.string().min(1),\n })\n .passthrough()\n\nexport type PluginManifestBasic = z.infer<typeof PluginManifestSchema>\n\n/**\n * Full Claude Code CLI plugin manifest schema\n * Used for strict validation\n */\nexport const FullPluginManifestSchema = z.object({\n // Required field\n name: z\n .string()\n .min(1)\n .regex(\n /^[a-z0-9-]+$/,\n 'Plugin name must be lowercase alphanumeric with hyphens',\n ),\n\n // Metadata fields (Claude Code CLI specification)\n version: z\n .string()\n .regex(/^\\d+\\.\\d+\\.\\d+$/, 'Version must follow semver format (e.g., 1.0.0)')\n .optional(),\n description: z.string().optional(),\n author: AuthorSchema.optional(),\n homepage: z.string().url().optional(),\n repository: z.string().optional(), // Can be URL or \"owner/repo\"\n license: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n\n // Component path fields\n commands: z.union([z.string(), z.array(z.string())]).optional(),\n agents: z.union([z.string(), z.array(z.string())]).optional(),\n skills: z.union([z.string(), z.array(z.string())]).optional(),\n hooks: HooksConfigSchema.optional(),\n mcpServers: McpServersConfigSchema.optional(),\n outputStyles: z.union([z.string(), z.array(z.string())]).optional(),\n lspServers: LspServersConfigSchema.optional(), // Claude Code CLI specific\n\n // Engine requirements\n engines: z\n .object({\n minto: z.string().optional(),\n 'claude-code': z.string().optional(),\n node: z.string().optional(),\n })\n .optional(),\n\n // Plugin-specific configuration schema\n configSchema: z.record(z.any()).optional(),\n\n // Dependencies\n dependencies: z.record(z.string()).optional(),\n})\n\nexport type FullPluginManifest = z.infer<typeof FullPluginManifestSchema>\n\n/**\n * Validation result type\n */\nexport interface ValidationResult {\n isValid: boolean\n errors: string[]\n warnings: string[]\n}\n\n/**\n * Validate a plugin manifest (permissive)\n */\nexport function validatePluginManifest(\n manifest: unknown,\n):\n | { success: true; data: PluginManifestBasic }\n | { success: false; error: z.ZodError } {\n const result = PluginManifestSchema.safeParse(manifest)\n if (result.success) {\n return { success: true, data: result.data }\n }\n return { success: false, error: result.error }\n}\n\n/**\n * Validate a plugin manifest (strict - full Claude Code CLI specification)\n */\nexport function validatePluginManifestStrict(\n manifest: unknown,\n):\n | { success: true; data: FullPluginManifest }\n | { success: false; error: z.ZodError } {\n const result = FullPluginManifestSchema.safeParse(manifest)\n if (result.success) {\n return { success: true, data: result.data }\n }\n return { success: false, error: result.error }\n}\n\n/**\n * Validate a plugin directory structure\n */\nexport function validatePluginDirectory(rootDir: string): ValidationResult {\n const errors: string[] = []\n const warnings: string[] = []\n\n // Resolve path\n const resolvedPath = resolve(rootDir)\n\n // Check directory exists\n if (!existsSync(resolvedPath)) {\n errors.push(`Directory does not exist: ${resolvedPath}`)\n return { isValid: false, errors, warnings }\n }\n\n // Check it's a directory\n try {\n if (!statSync(resolvedPath).isDirectory()) {\n errors.push(`Path is not a directory: ${resolvedPath}`)\n return { isValid: false, errors, warnings }\n }\n } catch {\n errors.push(`Cannot access path: ${resolvedPath}`)\n return { isValid: false, errors, warnings }\n }\n\n // Check for manifest file (.minto-plugin, .claude-plugin, or root)\n const mintoManifest = join(resolvedPath, '.minto-plugin', 'plugin.json')\n const claudeManifest = join(resolvedPath, '.claude-plugin', 'plugin.json')\n const rootManifest = join(resolvedPath, 'plugin.json')\n\n const hasMintoManifest = existsSync(mintoManifest)\n const hasClaudeManifest = existsSync(claudeManifest)\n const hasRootManifest = existsSync(rootManifest)\n\n if (!hasMintoManifest && !hasClaudeManifest && !hasRootManifest) {\n errors.push(\n 'No plugin manifest found. Expected .minto-plugin/plugin.json or plugin.json',\n )\n return { isValid: false, errors, warnings }\n }\n\n // Prefer .minto-plugin > .claude-plugin > root manifest\n const manifestPath = hasMintoManifest\n ? mintoManifest\n : hasClaudeManifest\n ? claudeManifest\n : rootManifest\n\n // Validate manifest contents\n try {\n const content = readFileSync(manifestPath, 'utf-8')\n const data = JSON.parse(content)\n\n // Permissive validation first\n const basicResult = validatePluginManifest(data)\n if (basicResult.success === false) {\n errors.push(`Invalid manifest: ${basicResult.error.message}`)\n return { isValid: false, errors, warnings }\n }\n\n // Check for recommended fields\n if (!data.version) {\n warnings.push('Manifest is missing recommended field: version')\n }\n if (!data.description) {\n warnings.push('Manifest is missing recommended field: description')\n }\n\n // Validate version format if present\n if (data.version && !/^\\d+\\.\\d+\\.\\d+$/.test(data.version)) {\n warnings.push(\n `Version \"${data.version}\" does not follow semver format (X.Y.Z)`,\n )\n }\n\n // Validate name format\n if (data.name && !/^[a-z0-9-]+$/.test(data.name)) {\n warnings.push(\n `Name \"${data.name}\" should be lowercase alphanumeric with hyphens`,\n )\n }\n\n // Check component paths exist\n const componentChecks = [\n { field: 'commands', paths: normalizeToArray(data.commands) },\n { field: 'agents', paths: normalizeToArray(data.agents) },\n { field: 'skills', paths: normalizeToArray(data.skills) },\n { field: 'outputStyles', paths: normalizeToArray(data.outputStyles) },\n ]\n\n for (const check of componentChecks) {\n for (const path of check.paths) {\n const fullPath = join(resolvedPath, path)\n if (!existsSync(fullPath)) {\n warnings.push(`${check.field} path does not exist: ${path}`)\n }\n }\n }\n } catch (error) {\n if (error instanceof SyntaxError) {\n errors.push(`Invalid JSON in manifest: ${error.message}`)\n } else {\n errors.push(\n `Error reading manifest: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n return { isValid: false, errors, warnings }\n }\n\n return { isValid: errors.length === 0, errors, warnings }\n}\n\n/**\n * Normalize string or array to array\n */\nfunction normalizeToArray(value: unknown): string[] {\n if (!value) return []\n if (typeof value === 'string') return [value]\n if (Array.isArray(value)) return value.filter(v => typeof v === 'string')\n return []\n}\n\n/**\n * Validate marketplace manifest path\n */\nexport function validateMarketplacePath(path: string): ValidationResult {\n const errors: string[] = []\n const warnings: string[] = []\n\n const resolvedPath = resolve(path)\n\n if (!existsSync(resolvedPath)) {\n errors.push(`Marketplace path does not exist: ${resolvedPath}`)\n return { isValid: false, errors, warnings }\n }\n\n // Check for marketplace manifest (.minto-plugin or .claude-plugin)\n const mintoManifest = join(resolvedPath, '.minto-plugin', 'marketplace.json')\n const claudeManifest = join(\n resolvedPath,\n '.claude-plugin',\n 'marketplace.json',\n )\n\n if (!existsSync(mintoManifest) && !existsSync(claudeManifest)) {\n errors.push(\n 'No marketplace manifest found. Expected .minto-plugin/marketplace.json',\n )\n }\n\n return { isValid: errors.length === 0, errors, warnings }\n}\n\n/**\n * Check if a manifest is valid for loading (permissive)\n */\nexport function isValidManifest(data: unknown): boolean {\n return validatePluginManifest(data).success\n}\n\n/**\n * Check if a manifest is strictly valid\n */\nexport function isStrictlyValidManifest(data: unknown): boolean {\n return validatePluginManifestStrict(data).success\n}\n"],
|
|
5
|
-
"mappings": "AAOA,SAAS,SAAS;AAClB,SAAS,YAAY,cAAc,gBAAgB;AACnD,SAAS,MAAM,eAAe;AAK9B,MAAM,eAAe,EAAE,MAAM;AAAA,EAC3B,EAAE,OAAO;AAAA,EACT,EAAE,OAAO;AAAA,IACP,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS;AAAA,IACnC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACjC,CAAC;AACH,CAAC;AAKD,MAAM,oBAAoB,EAAE,MAAM;AAAA,EAChC,EAAE,OAAO;AAAA,EACT,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,EAClB,EAAE;AAAA,IACA,EAAE,OAAO;AAAA,MACP,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,MAC7B,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,MAC5B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,MAC7B,UAAU,EAAE,QAAQ,EAAE,SAAS;AAAA,IACjC,CAAC;AAAA,EACH;AACF,CAAC;AAKD,MAAM,yBAAyB,EAAE,MAAM;AAAA,EACrC,EAAE,OAAO;AAAA,EACT,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,EAClB,EAAE;AAAA,IACA,EAAE,OAAO;AAAA,MACP,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,MAC7B,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,MACnC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,MACnC,MAAM,EAAE,KAAK,CAAC,SAAS,QAAQ,KAAK,CAAC,EAAE,SAAS;AAAA,MAChD,KAAK,EAAE,OAAO,EAAE,SAAS;AAAA,MACzB,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,MACvC,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,IAC/B,CAAC;AAAA,EACH;AACF,CAAC;AAKD,MAAM,yBAAyB,EAAE,MAAM;AAAA,EACrC,EAAE,OAAO;AAAA,EACT,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,EAClB,EAAE;AAAA,IACA,EAAE,OAAO;AAAA,MACP,SAAS,EAAE,OAAO;AAAA,MAClB,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,MACnC,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,MAC9B,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,IAC7C,CAAC;AAAA,EACH;AACF,CAAC;AAMM,MAAM,
|
|
4
|
+
"sourcesContent": ["/**\n * Plugin Validation\n *\n * Validates plugin manifests and configurations.\n * Compatible with Claude Code CLI plugin specification.\n */\n\nimport { z } from 'zod'\nimport { existsSync, readFileSync, statSync } from 'fs'\nimport { join, resolve } from 'path'\n\n/**\n * Author schema (can be string or object)\n */\nconst AuthorSchema = z.union([\n z.string(),\n z.object({\n name: z.string().optional(),\n email: z.string().email().optional(),\n url: z.string().url().optional(),\n }),\n])\n\n/**\n * Hooks configuration schema\n */\nconst HooksConfigSchema = z.union([\n z.string(),\n z.array(z.string()),\n z.record(\n z.object({\n command: z.string().optional(),\n script: z.string().optional(),\n timeout: z.number().optional(),\n blocking: z.boolean().optional(),\n }),\n ),\n])\n\n/**\n * MCP Servers configuration schema\n */\nconst McpServersConfigSchema = z.union([\n z.string(),\n z.array(z.string()),\n z.record(\n z.object({\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string()).optional(),\n type: z.enum(['stdio', 'http', 'sse']).optional(),\n url: z.string().optional(),\n headers: z.record(z.string()).optional(),\n timeout: z.number().optional(),\n }),\n ),\n])\n\n/**\n * LSP Servers configuration schema (Claude Code CLI specific)\n */\nconst LspServersConfigSchema = z.union([\n z.string(),\n z.array(z.string()),\n z.record(\n z.object({\n command: z.string(),\n args: z.array(z.string()).optional(),\n rootPath: z.string().optional(),\n filePatterns: z.array(z.string()).optional(),\n }),\n ),\n])\n\n/**\n * Minimal schema for quick validation. Full schema: src/types/plugin.ts PluginManifestSchema\n * More permissive than full schema to allow partial manifests\n */\nexport const MinimalPluginManifestSchema = z\n .object({\n name: z.string().min(1),\n })\n .passthrough()\n\nexport type PluginManifestBasic = z.infer<typeof MinimalPluginManifestSchema>\n\n/** @deprecated Use MinimalPluginManifestSchema instead */\nexport const PluginManifestSchema = MinimalPluginManifestSchema\n\n/**\n * Full Claude Code CLI plugin manifest schema\n * Used for strict validation\n */\nexport const FullPluginManifestSchema = z.object({\n // Required field\n name: z\n .string()\n .min(1)\n .regex(\n /^[a-z0-9-]+$/,\n 'Plugin name must be lowercase alphanumeric with hyphens',\n ),\n\n // Metadata fields (Claude Code CLI specification)\n version: z\n .string()\n .regex(/^\\d+\\.\\d+\\.\\d+$/, 'Version must follow semver format (e.g., 1.0.0)')\n .optional(),\n description: z.string().optional(),\n author: AuthorSchema.optional(),\n homepage: z.string().url().optional(),\n repository: z.string().optional(), // Can be URL or \"owner/repo\"\n license: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n\n // Component path fields\n commands: z.union([z.string(), z.array(z.string())]).optional(),\n agents: z.union([z.string(), z.array(z.string())]).optional(),\n skills: z.union([z.string(), z.array(z.string())]).optional(),\n hooks: HooksConfigSchema.optional(),\n mcpServers: McpServersConfigSchema.optional(),\n outputStyles: z.union([z.string(), z.array(z.string())]).optional(),\n lspServers: LspServersConfigSchema.optional(), // Claude Code CLI specific\n\n // Engine requirements\n engines: z\n .object({\n minto: z.string().optional(),\n 'claude-code': z.string().optional(),\n node: z.string().optional(),\n })\n .optional(),\n\n // Plugin-specific configuration schema\n configSchema: z.record(z.any()).optional(),\n\n // Dependencies\n dependencies: z.record(z.string()).optional(),\n})\n\nexport type FullPluginManifest = z.infer<typeof FullPluginManifestSchema>\n\n/**\n * Plugin directory/marketplace validation result.\n * Distinct from core ValidationResult (src/types/core.ts) which is for tool validation,\n * and from pluginValidator.ts ValidationResult which is for component-level validation.\n */\nexport interface PluginValidationResult {\n isValid: boolean\n errors: string[]\n warnings: string[]\n}\n\n/**\n * Validate a plugin manifest (permissive)\n */\nexport function validatePluginManifest(\n manifest: unknown,\n):\n | { success: true; data: PluginManifestBasic }\n | { success: false; error: z.ZodError } {\n const result = MinimalPluginManifestSchema.safeParse(manifest)\n if (result.success) {\n return { success: true, data: result.data }\n }\n return { success: false, error: result.error }\n}\n\n/**\n * Validate a plugin manifest (strict - full Claude Code CLI specification)\n */\nexport function validatePluginManifestStrict(\n manifest: unknown,\n):\n | { success: true; data: FullPluginManifest }\n | { success: false; error: z.ZodError } {\n const result = FullPluginManifestSchema.safeParse(manifest)\n if (result.success) {\n return { success: true, data: result.data }\n }\n return { success: false, error: result.error }\n}\n\n/**\n * Validate a plugin directory structure\n */\nexport function validatePluginDirectory(\n rootDir: string,\n): PluginValidationResult {\n const errors: string[] = []\n const warnings: string[] = []\n\n // Resolve path\n const resolvedPath = resolve(rootDir)\n\n // Check directory exists\n if (!existsSync(resolvedPath)) {\n errors.push(`Directory does not exist: ${resolvedPath}`)\n return { isValid: false, errors, warnings }\n }\n\n // Check it's a directory\n try {\n if (!statSync(resolvedPath).isDirectory()) {\n errors.push(`Path is not a directory: ${resolvedPath}`)\n return { isValid: false, errors, warnings }\n }\n } catch {\n errors.push(`Cannot access path: ${resolvedPath}`)\n return { isValid: false, errors, warnings }\n }\n\n // Check for manifest file (.minto-plugin, .claude-plugin, or root)\n const mintoManifest = join(resolvedPath, '.minto-plugin', 'plugin.json')\n const claudeManifest = join(resolvedPath, '.claude-plugin', 'plugin.json')\n const rootManifest = join(resolvedPath, 'plugin.json')\n\n const hasMintoManifest = existsSync(mintoManifest)\n const hasClaudeManifest = existsSync(claudeManifest)\n const hasRootManifest = existsSync(rootManifest)\n\n if (!hasMintoManifest && !hasClaudeManifest && !hasRootManifest) {\n errors.push(\n 'No plugin manifest found. Expected .minto-plugin/plugin.json or plugin.json',\n )\n return { isValid: false, errors, warnings }\n }\n\n // Prefer .minto-plugin > .claude-plugin > root manifest\n const manifestPath = hasMintoManifest\n ? mintoManifest\n : hasClaudeManifest\n ? claudeManifest\n : rootManifest\n\n // Validate manifest contents\n try {\n const content = readFileSync(manifestPath, 'utf-8')\n const data = JSON.parse(content)\n\n // Permissive validation first\n const basicResult = validatePluginManifest(data)\n if (basicResult.success === false) {\n errors.push(`Invalid manifest: ${basicResult.error.message}`)\n return { isValid: false, errors, warnings }\n }\n\n // Check for recommended fields\n if (!data.version) {\n warnings.push('Manifest is missing recommended field: version')\n }\n if (!data.description) {\n warnings.push('Manifest is missing recommended field: description')\n }\n\n // Validate version format if present\n if (data.version && !/^\\d+\\.\\d+\\.\\d+$/.test(data.version)) {\n warnings.push(\n `Version \"${data.version}\" does not follow semver format (X.Y.Z)`,\n )\n }\n\n // Validate name format\n if (data.name && !/^[a-z0-9-]+$/.test(data.name)) {\n warnings.push(\n `Name \"${data.name}\" should be lowercase alphanumeric with hyphens`,\n )\n }\n\n // Check component paths exist\n const componentChecks = [\n { field: 'commands', paths: normalizeToArray(data.commands) },\n { field: 'agents', paths: normalizeToArray(data.agents) },\n { field: 'skills', paths: normalizeToArray(data.skills) },\n { field: 'outputStyles', paths: normalizeToArray(data.outputStyles) },\n ]\n\n for (const check of componentChecks) {\n for (const path of check.paths) {\n const fullPath = join(resolvedPath, path)\n if (!existsSync(fullPath)) {\n warnings.push(`${check.field} path does not exist: ${path}`)\n }\n }\n }\n } catch (error) {\n if (error instanceof SyntaxError) {\n errors.push(`Invalid JSON in manifest: ${error.message}`)\n } else {\n errors.push(\n `Error reading manifest: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n return { isValid: false, errors, warnings }\n }\n\n return { isValid: errors.length === 0, errors, warnings }\n}\n\n/**\n * Normalize string or array to array\n */\nfunction normalizeToArray(value: unknown): string[] {\n if (!value) return []\n if (typeof value === 'string') return [value]\n if (Array.isArray(value)) return value.filter(v => typeof v === 'string')\n return []\n}\n\n/**\n * Validate marketplace manifest path\n */\nexport function validateMarketplacePath(path: string): PluginValidationResult {\n const errors: string[] = []\n const warnings: string[] = []\n\n const resolvedPath = resolve(path)\n\n if (!existsSync(resolvedPath)) {\n errors.push(`Marketplace path does not exist: ${resolvedPath}`)\n return { isValid: false, errors, warnings }\n }\n\n // Check for marketplace manifest (.minto-plugin or .claude-plugin)\n const mintoManifest = join(resolvedPath, '.minto-plugin', 'marketplace.json')\n const claudeManifest = join(\n resolvedPath,\n '.claude-plugin',\n 'marketplace.json',\n )\n\n if (!existsSync(mintoManifest) && !existsSync(claudeManifest)) {\n errors.push(\n 'No marketplace manifest found. Expected .minto-plugin/marketplace.json',\n )\n }\n\n return { isValid: errors.length === 0, errors, warnings }\n}\n\n/**\n * Check if a manifest is valid for loading (permissive)\n */\nexport function isValidManifest(data: unknown): boolean {\n return validatePluginManifest(data).success\n}\n\n/**\n * Check if a manifest is strictly valid\n */\nexport function isStrictlyValidManifest(data: unknown): boolean {\n return validatePluginManifestStrict(data).success\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|