@umsai/ums-code 0.3.0-v2 → 0.6.0-v1
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/package.json +6 -6
- package/dist/src/{zed-integration → acp-integration}/acp.d.ts +13 -0
- package/dist/src/{zed-integration → acp-integration}/acp.js +32 -0
- package/dist/src/acp-integration/acp.js.map +1 -0
- package/dist/src/acp-integration/acpAgent.d.ts +10 -0
- package/dist/src/acp-integration/acpAgent.js +264 -0
- package/dist/src/acp-integration/acpAgent.js.map +1 -0
- package/dist/src/{zed-integration → acp-integration}/schema.d.ts +2235 -905
- package/dist/src/{zed-integration → acp-integration}/schema.js +100 -2
- package/dist/src/acp-integration/schema.js.map +1 -0
- package/dist/src/{zed-integration/fileSystemService.d.ts → acp-integration/service/filesystem.d.ts} +1 -1
- package/dist/src/{zed-integration/fileSystemService.js → acp-integration/service/filesystem.js} +14 -1
- package/dist/src/acp-integration/service/filesystem.js.map +1 -0
- package/dist/src/{ui/hooks/useQuotaAndFallback.test.d.ts → acp-integration/service/filesystem.test.d.ts} +1 -1
- package/dist/src/acp-integration/service/filesystem.test.js +39 -0
- package/dist/src/acp-integration/service/filesystem.test.js.map +1 -0
- package/dist/src/acp-integration/session/HistoryReplayer.d.ts +51 -0
- package/dist/src/acp-integration/session/HistoryReplayer.js +164 -0
- package/dist/src/acp-integration/session/HistoryReplayer.js.map +1 -0
- package/dist/src/acp-integration/session/HistoryReplayer.test.d.ts +6 -0
- package/dist/src/acp-integration/session/HistoryReplayer.test.js +374 -0
- package/dist/src/acp-integration/session/HistoryReplayer.test.js.map +1 -0
- package/dist/src/acp-integration/session/Session.d.ts +61 -0
- package/dist/src/acp-integration/session/Session.js +839 -0
- package/dist/src/acp-integration/session/Session.js.map +1 -0
- package/dist/src/acp-integration/session/SubAgentTracker.d.ts +51 -0
- package/dist/src/acp-integration/session/SubAgentTracker.js +257 -0
- package/dist/src/acp-integration/session/SubAgentTracker.js.map +1 -0
- package/dist/src/acp-integration/session/SubAgentTracker.test.d.ts +6 -0
- package/dist/src/acp-integration/session/SubAgentTracker.test.js +369 -0
- package/dist/src/acp-integration/session/SubAgentTracker.test.js.map +1 -0
- package/dist/src/acp-integration/session/emitters/BaseEmitter.d.ts +27 -0
- package/dist/src/acp-integration/session/emitters/BaseEmitter.js +34 -0
- package/dist/src/acp-integration/session/emitters/BaseEmitter.js.map +1 -0
- package/dist/src/acp-integration/session/emitters/MessageEmitter.d.ts +41 -0
- package/dist/src/acp-integration/session/emitters/MessageEmitter.js +77 -0
- package/dist/src/acp-integration/session/emitters/MessageEmitter.js.map +1 -0
- package/dist/src/acp-integration/session/emitters/MessageEmitter.test.d.ts +6 -0
- package/dist/src/acp-integration/session/emitters/MessageEmitter.test.js +174 -0
- package/dist/src/acp-integration/session/emitters/MessageEmitter.test.js.map +1 -0
- package/dist/src/acp-integration/session/emitters/PlanEmitter.d.ts +39 -0
- package/dist/src/acp-integration/session/emitters/PlanEmitter.js +83 -0
- package/dist/src/acp-integration/session/emitters/PlanEmitter.js.map +1 -0
- package/dist/src/acp-integration/session/emitters/PlanEmitter.test.d.ts +6 -0
- package/dist/src/acp-integration/session/emitters/PlanEmitter.test.js +176 -0
- package/dist/src/acp-integration/session/emitters/PlanEmitter.test.js.map +1 -0
- package/dist/src/acp-integration/session/emitters/ToolCallEmitter.d.ts +80 -0
- package/dist/src/acp-integration/session/emitters/ToolCallEmitter.js +248 -0
- package/dist/src/acp-integration/session/emitters/ToolCallEmitter.js.map +1 -0
- package/dist/src/acp-integration/session/emitters/ToolCallEmitter.test.d.ts +6 -0
- package/dist/src/acp-integration/session/emitters/ToolCallEmitter.test.js +561 -0
- package/dist/src/acp-integration/session/emitters/ToolCallEmitter.test.js.map +1 -0
- package/dist/src/acp-integration/session/emitters/index.d.ts +9 -0
- package/dist/src/acp-integration/session/emitters/index.js +10 -0
- package/dist/src/acp-integration/session/emitters/index.js.map +1 -0
- package/dist/src/acp-integration/session/index.d.ts +24 -0
- package/dist/src/acp-integration/session/index.js +16 -0
- package/dist/src/acp-integration/session/index.js.map +1 -0
- package/dist/src/acp-integration/session/types.d.ts +71 -0
- package/dist/src/acp-integration/session/types.js +7 -0
- package/dist/src/acp-integration/session/types.js.map +1 -0
- package/dist/src/commandMode.d.ts +11 -0
- package/dist/src/commandMode.js +238 -0
- package/dist/src/commandMode.js.map +1 -0
- package/dist/src/config/auth.d.ts +1 -0
- package/dist/src/config/auth.js +29 -0
- package/dist/src/config/auth.js.map +1 -1
- package/dist/src/config/config.d.ts +19 -3
- package/dist/src/config/config.js +175 -24
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/extension.js +0 -2
- package/dist/src/config/extension.js.map +1 -1
- package/dist/src/config/extensions/update.test.js +9 -0
- package/dist/src/config/extensions/update.test.js.map +1 -1
- package/dist/src/config/settingsSchema.d.ts +53 -2
- package/dist/src/config/settingsSchema.js +46 -2
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/core/auth.d.ts +1 -1
- package/dist/src/core/auth.js +3 -2
- package/dist/src/core/auth.js.map +1 -1
- package/dist/src/core/initializer.js +3 -0
- package/dist/src/core/initializer.js.map +1 -1
- package/dist/src/gemini.js +75 -35
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/gemini.test.js +37 -4
- package/dist/src/gemini.test.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +3 -3
- package/dist/src/generated/git-commit.js +3 -3
- package/dist/src/i18n/index.d.ts +10 -2
- package/dist/src/i18n/index.js +26 -1
- package/dist/src/i18n/index.js.map +1 -1
- package/dist/src/i18n/languages.d.ts +20 -0
- package/dist/src/i18n/languages.js +36 -0
- package/dist/src/i18n/languages.js.map +1 -0
- package/dist/src/i18n/locales/de.js +1073 -0
- package/dist/src/i18n/locales/en.js +121 -175
- package/dist/src/i18n/locales/ru.js +1095 -0
- package/dist/src/i18n/locales/zh.js +52 -174
- package/dist/src/nonInteractive/control/ControlDispatcher.d.ts +24 -1
- package/dist/src/nonInteractive/control/ControlDispatcher.js +46 -17
- package/dist/src/nonInteractive/control/ControlDispatcher.js.map +1 -1
- package/dist/src/nonInteractive/control/ControlService.d.ts +2 -1
- package/dist/src/nonInteractive/control/ControlService.js +22 -37
- package/dist/src/nonInteractive/control/ControlService.js.map +1 -1
- package/dist/src/nonInteractive/control/controllers/baseController.d.ts +2 -1
- package/dist/src/nonInteractive/control/controllers/baseController.js +38 -5
- package/dist/src/nonInteractive/control/controllers/baseController.js.map +1 -1
- package/dist/src/nonInteractive/control/controllers/permissionController.d.ts +1 -22
- package/dist/src/nonInteractive/control/controllers/permissionController.js +38 -38
- package/dist/src/nonInteractive/control/controllers/permissionController.js.map +1 -1
- package/dist/src/nonInteractive/control/controllers/sdkMcpController.d.ts +54 -0
- package/dist/src/nonInteractive/control/controllers/sdkMcpController.js +84 -0
- package/dist/src/nonInteractive/control/controllers/sdkMcpController.js.map +1 -0
- package/dist/src/nonInteractive/control/controllers/systemController.d.ts +16 -6
- package/dist/src/nonInteractive/control/controllers/systemController.js +184 -44
- package/dist/src/nonInteractive/control/controllers/systemController.js.map +1 -1
- package/dist/src/nonInteractive/control/types/serviceAPIs.d.ts +1 -16
- package/dist/src/nonInteractive/io/BaseJsonOutputAdapter.d.ts +11 -0
- package/dist/src/nonInteractive/io/BaseJsonOutputAdapter.js +64 -5
- package/dist/src/nonInteractive/io/BaseJsonOutputAdapter.js.map +1 -1
- package/dist/src/nonInteractive/io/BaseJsonOutputAdapter.test.js +40 -0
- package/dist/src/nonInteractive/io/BaseJsonOutputAdapter.test.js.map +1 -1
- package/dist/src/nonInteractive/io/StreamJsonOutputAdapter.test.js +50 -0
- package/dist/src/nonInteractive/io/StreamJsonOutputAdapter.test.js.map +1 -1
- package/dist/src/nonInteractive/session.d.ts +0 -16
- package/dist/src/nonInteractive/session.js +317 -321
- package/dist/src/nonInteractive/session.js.map +1 -1
- package/dist/src/nonInteractive/session.test.js +6 -0
- package/dist/src/nonInteractive/session.test.js.map +1 -1
- package/dist/src/nonInteractive/types.d.ts +57 -3
- package/dist/src/nonInteractive/types.js +0 -1
- package/dist/src/nonInteractive/types.js.map +1 -1
- package/dist/src/nonInteractiveCli.js +121 -56
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/nonInteractiveCliCommands.d.ts +48 -9
- package/dist/src/nonInteractiveCliCommands.js +180 -64
- package/dist/src/nonInteractiveCliCommands.js.map +1 -1
- package/dist/src/nonInteractiveCliCommands.test.d.ts +6 -0
- package/dist/src/nonInteractiveCliCommands.test.js +157 -0
- package/dist/src/nonInteractiveCliCommands.test.js.map +1 -0
- package/dist/src/services/BuiltinCommandLoader.js +7 -6
- package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
- package/dist/src/services/BuiltinCommandLoader.test.js +0 -3
- package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
- package/dist/src/services/McpPromptLoader.js +4 -2
- package/dist/src/services/McpPromptLoader.js.map +1 -1
- package/dist/src/services/McpPromptLoader.test.js +1 -1
- package/dist/src/services/McpPromptLoader.test.js.map +1 -1
- package/dist/src/test-utils/mockCommandContext.js +11 -2
- package/dist/src/test-utils/mockCommandContext.js.map +1 -1
- package/dist/src/ui/AppContainer.js +62 -56
- package/dist/src/ui/AppContainer.js.map +1 -1
- package/dist/src/ui/AppContainer.test.js +0 -46
- package/dist/src/ui/AppContainer.test.js.map +1 -1
- package/dist/src/ui/auth/AuthDialog.test.js +4 -4
- package/dist/src/ui/auth/AuthDialog.test.js.map +1 -1
- package/dist/src/ui/auth/useAuth.js +31 -4
- package/dist/src/ui/auth/useAuth.js.map +1 -1
- package/dist/src/ui/commands/approvalModeCommand.js +53 -4
- package/dist/src/ui/commands/approvalModeCommand.js.map +1 -1
- package/dist/src/ui/commands/approvalModeCommand.test.js +72 -10
- package/dist/src/ui/commands/approvalModeCommand.test.js.map +1 -1
- package/dist/src/ui/commands/clearCommand.js +22 -10
- package/dist/src/ui/commands/clearCommand.js.map +1 -1
- package/dist/src/ui/commands/compressCommand.js +86 -16
- package/dist/src/ui/commands/compressCommand.js.map +1 -1
- package/dist/src/ui/commands/languageCommand.d.ts +6 -1
- package/dist/src/ui/commands/languageCommand.js +162 -183
- package/dist/src/ui/commands/languageCommand.js.map +1 -1
- package/dist/src/ui/commands/languageCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/languageCommand.test.js +558 -0
- package/dist/src/ui/commands/languageCommand.test.js.map +1 -0
- package/dist/src/ui/commands/modelCommand.js +4 -2
- package/dist/src/ui/commands/modelCommand.js.map +1 -1
- package/dist/src/ui/commands/quitCommand.d.ts +0 -1
- package/dist/src/ui/commands/quitCommand.js +0 -27
- package/dist/src/ui/commands/quitCommand.js.map +1 -1
- package/dist/src/ui/commands/restoreCommand.js +1 -1
- package/dist/src/ui/commands/restoreCommand.js.map +1 -1
- package/dist/src/ui/commands/resumeCommand.d.ts +7 -0
- package/dist/src/ui/commands/resumeCommand.js +19 -0
- package/dist/src/ui/commands/resumeCommand.js.map +1 -0
- package/dist/src/ui/commands/resumeCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/resumeCommand.test.js +32 -0
- package/dist/src/ui/commands/resumeCommand.test.js.map +1 -0
- package/dist/src/ui/commands/reviewCommand.d.ts +9 -0
- package/dist/src/ui/commands/reviewCommand.js +2046 -0
- package/dist/src/ui/commands/reviewCommand.js.map +1 -0
- package/dist/src/ui/commands/reviewCommand.test.js +600 -0
- package/dist/src/ui/commands/reviewCommand.test.js.map +1 -0
- package/dist/src/ui/commands/setupGithubCommand.js +11 -10
- package/dist/src/ui/commands/setupGithubCommand.js.map +1 -1
- package/dist/src/ui/commands/setupGithubCommand.test.js +14 -14
- package/dist/src/ui/commands/setupGithubCommand.test.js.map +1 -1
- package/dist/src/ui/commands/summaryCommand.js +129 -42
- package/dist/src/ui/commands/summaryCommand.js.map +1 -1
- package/dist/src/ui/commands/types.d.ts +24 -10
- package/dist/src/ui/commands/types.js.map +1 -1
- package/dist/src/ui/commands/ums/unittestCommand.d.ts +9 -0
- package/dist/src/ui/commands/ums/unittestCommand.js +387 -0
- package/dist/src/ui/commands/ums/unittestCommand.js.map +1 -0
- package/dist/src/ui/components/Composer.test.js +1 -2
- package/dist/src/ui/components/Composer.test.js.map +1 -1
- package/dist/src/ui/components/ContextUsageDisplay.d.ts +3 -2
- package/dist/src/ui/components/ContextUsageDisplay.js +8 -2
- package/dist/src/ui/components/ContextUsageDisplay.js.map +1 -1
- package/dist/src/ui/components/DialogManager.js +7 -23
- package/dist/src/ui/components/DialogManager.js.map +1 -1
- package/dist/src/ui/components/Footer.js +2 -3
- package/dist/src/ui/components/Footer.js.map +1 -1
- package/dist/src/ui/components/Help.js +13 -2
- package/dist/src/ui/components/Help.js.map +1 -1
- package/dist/src/ui/components/Help.test.js +6 -0
- package/dist/src/ui/components/Help.test.js.map +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js +3 -1
- package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.test.js +5 -2
- package/dist/src/ui/components/HistoryItemDisplay.test.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.js +6 -4
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.d.ts +3 -1
- package/dist/src/ui/components/ModelDialog.js +25 -5
- package/dist/src/ui/components/ModelDialog.js.map +1 -1
- package/dist/src/ui/components/OpenAIKeyPrompt.d.ts +3 -0
- package/dist/src/ui/components/OpenAIKeyPrompt.js +1 -0
- package/dist/src/ui/components/OpenAIKeyPrompt.js.map +1 -1
- package/dist/src/ui/components/PermissionsModifyTrustDialog.js +1 -1
- package/dist/src/ui/components/PermissionsModifyTrustDialog.js.map +1 -1
- package/dist/src/ui/components/SessionPicker.d.ts +18 -0
- package/dist/src/ui/components/SessionPicker.js +69 -0
- package/dist/src/ui/components/SessionPicker.js.map +1 -0
- package/dist/src/ui/components/SessionSummaryDisplay.js +14 -2
- package/dist/src/ui/components/SessionSummaryDisplay.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.test.js +2 -2
- package/dist/src/ui/components/StandaloneSessionPicker.d.ts +10 -0
- package/dist/src/ui/components/StandaloneSessionPicker.js +78 -0
- package/dist/src/ui/components/StandaloneSessionPicker.js.map +1 -0
- package/dist/src/ui/components/StandaloneSessionPicker.test.d.ts +6 -0
- package/dist/src/ui/components/StandaloneSessionPicker.test.js +410 -0
- package/dist/src/ui/components/StandaloneSessionPicker.test.js.map +1 -0
- package/dist/src/ui/components/SuggestionsDisplay.js +3 -2
- package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
- package/dist/src/ui/components/messages/GeminiThoughtMessage.d.ts +18 -0
- package/dist/src/ui/components/messages/GeminiThoughtMessage.js +14 -0
- package/dist/src/ui/components/messages/GeminiThoughtMessage.js.map +1 -0
- package/dist/src/ui/components/messages/GeminiThoughtMessageContent.d.ts +18 -0
- package/dist/src/ui/components/messages/GeminiThoughtMessageContent.js +14 -0
- package/dist/src/ui/components/messages/GeminiThoughtMessageContent.js.map +1 -0
- package/dist/src/ui/components/subagents/manage/AgentEditStep.js +4 -1
- package/dist/src/ui/components/subagents/manage/AgentEditStep.js.map +1 -1
- package/dist/src/ui/components/subagents/manage/AgentSelectionStep.js +2 -2
- package/dist/src/ui/components/subagents/manage/AgentSelectionStep.js.map +1 -1
- package/dist/src/ui/components/ums/UMSKeyPrompt.d.ts +1 -1
- package/dist/src/ui/components/ums/UMSKeyPrompt.js +24 -4
- package/dist/src/ui/components/ums/UMSKeyPrompt.js.map +1 -1
- package/dist/src/ui/components/ums/umsStartupWarnings.d.ts +6 -0
- package/dist/src/ui/components/ums/umsStartupWarnings.js +47 -0
- package/dist/src/ui/components/ums/umsStartupWarnings.js.map +1 -0
- package/dist/src/ui/contexts/SessionContext.d.ts +2 -0
- package/dist/src/ui/contexts/SessionContext.js +18 -10
- package/dist/src/ui/contexts/SessionContext.js.map +1 -1
- package/dist/src/ui/contexts/UIActionsContext.d.ts +3 -1
- package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
- package/dist/src/ui/contexts/UIStateContext.d.ts +3 -11
- package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.d.ts +3 -8
- package/dist/src/ui/hooks/slashCommandProcessor.js +77 -101
- package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/useAttentionNotifications.d.ts +3 -1
- package/dist/src/ui/hooks/useAttentionNotifications.js +10 -5
- package/dist/src/ui/hooks/useAttentionNotifications.js.map +1 -1
- package/dist/src/ui/hooks/useAttentionNotifications.test.js +39 -2
- package/dist/src/ui/hooks/useAttentionNotifications.test.js.map +1 -1
- package/dist/src/ui/hooks/useDialogClose.d.ts +0 -3
- package/dist/src/ui/hooks/useDialogClose.js +0 -2
- package/dist/src/ui/hooks/useDialogClose.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.js +87 -12
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.test.js +11 -6
- package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/useLogger.d.ts +1 -1
- package/dist/src/ui/hooks/useLogger.js +6 -3
- package/dist/src/ui/hooks/useLogger.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.js +12 -136
- package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
- package/dist/src/ui/hooks/useQwenAuth.test.js +1 -1
- package/dist/src/ui/hooks/useQwenAuth.test.js.map +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.js +2 -2
- package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
- package/dist/src/ui/hooks/useResumeCommand.d.ts +20 -0
- package/dist/src/ui/hooks/useResumeCommand.js +49 -0
- package/dist/src/ui/hooks/useResumeCommand.js.map +1 -0
- package/dist/src/ui/hooks/useResumeCommand.test.d.ts +6 -0
- package/dist/src/ui/hooks/useResumeCommand.test.js +144 -0
- package/dist/src/ui/hooks/useResumeCommand.test.js.map +1 -0
- package/dist/src/ui/hooks/useSessionPicker.d.ts +36 -0
- package/dist/src/ui/hooks/useSessionPicker.js +189 -0
- package/dist/src/ui/hooks/useSessionPicker.js.map +1 -0
- package/dist/src/ui/hooks/useSlashCompletion.js +9 -1
- package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.test.js +36 -31
- package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useToolScheduler.test.js +2 -1
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
- package/dist/src/ui/models/availableModels.d.ts +9 -2
- package/dist/src/ui/models/availableModels.js +32 -35
- package/dist/src/ui/models/availableModels.js.map +1 -1
- package/dist/src/ui/noninteractive/nonInteractiveUi.js +0 -1
- package/dist/src/ui/noninteractive/nonInteractiveUi.js.map +1 -1
- package/dist/src/ui/types.d.ts +9 -14
- package/dist/src/ui/types.js +0 -1
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/ui/utils/InlineMarkdownRenderer.d.ts +1 -0
- package/dist/src/ui/utils/InlineMarkdownRenderer.js +2 -2
- package/dist/src/ui/utils/InlineMarkdownRenderer.js.map +1 -1
- package/dist/src/ui/utils/MarkdownDisplay.d.ts +1 -0
- package/dist/src/ui/utils/MarkdownDisplay.js +13 -13
- package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
- package/dist/src/ui/utils/formatters.d.ts +6 -0
- package/dist/src/ui/utils/formatters.js +31 -0
- package/dist/src/ui/utils/formatters.js.map +1 -1
- package/dist/src/ui/utils/formatters.test.js +51 -2
- package/dist/src/ui/utils/formatters.test.js.map +1 -1
- package/dist/src/ui/utils/resumeHistoryUtils.d.ts +19 -0
- package/dist/src/ui/utils/resumeHistoryUtils.js +267 -0
- package/dist/src/ui/utils/resumeHistoryUtils.js.map +1 -0
- package/dist/src/ui/utils/resumeHistoryUtils.test.d.ts +6 -0
- package/dist/src/ui/utils/resumeHistoryUtils.test.js +253 -0
- package/dist/src/ui/utils/resumeHistoryUtils.test.js.map +1 -0
- package/dist/src/ui/utils/sessionPickerUtils.d.ts +30 -0
- package/dist/src/ui/utils/sessionPickerUtils.js +41 -0
- package/dist/src/ui/utils/sessionPickerUtils.js.map +1 -0
- package/dist/src/ui/utils/sessionPickerUtils.test.d.ts +6 -0
- package/dist/src/ui/utils/sessionPickerUtils.test.js +38 -0
- package/dist/src/ui/utils/sessionPickerUtils.test.js.map +1 -0
- package/dist/src/utils/attentionNotification.d.ts +1 -0
- package/dist/src/utils/attentionNotification.js +4 -0
- package/dist/src/utils/attentionNotification.js.map +1 -1
- package/dist/src/utils/errors.d.ts +1 -1
- package/dist/src/utils/errors.js +14 -3
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/errors.test.js +43 -1
- package/dist/src/utils/errors.test.js.map +1 -1
- package/dist/src/utils/gitUtils.js +25 -8
- package/dist/src/utils/gitUtils.js.map +1 -1
- package/dist/src/utils/gitUtils.test.js +59 -0
- package/dist/src/utils/gitUtils.test.js.map +1 -1
- package/dist/src/utils/nonInteractiveHelpers.d.ts +3 -1
- package/dist/src/utils/nonInteractiveHelpers.js +14 -15
- package/dist/src/utils/nonInteractiveHelpers.js.map +1 -1
- package/dist/src/utils/nonInteractiveHelpers.test.js +36 -21
- package/dist/src/utils/nonInteractiveHelpers.test.js.map +1 -1
- package/dist/src/utils/relaunch.js +2 -2
- package/dist/src/utils/relaunch.js.map +1 -1
- package/dist/src/utils/relaunch.test.js +5 -5
- package/dist/src/utils/relaunch.test.js.map +1 -1
- package/dist/src/utils/systemInfo.js +2 -1
- package/dist/src/utils/systemInfo.js.map +1 -1
- package/dist/src/validateNonInterActiveAuth.js +10 -1
- package/dist/src/validateNonInterActiveAuth.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/dist/src/nonInteractive/control/controllers/mcpController.d.ts +0 -42
- package/dist/src/nonInteractive/control/controllers/mcpController.js +0 -205
- package/dist/src/nonInteractive/control/controllers/mcpController.js.map +0 -1
- package/dist/src/ui/commands/chatCommand.d.ts +0 -9
- package/dist/src/ui/commands/chatCommand.js +0 -351
- package/dist/src/ui/commands/chatCommand.js.map +0 -1
- package/dist/src/ui/commands/corgiCommand.d.ts +0 -7
- package/dist/src/ui/commands/corgiCommand.js +0 -16
- package/dist/src/ui/commands/corgiCommand.js.map +0 -1
- package/dist/src/ui/components/ProQuotaDialog.d.ts +0 -13
- package/dist/src/ui/components/ProQuotaDialog.js +0 -24
- package/dist/src/ui/components/ProQuotaDialog.js.map +0 -1
- package/dist/src/ui/components/ProQuotaDialog.test.js +0 -58
- package/dist/src/ui/components/ProQuotaDialog.test.js.map +0 -1
- package/dist/src/ui/components/QuitConfirmationDialog.d.ts +0 -17
- package/dist/src/ui/components/QuitConfirmationDialog.js +0 -49
- package/dist/src/ui/components/QuitConfirmationDialog.js.map +0 -1
- package/dist/src/ui/hooks/usePromptCompletion.d.ts +0 -23
- package/dist/src/ui/hooks/usePromptCompletion.js +0 -177
- package/dist/src/ui/hooks/usePromptCompletion.js.map +0 -1
- package/dist/src/ui/hooks/useQuitConfirmation.d.ts +0 -14
- package/dist/src/ui/hooks/useQuitConfirmation.js +0 -36
- package/dist/src/ui/hooks/useQuitConfirmation.js.map +0 -1
- package/dist/src/ui/hooks/useQuotaAndFallback.d.ts +0 -21
- package/dist/src/ui/hooks/useQuotaAndFallback.js +0 -122
- package/dist/src/ui/hooks/useQuotaAndFallback.js.map +0 -1
- package/dist/src/ui/hooks/useQuotaAndFallback.test.js +0 -269
- package/dist/src/ui/hooks/useQuotaAndFallback.test.js.map +0 -1
- package/dist/src/zed-integration/acp.js.map +0 -1
- package/dist/src/zed-integration/fileSystemService.js.map +0 -1
- package/dist/src/zed-integration/schema.js.map +0 -1
- package/dist/src/zed-integration/zedIntegration.d.ts +0 -17
- package/dist/src/zed-integration/zedIntegration.js +0 -1135
- package/dist/src/zed-integration/zedIntegration.js.map +0 -1
- /package/dist/src/ui/{components/ProQuotaDialog.test.d.ts → commands/reviewCommand.test.d.ts} +0 -0
|
@@ -0,0 +1,839 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Qwen
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { ApprovalMode, convertToFunctionResponse, DiscoveredMCPTool, StreamEventType, ToolConfirmationOutcome, logToolCall, logUserPrompt, getErrorStatus, isWithinRoot, isNodeError, TaskTool, UserPromptEvent, TodoWriteTool, ExitPlanModeTool, } from '@umsai/ums-code-core';
|
|
7
|
+
import * as acp from '../acp.js';
|
|
8
|
+
import * as fs from 'node:fs/promises';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { getErrorMessage } from '../../utils/errors.js';
|
|
12
|
+
import { normalizePartList } from '../../utils/nonInteractiveHelpers.js';
|
|
13
|
+
import { handleSlashCommand, getAvailableCommands, } from '../../nonInteractiveCliCommands.js';
|
|
14
|
+
import { isSlashCommand } from '../../ui/utils/commandUtils.js';
|
|
15
|
+
import { HistoryReplayer } from './HistoryReplayer.js';
|
|
16
|
+
import { ToolCallEmitter } from './emitters/ToolCallEmitter.js';
|
|
17
|
+
import { PlanEmitter } from './emitters/PlanEmitter.js';
|
|
18
|
+
import { MessageEmitter } from './emitters/MessageEmitter.js';
|
|
19
|
+
import { SubAgentTracker } from './SubAgentTracker.js';
|
|
20
|
+
/**
|
|
21
|
+
* Session represents an active conversation session with the AI model.
|
|
22
|
+
* It uses modular components for consistent event emission:
|
|
23
|
+
* - HistoryReplayer for replaying past conversations
|
|
24
|
+
* - ToolCallEmitter for tool-related session updates
|
|
25
|
+
* - PlanEmitter for todo/plan updates
|
|
26
|
+
* - SubAgentTracker for tracking sub-agent tool calls
|
|
27
|
+
*/
|
|
28
|
+
export class Session {
|
|
29
|
+
chat;
|
|
30
|
+
config;
|
|
31
|
+
client;
|
|
32
|
+
settings;
|
|
33
|
+
pendingPrompt = null;
|
|
34
|
+
turn = 0;
|
|
35
|
+
// Modular components
|
|
36
|
+
historyReplayer;
|
|
37
|
+
toolCallEmitter;
|
|
38
|
+
planEmitter;
|
|
39
|
+
messageEmitter;
|
|
40
|
+
// Implement SessionContext interface
|
|
41
|
+
sessionId;
|
|
42
|
+
constructor(id, chat, config, client, settings) {
|
|
43
|
+
this.chat = chat;
|
|
44
|
+
this.config = config;
|
|
45
|
+
this.client = client;
|
|
46
|
+
this.settings = settings;
|
|
47
|
+
this.sessionId = id;
|
|
48
|
+
// Initialize modular components with this session as context
|
|
49
|
+
this.toolCallEmitter = new ToolCallEmitter(this);
|
|
50
|
+
this.planEmitter = new PlanEmitter(this);
|
|
51
|
+
this.historyReplayer = new HistoryReplayer(this);
|
|
52
|
+
this.messageEmitter = new MessageEmitter(this);
|
|
53
|
+
}
|
|
54
|
+
getId() {
|
|
55
|
+
return this.sessionId;
|
|
56
|
+
}
|
|
57
|
+
getConfig() {
|
|
58
|
+
return this.config;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Replays conversation history to the client using modular components.
|
|
62
|
+
* Delegates to HistoryReplayer for consistent event emission.
|
|
63
|
+
*/
|
|
64
|
+
async replayHistory(records) {
|
|
65
|
+
await this.historyReplayer.replay(records);
|
|
66
|
+
}
|
|
67
|
+
async cancelPendingPrompt() {
|
|
68
|
+
if (!this.pendingPrompt) {
|
|
69
|
+
throw new Error('Not currently generating');
|
|
70
|
+
}
|
|
71
|
+
this.pendingPrompt.abort();
|
|
72
|
+
this.pendingPrompt = null;
|
|
73
|
+
}
|
|
74
|
+
async prompt(params) {
|
|
75
|
+
this.pendingPrompt?.abort();
|
|
76
|
+
const pendingSend = new AbortController();
|
|
77
|
+
this.pendingPrompt = pendingSend;
|
|
78
|
+
// Increment turn counter for each user prompt
|
|
79
|
+
this.turn += 1;
|
|
80
|
+
const chat = this.chat;
|
|
81
|
+
const promptId = this.config.getSessionId() + '########' + this.turn;
|
|
82
|
+
// Extract text from all text blocks to construct the full prompt text for logging
|
|
83
|
+
const promptText = params.prompt
|
|
84
|
+
.filter((block) => block.type === 'text')
|
|
85
|
+
.map((block) => (block.type === 'text' ? block.text : ''))
|
|
86
|
+
.join(' ');
|
|
87
|
+
// Log user prompt
|
|
88
|
+
logUserPrompt(this.config, new UserPromptEvent(promptText.length, promptId, this.config.getContentGeneratorConfig()?.authType, promptText));
|
|
89
|
+
// record user message for session management
|
|
90
|
+
this.config.getChatRecordingService()?.recordUserMessage(promptText);
|
|
91
|
+
// Check if the input contains a slash command
|
|
92
|
+
// Extract text from the first text block if present
|
|
93
|
+
const firstTextBlock = params.prompt.find((block) => block.type === 'text');
|
|
94
|
+
const inputText = firstTextBlock?.text || '';
|
|
95
|
+
let parts;
|
|
96
|
+
if (isSlashCommand(inputText)) {
|
|
97
|
+
// Handle slash command - uses default allowed commands (init, summary, compress)
|
|
98
|
+
const slashCommandResult = await handleSlashCommand(inputText, pendingSend, this.config, this.settings);
|
|
99
|
+
parts = await this.#processSlashCommandResult(slashCommandResult, params.prompt);
|
|
100
|
+
// If parts is null, the command was fully handled (e.g., /summary completed)
|
|
101
|
+
// Return early without sending to the model
|
|
102
|
+
if (parts === null) {
|
|
103
|
+
return { stopReason: 'end_turn' };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// Normal processing for non-slash commands
|
|
108
|
+
parts = await this.#resolvePrompt(params.prompt, pendingSend.signal);
|
|
109
|
+
}
|
|
110
|
+
let nextMessage = { role: 'user', parts };
|
|
111
|
+
while (nextMessage !== null) {
|
|
112
|
+
if (pendingSend.signal.aborted) {
|
|
113
|
+
chat.addHistory(nextMessage);
|
|
114
|
+
return { stopReason: 'cancelled' };
|
|
115
|
+
}
|
|
116
|
+
const functionCalls = [];
|
|
117
|
+
let usageMetadata = null;
|
|
118
|
+
const streamStartTime = Date.now();
|
|
119
|
+
try {
|
|
120
|
+
const responseStream = await chat.sendMessageStream(this.config.getModel(), {
|
|
121
|
+
message: nextMessage?.parts ?? [],
|
|
122
|
+
config: {
|
|
123
|
+
abortSignal: pendingSend.signal,
|
|
124
|
+
},
|
|
125
|
+
}, promptId);
|
|
126
|
+
nextMessage = null;
|
|
127
|
+
for await (const resp of responseStream) {
|
|
128
|
+
if (pendingSend.signal.aborted) {
|
|
129
|
+
return { stopReason: 'cancelled' };
|
|
130
|
+
}
|
|
131
|
+
if (resp.type === StreamEventType.CHUNK &&
|
|
132
|
+
resp.value.candidates &&
|
|
133
|
+
resp.value.candidates.length > 0) {
|
|
134
|
+
const candidate = resp.value.candidates[0];
|
|
135
|
+
for (const part of candidate.content?.parts ?? []) {
|
|
136
|
+
if (!part.text) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
this.messageEmitter.emitMessage(part.text, 'assistant', part.thought);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (resp.type === StreamEventType.CHUNK && resp.value.usageMetadata) {
|
|
143
|
+
usageMetadata = resp.value.usageMetadata;
|
|
144
|
+
}
|
|
145
|
+
if (resp.type === StreamEventType.CHUNK && resp.value.functionCalls) {
|
|
146
|
+
functionCalls.push(...resp.value.functionCalls);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
if (getErrorStatus(error) === 429) {
|
|
152
|
+
throw new acp.RequestError(429, 'Rate limit exceeded. Try again later.');
|
|
153
|
+
}
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
if (usageMetadata) {
|
|
157
|
+
const durationMs = Date.now() - streamStartTime;
|
|
158
|
+
await this.messageEmitter.emitUsageMetadata(usageMetadata, '', durationMs);
|
|
159
|
+
}
|
|
160
|
+
if (functionCalls.length > 0) {
|
|
161
|
+
const toolResponseParts = [];
|
|
162
|
+
for (const fc of functionCalls) {
|
|
163
|
+
const response = await this.runTool(pendingSend.signal, promptId, fc);
|
|
164
|
+
toolResponseParts.push(...response);
|
|
165
|
+
}
|
|
166
|
+
nextMessage = { role: 'user', parts: toolResponseParts };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return { stopReason: 'end_turn' };
|
|
170
|
+
}
|
|
171
|
+
async sendUpdate(update) {
|
|
172
|
+
const params = {
|
|
173
|
+
sessionId: this.sessionId,
|
|
174
|
+
update,
|
|
175
|
+
};
|
|
176
|
+
await this.client.sessionUpdate(params);
|
|
177
|
+
}
|
|
178
|
+
async sendAvailableCommandsUpdate() {
|
|
179
|
+
const abortController = new AbortController();
|
|
180
|
+
try {
|
|
181
|
+
// Use default allowed commands from getAvailableCommands
|
|
182
|
+
const slashCommands = await getAvailableCommands(this.config, abortController.signal);
|
|
183
|
+
// Convert SlashCommand[] to AvailableCommand[] format for ACP protocol
|
|
184
|
+
const availableCommands = slashCommands.map((cmd) => ({
|
|
185
|
+
name: cmd.name,
|
|
186
|
+
description: cmd.description,
|
|
187
|
+
input: null,
|
|
188
|
+
}));
|
|
189
|
+
const update = {
|
|
190
|
+
sessionUpdate: 'available_commands_update',
|
|
191
|
+
availableCommands,
|
|
192
|
+
};
|
|
193
|
+
await this.sendUpdate(update);
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
// Log error but don't fail session creation
|
|
197
|
+
console.error('Error sending available commands update:', error);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Requests permission from the client for a tool call.
|
|
202
|
+
* Used by SubAgentTracker for sub-agent approval requests.
|
|
203
|
+
*/
|
|
204
|
+
async requestPermission(params) {
|
|
205
|
+
return this.client.requestPermission(params);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Sets the approval mode for the current session.
|
|
209
|
+
* Maps ACP approval mode values to core ApprovalMode enum.
|
|
210
|
+
*/
|
|
211
|
+
async setMode(params) {
|
|
212
|
+
const modeMap = {
|
|
213
|
+
plan: ApprovalMode.PLAN,
|
|
214
|
+
default: ApprovalMode.DEFAULT,
|
|
215
|
+
'auto-edit': ApprovalMode.AUTO_EDIT,
|
|
216
|
+
yolo: ApprovalMode.YOLO,
|
|
217
|
+
};
|
|
218
|
+
const approvalMode = modeMap[params.modeId];
|
|
219
|
+
this.config.setApprovalMode(approvalMode);
|
|
220
|
+
return { modeId: params.modeId };
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Sends a current_mode_update notification to the client.
|
|
224
|
+
* Called after the agent switches modes (e.g., from exit_plan_mode tool).
|
|
225
|
+
*/
|
|
226
|
+
async sendCurrentModeUpdateNotification(outcome) {
|
|
227
|
+
// Determine the new mode based on the approval outcome
|
|
228
|
+
// This mirrors the logic in ExitPlanModeTool.onConfirm
|
|
229
|
+
let newModeId;
|
|
230
|
+
switch (outcome) {
|
|
231
|
+
case ToolConfirmationOutcome.ProceedAlways:
|
|
232
|
+
newModeId = 'auto-edit';
|
|
233
|
+
break;
|
|
234
|
+
case ToolConfirmationOutcome.ProceedOnce:
|
|
235
|
+
default:
|
|
236
|
+
newModeId = 'default';
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
const update = {
|
|
240
|
+
sessionUpdate: 'current_mode_update',
|
|
241
|
+
modeId: newModeId,
|
|
242
|
+
};
|
|
243
|
+
await this.sendUpdate(update);
|
|
244
|
+
}
|
|
245
|
+
async runTool(abortSignal, promptId, fc) {
|
|
246
|
+
const callId = fc.id ?? `${fc.name}-${Date.now()}`;
|
|
247
|
+
const args = (fc.args ?? {});
|
|
248
|
+
const startTime = Date.now();
|
|
249
|
+
const errorResponse = (error) => {
|
|
250
|
+
const durationMs = Date.now() - startTime;
|
|
251
|
+
logToolCall(this.config, {
|
|
252
|
+
'event.name': 'tool_call',
|
|
253
|
+
'event.timestamp': new Date().toISOString(),
|
|
254
|
+
prompt_id: promptId,
|
|
255
|
+
function_name: fc.name ?? '',
|
|
256
|
+
function_args: args,
|
|
257
|
+
duration_ms: durationMs,
|
|
258
|
+
status: 'error',
|
|
259
|
+
success: false,
|
|
260
|
+
error: error.message,
|
|
261
|
+
tool_type: typeof tool !== 'undefined' && tool instanceof DiscoveredMCPTool
|
|
262
|
+
? 'mcp'
|
|
263
|
+
: 'native',
|
|
264
|
+
});
|
|
265
|
+
return [
|
|
266
|
+
{
|
|
267
|
+
functionResponse: {
|
|
268
|
+
id: callId,
|
|
269
|
+
name: fc.name ?? '',
|
|
270
|
+
response: { error: error.message },
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
];
|
|
274
|
+
};
|
|
275
|
+
if (!fc.name) {
|
|
276
|
+
return errorResponse(new Error('Missing function name'));
|
|
277
|
+
}
|
|
278
|
+
const toolRegistry = this.config.getToolRegistry();
|
|
279
|
+
const tool = toolRegistry.getTool(fc.name);
|
|
280
|
+
if (!tool) {
|
|
281
|
+
return errorResponse(new Error(`Tool "${fc.name}" not found in registry.`));
|
|
282
|
+
}
|
|
283
|
+
// Detect TodoWriteTool early - route to plan updates instead of tool_call events
|
|
284
|
+
const isTodoWriteTool = tool.name === TodoWriteTool.Name;
|
|
285
|
+
const isTaskTool = tool.name === TaskTool.Name;
|
|
286
|
+
const isExitPlanModeTool = tool.name === ExitPlanModeTool.Name;
|
|
287
|
+
// Track cleanup functions for sub-agent event listeners
|
|
288
|
+
let subAgentCleanupFunctions = [];
|
|
289
|
+
try {
|
|
290
|
+
const invocation = tool.build(args);
|
|
291
|
+
if (isTaskTool && 'eventEmitter' in invocation) {
|
|
292
|
+
// Access eventEmitter from TaskTool invocation
|
|
293
|
+
const taskEventEmitter = invocation.eventEmitter;
|
|
294
|
+
// Create a SubAgentTracker for this tool execution
|
|
295
|
+
const subAgentTracker = new SubAgentTracker(this, this.client);
|
|
296
|
+
// Set up sub-agent tool tracking
|
|
297
|
+
subAgentCleanupFunctions = subAgentTracker.setup(taskEventEmitter, abortSignal);
|
|
298
|
+
}
|
|
299
|
+
const confirmationDetails = this.config.getApprovalMode() !== ApprovalMode.YOLO
|
|
300
|
+
? await invocation.shouldConfirmExecute(abortSignal)
|
|
301
|
+
: false;
|
|
302
|
+
if (confirmationDetails) {
|
|
303
|
+
const content = [];
|
|
304
|
+
if (confirmationDetails.type === 'edit') {
|
|
305
|
+
content.push({
|
|
306
|
+
type: 'diff',
|
|
307
|
+
path: confirmationDetails.fileName,
|
|
308
|
+
oldText: confirmationDetails.originalContent,
|
|
309
|
+
newText: confirmationDetails.newContent,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
// Add plan content for exit_plan_mode
|
|
313
|
+
if (confirmationDetails.type === 'plan') {
|
|
314
|
+
content.push({
|
|
315
|
+
type: 'content',
|
|
316
|
+
content: {
|
|
317
|
+
type: 'text',
|
|
318
|
+
text: confirmationDetails.plan,
|
|
319
|
+
},
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
// Map tool kind, using switch_mode for exit_plan_mode per ACP spec
|
|
323
|
+
const mappedKind = this.toolCallEmitter.mapToolKind(tool.kind, fc.name);
|
|
324
|
+
const params = {
|
|
325
|
+
sessionId: this.sessionId,
|
|
326
|
+
options: toPermissionOptions(confirmationDetails),
|
|
327
|
+
toolCall: {
|
|
328
|
+
toolCallId: callId,
|
|
329
|
+
status: 'pending',
|
|
330
|
+
title: invocation.getDescription(),
|
|
331
|
+
content,
|
|
332
|
+
locations: invocation.toolLocations(),
|
|
333
|
+
kind: mappedKind,
|
|
334
|
+
},
|
|
335
|
+
};
|
|
336
|
+
const output = await this.client.requestPermission(params);
|
|
337
|
+
const outcome = output.outcome.outcome === 'cancelled'
|
|
338
|
+
? ToolConfirmationOutcome.Cancel
|
|
339
|
+
: z
|
|
340
|
+
.nativeEnum(ToolConfirmationOutcome)
|
|
341
|
+
.parse(output.outcome.optionId);
|
|
342
|
+
await confirmationDetails.onConfirm(outcome);
|
|
343
|
+
// After exit_plan_mode confirmation, send current_mode_update notification
|
|
344
|
+
if (isExitPlanModeTool && outcome !== ToolConfirmationOutcome.Cancel) {
|
|
345
|
+
await this.sendCurrentModeUpdateNotification(outcome);
|
|
346
|
+
}
|
|
347
|
+
switch (outcome) {
|
|
348
|
+
case ToolConfirmationOutcome.Cancel:
|
|
349
|
+
return errorResponse(new Error(`Tool "${fc.name}" was canceled by the user.`));
|
|
350
|
+
case ToolConfirmationOutcome.ProceedOnce:
|
|
351
|
+
case ToolConfirmationOutcome.ProceedAlways:
|
|
352
|
+
case ToolConfirmationOutcome.ProceedAlwaysServer:
|
|
353
|
+
case ToolConfirmationOutcome.ProceedAlwaysTool:
|
|
354
|
+
case ToolConfirmationOutcome.ModifyWithEditor:
|
|
355
|
+
break;
|
|
356
|
+
default: {
|
|
357
|
+
const resultOutcome = outcome;
|
|
358
|
+
throw new Error(`Unexpected: ${resultOutcome}`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
else if (!isTodoWriteTool) {
|
|
363
|
+
// Skip tool_call event for TodoWriteTool - use ToolCallEmitter
|
|
364
|
+
const startParams = {
|
|
365
|
+
callId,
|
|
366
|
+
toolName: fc.name,
|
|
367
|
+
args,
|
|
368
|
+
status: 'in_progress',
|
|
369
|
+
};
|
|
370
|
+
await this.toolCallEmitter.emitStart(startParams);
|
|
371
|
+
}
|
|
372
|
+
const toolResult = await invocation.execute(abortSignal);
|
|
373
|
+
// Clean up event listeners
|
|
374
|
+
subAgentCleanupFunctions.forEach((cleanup) => cleanup());
|
|
375
|
+
// Create response parts first (needed for emitResult and recordToolResult)
|
|
376
|
+
const responseParts = convertToFunctionResponse(fc.name, callId, toolResult.llmContent);
|
|
377
|
+
// Handle TodoWriteTool: extract todos and send plan update
|
|
378
|
+
if (isTodoWriteTool) {
|
|
379
|
+
const todos = this.planEmitter.extractTodos(toolResult.returnDisplay, args);
|
|
380
|
+
// Match original logic: emit plan if todos.length > 0 OR if args had todos
|
|
381
|
+
if ((todos && todos.length > 0) || Array.isArray(args['todos'])) {
|
|
382
|
+
await this.planEmitter.emitPlan(todos ?? []);
|
|
383
|
+
}
|
|
384
|
+
// Skip tool_call_update event for TodoWriteTool
|
|
385
|
+
// Still log and return function response for LLM
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
// Normal tool handling: emit result using ToolCallEmitter
|
|
389
|
+
// Convert toolResult.error to Error type if present
|
|
390
|
+
const error = toolResult.error
|
|
391
|
+
? new Error(toolResult.error.message)
|
|
392
|
+
: undefined;
|
|
393
|
+
await this.toolCallEmitter.emitResult({
|
|
394
|
+
callId,
|
|
395
|
+
toolName: fc.name,
|
|
396
|
+
args,
|
|
397
|
+
message: responseParts,
|
|
398
|
+
resultDisplay: toolResult.returnDisplay,
|
|
399
|
+
error,
|
|
400
|
+
success: !toolResult.error,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
const durationMs = Date.now() - startTime;
|
|
404
|
+
logToolCall(this.config, {
|
|
405
|
+
'event.name': 'tool_call',
|
|
406
|
+
'event.timestamp': new Date().toISOString(),
|
|
407
|
+
function_name: fc.name,
|
|
408
|
+
function_args: args,
|
|
409
|
+
duration_ms: durationMs,
|
|
410
|
+
status: 'success',
|
|
411
|
+
success: true,
|
|
412
|
+
prompt_id: promptId,
|
|
413
|
+
tool_type: typeof tool !== 'undefined' && tool instanceof DiscoveredMCPTool
|
|
414
|
+
? 'mcp'
|
|
415
|
+
: 'native',
|
|
416
|
+
});
|
|
417
|
+
// Record tool result for session management
|
|
418
|
+
this.config.getChatRecordingService()?.recordToolResult(responseParts, {
|
|
419
|
+
callId,
|
|
420
|
+
status: 'success',
|
|
421
|
+
resultDisplay: toolResult.returnDisplay,
|
|
422
|
+
error: undefined,
|
|
423
|
+
errorType: undefined,
|
|
424
|
+
});
|
|
425
|
+
return responseParts;
|
|
426
|
+
}
|
|
427
|
+
catch (e) {
|
|
428
|
+
// Ensure cleanup on error
|
|
429
|
+
subAgentCleanupFunctions.forEach((cleanup) => cleanup());
|
|
430
|
+
const error = e instanceof Error ? e : new Error(String(e));
|
|
431
|
+
// Use ToolCallEmitter for error handling
|
|
432
|
+
await this.toolCallEmitter.emitError(callId, error);
|
|
433
|
+
// Record tool error for session management
|
|
434
|
+
const errorParts = [
|
|
435
|
+
{
|
|
436
|
+
functionResponse: {
|
|
437
|
+
id: callId,
|
|
438
|
+
name: fc.name ?? '',
|
|
439
|
+
response: { error: error.message },
|
|
440
|
+
},
|
|
441
|
+
},
|
|
442
|
+
];
|
|
443
|
+
this.config.getChatRecordingService()?.recordToolResult(errorParts, {
|
|
444
|
+
callId,
|
|
445
|
+
status: 'error',
|
|
446
|
+
resultDisplay: undefined,
|
|
447
|
+
error,
|
|
448
|
+
errorType: undefined,
|
|
449
|
+
});
|
|
450
|
+
return errorResponse(error);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Processes the result of a slash command execution.
|
|
455
|
+
*
|
|
456
|
+
* Supported result types in ACP mode:
|
|
457
|
+
* - submit_prompt: Submits content to the model
|
|
458
|
+
* - stream_messages: Streams multiple messages to the client (ACP-specific)
|
|
459
|
+
* - unsupported: Command cannot be executed in ACP mode
|
|
460
|
+
* - no_command: No command was found, use original prompt
|
|
461
|
+
*
|
|
462
|
+
* Note: 'message' type is not supported in ACP mode - commands should use
|
|
463
|
+
* 'stream_messages' instead for consistent async handling.
|
|
464
|
+
*
|
|
465
|
+
* @param result The result from handleSlashCommand
|
|
466
|
+
* @param originalPrompt The original prompt blocks
|
|
467
|
+
* @returns Parts to use for the prompt, or null if command was handled without needing model interaction
|
|
468
|
+
*/
|
|
469
|
+
async #processSlashCommandResult(result, originalPrompt) {
|
|
470
|
+
switch (result.type) {
|
|
471
|
+
case 'submit_prompt':
|
|
472
|
+
// Command wants to submit a prompt to the model
|
|
473
|
+
// Convert PartListUnion to Part[]
|
|
474
|
+
return normalizePartList(result.content);
|
|
475
|
+
case 'message': {
|
|
476
|
+
// 'message' type is not ideal for ACP mode, but we handle it for compatibility
|
|
477
|
+
// by converting it to a stream_messages-like notification
|
|
478
|
+
await this.client.sendCustomNotification('_qwencode/slash_command', {
|
|
479
|
+
sessionId: this.sessionId,
|
|
480
|
+
command: originalPrompt
|
|
481
|
+
.filter((block) => block.type === 'text')
|
|
482
|
+
.map((block) => (block.type === 'text' ? block.text : ''))
|
|
483
|
+
.join(' '),
|
|
484
|
+
messageType: result.messageType,
|
|
485
|
+
message: result.content || '',
|
|
486
|
+
});
|
|
487
|
+
if (result.messageType === 'error') {
|
|
488
|
+
// Throw error to stop execution
|
|
489
|
+
throw new Error(result.content || 'Slash command failed.');
|
|
490
|
+
}
|
|
491
|
+
// For info messages, return null to indicate command was handled
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
case 'stream_messages': {
|
|
495
|
+
// Command returns multiple messages via async generator (ACP-preferred)
|
|
496
|
+
const command = originalPrompt
|
|
497
|
+
.filter((block) => block.type === 'text')
|
|
498
|
+
.map((block) => (block.type === 'text' ? block.text : ''))
|
|
499
|
+
.join(' ');
|
|
500
|
+
// Stream all messages to the client
|
|
501
|
+
for await (const msg of result.messages) {
|
|
502
|
+
await this.client.sendCustomNotification('_qwencode/slash_command', {
|
|
503
|
+
sessionId: this.sessionId,
|
|
504
|
+
command,
|
|
505
|
+
messageType: msg.messageType,
|
|
506
|
+
message: msg.content,
|
|
507
|
+
});
|
|
508
|
+
// If we encounter an error message, throw after sending
|
|
509
|
+
if (msg.messageType === 'error') {
|
|
510
|
+
throw new Error(msg.content || 'Slash command failed.');
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
// All messages sent successfully, return null to indicate command was handled
|
|
514
|
+
return null;
|
|
515
|
+
}
|
|
516
|
+
case 'unsupported': {
|
|
517
|
+
// Command returned an unsupported result type
|
|
518
|
+
const unsupportedError = `Slash command not supported in ACP integration: ${result.reason}`;
|
|
519
|
+
throw new Error(unsupportedError);
|
|
520
|
+
}
|
|
521
|
+
case 'no_command':
|
|
522
|
+
// No command was found or executed, use original prompt
|
|
523
|
+
return originalPrompt.map((block) => {
|
|
524
|
+
if (block.type === 'text') {
|
|
525
|
+
return { text: block.text };
|
|
526
|
+
}
|
|
527
|
+
throw new Error(`Unsupported block type: ${block.type}`);
|
|
528
|
+
});
|
|
529
|
+
default: {
|
|
530
|
+
// Exhaustiveness check
|
|
531
|
+
const _exhaustive = result;
|
|
532
|
+
const unknownError = `Unknown slash command result type: ${_exhaustive.type}`;
|
|
533
|
+
throw new Error(unknownError);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
async #resolvePrompt(message, abortSignal) {
|
|
538
|
+
const FILE_URI_SCHEME = 'file://';
|
|
539
|
+
const embeddedContext = [];
|
|
540
|
+
const parts = message.map((part) => {
|
|
541
|
+
switch (part.type) {
|
|
542
|
+
case 'text':
|
|
543
|
+
return { text: part.text };
|
|
544
|
+
case 'image':
|
|
545
|
+
case 'audio':
|
|
546
|
+
return {
|
|
547
|
+
inlineData: {
|
|
548
|
+
mimeType: part.mimeType,
|
|
549
|
+
data: part.data,
|
|
550
|
+
},
|
|
551
|
+
};
|
|
552
|
+
case 'resource_link': {
|
|
553
|
+
if (part.uri.startsWith(FILE_URI_SCHEME)) {
|
|
554
|
+
return {
|
|
555
|
+
fileData: {
|
|
556
|
+
mimeData: part.mimeType,
|
|
557
|
+
name: part.name,
|
|
558
|
+
fileUri: part.uri.slice(FILE_URI_SCHEME.length),
|
|
559
|
+
},
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
return { text: `@${part.uri}` };
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
case 'resource': {
|
|
567
|
+
embeddedContext.push(part.resource);
|
|
568
|
+
return { text: `@${part.resource.uri}` };
|
|
569
|
+
}
|
|
570
|
+
default: {
|
|
571
|
+
const unreachable = part;
|
|
572
|
+
throw new Error(`Unexpected chunk type: '${unreachable}'`);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
const atPathCommandParts = parts.filter((part) => 'fileData' in part);
|
|
577
|
+
if (atPathCommandParts.length === 0 && embeddedContext.length === 0) {
|
|
578
|
+
return parts;
|
|
579
|
+
}
|
|
580
|
+
const atPathToResolvedSpecMap = new Map();
|
|
581
|
+
// Get centralized file discovery service
|
|
582
|
+
const fileDiscovery = this.config.getFileService();
|
|
583
|
+
const respectGitIgnore = this.config.getFileFilteringRespectGitIgnore();
|
|
584
|
+
const pathSpecsToRead = [];
|
|
585
|
+
const contentLabelsForDisplay = [];
|
|
586
|
+
const ignoredPaths = [];
|
|
587
|
+
const toolRegistry = this.config.getToolRegistry();
|
|
588
|
+
const readManyFilesTool = toolRegistry.getTool('read_many_files');
|
|
589
|
+
const globTool = toolRegistry.getTool('glob');
|
|
590
|
+
if (!readManyFilesTool) {
|
|
591
|
+
throw new Error('Error: read_many_files tool not found.');
|
|
592
|
+
}
|
|
593
|
+
for (const atPathPart of atPathCommandParts) {
|
|
594
|
+
const pathName = atPathPart.fileData.fileUri;
|
|
595
|
+
// Check if path should be ignored by git
|
|
596
|
+
if (fileDiscovery.shouldGitIgnoreFile(pathName)) {
|
|
597
|
+
ignoredPaths.push(pathName);
|
|
598
|
+
const reason = respectGitIgnore
|
|
599
|
+
? 'git-ignored and will be skipped'
|
|
600
|
+
: 'ignored by custom patterns';
|
|
601
|
+
console.warn(`Path ${pathName} is ${reason}.`);
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
let currentPathSpec = pathName;
|
|
605
|
+
let resolvedSuccessfully = false;
|
|
606
|
+
try {
|
|
607
|
+
const absolutePath = path.resolve(this.config.getTargetDir(), pathName);
|
|
608
|
+
if (isWithinRoot(absolutePath, this.config.getTargetDir())) {
|
|
609
|
+
const stats = await fs.stat(absolutePath);
|
|
610
|
+
if (stats.isDirectory()) {
|
|
611
|
+
currentPathSpec = pathName.endsWith('/')
|
|
612
|
+
? `${pathName}**`
|
|
613
|
+
: `${pathName}/**`;
|
|
614
|
+
this.debug(`Path ${pathName} resolved to directory, using glob: ${currentPathSpec}`);
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
this.debug(`Path ${pathName} resolved to file: ${currentPathSpec}`);
|
|
618
|
+
}
|
|
619
|
+
resolvedSuccessfully = true;
|
|
620
|
+
}
|
|
621
|
+
else {
|
|
622
|
+
this.debug(`Path ${pathName} is outside the project directory. Skipping.`);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
catch (error) {
|
|
626
|
+
if (isNodeError(error) && error.code === 'ENOENT') {
|
|
627
|
+
if (this.config.getEnableRecursiveFileSearch() && globTool) {
|
|
628
|
+
this.debug(`Path ${pathName} not found directly, attempting glob search.`);
|
|
629
|
+
try {
|
|
630
|
+
const globResult = await globTool.buildAndExecute({
|
|
631
|
+
pattern: `**/*${pathName}*`,
|
|
632
|
+
path: this.config.getTargetDir(),
|
|
633
|
+
}, abortSignal);
|
|
634
|
+
if (globResult.llmContent &&
|
|
635
|
+
typeof globResult.llmContent === 'string' &&
|
|
636
|
+
!globResult.llmContent.startsWith('No files found') &&
|
|
637
|
+
!globResult.llmContent.startsWith('Error:')) {
|
|
638
|
+
const lines = globResult.llmContent.split('\n');
|
|
639
|
+
if (lines.length > 1 && lines[1]) {
|
|
640
|
+
const firstMatchAbsolute = lines[1].trim();
|
|
641
|
+
currentPathSpec = path.relative(this.config.getTargetDir(), firstMatchAbsolute);
|
|
642
|
+
this.debug(`Glob search for ${pathName} found ${firstMatchAbsolute}, using relative path: ${currentPathSpec}`);
|
|
643
|
+
resolvedSuccessfully = true;
|
|
644
|
+
}
|
|
645
|
+
else {
|
|
646
|
+
this.debug(`Glob search for '**/*${pathName}*' did not return a usable path. Path ${pathName} will be skipped.`);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
this.debug(`Glob search for '**/*${pathName}*' found no files or an error. Path ${pathName} will be skipped.`);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
catch (globError) {
|
|
654
|
+
console.error(`Error during glob search for ${pathName}: ${getErrorMessage(globError)}`);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
this.debug(`Glob tool not found. Path ${pathName} will be skipped.`);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
console.error(`Error stating path ${pathName}. Path ${pathName} will be skipped.`);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
if (resolvedSuccessfully) {
|
|
666
|
+
pathSpecsToRead.push(currentPathSpec);
|
|
667
|
+
atPathToResolvedSpecMap.set(pathName, currentPathSpec);
|
|
668
|
+
contentLabelsForDisplay.push(pathName);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
// Construct the initial part of the query for the LLM
|
|
672
|
+
let initialQueryText = '';
|
|
673
|
+
for (let i = 0; i < parts.length; i++) {
|
|
674
|
+
const chunk = parts[i];
|
|
675
|
+
if ('text' in chunk) {
|
|
676
|
+
initialQueryText += chunk.text;
|
|
677
|
+
}
|
|
678
|
+
else {
|
|
679
|
+
// type === 'atPath'
|
|
680
|
+
const resolvedSpec = chunk.fileData && atPathToResolvedSpecMap.get(chunk.fileData.fileUri);
|
|
681
|
+
if (i > 0 &&
|
|
682
|
+
initialQueryText.length > 0 &&
|
|
683
|
+
!initialQueryText.endsWith(' ') &&
|
|
684
|
+
resolvedSpec) {
|
|
685
|
+
// Add space if previous part was text and didn't end with space, or if previous was @path
|
|
686
|
+
const prevPart = parts[i - 1];
|
|
687
|
+
if ('text' in prevPart ||
|
|
688
|
+
('fileData' in prevPart &&
|
|
689
|
+
atPathToResolvedSpecMap.has(prevPart.fileData.fileUri))) {
|
|
690
|
+
initialQueryText += ' ';
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
// Append the resolved path spec for display purposes
|
|
694
|
+
if (resolvedSpec) {
|
|
695
|
+
initialQueryText += `@${resolvedSpec}`;
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
// Handle ignored paths message
|
|
700
|
+
let ignoredPathsMessage = '';
|
|
701
|
+
if (ignoredPaths.length > 0) {
|
|
702
|
+
const pathList = ignoredPaths.map((p) => `- ${p}`).join('\n');
|
|
703
|
+
ignoredPathsMessage = `Note: The following paths were skipped because they are ignored:\n${pathList}\n\n`;
|
|
704
|
+
}
|
|
705
|
+
const processedQueryParts = [];
|
|
706
|
+
// Read files using read_many_files tool
|
|
707
|
+
if (pathSpecsToRead.length > 0) {
|
|
708
|
+
const readResult = await readManyFilesTool.buildAndExecute({
|
|
709
|
+
paths_with_line_ranges: pathSpecsToRead,
|
|
710
|
+
}, abortSignal);
|
|
711
|
+
const contentForLlm = typeof readResult.llmContent === 'string'
|
|
712
|
+
? readResult.llmContent
|
|
713
|
+
: JSON.stringify(readResult.llmContent);
|
|
714
|
+
// Combine content label, ignored paths message, file content, and user query
|
|
715
|
+
const combinedText = `${ignoredPathsMessage}${contentForLlm}`.trim();
|
|
716
|
+
processedQueryParts.push({ text: combinedText });
|
|
717
|
+
processedQueryParts.push({ text: initialQueryText });
|
|
718
|
+
}
|
|
719
|
+
else if (embeddedContext.length > 0) {
|
|
720
|
+
// No @path files to read, but we have embedded context
|
|
721
|
+
processedQueryParts.push({
|
|
722
|
+
text: `${ignoredPathsMessage}${initialQueryText}`.trim(),
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
else {
|
|
726
|
+
// No @path files found or resolved
|
|
727
|
+
processedQueryParts.push({
|
|
728
|
+
text: `${ignoredPathsMessage}${initialQueryText}`.trim(),
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
// Process embedded context from resource blocks
|
|
732
|
+
for (const contextPart of embeddedContext) {
|
|
733
|
+
// Type guard for text resources
|
|
734
|
+
if ('text' in contextPart && contextPart.text) {
|
|
735
|
+
processedQueryParts.push({
|
|
736
|
+
text: `File: ${contextPart.uri}\n${contextPart.text}`,
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
// Type guard for blob resources
|
|
740
|
+
if ('blob' in contextPart && contextPart.blob) {
|
|
741
|
+
processedQueryParts.push({
|
|
742
|
+
inlineData: {
|
|
743
|
+
mimeType: contextPart.mimeType ?? 'application/octet-stream',
|
|
744
|
+
data: contextPart.blob,
|
|
745
|
+
},
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
return processedQueryParts;
|
|
750
|
+
}
|
|
751
|
+
debug(msg) {
|
|
752
|
+
if (this.config.getDebugMode()) {
|
|
753
|
+
console.warn(msg);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
// ============================================================================
|
|
758
|
+
// Helper functions
|
|
759
|
+
// ============================================================================
|
|
760
|
+
const basicPermissionOptions = [
|
|
761
|
+
{
|
|
762
|
+
optionId: ToolConfirmationOutcome.ProceedOnce,
|
|
763
|
+
name: 'Allow',
|
|
764
|
+
kind: 'allow_once',
|
|
765
|
+
},
|
|
766
|
+
{
|
|
767
|
+
optionId: ToolConfirmationOutcome.Cancel,
|
|
768
|
+
name: 'Reject',
|
|
769
|
+
kind: 'reject_once',
|
|
770
|
+
},
|
|
771
|
+
];
|
|
772
|
+
function toPermissionOptions(confirmation) {
|
|
773
|
+
switch (confirmation.type) {
|
|
774
|
+
case 'edit':
|
|
775
|
+
return [
|
|
776
|
+
{
|
|
777
|
+
optionId: ToolConfirmationOutcome.ProceedAlways,
|
|
778
|
+
name: 'Allow All Edits',
|
|
779
|
+
kind: 'allow_always',
|
|
780
|
+
},
|
|
781
|
+
...basicPermissionOptions,
|
|
782
|
+
];
|
|
783
|
+
case 'exec':
|
|
784
|
+
return [
|
|
785
|
+
{
|
|
786
|
+
optionId: ToolConfirmationOutcome.ProceedAlways,
|
|
787
|
+
name: `Always Allow ${confirmation.rootCommand}`,
|
|
788
|
+
kind: 'allow_always',
|
|
789
|
+
},
|
|
790
|
+
...basicPermissionOptions,
|
|
791
|
+
];
|
|
792
|
+
case 'mcp':
|
|
793
|
+
return [
|
|
794
|
+
{
|
|
795
|
+
optionId: ToolConfirmationOutcome.ProceedAlwaysServer,
|
|
796
|
+
name: `Always Allow ${confirmation.serverName}`,
|
|
797
|
+
kind: 'allow_always',
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
optionId: ToolConfirmationOutcome.ProceedAlwaysTool,
|
|
801
|
+
name: `Always Allow ${confirmation.toolName}`,
|
|
802
|
+
kind: 'allow_always',
|
|
803
|
+
},
|
|
804
|
+
...basicPermissionOptions,
|
|
805
|
+
];
|
|
806
|
+
case 'info':
|
|
807
|
+
return [
|
|
808
|
+
{
|
|
809
|
+
optionId: ToolConfirmationOutcome.ProceedAlways,
|
|
810
|
+
name: `Always Allow`,
|
|
811
|
+
kind: 'allow_always',
|
|
812
|
+
},
|
|
813
|
+
...basicPermissionOptions,
|
|
814
|
+
];
|
|
815
|
+
case 'plan':
|
|
816
|
+
return [
|
|
817
|
+
{
|
|
818
|
+
optionId: ToolConfirmationOutcome.ProceedAlways,
|
|
819
|
+
name: `Yes, and auto-accept edits`,
|
|
820
|
+
kind: 'allow_always',
|
|
821
|
+
},
|
|
822
|
+
{
|
|
823
|
+
optionId: ToolConfirmationOutcome.ProceedOnce,
|
|
824
|
+
name: `Yes, and manually approve edits`,
|
|
825
|
+
kind: 'allow_once',
|
|
826
|
+
},
|
|
827
|
+
{
|
|
828
|
+
optionId: ToolConfirmationOutcome.Cancel,
|
|
829
|
+
name: `No, keep planning (esc)`,
|
|
830
|
+
kind: 'reject_once',
|
|
831
|
+
},
|
|
832
|
+
];
|
|
833
|
+
default: {
|
|
834
|
+
const unreachable = confirmation;
|
|
835
|
+
throw new Error(`Unexpected: ${unreachable}`);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
//# sourceMappingURL=Session.js.map
|