fss-link 1.0.49 → 1.0.51
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/index.js +0 -0
- package/dist/package.json +2 -2
- package/dist/src/config/auth.js +8 -5
- package/dist/src/config/auth.js.map +1 -1
- package/dist/src/config/database.d.ts +103 -11
- package/dist/src/config/database.js +301 -59
- package/dist/src/config/database.js.map +1 -1
- package/dist/src/config/databaseBackup.d.ts +114 -0
- package/dist/src/config/databaseBackup.js +334 -0
- package/dist/src/config/databaseBackup.js.map +1 -0
- package/dist/src/config/databaseMigrations.d.ts +63 -0
- package/dist/src/config/databaseMigrations.js +379 -0
- package/dist/src/config/databaseMigrations.js.map +1 -0
- package/dist/src/config/databasePool.d.ts +70 -0
- package/dist/src/config/databasePool.js +193 -0
- package/dist/src/config/databasePool.js.map +1 -0
- package/dist/src/config/queryOptimizer.d.ts +127 -0
- package/dist/src/config/queryOptimizer.js +309 -0
- package/dist/src/config/queryOptimizer.js.map +1 -0
- package/dist/src/utils/sandbox.js +2 -8
- package/dist/src/utils/sandbox.js.map +1 -1
- package/dist/src/validateNonInterActiveAuth.js +3 -7
- package/dist/src/validateNonInterActiveAuth.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/dist/commands/mcp/add.test.ts +0 -122
- package/dist/commands/mcp/add.ts +0 -222
- package/dist/commands/mcp/list.test.ts +0 -154
- package/dist/commands/mcp/list.ts +0 -139
- package/dist/commands/mcp/remove.test.ts +0 -69
- package/dist/commands/mcp/remove.ts +0 -60
- package/dist/commands/mcp.test.ts +0 -55
- package/dist/commands/mcp.ts +0 -27
- package/dist/config/apiValidation.test.ts +0 -118
- package/dist/config/auth.test.ts +0 -79
- package/dist/config/auth.ts +0 -100
- package/dist/config/config.integration.test.ts +0 -407
- package/dist/config/config.test.ts +0 -1952
- package/dist/config/config.ts +0 -690
- package/dist/config/database.test.ts +0 -96
- package/dist/config/database.ts +0 -824
- package/dist/config/extension.test.ts +0 -236
- package/dist/config/extension.ts +0 -180
- package/dist/config/keyBindings.test.ts +0 -62
- package/dist/config/keyBindings.ts +0 -184
- package/dist/config/modelManager.ts +0 -326
- package/dist/config/providerManager.ts +0 -244
- package/dist/config/providerPersistence.test.ts +0 -377
- package/dist/config/providerPersistence.ts +0 -105
- package/dist/config/sandboxConfig.ts +0 -107
- package/dist/config/settings.test.ts +0 -1424
- package/dist/config/settings.ts +0 -517
- package/dist/config/settingsSchema.test.ts +0 -252
- package/dist/config/settingsSchema.ts +0 -728
- package/dist/config/trustedFolders.test.ts +0 -208
- package/dist/config/trustedFolders.ts +0 -167
- package/dist/gemini.test.tsx +0 -252
- package/dist/gemini.tsx +0 -357
- package/dist/generated/git-commit.ts +0 -10
- package/dist/index.ts +0 -21
- package/dist/nonInteractiveCli.test.ts +0 -276
- package/dist/nonInteractiveCli.ts +0 -143
- package/dist/patches/is-in-ci.ts +0 -17
- package/dist/services/BuiltinCommandLoader.test.ts +0 -127
- package/dist/services/BuiltinCommandLoader.ts +0 -95
- package/dist/services/CommandService.test.ts +0 -352
- package/dist/services/CommandService.ts +0 -103
- package/dist/services/FileCommandLoader.test.ts +0 -1002
- package/dist/services/FileCommandLoader.ts +0 -289
- package/dist/services/McpPromptLoader.ts +0 -231
- package/dist/services/SearchEngineConfigProvider.ts +0 -100
- package/dist/services/prompt-processors/argumentProcessor.test.ts +0 -41
- package/dist/services/prompt-processors/argumentProcessor.ts +0 -23
- package/dist/services/prompt-processors/shellProcessor.test.ts +0 -709
- package/dist/services/prompt-processors/shellProcessor.ts +0 -248
- package/dist/services/prompt-processors/types.ts +0 -44
- package/dist/services/types.ts +0 -24
- package/dist/src/config/apiValidation.test.d.ts +0 -6
- package/dist/src/config/apiValidation.test.js +0 -99
- package/dist/src/config/apiValidation.test.js.map +0 -1
- package/dist/src/config/database.test.d.ts +0 -6
- package/dist/src/config/database.test.js +0 -80
- package/dist/src/config/database.test.js.map +0 -1
- package/dist/src/config/providerManager.d.ts +0 -74
- package/dist/src/config/providerManager.js +0 -203
- package/dist/src/config/providerManager.js.map +0 -1
- package/dist/src/config/providerPersistence.test.d.ts +0 -6
- package/dist/src/config/providerPersistence.test.js +0 -283
- package/dist/src/config/providerPersistence.test.js.map +0 -1
- package/dist/src/ui/components/GeminiKeyDialog.d.ts +0 -11
- package/dist/src/ui/components/GeminiKeyDialog.js +0 -156
- package/dist/src/ui/components/GeminiKeyDialog.js.map +0 -1
- package/dist/src/ui/components/OpenAIEndpointDialog.d.ts +0 -19
- package/dist/src/ui/components/OpenAIEndpointDialog.js +0 -163
- package/dist/src/ui/components/OpenAIEndpointDialog.js.map +0 -1
- package/dist/test-setup.ts +0 -12
- package/dist/test-utils/customMatchers.ts +0 -65
- package/dist/test-utils/mockCommandContext.test.ts +0 -62
- package/dist/test-utils/mockCommandContext.ts +0 -105
- package/dist/test-utils/render.tsx +0 -18
- package/dist/ui/App.test.tsx +0 -2181
- package/dist/ui/App.tsx +0 -1344
- package/dist/ui/IdeIntegrationNudge.tsx +0 -98
- package/dist/ui/__snapshots__/App.test.tsx.snap +0 -124
- package/dist/ui/colors.ts +0 -56
- package/dist/ui/commands/aboutCommand.test.ts +0 -153
- package/dist/ui/commands/aboutCommand.ts +0 -49
- package/dist/ui/commands/authCommand.test.ts +0 -36
- package/dist/ui/commands/authCommand.ts +0 -17
- package/dist/ui/commands/bugCommand.test.ts +0 -114
- package/dist/ui/commands/bugCommand.ts +0 -92
- package/dist/ui/commands/chatCommand.test.ts +0 -414
- package/dist/ui/commands/chatCommand.ts +0 -280
- package/dist/ui/commands/clearCommand.test.ts +0 -100
- package/dist/ui/commands/clearCommand.ts +0 -29
- package/dist/ui/commands/compressCommand.test.ts +0 -129
- package/dist/ui/commands/compressCommand.ts +0 -78
- package/dist/ui/commands/contextCommand.ts +0 -132
- package/dist/ui/commands/copyCommand.test.ts +0 -296
- package/dist/ui/commands/copyCommand.ts +0 -67
- package/dist/ui/commands/corgiCommand.test.ts +0 -34
- package/dist/ui/commands/corgiCommand.ts +0 -16
- package/dist/ui/commands/directoryCommand.test.tsx +0 -185
- package/dist/ui/commands/directoryCommand.tsx +0 -179
- package/dist/ui/commands/docsCommand.test.ts +0 -99
- package/dist/ui/commands/docsCommand.ts +0 -42
- package/dist/ui/commands/editorCommand.test.ts +0 -30
- package/dist/ui/commands/editorCommand.ts +0 -21
- package/dist/ui/commands/extensionsCommand.test.ts +0 -67
- package/dist/ui/commands/extensionsCommand.ts +0 -46
- package/dist/ui/commands/helpCommand.test.ts +0 -52
- package/dist/ui/commands/helpCommand.ts +0 -23
- package/dist/ui/commands/ideCommand.test.ts +0 -255
- package/dist/ui/commands/ideCommand.ts +0 -283
- package/dist/ui/commands/initCommand.test.ts +0 -127
- package/dist/ui/commands/initCommand.ts +0 -117
- package/dist/ui/commands/mcpCommand.test.ts +0 -1057
- package/dist/ui/commands/mcpCommand.ts +0 -531
- package/dist/ui/commands/memoryCommand.test.ts +0 -344
- package/dist/ui/commands/memoryCommand.ts +0 -305
- package/dist/ui/commands/privacyCommand.test.ts +0 -38
- package/dist/ui/commands/privacyCommand.ts +0 -17
- package/dist/ui/commands/quitCommand.test.ts +0 -55
- package/dist/ui/commands/quitCommand.ts +0 -36
- package/dist/ui/commands/restoreCommand.test.ts +0 -250
- package/dist/ui/commands/restoreCommand.ts +0 -157
- package/dist/ui/commands/searchEngineSetupCommand.ts +0 -18
- package/dist/ui/commands/settingsCommand.test.ts +0 -36
- package/dist/ui/commands/settingsCommand.ts +0 -17
- package/dist/ui/commands/setupGithubCommand.test.ts +0 -238
- package/dist/ui/commands/setupGithubCommand.ts +0 -212
- package/dist/ui/commands/speakCommand.ts +0 -175
- package/dist/ui/commands/statsCommand.test.ts +0 -78
- package/dist/ui/commands/statsCommand.ts +0 -70
- package/dist/ui/commands/terminalSetupCommand.test.ts +0 -85
- package/dist/ui/commands/terminalSetupCommand.ts +0 -45
- package/dist/ui/commands/themeCommand.test.ts +0 -38
- package/dist/ui/commands/themeCommand.ts +0 -17
- package/dist/ui/commands/toolsCommand.test.ts +0 -105
- package/dist/ui/commands/toolsCommand.ts +0 -71
- package/dist/ui/commands/ttsCommand.ts +0 -143
- package/dist/ui/commands/types.ts +0 -204
- package/dist/ui/commands/vimCommand.ts +0 -25
- package/dist/ui/commands/voiceCommand.ts +0 -125
- package/dist/ui/components/AboutBox.tsx +0 -133
- package/dist/ui/components/AsciiArt.ts +0 -54
- package/dist/ui/components/AuthDialog.test.tsx +0 -334
- package/dist/ui/components/AuthDialog.tsx +0 -289
- package/dist/ui/components/AuthInProgress.tsx +0 -62
- package/dist/ui/components/AutoAcceptIndicator.tsx +0 -47
- package/dist/ui/components/ConsoleSummaryDisplay.tsx +0 -35
- package/dist/ui/components/ContextSummaryDisplay.test.tsx +0 -85
- package/dist/ui/components/ContextSummaryDisplay.tsx +0 -120
- package/dist/ui/components/ContextUsageDisplay.tsx +0 -77
- package/dist/ui/components/DebugProfiler.tsx +0 -36
- package/dist/ui/components/DetailedMessagesDisplay.tsx +0 -82
- package/dist/ui/components/EditorSettingsDialog.tsx +0 -172
- package/dist/ui/components/FolderTrustDialog.test.tsx +0 -36
- package/dist/ui/components/FolderTrustDialog.tsx +0 -74
- package/dist/ui/components/Footer.test.tsx +0 -159
- package/dist/ui/components/Footer.tsx +0 -158
- package/dist/ui/components/GeminiKeyDialog.tsx +0 -252
- package/dist/ui/components/GeminiRespondingSpinner.tsx +0 -34
- package/dist/ui/components/Header.test.tsx +0 -44
- package/dist/ui/components/Header.tsx +0 -70
- package/dist/ui/components/Help.tsx +0 -174
- package/dist/ui/components/HistoryItemDisplay.test.tsx +0 -125
- package/dist/ui/components/HistoryItemDisplay.tsx +0 -98
- package/dist/ui/components/InputPrompt.test.tsx +0 -1467
- package/dist/ui/components/InputPrompt.tsx +0 -641
- package/dist/ui/components/LMStudioModelPrompt.tsx +0 -215
- package/dist/ui/components/LoadingIndicator.test.tsx +0 -296
- package/dist/ui/components/LoadingIndicator.tsx +0 -82
- package/dist/ui/components/MemoryUsageDisplay.tsx +0 -36
- package/dist/ui/components/ModelStatsDisplay.test.tsx +0 -252
- package/dist/ui/components/ModelStatsDisplay.tsx +0 -197
- package/dist/ui/components/OllamaModelPrompt.tsx +0 -206
- package/dist/ui/components/OpenAIEndpointDialog.tsx +0 -261
- package/dist/ui/components/OpenAIKeyPrompt.test.tsx +0 -64
- package/dist/ui/components/OpenAIKeyPrompt.tsx +0 -197
- package/dist/ui/components/PrepareLabel.tsx +0 -48
- package/dist/ui/components/SearchEngineConfigDialog.tsx +0 -280
- package/dist/ui/components/SessionSummaryDisplay.test.tsx +0 -75
- package/dist/ui/components/SessionSummaryDisplay.tsx +0 -18
- package/dist/ui/components/SettingsDialog.test.tsx +0 -865
- package/dist/ui/components/SettingsDialog.tsx +0 -753
- package/dist/ui/components/ShellConfirmationDialog.test.tsx +0 -53
- package/dist/ui/components/ShellConfirmationDialog.tsx +0 -103
- package/dist/ui/components/ShellModeIndicator.tsx +0 -18
- package/dist/ui/components/ShowMoreLines.tsx +0 -40
- package/dist/ui/components/StatsDisplay.test.tsx +0 -401
- package/dist/ui/components/StatsDisplay.tsx +0 -273
- package/dist/ui/components/SuggestionsDisplay.tsx +0 -102
- package/dist/ui/components/ThemeDialog.tsx +0 -310
- package/dist/ui/components/Tips.tsx +0 -45
- package/dist/ui/components/TodoDisplay.test.tsx +0 -97
- package/dist/ui/components/TodoDisplay.tsx +0 -72
- package/dist/ui/components/ToolStatsDisplay.test.tsx +0 -180
- package/dist/ui/components/ToolStatsDisplay.tsx +0 -208
- package/dist/ui/components/UpdateNotification.tsx +0 -23
- package/dist/ui/components/WelcomeBackDialog.tsx +0 -290
- package/dist/ui/components/__snapshots__/IDEContextDetailDisplay.test.tsx.snap +0 -24
- package/dist/ui/components/__snapshots__/ModelStatsDisplay.test.tsx.snap +0 -121
- package/dist/ui/components/__snapshots__/SessionSummaryDisplay.test.tsx.snap +0 -30
- package/dist/ui/components/__snapshots__/ShellConfirmationDialog.test.tsx.snap +0 -21
- package/dist/ui/components/__snapshots__/StatsDisplay.test.tsx.snap +0 -264
- package/dist/ui/components/__snapshots__/ToolStatsDisplay.test.tsx.snap +0 -91
- package/dist/ui/components/messages/CompressionMessage.tsx +0 -49
- package/dist/ui/components/messages/DiffRenderer.test.tsx +0 -365
- package/dist/ui/components/messages/DiffRenderer.tsx +0 -358
- package/dist/ui/components/messages/ErrorMessage.tsx +0 -31
- package/dist/ui/components/messages/GeminiMessage.tsx +0 -43
- package/dist/ui/components/messages/GeminiMessageContent.tsx +0 -43
- package/dist/ui/components/messages/InfoMessage.tsx +0 -32
- package/dist/ui/components/messages/ToolConfirmationMessage.test.tsx +0 -58
- package/dist/ui/components/messages/ToolConfirmationMessage.tsx +0 -297
- package/dist/ui/components/messages/ToolGroupMessage.tsx +0 -126
- package/dist/ui/components/messages/ToolMessage.test.tsx +0 -183
- package/dist/ui/components/messages/ToolMessage.tsx +0 -296
- package/dist/ui/components/messages/UserMessage.tsx +0 -43
- package/dist/ui/components/messages/UserShellMessage.tsx +0 -25
- package/dist/ui/components/shared/MaxSizedBox.test.tsx +0 -425
- package/dist/ui/components/shared/MaxSizedBox.tsx +0 -624
- package/dist/ui/components/shared/RadioButtonSelect.test.tsx +0 -181
- package/dist/ui/components/shared/RadioButtonSelect.tsx +0 -234
- package/dist/ui/components/shared/__snapshots__/RadioButtonSelect.test.tsx.snap +0 -47
- package/dist/ui/components/shared/text-buffer.test.ts +0 -1728
- package/dist/ui/components/shared/text-buffer.ts +0 -2227
- package/dist/ui/components/shared/vim-buffer-actions.test.ts +0 -1119
- package/dist/ui/components/shared/vim-buffer-actions.ts +0 -814
- package/dist/ui/constants.ts +0 -17
- package/dist/ui/contexts/KeypressContext.test.tsx +0 -391
- package/dist/ui/contexts/KeypressContext.tsx +0 -440
- package/dist/ui/contexts/OverflowContext.tsx +0 -87
- package/dist/ui/contexts/SessionContext.test.tsx +0 -132
- package/dist/ui/contexts/SessionContext.tsx +0 -143
- package/dist/ui/contexts/SettingsContext.tsx +0 -20
- package/dist/ui/contexts/StreamingContext.tsx +0 -22
- package/dist/ui/contexts/VimModeContext.tsx +0 -79
- package/dist/ui/editors/editorSettingsManager.ts +0 -66
- package/dist/ui/hooks/atCommandProcessor.test.ts +0 -1102
- package/dist/ui/hooks/atCommandProcessor.ts +0 -485
- package/dist/ui/hooks/shellCommandProcessor.test.ts +0 -481
- package/dist/ui/hooks/shellCommandProcessor.ts +0 -314
- package/dist/ui/hooks/slashCommandProcessor.test.ts +0 -1044
- package/dist/ui/hooks/slashCommandProcessor.ts +0 -595
- package/dist/ui/hooks/useAtCompletion.test.ts +0 -497
- package/dist/ui/hooks/useAtCompletion.ts +0 -244
- package/dist/ui/hooks/useAuthCommand.ts +0 -129
- package/dist/ui/hooks/useAutoAcceptIndicator.test.ts +0 -300
- package/dist/ui/hooks/useAutoAcceptIndicator.ts +0 -52
- package/dist/ui/hooks/useBracketedPaste.ts +0 -37
- package/dist/ui/hooks/useCommandCompletion.test.ts +0 -518
- package/dist/ui/hooks/useCommandCompletion.tsx +0 -238
- package/dist/ui/hooks/useCompletion.ts +0 -128
- package/dist/ui/hooks/useConsoleMessages.test.ts +0 -147
- package/dist/ui/hooks/useConsoleMessages.ts +0 -110
- package/dist/ui/hooks/useEditorSettings.test.ts +0 -283
- package/dist/ui/hooks/useEditorSettings.ts +0 -75
- package/dist/ui/hooks/useFocus.test.ts +0 -119
- package/dist/ui/hooks/useFocus.ts +0 -48
- package/dist/ui/hooks/useFolderTrust.test.ts +0 -159
- package/dist/ui/hooks/useFolderTrust.ts +0 -72
- package/dist/ui/hooks/useGeminiStream.test.tsx +0 -1998
- package/dist/ui/hooks/useGeminiStream.ts +0 -1017
- package/dist/ui/hooks/useGitBranchName.test.ts +0 -280
- package/dist/ui/hooks/useGitBranchName.ts +0 -79
- package/dist/ui/hooks/useHistoryManager.test.ts +0 -202
- package/dist/ui/hooks/useHistoryManager.ts +0 -111
- package/dist/ui/hooks/useInputHistory.test.ts +0 -261
- package/dist/ui/hooks/useInputHistory.ts +0 -111
- package/dist/ui/hooks/useKeypress.test.ts +0 -280
- package/dist/ui/hooks/useKeypress.ts +0 -39
- package/dist/ui/hooks/useKittyKeyboardProtocol.ts +0 -31
- package/dist/ui/hooks/useLoadingIndicator.test.ts +0 -139
- package/dist/ui/hooks/useLoadingIndicator.ts +0 -57
- package/dist/ui/hooks/useLogger.ts +0 -32
- package/dist/ui/hooks/useMessageQueue.test.ts +0 -226
- package/dist/ui/hooks/useMessageQueue.ts +0 -69
- package/dist/ui/hooks/usePhraseCycler.test.ts +0 -145
- package/dist/ui/hooks/usePhraseCycler.ts +0 -198
- package/dist/ui/hooks/usePrivacySettings.test.ts +0 -242
- package/dist/ui/hooks/usePrivacySettings.ts +0 -150
- package/dist/ui/hooks/useReactToolScheduler.ts +0 -309
- package/dist/ui/hooks/useRefreshMemoryCommand.ts +0 -7
- package/dist/ui/hooks/useReverseSearchCompletion.test.tsx +0 -260
- package/dist/ui/hooks/useReverseSearchCompletion.tsx +0 -95
- package/dist/ui/hooks/useSettingsCommand.ts +0 -25
- package/dist/ui/hooks/useShellHistory.test.ts +0 -219
- package/dist/ui/hooks/useShellHistory.ts +0 -133
- package/dist/ui/hooks/useShowMemoryCommand.ts +0 -75
- package/dist/ui/hooks/useSlashCompletion.test.ts +0 -434
- package/dist/ui/hooks/useSlashCompletion.ts +0 -187
- package/dist/ui/hooks/useStateAndRef.ts +0 -36
- package/dist/ui/hooks/useTerminalSize.ts +0 -32
- package/dist/ui/hooks/useThemeCommand.ts +0 -110
- package/dist/ui/hooks/useTimer.test.ts +0 -120
- package/dist/ui/hooks/useTimer.ts +0 -65
- package/dist/ui/hooks/useToolScheduler.test.ts +0 -1123
- package/dist/ui/hooks/useWelcomeBack.ts +0 -253
- package/dist/ui/hooks/vim.test.ts +0 -1691
- package/dist/ui/hooks/vim.ts +0 -784
- package/dist/ui/keyMatchers.test.ts +0 -337
- package/dist/ui/keyMatchers.ts +0 -105
- package/dist/ui/privacy/CloudFreePrivacyNotice.tsx +0 -117
- package/dist/ui/privacy/CloudPaidPrivacyNotice.tsx +0 -59
- package/dist/ui/privacy/GeminiPrivacyNotice.tsx +0 -62
- package/dist/ui/privacy/PrivacyNotice.tsx +0 -42
- package/dist/ui/semantic-colors.ts +0 -26
- package/dist/ui/themes/ansi-light.ts +0 -150
- package/dist/ui/themes/ansi.ts +0 -159
- package/dist/ui/themes/atom-one-dark.ts +0 -147
- package/dist/ui/themes/ayu-light.ts +0 -139
- package/dist/ui/themes/ayu.ts +0 -113
- package/dist/ui/themes/color-utils.test.ts +0 -221
- package/dist/ui/themes/color-utils.ts +0 -231
- package/dist/ui/themes/default-light.ts +0 -108
- package/dist/ui/themes/default.ts +0 -151
- package/dist/ui/themes/dracula.ts +0 -124
- package/dist/ui/themes/fss-code-dark.ts +0 -156
- package/dist/ui/themes/fss-dark.ts +0 -113
- package/dist/ui/themes/fss-light.ts +0 -139
- package/dist/ui/themes/github-dark.ts +0 -147
- package/dist/ui/themes/github-light.ts +0 -149
- package/dist/ui/themes/googlecode.ts +0 -146
- package/dist/ui/themes/no-color.ts +0 -125
- package/dist/ui/themes/qwen-dark.ts +0 -118
- package/dist/ui/themes/qwen-light.ts +0 -144
- package/dist/ui/themes/semantic-tokens.ts +0 -127
- package/dist/ui/themes/shades-of-purple.ts +0 -352
- package/dist/ui/themes/theme-manager.test.ts +0 -99
- package/dist/ui/themes/theme-manager.ts +0 -257
- package/dist/ui/themes/theme.test.ts +0 -97
- package/dist/ui/themes/theme.ts +0 -451
- package/dist/ui/themes/xcode.ts +0 -154
- package/dist/ui/types.ts +0 -255
- package/dist/ui/utils/CodeColorizer.tsx +0 -217
- package/dist/ui/utils/ConsolePatcher.ts +0 -71
- package/dist/ui/utils/InlineMarkdownRenderer.tsx +0 -173
- package/dist/ui/utils/MarkdownDisplay.test.tsx +0 -244
- package/dist/ui/utils/MarkdownDisplay.tsx +0 -415
- package/dist/ui/utils/TableRenderer.tsx +0 -159
- package/dist/ui/utils/__snapshots__/MarkdownDisplay.test.tsx.snap +0 -93
- package/dist/ui/utils/clipboardUtils.test.ts +0 -76
- package/dist/ui/utils/clipboardUtils.ts +0 -149
- package/dist/ui/utils/commandUtils.test.ts +0 -384
- package/dist/ui/utils/commandUtils.ts +0 -106
- package/dist/ui/utils/computeStats.test.ts +0 -292
- package/dist/ui/utils/computeStats.ts +0 -86
- package/dist/ui/utils/displayUtils.test.ts +0 -58
- package/dist/ui/utils/displayUtils.ts +0 -32
- package/dist/ui/utils/formatters.test.ts +0 -72
- package/dist/ui/utils/formatters.ts +0 -63
- package/dist/ui/utils/isNarrowWidth.ts +0 -9
- package/dist/ui/utils/kittyProtocolDetector.ts +0 -105
- package/dist/ui/utils/markdownUtilities.test.ts +0 -50
- package/dist/ui/utils/markdownUtilities.ts +0 -125
- package/dist/ui/utils/platformConstants.ts +0 -52
- package/dist/ui/utils/terminalSetup.ts +0 -342
- package/dist/ui/utils/textUtils.ts +0 -40
- package/dist/ui/utils/updateCheck.test.ts +0 -163
- package/dist/ui/utils/updateCheck.ts +0 -100
- package/dist/utils/checks.ts +0 -28
- package/dist/utils/cleanup.test.ts +0 -68
- package/dist/utils/cleanup.ts +0 -36
- package/dist/utils/dialogScopeUtils.ts +0 -64
- package/dist/utils/events.ts +0 -14
- package/dist/utils/gitUtils.test.ts +0 -149
- package/dist/utils/gitUtils.ts +0 -116
- package/dist/utils/handleAutoUpdate.test.ts +0 -272
- package/dist/utils/handleAutoUpdate.ts +0 -145
- package/dist/utils/installationInfo.test.ts +0 -315
- package/dist/utils/installationInfo.ts +0 -176
- package/dist/utils/package.ts +0 -38
- package/dist/utils/readStdin.ts +0 -51
- package/dist/utils/resolvePath.ts +0 -21
- package/dist/utils/sandbox-macos-permissive-closed.sb +0 -32
- package/dist/utils/sandbox-macos-permissive-open.sb +0 -25
- package/dist/utils/sandbox-macos-permissive-proxied.sb +0 -37
- package/dist/utils/sandbox-macos-restrictive-closed.sb +0 -93
- package/dist/utils/sandbox-macos-restrictive-open.sb +0 -96
- package/dist/utils/sandbox-macos-restrictive-proxied.sb +0 -98
- package/dist/utils/sandbox.ts +0 -962
- package/dist/utils/settingsUtils.test.ts +0 -797
- package/dist/utils/settingsUtils.ts +0 -489
- package/dist/utils/spawnWrapper.ts +0 -9
- package/dist/utils/startupWarnings.test.ts +0 -83
- package/dist/utils/startupWarnings.ts +0 -40
- package/dist/utils/updateEventEmitter.ts +0 -13
- package/dist/utils/userStartupWarnings.test.ts +0 -87
- package/dist/utils/userStartupWarnings.ts +0 -69
- package/dist/utils/version.ts +0 -12
- package/dist/validateNonInterActiveAuth.test.ts +0 -260
- package/dist/validateNonInterActiveAuth.ts +0 -51
- package/dist/vitest.config.ts +0 -37
- package/dist/zed-integration/acp.ts +0 -366
- package/dist/zed-integration/fileSystemService.ts +0 -47
- package/dist/zed-integration/schema.ts +0 -466
- package/dist/zed-integration/zedIntegration.ts +0 -944
|
@@ -1,944 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2025 Google LLC
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { ReadableStream, WritableStream } from 'node:stream/web';
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
AuthType,
|
|
11
|
-
clearCachedCredentialFile,
|
|
12
|
-
Config,
|
|
13
|
-
GeminiChat,
|
|
14
|
-
logToolCall,
|
|
15
|
-
ToolResult,
|
|
16
|
-
convertToFunctionResponse,
|
|
17
|
-
getErrorMessage,
|
|
18
|
-
getErrorStatus,
|
|
19
|
-
isNodeError,
|
|
20
|
-
isWithinRoot,
|
|
21
|
-
MCPServerConfig,
|
|
22
|
-
ToolCallConfirmationDetails,
|
|
23
|
-
ToolConfirmationOutcome,
|
|
24
|
-
DiscoveredMCPTool,
|
|
25
|
-
} from 'fss-link-core';
|
|
26
|
-
import { AcpFileSystemService } from './fileSystemService.js';
|
|
27
|
-
import { Content, Part, FunctionCall, PartListUnion } from '@google/genai';
|
|
28
|
-
import * as fs from 'fs/promises';
|
|
29
|
-
import { Readable, Writable } from 'node:stream';
|
|
30
|
-
import * as path from 'path';
|
|
31
|
-
import { z } from 'zod';
|
|
32
|
-
import { LoadedSettings, SettingScope } from '../config/settings.js';
|
|
33
|
-
import * as acp from './acp.js';
|
|
34
|
-
|
|
35
|
-
import { randomUUID } from 'crypto';
|
|
36
|
-
import { CliArgs, loadCliConfig } from '../config/config.js';
|
|
37
|
-
import { Extension } from '../config/extension.js';
|
|
38
|
-
|
|
39
|
-
export async function runZedIntegration(
|
|
40
|
-
config: Config,
|
|
41
|
-
settings: LoadedSettings,
|
|
42
|
-
extensions: Extension[],
|
|
43
|
-
argv: CliArgs,
|
|
44
|
-
) {
|
|
45
|
-
const stdout = Writable.toWeb(process.stdout) as WritableStream;
|
|
46
|
-
const stdin = Readable.toWeb(process.stdin) as ReadableStream<Uint8Array>;
|
|
47
|
-
|
|
48
|
-
// Stdout is used to send messages to the client, so console.log/console.info
|
|
49
|
-
// messages to stderr so that they don't interfere with ACP.
|
|
50
|
-
console.log = console.error;
|
|
51
|
-
console.info = console.error;
|
|
52
|
-
console.debug = console.error;
|
|
53
|
-
|
|
54
|
-
new acp.AgentSideConnection(
|
|
55
|
-
(client: acp.Client) =>
|
|
56
|
-
new GeminiAgent(config, settings, extensions, argv, client),
|
|
57
|
-
stdout,
|
|
58
|
-
stdin,
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
class GeminiAgent {
|
|
63
|
-
private sessions: Map<string, Session> = new Map();
|
|
64
|
-
private clientCapabilities: acp.ClientCapabilities | undefined;
|
|
65
|
-
|
|
66
|
-
constructor(
|
|
67
|
-
private config: Config,
|
|
68
|
-
private settings: LoadedSettings,
|
|
69
|
-
private extensions: Extension[],
|
|
70
|
-
private argv: CliArgs,
|
|
71
|
-
private client: acp.Client,
|
|
72
|
-
) {}
|
|
73
|
-
|
|
74
|
-
async initialize(
|
|
75
|
-
args: acp.InitializeRequest,
|
|
76
|
-
): Promise<acp.InitializeResponse> {
|
|
77
|
-
this.clientCapabilities = args.clientCapabilities;
|
|
78
|
-
const authMethods = [
|
|
79
|
-
{
|
|
80
|
-
id: AuthType.LOGIN_WITH_GOOGLE,
|
|
81
|
-
name: 'Log in with Google',
|
|
82
|
-
description: null,
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
id: AuthType.USE_GEMINI,
|
|
86
|
-
name: 'Use Gemini API key',
|
|
87
|
-
description:
|
|
88
|
-
'Requires setting the `GEMINI_API_KEY` environment variable',
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
id: AuthType.USE_VERTEX_AI,
|
|
92
|
-
name: 'Vertex AI',
|
|
93
|
-
description: null,
|
|
94
|
-
},
|
|
95
|
-
];
|
|
96
|
-
|
|
97
|
-
return {
|
|
98
|
-
protocolVersion: acp.PROTOCOL_VERSION,
|
|
99
|
-
authMethods,
|
|
100
|
-
agentCapabilities: {
|
|
101
|
-
loadSession: false,
|
|
102
|
-
promptCapabilities: {
|
|
103
|
-
image: true,
|
|
104
|
-
audio: true,
|
|
105
|
-
embeddedContext: true,
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async authenticate({ methodId }: acp.AuthenticateRequest): Promise<void> {
|
|
112
|
-
const method = z.nativeEnum(AuthType).parse(methodId);
|
|
113
|
-
|
|
114
|
-
await clearCachedCredentialFile();
|
|
115
|
-
await this.config.refreshAuth(method);
|
|
116
|
-
this.settings.setValue(SettingScope.User, 'selectedAuthType', method);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async newSession({
|
|
120
|
-
cwd,
|
|
121
|
-
mcpServers,
|
|
122
|
-
}: acp.NewSessionRequest): Promise<acp.NewSessionResponse> {
|
|
123
|
-
const sessionId = randomUUID();
|
|
124
|
-
const config = await this.newSessionConfig(sessionId, cwd, mcpServers);
|
|
125
|
-
|
|
126
|
-
let isAuthenticated = false;
|
|
127
|
-
if (this.settings.merged.selectedAuthType) {
|
|
128
|
-
try {
|
|
129
|
-
await config.refreshAuth(this.settings.merged.selectedAuthType);
|
|
130
|
-
isAuthenticated = true;
|
|
131
|
-
} catch (e) {
|
|
132
|
-
console.error(`Authentication failed: ${e}`);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (!isAuthenticated) {
|
|
137
|
-
throw acp.RequestError.authRequired();
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (this.clientCapabilities?.fs) {
|
|
141
|
-
const acpFileSystemService = new AcpFileSystemService(
|
|
142
|
-
this.client,
|
|
143
|
-
sessionId,
|
|
144
|
-
this.clientCapabilities.fs,
|
|
145
|
-
config.getFileSystemService(),
|
|
146
|
-
);
|
|
147
|
-
config.setFileSystemService(acpFileSystemService);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const geminiClient = config.getGeminiClient();
|
|
151
|
-
const chat = await geminiClient.startChat();
|
|
152
|
-
const session = new Session(sessionId, chat, config, this.client);
|
|
153
|
-
this.sessions.set(sessionId, session);
|
|
154
|
-
|
|
155
|
-
return {
|
|
156
|
-
sessionId,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
async newSessionConfig(
|
|
161
|
-
sessionId: string,
|
|
162
|
-
cwd: string,
|
|
163
|
-
mcpServers: acp.McpServer[],
|
|
164
|
-
): Promise<Config> {
|
|
165
|
-
const mergedMcpServers = { ...this.settings.merged.mcpServers };
|
|
166
|
-
|
|
167
|
-
for (const { command, args, env: rawEnv, name } of mcpServers) {
|
|
168
|
-
const env: Record<string, string> = {};
|
|
169
|
-
for (const { name: envName, value } of rawEnv) {
|
|
170
|
-
env[envName] = value;
|
|
171
|
-
}
|
|
172
|
-
mergedMcpServers[name] = new MCPServerConfig(command, args, env, cwd);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const settings = { ...this.settings.merged, mcpServers: mergedMcpServers };
|
|
176
|
-
|
|
177
|
-
const config = await loadCliConfig(
|
|
178
|
-
settings,
|
|
179
|
-
this.extensions,
|
|
180
|
-
sessionId,
|
|
181
|
-
this.argv,
|
|
182
|
-
cwd,
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
await config.initialize();
|
|
186
|
-
return config;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
async cancel(params: acp.CancelNotification): Promise<void> {
|
|
190
|
-
const session = this.sessions.get(params.sessionId);
|
|
191
|
-
if (!session) {
|
|
192
|
-
throw new Error(`Session not found: ${params.sessionId}`);
|
|
193
|
-
}
|
|
194
|
-
await session.cancelPendingPrompt();
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
async prompt(params: acp.PromptRequest): Promise<acp.PromptResponse> {
|
|
198
|
-
const session = this.sessions.get(params.sessionId);
|
|
199
|
-
if (!session) {
|
|
200
|
-
throw new Error(`Session not found: ${params.sessionId}`);
|
|
201
|
-
}
|
|
202
|
-
return session.prompt(params);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
class Session {
|
|
207
|
-
private pendingPrompt: AbortController | null = null;
|
|
208
|
-
|
|
209
|
-
constructor(
|
|
210
|
-
private readonly id: string,
|
|
211
|
-
private readonly chat: GeminiChat,
|
|
212
|
-
private readonly config: Config,
|
|
213
|
-
private readonly client: acp.Client,
|
|
214
|
-
) {}
|
|
215
|
-
|
|
216
|
-
async cancelPendingPrompt(): Promise<void> {
|
|
217
|
-
if (!this.pendingPrompt) {
|
|
218
|
-
throw new Error('Not currently generating');
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
this.pendingPrompt.abort();
|
|
222
|
-
this.pendingPrompt = null;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
async prompt(params: acp.PromptRequest): Promise<acp.PromptResponse> {
|
|
226
|
-
this.pendingPrompt?.abort();
|
|
227
|
-
const pendingSend = new AbortController();
|
|
228
|
-
this.pendingPrompt = pendingSend;
|
|
229
|
-
|
|
230
|
-
const promptId = Math.random().toString(16).slice(2);
|
|
231
|
-
const chat = this.chat;
|
|
232
|
-
|
|
233
|
-
const parts = await this.#resolvePrompt(params.prompt, pendingSend.signal);
|
|
234
|
-
|
|
235
|
-
let nextMessage: Content | null = { role: 'user', parts };
|
|
236
|
-
|
|
237
|
-
while (nextMessage !== null) {
|
|
238
|
-
if (pendingSend.signal.aborted) {
|
|
239
|
-
chat.addHistory(nextMessage);
|
|
240
|
-
return { stopReason: 'cancelled' };
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const functionCalls: FunctionCall[] = [];
|
|
244
|
-
|
|
245
|
-
try {
|
|
246
|
-
const responseStream = await chat.sendMessageStream(
|
|
247
|
-
{
|
|
248
|
-
message: nextMessage?.parts ?? [],
|
|
249
|
-
config: {
|
|
250
|
-
abortSignal: pendingSend.signal,
|
|
251
|
-
},
|
|
252
|
-
},
|
|
253
|
-
promptId,
|
|
254
|
-
);
|
|
255
|
-
nextMessage = null;
|
|
256
|
-
|
|
257
|
-
for await (const resp of responseStream) {
|
|
258
|
-
if (pendingSend.signal.aborted) {
|
|
259
|
-
return { stopReason: 'cancelled' };
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
if (resp.candidates && resp.candidates.length > 0) {
|
|
263
|
-
const candidate = resp.candidates[0];
|
|
264
|
-
for (const part of candidate.content?.parts ?? []) {
|
|
265
|
-
if (!part.text) {
|
|
266
|
-
continue;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const content: acp.ContentBlock = {
|
|
270
|
-
type: 'text',
|
|
271
|
-
text: part.text,
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
this.sendUpdate({
|
|
275
|
-
sessionUpdate: part.thought
|
|
276
|
-
? 'agent_thought_chunk'
|
|
277
|
-
: 'agent_message_chunk',
|
|
278
|
-
content,
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
if (resp.functionCalls) {
|
|
284
|
-
functionCalls.push(...resp.functionCalls);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
} catch (error) {
|
|
288
|
-
if (getErrorStatus(error) === 429) {
|
|
289
|
-
throw new acp.RequestError(
|
|
290
|
-
429,
|
|
291
|
-
'Rate limit exceeded. Try again later.',
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
throw error;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (functionCalls.length > 0) {
|
|
299
|
-
const toolResponseParts: Part[] = [];
|
|
300
|
-
|
|
301
|
-
for (const fc of functionCalls) {
|
|
302
|
-
const response = await this.runTool(pendingSend.signal, promptId, fc);
|
|
303
|
-
|
|
304
|
-
const parts = Array.isArray(response) ? response : [response];
|
|
305
|
-
|
|
306
|
-
for (const part of parts) {
|
|
307
|
-
if (typeof part === 'string') {
|
|
308
|
-
toolResponseParts.push({ text: part });
|
|
309
|
-
} else if (part) {
|
|
310
|
-
toolResponseParts.push(part);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
nextMessage = { role: 'user', parts: toolResponseParts };
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
return { stopReason: 'end_turn' };
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
private async sendUpdate(update: acp.SessionUpdate): Promise<void> {
|
|
323
|
-
const params: acp.SessionNotification = {
|
|
324
|
-
sessionId: this.id,
|
|
325
|
-
update,
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
await this.client.sessionUpdate(params);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
private async runTool(
|
|
332
|
-
abortSignal: AbortSignal,
|
|
333
|
-
promptId: string,
|
|
334
|
-
fc: FunctionCall,
|
|
335
|
-
): Promise<PartListUnion> {
|
|
336
|
-
const callId = fc.id ?? `${fc.name}-${Date.now()}`;
|
|
337
|
-
const args = (fc.args ?? {}) as Record<string, unknown>;
|
|
338
|
-
|
|
339
|
-
const startTime = Date.now();
|
|
340
|
-
|
|
341
|
-
const errorResponse = (error: Error) => {
|
|
342
|
-
const durationMs = Date.now() - startTime;
|
|
343
|
-
logToolCall(this.config, {
|
|
344
|
-
'event.name': 'tool_call',
|
|
345
|
-
'event.timestamp': new Date().toISOString(),
|
|
346
|
-
prompt_id: promptId,
|
|
347
|
-
function_name: fc.name ?? '',
|
|
348
|
-
function_args: args,
|
|
349
|
-
duration_ms: durationMs,
|
|
350
|
-
success: false,
|
|
351
|
-
error: error.message,
|
|
352
|
-
tool_type:
|
|
353
|
-
typeof tool !== 'undefined' && tool instanceof DiscoveredMCPTool
|
|
354
|
-
? 'mcp'
|
|
355
|
-
: 'native',
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
return [
|
|
359
|
-
{
|
|
360
|
-
functionResponse: {
|
|
361
|
-
id: callId,
|
|
362
|
-
name: fc.name ?? '',
|
|
363
|
-
response: { error: error.message },
|
|
364
|
-
},
|
|
365
|
-
},
|
|
366
|
-
];
|
|
367
|
-
};
|
|
368
|
-
|
|
369
|
-
if (!fc.name) {
|
|
370
|
-
return errorResponse(new Error('Missing function name'));
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
const toolRegistry = this.config.getToolRegistry();
|
|
374
|
-
const tool = toolRegistry.getTool(fc.name as string);
|
|
375
|
-
|
|
376
|
-
if (!tool) {
|
|
377
|
-
return errorResponse(
|
|
378
|
-
new Error(`Tool "${fc.name}" not found in registry.`),
|
|
379
|
-
);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
try {
|
|
383
|
-
const invocation = tool.build(args);
|
|
384
|
-
|
|
385
|
-
const confirmationDetails =
|
|
386
|
-
await invocation.shouldConfirmExecute(abortSignal);
|
|
387
|
-
|
|
388
|
-
if (confirmationDetails) {
|
|
389
|
-
const content: acp.ToolCallContent[] = [];
|
|
390
|
-
|
|
391
|
-
if (confirmationDetails.type === 'edit') {
|
|
392
|
-
content.push({
|
|
393
|
-
type: 'diff',
|
|
394
|
-
path: confirmationDetails.fileName,
|
|
395
|
-
oldText: confirmationDetails.originalContent,
|
|
396
|
-
newText: confirmationDetails.newContent,
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
const params: acp.RequestPermissionRequest = {
|
|
401
|
-
sessionId: this.id,
|
|
402
|
-
options: toPermissionOptions(confirmationDetails),
|
|
403
|
-
toolCall: {
|
|
404
|
-
toolCallId: callId,
|
|
405
|
-
status: 'pending',
|
|
406
|
-
title: invocation.getDescription(),
|
|
407
|
-
content,
|
|
408
|
-
locations: invocation.toolLocations(),
|
|
409
|
-
kind: tool.kind,
|
|
410
|
-
},
|
|
411
|
-
};
|
|
412
|
-
|
|
413
|
-
const output = await this.client.requestPermission(params);
|
|
414
|
-
const outcome =
|
|
415
|
-
output.outcome.outcome === 'cancelled'
|
|
416
|
-
? ToolConfirmationOutcome.Cancel
|
|
417
|
-
: z
|
|
418
|
-
.nativeEnum(ToolConfirmationOutcome)
|
|
419
|
-
.parse(output.outcome.optionId);
|
|
420
|
-
|
|
421
|
-
await confirmationDetails.onConfirm(outcome);
|
|
422
|
-
|
|
423
|
-
switch (outcome) {
|
|
424
|
-
case ToolConfirmationOutcome.Cancel:
|
|
425
|
-
return errorResponse(
|
|
426
|
-
new Error(`Tool "${fc.name}" was canceled by the user.`),
|
|
427
|
-
);
|
|
428
|
-
case ToolConfirmationOutcome.ProceedOnce:
|
|
429
|
-
case ToolConfirmationOutcome.ProceedAlways:
|
|
430
|
-
case ToolConfirmationOutcome.ProceedAlwaysServer:
|
|
431
|
-
case ToolConfirmationOutcome.ProceedAlwaysTool:
|
|
432
|
-
case ToolConfirmationOutcome.ModifyWithEditor:
|
|
433
|
-
break;
|
|
434
|
-
default: {
|
|
435
|
-
const resultOutcome: never = outcome;
|
|
436
|
-
throw new Error(`Unexpected: ${resultOutcome}`);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
} else {
|
|
440
|
-
await this.sendUpdate({
|
|
441
|
-
sessionUpdate: 'tool_call',
|
|
442
|
-
toolCallId: callId,
|
|
443
|
-
status: 'in_progress',
|
|
444
|
-
title: invocation.getDescription(),
|
|
445
|
-
content: [],
|
|
446
|
-
locations: invocation.toolLocations(),
|
|
447
|
-
kind: tool.kind,
|
|
448
|
-
});
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
const toolResult: ToolResult = await invocation.execute(abortSignal);
|
|
452
|
-
const content = toToolCallContent(toolResult);
|
|
453
|
-
|
|
454
|
-
await this.sendUpdate({
|
|
455
|
-
sessionUpdate: 'tool_call_update',
|
|
456
|
-
toolCallId: callId,
|
|
457
|
-
status: 'completed',
|
|
458
|
-
content: content ? [content] : [],
|
|
459
|
-
});
|
|
460
|
-
|
|
461
|
-
const durationMs = Date.now() - startTime;
|
|
462
|
-
logToolCall(this.config, {
|
|
463
|
-
'event.name': 'tool_call',
|
|
464
|
-
'event.timestamp': new Date().toISOString(),
|
|
465
|
-
function_name: fc.name,
|
|
466
|
-
function_args: args,
|
|
467
|
-
duration_ms: durationMs,
|
|
468
|
-
success: true,
|
|
469
|
-
prompt_id: promptId,
|
|
470
|
-
tool_type:
|
|
471
|
-
typeof tool !== 'undefined' && tool instanceof DiscoveredMCPTool
|
|
472
|
-
? 'mcp'
|
|
473
|
-
: 'native',
|
|
474
|
-
});
|
|
475
|
-
|
|
476
|
-
return convertToFunctionResponse(fc.name, callId, toolResult.llmContent);
|
|
477
|
-
} catch (e) {
|
|
478
|
-
const error = e instanceof Error ? e : new Error(String(e));
|
|
479
|
-
|
|
480
|
-
await this.sendUpdate({
|
|
481
|
-
sessionUpdate: 'tool_call_update',
|
|
482
|
-
toolCallId: callId,
|
|
483
|
-
status: 'failed',
|
|
484
|
-
content: [
|
|
485
|
-
{ type: 'content', content: { type: 'text', text: error.message } },
|
|
486
|
-
],
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
return errorResponse(error);
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
async #resolvePrompt(
|
|
494
|
-
message: acp.ContentBlock[],
|
|
495
|
-
abortSignal: AbortSignal,
|
|
496
|
-
): Promise<Part[]> {
|
|
497
|
-
const FILE_URI_SCHEME = 'file://';
|
|
498
|
-
|
|
499
|
-
const embeddedContext: acp.EmbeddedResourceResource[] = [];
|
|
500
|
-
|
|
501
|
-
const parts = message.map((part) => {
|
|
502
|
-
switch (part.type) {
|
|
503
|
-
case 'text':
|
|
504
|
-
return { text: part.text };
|
|
505
|
-
case 'image':
|
|
506
|
-
case 'audio':
|
|
507
|
-
return {
|
|
508
|
-
inlineData: {
|
|
509
|
-
mimeType: part.mimeType,
|
|
510
|
-
data: part.data,
|
|
511
|
-
},
|
|
512
|
-
};
|
|
513
|
-
case 'resource_link': {
|
|
514
|
-
if (part.uri.startsWith(FILE_URI_SCHEME)) {
|
|
515
|
-
return {
|
|
516
|
-
fileData: {
|
|
517
|
-
mimeData: part.mimeType,
|
|
518
|
-
name: part.name,
|
|
519
|
-
fileUri: part.uri.slice(FILE_URI_SCHEME.length),
|
|
520
|
-
},
|
|
521
|
-
};
|
|
522
|
-
} else {
|
|
523
|
-
return { text: `@${part.uri}` };
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
case 'resource': {
|
|
527
|
-
embeddedContext.push(part.resource);
|
|
528
|
-
return { text: `@${part.resource.uri}` };
|
|
529
|
-
}
|
|
530
|
-
default: {
|
|
531
|
-
const unreachable: never = part;
|
|
532
|
-
throw new Error(`Unexpected chunk type: '${unreachable}'`);
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
});
|
|
536
|
-
|
|
537
|
-
const atPathCommandParts = parts.filter((part) => 'fileData' in part);
|
|
538
|
-
|
|
539
|
-
if (atPathCommandParts.length === 0 && embeddedContext.length === 0) {
|
|
540
|
-
return parts;
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
const atPathToResolvedSpecMap = new Map<string, string>();
|
|
544
|
-
|
|
545
|
-
// Get centralized file discovery service
|
|
546
|
-
const fileDiscovery = this.config.getFileService();
|
|
547
|
-
const respectGitIgnore = this.config.getFileFilteringRespectGitIgnore();
|
|
548
|
-
|
|
549
|
-
const pathSpecsToRead: string[] = [];
|
|
550
|
-
const contentLabelsForDisplay: string[] = [];
|
|
551
|
-
const ignoredPaths: string[] = [];
|
|
552
|
-
|
|
553
|
-
const toolRegistry = this.config.getToolRegistry();
|
|
554
|
-
const readManyFilesTool = toolRegistry.getTool('read_many_files');
|
|
555
|
-
const globTool = toolRegistry.getTool('glob');
|
|
556
|
-
|
|
557
|
-
if (!readManyFilesTool) {
|
|
558
|
-
throw new Error('Error: read_many_files tool not found.');
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
for (const atPathPart of atPathCommandParts) {
|
|
562
|
-
const pathName = atPathPart.fileData!.fileUri;
|
|
563
|
-
// Check if path should be ignored by git
|
|
564
|
-
if (fileDiscovery.shouldGitIgnoreFile(pathName)) {
|
|
565
|
-
ignoredPaths.push(pathName);
|
|
566
|
-
const reason = respectGitIgnore
|
|
567
|
-
? 'git-ignored and will be skipped'
|
|
568
|
-
: 'ignored by custom patterns';
|
|
569
|
-
console.warn(`Path ${pathName} is ${reason}.`);
|
|
570
|
-
continue;
|
|
571
|
-
}
|
|
572
|
-
let currentPathSpec = pathName;
|
|
573
|
-
let resolvedSuccessfully = false;
|
|
574
|
-
try {
|
|
575
|
-
const absolutePath = path.resolve(this.config.getTargetDir(), pathName);
|
|
576
|
-
if (isWithinRoot(absolutePath, this.config.getTargetDir())) {
|
|
577
|
-
const stats = await fs.stat(absolutePath);
|
|
578
|
-
if (stats.isDirectory()) {
|
|
579
|
-
currentPathSpec = pathName.endsWith('/')
|
|
580
|
-
? `${pathName}**`
|
|
581
|
-
: `${pathName}/**`;
|
|
582
|
-
this.debug(
|
|
583
|
-
`Path ${pathName} resolved to directory, using glob: ${currentPathSpec}`,
|
|
584
|
-
);
|
|
585
|
-
} else {
|
|
586
|
-
this.debug(`Path ${pathName} resolved to file: ${currentPathSpec}`);
|
|
587
|
-
}
|
|
588
|
-
resolvedSuccessfully = true;
|
|
589
|
-
} else {
|
|
590
|
-
this.debug(
|
|
591
|
-
`Path ${pathName} is outside the project directory. Skipping.`,
|
|
592
|
-
);
|
|
593
|
-
}
|
|
594
|
-
} catch (error) {
|
|
595
|
-
if (isNodeError(error) && error.code === 'ENOENT') {
|
|
596
|
-
if (this.config.getEnableRecursiveFileSearch() && globTool) {
|
|
597
|
-
this.debug(
|
|
598
|
-
`Path ${pathName} not found directly, attempting glob search.`,
|
|
599
|
-
);
|
|
600
|
-
try {
|
|
601
|
-
const globResult = await globTool.buildAndExecute(
|
|
602
|
-
{
|
|
603
|
-
pattern: `**/*${pathName}*`,
|
|
604
|
-
path: this.config.getTargetDir(),
|
|
605
|
-
},
|
|
606
|
-
abortSignal,
|
|
607
|
-
);
|
|
608
|
-
if (
|
|
609
|
-
globResult.llmContent &&
|
|
610
|
-
typeof globResult.llmContent === 'string' &&
|
|
611
|
-
!globResult.llmContent.startsWith('No files found') &&
|
|
612
|
-
!globResult.llmContent.startsWith('Error:')
|
|
613
|
-
) {
|
|
614
|
-
const lines = globResult.llmContent.split('\n');
|
|
615
|
-
if (lines.length > 1 && lines[1]) {
|
|
616
|
-
const firstMatchAbsolute = lines[1].trim();
|
|
617
|
-
currentPathSpec = path.relative(
|
|
618
|
-
this.config.getTargetDir(),
|
|
619
|
-
firstMatchAbsolute,
|
|
620
|
-
);
|
|
621
|
-
this.debug(
|
|
622
|
-
`Glob search for ${pathName} found ${firstMatchAbsolute}, using relative path: ${currentPathSpec}`,
|
|
623
|
-
);
|
|
624
|
-
resolvedSuccessfully = true;
|
|
625
|
-
} else {
|
|
626
|
-
this.debug(
|
|
627
|
-
`Glob search for '**/*${pathName}*' did not return a usable path. Path ${pathName} will be skipped.`,
|
|
628
|
-
);
|
|
629
|
-
}
|
|
630
|
-
} else {
|
|
631
|
-
this.debug(
|
|
632
|
-
`Glob search for '**/*${pathName}*' found no files or an error. Path ${pathName} will be skipped.`,
|
|
633
|
-
);
|
|
634
|
-
}
|
|
635
|
-
} catch (globError) {
|
|
636
|
-
console.error(
|
|
637
|
-
`Error during glob search for ${pathName}: ${getErrorMessage(globError)}`,
|
|
638
|
-
);
|
|
639
|
-
}
|
|
640
|
-
} else {
|
|
641
|
-
this.debug(
|
|
642
|
-
`Glob tool not found. Path ${pathName} will be skipped.`,
|
|
643
|
-
);
|
|
644
|
-
}
|
|
645
|
-
} else {
|
|
646
|
-
console.error(
|
|
647
|
-
`Error stating path ${pathName}. Path ${pathName} will be skipped.`,
|
|
648
|
-
);
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
if (resolvedSuccessfully) {
|
|
652
|
-
pathSpecsToRead.push(currentPathSpec);
|
|
653
|
-
atPathToResolvedSpecMap.set(pathName, currentPathSpec);
|
|
654
|
-
contentLabelsForDisplay.push(pathName);
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
// Construct the initial part of the query for the LLM
|
|
659
|
-
let initialQueryText = '';
|
|
660
|
-
for (let i = 0; i < parts.length; i++) {
|
|
661
|
-
const chunk = parts[i];
|
|
662
|
-
if ('text' in chunk) {
|
|
663
|
-
initialQueryText += chunk.text;
|
|
664
|
-
} else {
|
|
665
|
-
// type === 'atPath'
|
|
666
|
-
const resolvedSpec =
|
|
667
|
-
chunk.fileData && atPathToResolvedSpecMap.get(chunk.fileData.fileUri);
|
|
668
|
-
if (
|
|
669
|
-
i > 0 &&
|
|
670
|
-
initialQueryText.length > 0 &&
|
|
671
|
-
!initialQueryText.endsWith(' ') &&
|
|
672
|
-
resolvedSpec
|
|
673
|
-
) {
|
|
674
|
-
// Add space if previous part was text and didn't end with space, or if previous was @path
|
|
675
|
-
const prevPart = parts[i - 1];
|
|
676
|
-
if (
|
|
677
|
-
'text' in prevPart ||
|
|
678
|
-
('fileData' in prevPart &&
|
|
679
|
-
atPathToResolvedSpecMap.has(prevPart.fileData!.fileUri))
|
|
680
|
-
) {
|
|
681
|
-
initialQueryText += ' ';
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
if (resolvedSpec) {
|
|
685
|
-
initialQueryText += `@${resolvedSpec}`;
|
|
686
|
-
} else {
|
|
687
|
-
// If not resolved for reading (e.g. lone @ or invalid path that was skipped),
|
|
688
|
-
// add the original @-string back, ensuring spacing if it's not the first element.
|
|
689
|
-
if (
|
|
690
|
-
i > 0 &&
|
|
691
|
-
initialQueryText.length > 0 &&
|
|
692
|
-
!initialQueryText.endsWith(' ') &&
|
|
693
|
-
!chunk.fileData?.fileUri.startsWith(' ')
|
|
694
|
-
) {
|
|
695
|
-
initialQueryText += ' ';
|
|
696
|
-
}
|
|
697
|
-
if (chunk.fileData?.fileUri) {
|
|
698
|
-
initialQueryText += `@${chunk.fileData.fileUri}`;
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
initialQueryText = initialQueryText.trim();
|
|
704
|
-
// Inform user about ignored paths
|
|
705
|
-
if (ignoredPaths.length > 0) {
|
|
706
|
-
const ignoreType = respectGitIgnore ? 'git-ignored' : 'custom-ignored';
|
|
707
|
-
this.debug(
|
|
708
|
-
`Ignored ${ignoredPaths.length} ${ignoreType} files: ${ignoredPaths.join(', ')}`,
|
|
709
|
-
);
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
const processedQueryParts: Part[] = [{ text: initialQueryText }];
|
|
713
|
-
|
|
714
|
-
if (pathSpecsToRead.length === 0 && embeddedContext.length === 0) {
|
|
715
|
-
// Fallback for lone "@" or completely invalid @-commands resulting in empty initialQueryText
|
|
716
|
-
console.warn('No valid file paths found in @ commands to read.');
|
|
717
|
-
return [{ text: initialQueryText }];
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
if (pathSpecsToRead.length > 0) {
|
|
721
|
-
const toolArgs = {
|
|
722
|
-
paths: pathSpecsToRead,
|
|
723
|
-
respectGitIgnore, // Use configuration setting
|
|
724
|
-
};
|
|
725
|
-
|
|
726
|
-
const callId = `${readManyFilesTool.name}-${Date.now()}`;
|
|
727
|
-
|
|
728
|
-
try {
|
|
729
|
-
const invocation = readManyFilesTool.build(toolArgs);
|
|
730
|
-
|
|
731
|
-
await this.sendUpdate({
|
|
732
|
-
sessionUpdate: 'tool_call',
|
|
733
|
-
toolCallId: callId,
|
|
734
|
-
status: 'in_progress',
|
|
735
|
-
title: invocation.getDescription(),
|
|
736
|
-
content: [],
|
|
737
|
-
locations: invocation.toolLocations(),
|
|
738
|
-
kind: readManyFilesTool.kind,
|
|
739
|
-
});
|
|
740
|
-
|
|
741
|
-
const result = await invocation.execute(abortSignal);
|
|
742
|
-
const content = toToolCallContent(result) || {
|
|
743
|
-
type: 'content',
|
|
744
|
-
content: {
|
|
745
|
-
type: 'text',
|
|
746
|
-
text: `Successfully read: ${contentLabelsForDisplay.join(', ')}`,
|
|
747
|
-
},
|
|
748
|
-
};
|
|
749
|
-
await this.sendUpdate({
|
|
750
|
-
sessionUpdate: 'tool_call_update',
|
|
751
|
-
toolCallId: callId,
|
|
752
|
-
status: 'completed',
|
|
753
|
-
content: content ? [content] : [],
|
|
754
|
-
});
|
|
755
|
-
if (Array.isArray(result.llmContent)) {
|
|
756
|
-
const fileContentRegex = /^--- (.*?) ---\n\n([\s\S]*?)\n\n$/;
|
|
757
|
-
processedQueryParts.push({
|
|
758
|
-
text: '\n--- Content from referenced files ---',
|
|
759
|
-
});
|
|
760
|
-
for (const part of result.llmContent) {
|
|
761
|
-
if (typeof part === 'string') {
|
|
762
|
-
const match = fileContentRegex.exec(part);
|
|
763
|
-
if (match) {
|
|
764
|
-
const filePathSpecInContent = match[1]; // This is a resolved pathSpec
|
|
765
|
-
const fileActualContent = match[2].trim();
|
|
766
|
-
processedQueryParts.push({
|
|
767
|
-
text: `\nContent from @${filePathSpecInContent}:\n`,
|
|
768
|
-
});
|
|
769
|
-
processedQueryParts.push({ text: fileActualContent });
|
|
770
|
-
} else {
|
|
771
|
-
processedQueryParts.push({ text: part });
|
|
772
|
-
}
|
|
773
|
-
} else {
|
|
774
|
-
// part is a Part object.
|
|
775
|
-
processedQueryParts.push(part);
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
} else {
|
|
779
|
-
console.warn(
|
|
780
|
-
'read_many_files tool returned no content or empty content.',
|
|
781
|
-
);
|
|
782
|
-
}
|
|
783
|
-
} catch (error: unknown) {
|
|
784
|
-
await this.sendUpdate({
|
|
785
|
-
sessionUpdate: 'tool_call_update',
|
|
786
|
-
toolCallId: callId,
|
|
787
|
-
status: 'failed',
|
|
788
|
-
content: [
|
|
789
|
-
{
|
|
790
|
-
type: 'content',
|
|
791
|
-
content: {
|
|
792
|
-
type: 'text',
|
|
793
|
-
text: `Error reading files (${contentLabelsForDisplay.join(', ')}): ${getErrorMessage(error)}`,
|
|
794
|
-
},
|
|
795
|
-
},
|
|
796
|
-
],
|
|
797
|
-
});
|
|
798
|
-
|
|
799
|
-
throw error;
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
if (embeddedContext.length > 0) {
|
|
804
|
-
processedQueryParts.push({
|
|
805
|
-
text: '\n--- Content from referenced context ---',
|
|
806
|
-
});
|
|
807
|
-
|
|
808
|
-
for (const contextPart of embeddedContext) {
|
|
809
|
-
processedQueryParts.push({
|
|
810
|
-
text: `\nContent from @${contextPart.uri}:\n`,
|
|
811
|
-
});
|
|
812
|
-
if ('text' in contextPart) {
|
|
813
|
-
processedQueryParts.push({
|
|
814
|
-
text: contextPart.text,
|
|
815
|
-
});
|
|
816
|
-
} else {
|
|
817
|
-
processedQueryParts.push({
|
|
818
|
-
inlineData: {
|
|
819
|
-
mimeType: contextPart.mimeType ?? 'application/octet-stream',
|
|
820
|
-
data: contextPart.blob,
|
|
821
|
-
},
|
|
822
|
-
});
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
return processedQueryParts;
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
debug(msg: string) {
|
|
831
|
-
if (this.config.getDebugMode()) {
|
|
832
|
-
console.warn(msg);
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
function toToolCallContent(toolResult: ToolResult): acp.ToolCallContent | null {
|
|
838
|
-
if (toolResult.error?.message) {
|
|
839
|
-
throw new Error(toolResult.error.message);
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
if (toolResult.returnDisplay) {
|
|
843
|
-
if (typeof toolResult.returnDisplay === 'string') {
|
|
844
|
-
return {
|
|
845
|
-
type: 'content',
|
|
846
|
-
content: { type: 'text', text: toolResult.returnDisplay },
|
|
847
|
-
};
|
|
848
|
-
} else if (
|
|
849
|
-
'type' in toolResult.returnDisplay &&
|
|
850
|
-
toolResult.returnDisplay.type === 'todo_list'
|
|
851
|
-
) {
|
|
852
|
-
// Handle TodoResultDisplay - convert to text representation
|
|
853
|
-
const todoText = toolResult.returnDisplay.todos
|
|
854
|
-
.map((todo) => {
|
|
855
|
-
const statusIcon = {
|
|
856
|
-
pending: '○',
|
|
857
|
-
in_progress: '◐',
|
|
858
|
-
completed: '●',
|
|
859
|
-
}[todo.status];
|
|
860
|
-
return `${statusIcon} ${todo.content}`;
|
|
861
|
-
})
|
|
862
|
-
.join('\n');
|
|
863
|
-
|
|
864
|
-
return {
|
|
865
|
-
type: 'content',
|
|
866
|
-
content: { type: 'text', text: todoText },
|
|
867
|
-
};
|
|
868
|
-
} else if ('fileDiff' in toolResult.returnDisplay) {
|
|
869
|
-
// Handle FileDiff
|
|
870
|
-
return {
|
|
871
|
-
type: 'diff',
|
|
872
|
-
path: toolResult.returnDisplay.fileName,
|
|
873
|
-
oldText: toolResult.returnDisplay.originalContent,
|
|
874
|
-
newText: toolResult.returnDisplay.newContent,
|
|
875
|
-
};
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
return null;
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
const basicPermissionOptions = [
|
|
882
|
-
{
|
|
883
|
-
optionId: ToolConfirmationOutcome.ProceedOnce,
|
|
884
|
-
name: 'Allow',
|
|
885
|
-
kind: 'allow_once',
|
|
886
|
-
},
|
|
887
|
-
{
|
|
888
|
-
optionId: ToolConfirmationOutcome.Cancel,
|
|
889
|
-
name: 'Reject',
|
|
890
|
-
kind: 'reject_once',
|
|
891
|
-
},
|
|
892
|
-
] as const;
|
|
893
|
-
|
|
894
|
-
function toPermissionOptions(
|
|
895
|
-
confirmation: ToolCallConfirmationDetails,
|
|
896
|
-
): acp.PermissionOption[] {
|
|
897
|
-
switch (confirmation.type) {
|
|
898
|
-
case 'edit':
|
|
899
|
-
return [
|
|
900
|
-
{
|
|
901
|
-
optionId: ToolConfirmationOutcome.ProceedAlways,
|
|
902
|
-
name: 'Allow All Edits',
|
|
903
|
-
kind: 'allow_always',
|
|
904
|
-
},
|
|
905
|
-
...basicPermissionOptions,
|
|
906
|
-
];
|
|
907
|
-
case 'exec':
|
|
908
|
-
return [
|
|
909
|
-
{
|
|
910
|
-
optionId: ToolConfirmationOutcome.ProceedAlways,
|
|
911
|
-
name: `Always Allow ${confirmation.rootCommand}`,
|
|
912
|
-
kind: 'allow_always',
|
|
913
|
-
},
|
|
914
|
-
...basicPermissionOptions,
|
|
915
|
-
];
|
|
916
|
-
case 'mcp':
|
|
917
|
-
return [
|
|
918
|
-
{
|
|
919
|
-
optionId: ToolConfirmationOutcome.ProceedAlwaysServer,
|
|
920
|
-
name: `Always Allow ${confirmation.serverName}`,
|
|
921
|
-
kind: 'allow_always',
|
|
922
|
-
},
|
|
923
|
-
{
|
|
924
|
-
optionId: ToolConfirmationOutcome.ProceedAlwaysTool,
|
|
925
|
-
name: `Always Allow ${confirmation.toolName}`,
|
|
926
|
-
kind: 'allow_always',
|
|
927
|
-
},
|
|
928
|
-
...basicPermissionOptions,
|
|
929
|
-
];
|
|
930
|
-
case 'info':
|
|
931
|
-
return [
|
|
932
|
-
{
|
|
933
|
-
optionId: ToolConfirmationOutcome.ProceedAlways,
|
|
934
|
-
name: `Always Allow`,
|
|
935
|
-
kind: 'allow_always',
|
|
936
|
-
},
|
|
937
|
-
...basicPermissionOptions,
|
|
938
|
-
];
|
|
939
|
-
default: {
|
|
940
|
-
const unreachable: never = confirmation;
|
|
941
|
-
throw new Error(`Unexpected: ${unreachable}`);
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
}
|