@machina.ai/cell-cli 1.10.0-rc1 → 1.13.0-rc1
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 +5 -5
- package/dist/index.js.map +1 -1
- package/dist/package.json +14 -12
- package/dist/src/commands/extensions/disable.d.ts +1 -1
- package/dist/src/commands/extensions/disable.js +19 -8
- package/dist/src/commands/extensions/disable.js.map +1 -1
- package/dist/src/commands/extensions/enable.d.ts +1 -1
- package/dist/src/commands/extensions/enable.js +19 -9
- package/dist/src/commands/extensions/enable.js.map +1 -1
- package/dist/src/commands/extensions/examples/mcp-server/example.js +46 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.js.map +1 -0
- package/dist/src/commands/extensions/install.d.ts +1 -0
- package/dist/src/commands/extensions/install.js +29 -4
- package/dist/src/commands/extensions/install.js.map +1 -1
- package/dist/src/commands/extensions/install.test.js +39 -19
- package/dist/src/commands/extensions/install.test.js.map +1 -1
- package/dist/src/commands/extensions/link.js +16 -4
- package/dist/src/commands/extensions/link.js.map +1 -1
- package/dist/src/commands/extensions/list.js +17 -6
- package/dist/src/commands/extensions/list.js.map +1 -1
- package/dist/src/commands/extensions/new.js +14 -20
- package/dist/src/commands/extensions/new.js.map +1 -1
- package/dist/src/commands/extensions/uninstall.js +16 -4
- package/dist/src/commands/extensions/uninstall.js.map +1 -1
- package/dist/src/commands/extensions/update.js +28 -23
- package/dist/src/commands/extensions/update.js.map +1 -1
- package/dist/src/commands/extensions/validate.d.ts +12 -0
- package/dist/src/commands/extensions/validate.js +83 -0
- package/dist/src/commands/extensions/validate.js.map +1 -0
- package/dist/src/commands/extensions/validate.test.d.ts +6 -0
- package/dist/src/commands/extensions/validate.test.js +93 -0
- package/dist/src/commands/extensions/validate.test.js.map +1 -0
- package/dist/src/commands/extensions.js +3 -0
- package/dist/src/commands/extensions.js.map +1 -1
- package/dist/src/commands/mcp/add.js +7 -4
- package/dist/src/commands/mcp/add.js.map +1 -1
- package/dist/src/commands/mcp/add.test.d.ts +6 -0
- package/dist/src/commands/mcp/add.test.js +247 -0
- package/dist/src/commands/mcp/add.test.js.map +1 -0
- package/dist/src/commands/mcp/list.js +18 -9
- package/dist/src/commands/mcp/list.js.map +1 -1
- package/dist/src/commands/mcp/list.test.d.ts +6 -0
- package/dist/src/commands/mcp/list.test.js +128 -0
- package/dist/src/commands/mcp/list.test.js.map +1 -0
- package/dist/src/commands/mcp/remove.js +3 -2
- package/dist/src/commands/mcp/remove.js.map +1 -1
- package/dist/src/commands/mcp/remove.test.d.ts +6 -0
- package/dist/src/commands/mcp/remove.test.js +175 -0
- package/dist/src/commands/mcp/remove.test.js.map +1 -0
- package/dist/src/commands/mcp.test.d.ts +6 -0
- package/dist/src/commands/mcp.test.js +62 -0
- package/dist/src/commands/mcp.test.js.map +1 -0
- package/dist/src/config/auth.js +0 -3
- package/dist/src/config/auth.js.map +1 -1
- package/dist/src/config/config.d.ts +6 -15
- package/dist/src/config/config.integration.test.d.ts +6 -0
- package/dist/src/config/config.integration.test.js +321 -0
- package/dist/src/config/config.integration.test.js.map +1 -0
- package/dist/src/config/config.js +85 -164
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.d.ts +6 -0
- package/dist/src/config/config.test.js +1972 -0
- package/dist/src/config/config.test.js.map +1 -0
- package/dist/src/config/extension-manager.d.ts +63 -0
- package/dist/src/config/extension-manager.js +450 -0
- package/dist/src/config/extension-manager.js.map +1 -0
- package/dist/src/config/extension.d.ts +4 -61
- package/dist/src/config/extension.js +1 -538
- package/dist/src/config/extension.js.map +1 -1
- package/dist/src/config/extension.test.d.ts +6 -0
- package/dist/src/config/extension.test.js +1412 -0
- package/dist/src/config/extension.test.js.map +1 -0
- package/dist/src/config/extensions/consent.d.ts +38 -0
- package/dist/src/config/extensions/consent.js +123 -0
- package/dist/src/config/extensions/consent.js.map +1 -0
- package/dist/src/config/extensions/extensionEnablement.d.ts +2 -2
- package/dist/src/config/extensions/extensionEnablement.js +7 -5
- package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
- package/dist/src/config/extensions/extensionEnablement.test.js +31 -28
- package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -1
- package/dist/src/config/extensions/extensionSettings.d.ts +15 -0
- package/dist/src/config/extensions/extensionSettings.js +113 -0
- package/dist/src/config/extensions/extensionSettings.js.map +1 -0
- package/dist/src/config/extensions/extensionSettings.test.d.ts +6 -0
- package/dist/src/config/extensions/extensionSettings.test.js +254 -0
- package/dist/src/config/extensions/extensionSettings.test.js.map +1 -0
- package/dist/src/config/extensions/github.d.ts +18 -9
- package/dist/src/config/extensions/github.js +108 -36
- package/dist/src/config/extensions/github.js.map +1 -1
- package/dist/src/config/extensions/github.test.js +158 -164
- package/dist/src/config/extensions/github.test.js.map +1 -1
- package/dist/src/config/extensions/github_fetch.d.ts +1 -1
- package/dist/src/config/extensions/github_fetch.js +13 -1
- package/dist/src/config/extensions/github_fetch.js.map +1 -1
- package/dist/src/config/extensions/github_fetch.test.d.ts +6 -0
- package/dist/src/config/extensions/github_fetch.test.js +169 -0
- package/dist/src/config/extensions/github_fetch.test.js.map +1 -0
- package/dist/src/config/extensions/storage.d.ts +14 -0
- package/dist/src/config/extensions/storage.js +32 -0
- package/dist/src/config/extensions/storage.js.map +1 -0
- package/dist/src/config/extensions/update.d.ts +5 -4
- package/dist/src/config/extensions/update.js +41 -37
- package/dist/src/config/extensions/update.js.map +1 -1
- package/dist/src/config/extensions/update.test.js +72 -74
- package/dist/src/config/extensions/update.test.js.map +1 -1
- package/dist/src/config/extensions/variableSchema.d.ts +0 -4
- package/dist/src/config/extensions/variableSchema.js.map +1 -1
- package/dist/src/config/extensions/variables.d.ts +4 -0
- package/dist/src/config/extensions/variables.js +6 -0
- package/dist/src/config/extensions/variables.js.map +1 -1
- package/dist/src/config/keyBindings.d.ts +5 -1
- package/dist/src/config/keyBindings.js +34 -10
- package/dist/src/config/keyBindings.js.map +1 -1
- package/dist/src/config/keyBindings.test.js +17 -0
- package/dist/src/config/keyBindings.test.js.map +1 -1
- package/dist/src/config/policies/read-only.toml +56 -0
- package/dist/src/config/policies/write.toml +63 -0
- package/dist/src/config/policies/yolo.toml +31 -0
- package/dist/src/config/policy-engine.integration.test.js +41 -38
- package/dist/src/config/policy-engine.integration.test.js.map +1 -1
- package/dist/src/config/policy.d.ts +4 -3
- package/dist/src/config/policy.js +13 -142
- package/dist/src/config/policy.js.map +1 -1
- package/dist/src/config/sandboxConfig.d.ts +1 -2
- package/dist/src/config/sandboxConfig.js +7 -6
- package/dist/src/config/sandboxConfig.js.map +1 -1
- package/dist/src/config/settings.d.ts +2 -1
- package/dist/src/config/settings.js +59 -15
- package/dist/src/config/settings.js.map +1 -1
- package/dist/src/config/settings.test.d.ts +6 -0
- package/dist/src/config/settings.test.js +2000 -0
- package/dist/src/config/settings.test.js.map +1 -0
- package/dist/src/config/settingsSchema.d.ts +170 -28
- package/dist/src/config/settingsSchema.js +418 -27
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/config/settingsSchema.test.js +42 -1
- package/dist/src/config/settingsSchema.test.js.map +1 -1
- package/dist/src/config/trustedFolders.d.ts +1 -1
- package/dist/src/config/trustedFolders.js +4 -2
- package/dist/src/config/trustedFolders.js.map +1 -1
- package/dist/src/core/initializer.js +2 -1
- package/dist/src/core/initializer.js.map +1 -1
- package/dist/src/gemini.d.ts +1 -1
- package/dist/src/gemini.js +63 -27
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/gemini.test.js +123 -34
- package/dist/src/gemini.test.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/nonInteractiveCli.d.ts +9 -1
- package/dist/src/nonInteractiveCli.js +205 -10
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/nonInteractiveCli.test.d.ts +6 -0
- package/dist/src/nonInteractiveCli.test.js +984 -0
- package/dist/src/nonInteractiveCli.test.js.map +1 -0
- package/dist/src/nonInteractiveCliCommands.js +2 -2
- package/dist/src/nonInteractiveCliCommands.js.map +1 -1
- package/dist/src/services/BuiltinCommandLoader.js +4 -0
- package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
- package/dist/src/services/BuiltinCommandLoader.test.js +22 -0
- package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
- package/dist/src/services/CommandService.js +2 -1
- package/dist/src/services/CommandService.js.map +1 -1
- package/dist/src/services/FeedbackService.js +2 -2
- package/dist/src/services/FeedbackService.js.map +1 -1
- package/dist/src/services/FileCommandLoader.test.d.ts +6 -0
- package/dist/src/services/FileCommandLoader.test.js +971 -0
- package/dist/src/services/FileCommandLoader.test.js.map +1 -0
- package/dist/src/services/McpPromptLoader.js +2 -2
- package/dist/src/services/McpPromptLoader.js.map +1 -1
- package/dist/src/services/McpPromptLoader.test.js +4 -2
- package/dist/src/services/McpPromptLoader.test.js.map +1 -1
- package/dist/src/services/prompt-processors/argumentProcessor.test.d.ts +6 -0
- package/dist/src/services/prompt-processors/argumentProcessor.test.js +40 -0
- package/dist/src/services/prompt-processors/argumentProcessor.test.js.map +1 -0
- package/dist/src/services/prompt-processors/atFileProcessor.js +3 -2
- package/dist/src/services/prompt-processors/atFileProcessor.js.map +1 -1
- package/dist/src/services/prompt-processors/shellProcessor.test.d.ts +6 -0
- package/dist/src/services/prompt-processors/shellProcessor.test.js +482 -0
- package/dist/src/services/prompt-processors/shellProcessor.test.js.map +1 -0
- package/dist/src/test-utils/async.d.ts +9 -0
- package/dist/src/test-utils/async.js +29 -0
- package/dist/src/test-utils/async.js.map +1 -0
- package/dist/src/test-utils/createExtension.d.ts +3 -1
- package/dist/src/test-utils/createExtension.js +3 -3
- package/dist/src/test-utils/createExtension.js.map +1 -1
- package/dist/src/test-utils/render.d.ts +17 -2
- package/dist/src/test-utils/render.js +69 -4
- package/dist/src/test-utils/render.js.map +1 -1
- package/dist/src/test-utils/render.test.d.ts +6 -0
- package/dist/src/test-utils/render.test.js +79 -0
- package/dist/src/test-utils/render.test.js.map +1 -0
- package/dist/src/ui/App.test.d.ts +6 -0
- package/dist/src/ui/App.test.js +110 -0
- package/dist/src/ui/App.test.js.map +1 -0
- package/dist/src/ui/AppContainer.js +223 -92
- package/dist/src/ui/AppContainer.js.map +1 -1
- package/dist/src/ui/AppContainer.test.js +531 -147
- package/dist/src/ui/AppContainer.test.js.map +1 -1
- package/dist/src/ui/IdeIntegrationNudge.js +1 -1
- package/dist/src/ui/IdeIntegrationNudge.js.map +1 -1
- package/dist/src/ui/auth/ApiAuthDialog.d.ts +14 -0
- package/dist/src/ui/auth/ApiAuthDialog.js +26 -0
- package/dist/src/ui/auth/ApiAuthDialog.js.map +1 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.d.ts +6 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.js +91 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.js.map +1 -0
- package/dist/src/ui/auth/AuthDialog.d.ts +1 -1
- package/dist/src/ui/auth/AuthDialog.js +9 -3
- package/dist/src/ui/auth/AuthDialog.js.map +1 -1
- package/dist/src/ui/auth/useAuth.d.ts +3 -1
- package/dist/src/ui/auth/useAuth.js +35 -4
- package/dist/src/ui/auth/useAuth.js.map +1 -1
- package/dist/src/ui/colors.js +3 -0
- package/dist/src/ui/colors.js.map +1 -1
- package/dist/src/ui/commands/aboutCommand.js +1 -1
- package/dist/src/ui/commands/aboutCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/aboutCommand.test.js +130 -0
- package/dist/src/ui/commands/aboutCommand.test.js.map +1 -0
- package/dist/src/ui/commands/authCommand.js +1 -1
- package/dist/src/ui/commands/authCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/authCommand.test.js +30 -0
- package/dist/src/ui/commands/authCommand.test.js.map +1 -0
- package/dist/src/ui/commands/bugCommand.js +1 -1
- package/dist/src/ui/commands/bugCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/bugCommand.test.js +105 -0
- package/dist/src/ui/commands/bugCommand.test.js.map +1 -0
- package/dist/src/ui/commands/chatCommand.js +1 -1
- package/dist/src/ui/commands/chatCommand.js.map +1 -1
- package/dist/src/ui/commands/chatCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/chatCommand.test.js +555 -0
- package/dist/src/ui/commands/chatCommand.test.js.map +1 -0
- package/dist/src/ui/commands/clearCommand.js +1 -1
- package/dist/src/ui/commands/clearCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/clearCommand.test.js +76 -0
- package/dist/src/ui/commands/clearCommand.test.js.map +1 -0
- package/dist/src/ui/commands/compressCommand.js +1 -1
- package/dist/src/ui/commands/compressCommand.js.map +1 -1
- package/dist/src/ui/commands/compressCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/compressCommand.test.js +98 -0
- package/dist/src/ui/commands/compressCommand.test.js.map +1 -0
- package/dist/src/ui/commands/copyCommand.js +2 -1
- package/dist/src/ui/commands/copyCommand.js.map +1 -1
- package/dist/src/ui/commands/copyCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/copyCommand.test.js +242 -0
- package/dist/src/ui/commands/copyCommand.test.js.map +1 -0
- package/dist/src/ui/commands/corgiCommand.js +1 -1
- package/dist/src/ui/commands/corgiCommand.js.map +1 -1
- package/dist/src/ui/commands/corgiCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/corgiCommand.test.js +28 -0
- package/dist/src/ui/commands/corgiCommand.test.js.map +1 -0
- package/dist/src/ui/commands/directoryCommand.js +1 -1
- package/dist/src/ui/commands/directoryCommand.js.map +1 -1
- package/dist/src/ui/commands/directoryCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/directoryCommand.test.js +144 -0
- package/dist/src/ui/commands/directoryCommand.test.js.map +1 -0
- package/dist/src/ui/commands/docsCommand.js +1 -1
- package/dist/src/ui/commands/docsCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/docsCommand.test.js +72 -0
- package/dist/src/ui/commands/docsCommand.test.js.map +1 -0
- package/dist/src/ui/commands/editorCommand.js +1 -1
- package/dist/src/ui/commands/editorCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/editorCommand.test.js +27 -0
- package/dist/src/ui/commands/editorCommand.test.js.map +1 -0
- package/dist/src/ui/commands/extensionsCommand.js +64 -11
- package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
- package/dist/src/ui/commands/extensionsCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/extensionsCommand.test.js +315 -0
- package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -0
- package/dist/src/ui/commands/helpCommand.js +1 -1
- package/dist/src/ui/commands/helpCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/helpCommand.test.js +42 -0
- package/dist/src/ui/commands/helpCommand.test.js.map +1 -0
- package/dist/src/ui/commands/ideCommand.js +6 -6
- package/dist/src/ui/commands/ideCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/ideCommand.test.js +205 -0
- package/dist/src/ui/commands/ideCommand.test.js.map +1 -0
- package/dist/src/ui/commands/initCommand.js +1 -1
- package/dist/src/ui/commands/initCommand.js.map +1 -1
- package/dist/src/ui/commands/initCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/initCommand.test.js +80 -0
- package/dist/src/ui/commands/initCommand.test.js.map +1 -0
- package/dist/src/ui/commands/mcpCommand.js +110 -100
- package/dist/src/ui/commands/mcpCommand.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/mcpCommand.test.js +152 -0
- package/dist/src/ui/commands/mcpCommand.test.js.map +1 -0
- package/dist/src/ui/commands/memoryCommand.js +6 -6
- package/dist/src/ui/commands/memoryCommand.js.map +1 -1
- package/dist/src/ui/commands/memoryCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/memoryCommand.test.js +268 -0
- package/dist/src/ui/commands/memoryCommand.test.js.map +1 -0
- package/dist/src/ui/commands/policiesCommand.d.ts +7 -0
- package/dist/src/ui/commands/policiesCommand.js +59 -0
- package/dist/src/ui/commands/policiesCommand.js.map +1 -0
- package/dist/src/ui/commands/policiesCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/policiesCommand.test.js +83 -0
- package/dist/src/ui/commands/policiesCommand.test.js.map +1 -0
- package/dist/src/ui/commands/privacyCommand.js +1 -1
- package/dist/src/ui/commands/privacyCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/privacyCommand.test.js +32 -0
- package/dist/src/ui/commands/privacyCommand.test.js.map +1 -0
- package/dist/src/ui/commands/quitCommand.js +1 -1
- package/dist/src/ui/commands/quitCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/quitCommand.test.js +50 -0
- package/dist/src/ui/commands/quitCommand.test.js.map +1 -0
- package/dist/src/ui/commands/restoreCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/restoreCommand.test.js +190 -0
- package/dist/src/ui/commands/restoreCommand.test.js.map +1 -0
- package/dist/src/ui/commands/settingsCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/settingsCommand.test.js +30 -0
- package/dist/src/ui/commands/settingsCommand.test.js.map +1 -0
- package/dist/src/ui/commands/setupGithubCommand.js +4 -3
- package/dist/src/ui/commands/setupGithubCommand.js.map +1 -1
- package/dist/src/ui/commands/setupGithubCommand.test.js +1 -2
- package/dist/src/ui/commands/setupGithubCommand.test.js.map +1 -1
- package/dist/src/ui/commands/statsCommand.js +3 -3
- package/dist/src/ui/commands/statsCommand.js.map +1 -1
- package/dist/src/ui/commands/statsCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/statsCommand.test.js +53 -0
- package/dist/src/ui/commands/statsCommand.test.js.map +1 -0
- package/dist/src/ui/commands/terminalSetupCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/terminalSetupCommand.test.js +66 -0
- package/dist/src/ui/commands/terminalSetupCommand.test.js.map +1 -0
- package/dist/src/ui/commands/themeCommand.js +1 -1
- package/dist/src/ui/commands/themeCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/themeCommand.test.js +32 -0
- package/dist/src/ui/commands/themeCommand.test.js.map +1 -0
- package/dist/src/ui/commands/toolsCommand.js +1 -1
- package/dist/src/ui/commands/toolsCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/toolsCommand.test.js +100 -0
- package/dist/src/ui/commands/toolsCommand.test.js.map +1 -0
- package/dist/src/ui/commands/types.d.ts +1 -0
- package/dist/src/ui/commands/vimCommand.js +1 -1
- package/dist/src/ui/components/AnsiOutput.test.js +1 -1
- package/dist/src/ui/components/AnsiOutput.test.js.map +1 -1
- package/dist/src/ui/components/AsciiArt.d.ts +3 -3
- package/dist/src/ui/components/AsciiArt.js +3 -3
- package/dist/src/ui/components/Composer.js +6 -4
- package/dist/src/ui/components/Composer.js.map +1 -1
- package/dist/src/ui/components/Composer.test.js +21 -3
- package/dist/src/ui/components/Composer.test.js.map +1 -1
- package/dist/src/ui/components/ConfigInitDisplay.js +4 -6
- package/dist/src/ui/components/ConfigInitDisplay.js.map +1 -1
- package/dist/src/ui/components/ConsentPrompt.test.js +18 -8
- package/dist/src/ui/components/ConsentPrompt.test.js.map +1 -1
- package/dist/src/ui/components/ConsoleSummaryDisplay.js +1 -1
- package/dist/src/ui/components/ConsoleSummaryDisplay.js.map +1 -1
- package/dist/src/ui/components/ContextSummaryDisplay.d.ts +0 -1
- package/dist/src/ui/components/ContextSummaryDisplay.js +2 -12
- package/dist/src/ui/components/ContextSummaryDisplay.js.map +1 -1
- package/dist/src/ui/components/ContextSummaryDisplay.test.d.ts +6 -0
- package/dist/src/ui/components/ContextSummaryDisplay.test.js +71 -0
- package/dist/src/ui/components/ContextSummaryDisplay.test.js.map +1 -0
- package/dist/src/ui/components/DetailedMessagesDisplay.js +1 -1
- package/dist/src/ui/components/DetailedMessagesDisplay.js.map +1 -1
- package/dist/src/ui/components/DialogManager.js +5 -5
- package/dist/src/ui/components/DialogManager.js.map +1 -1
- package/dist/src/ui/components/EditorSettingsDialog.js +1 -1
- package/dist/src/ui/components/EditorSettingsDialog.js.map +1 -1
- package/dist/src/ui/components/FolderTrustDialog.test.js +8 -3
- package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/Footer.js +4 -3
- package/dist/src/ui/components/Footer.js.map +1 -1
- package/dist/src/ui/components/Footer.test.d.ts +6 -0
- package/dist/src/ui/components/Footer.test.js +314 -0
- package/dist/src/ui/components/Footer.test.js.map +1 -0
- package/dist/src/ui/components/Header.test.js +13 -5
- package/dist/src/ui/components/Header.test.js.map +1 -1
- package/dist/src/ui/components/Help.test.js +5 -4
- package/dist/src/ui/components/Help.test.js.map +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.d.ts +4 -0
- package/dist/src/ui/components/InputPrompt.js +80 -12
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.test.d.ts +6 -0
- package/dist/src/ui/components/InputPrompt.test.js +1786 -0
- package/dist/src/ui/components/InputPrompt.test.js.map +1 -0
- package/dist/src/ui/components/LoadingIndicator.js +2 -2
- package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
- package/dist/src/ui/components/LoadingIndicator.test.js +28 -15
- package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/components/LoopDetectionConfirmation.js +1 -1
- package/dist/src/ui/components/LoopDetectionConfirmation.js.map +1 -1
- package/dist/src/ui/components/LoopDetectionConfirmation.test.js +2 -2
- package/dist/src/ui/components/LoopDetectionConfirmation.test.js.map +1 -1
- package/dist/src/ui/components/MainContent.js +15 -4
- package/dist/src/ui/components/MainContent.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.js +1 -1
- package/dist/src/ui/components/ModelDialog.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.test.js +23 -13
- package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
- package/dist/src/ui/components/ModelStatsDisplay.test.d.ts +6 -0
- package/dist/src/ui/components/ModelStatsDisplay.test.js +285 -0
- package/dist/src/ui/components/ModelStatsDisplay.test.js.map +1 -0
- package/dist/src/ui/components/Notifications.js +38 -5
- package/dist/src/ui/components/Notifications.js.map +1 -1
- package/dist/src/ui/components/PermissionsModifyTrustDialog.js +22 -18
- package/dist/src/ui/components/PermissionsModifyTrustDialog.js.map +1 -1
- package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +12 -4
- package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/PrepareLabel.test.js +14 -8
- package/dist/src/ui/components/PrepareLabel.test.js.map +1 -1
- package/dist/src/ui/components/ProQuotaDialog.test.js +14 -6
- package/dist/src/ui/components/ProQuotaDialog.test.js.map +1 -1
- package/dist/src/ui/components/QueuedMessageDisplay.js +3 -3
- package/dist/src/ui/components/QueuedMessageDisplay.js.map +1 -1
- package/dist/src/ui/components/QueuedMessageDisplay.test.js +15 -6
- package/dist/src/ui/components/QueuedMessageDisplay.test.js.map +1 -1
- package/dist/src/ui/components/RawMarkdownIndicator.d.ts +7 -0
- package/dist/src/ui/components/RawMarkdownIndicator.js +8 -0
- package/dist/src/ui/components/RawMarkdownIndicator.js.map +1 -0
- package/dist/src/ui/components/SessionSummaryDisplay.test.d.ts +6 -0
- package/dist/src/ui/components/SessionSummaryDisplay.test.js +74 -0
- package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +1 -0
- package/dist/src/ui/components/SettingsDialog.js +43 -35
- package/dist/src/ui/components/SettingsDialog.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.test.js +554 -545
- package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.js +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.test.js +2 -2
- package/dist/src/ui/components/ShellConfirmationDialog.test.js.map +1 -1
- package/dist/src/ui/components/StatsDisplay.test.d.ts +6 -0
- package/dist/src/ui/components/StatsDisplay.test.js +351 -0
- package/dist/src/ui/components/StatsDisplay.test.js.map +1 -0
- package/dist/src/ui/components/SuggestionsDisplay.js +1 -1
- package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
- package/dist/src/ui/components/ThemeDialog.d.ts +4 -2
- package/dist/src/ui/components/ThemeDialog.js +3 -3
- package/dist/src/ui/components/ThemeDialog.js.map +1 -1
- package/dist/src/ui/components/ThemeDialog.test.js +14 -1
- package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
- package/dist/src/ui/components/ToolStatsDisplay.test.d.ts +6 -0
- package/dist/src/ui/components/ToolStatsDisplay.test.js +227 -0
- package/dist/src/ui/components/ToolStatsDisplay.test.js.map +1 -0
- package/dist/src/ui/components/messages/CompressionMessage.test.js +25 -17
- package/dist/src/ui/components/messages/CompressionMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.test.js +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -1
- package/dist/src/ui/components/messages/GeminiMessage.js +3 -1
- package/dist/src/ui/components/messages/GeminiMessage.js.map +1 -1
- package/dist/src/ui/components/messages/GeminiMessage.test.d.ts +6 -0
- package/dist/src/ui/components/messages/GeminiMessage.test.js +35 -0
- package/dist/src/ui/components/messages/GeminiMessage.test.js.map +1 -0
- package/dist/src/ui/components/messages/GeminiMessageContent.js +3 -1
- package/dist/src/ui/components/messages/GeminiMessageContent.js.map +1 -1
- package/dist/src/ui/components/messages/InfoMessage.js +1 -1
- package/dist/src/ui/components/messages/InfoMessage.js.map +1 -1
- package/dist/src/ui/components/messages/Todo.d.ts +7 -0
- package/dist/src/ui/components/messages/Todo.js +91 -0
- package/dist/src/ui/components/messages/Todo.js.map +1 -0
- package/dist/src/ui/components/messages/Todo.test.d.ts +6 -0
- package/dist/src/ui/components/messages/Todo.test.js +114 -0
- package/dist/src/ui/components/messages/Todo.test.js.map +1 -0
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.js +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js +29 -15
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolMessage.js +8 -3
- package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolMessage.test.js +2 -2
- package/dist/src/ui/components/messages/ToolMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.d.ts +6 -0
- package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js +30 -0
- package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js.map +1 -0
- package/dist/src/ui/components/messages/UserShellMessage.js +1 -1
- package/dist/src/ui/components/messages/UserShellMessage.js.map +1 -1
- package/dist/src/ui/components/messages/WarningMessage.js +2 -2
- package/dist/src/ui/components/messages/WarningMessage.js.map +1 -1
- package/dist/src/ui/components/shared/BaseSelectionList.test.js +34 -25
- package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
- package/dist/src/ui/components/shared/MaxSizedBox.test.js +43 -22
- package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -1
- package/dist/src/ui/components/shared/TextInput.d.ts +15 -0
- package/dist/src/ui/components/shared/TextInput.js +38 -0
- package/dist/src/ui/components/shared/TextInput.js.map +1 -0
- package/dist/src/ui/components/shared/TextInput.test.d.ts +6 -0
- package/dist/src/ui/components/shared/TextInput.test.js +242 -0
- package/dist/src/ui/components/shared/TextInput.test.js.map +1 -0
- package/dist/src/ui/components/shared/text-buffer.d.ts +9 -2
- package/dist/src/ui/components/shared/text-buffer.js +52 -14
- package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
- package/dist/src/ui/components/shared/text-buffer.test.d.ts +6 -0
- package/dist/src/ui/components/shared/text-buffer.test.js +1761 -0
- package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -0
- package/dist/src/ui/components/shared/vim-buffer-actions.test.d.ts +6 -0
- package/dist/src/ui/components/shared/vim-buffer-actions.test.js +951 -0
- package/dist/src/ui/components/shared/vim-buffer-actions.test.js.map +1 -0
- package/dist/src/ui/components/views/ChatList.test.js +7 -4
- package/dist/src/ui/components/views/ChatList.test.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionsList.d.ts +7 -1
- package/dist/src/ui/components/views/ExtensionsList.js +12 -15
- package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionsList.test.js +43 -29
- package/dist/src/ui/components/views/ExtensionsList.test.js.map +1 -1
- package/dist/src/ui/components/views/McpStatus.d.ts +0 -1
- package/dist/src/ui/components/views/McpStatus.js +4 -4
- package/dist/src/ui/components/views/McpStatus.js.map +1 -1
- package/dist/src/ui/components/views/McpStatus.test.js +23 -17
- package/dist/src/ui/components/views/McpStatus.test.js.map +1 -1
- package/dist/src/ui/components/views/ToolsList.test.js +4 -4
- package/dist/src/ui/components/views/ToolsList.test.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.d.ts +4 -2
- package/dist/src/ui/contexts/KeypressContext.js +635 -439
- package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.test.js +634 -515
- package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
- package/dist/src/ui/contexts/MouseContext.d.ts +21 -0
- package/dist/src/ui/contexts/MouseContext.js +89 -0
- package/dist/src/ui/contexts/MouseContext.js.map +1 -0
- package/dist/src/ui/contexts/MouseContext.test.d.ts +6 -0
- package/dist/src/ui/contexts/MouseContext.test.js +164 -0
- package/dist/src/ui/contexts/MouseContext.test.js.map +1 -0
- package/dist/src/ui/contexts/SessionContext.test.d.ts +6 -0
- package/dist/src/ui/contexts/SessionContext.test.js +195 -0
- package/dist/src/ui/contexts/SessionContext.test.js.map +1 -0
- package/dist/src/ui/contexts/UIActionsContext.d.ts +7 -4
- package/dist/src/ui/contexts/UIStateContext.d.ts +5 -3
- package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.js +33 -11
- package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.test.js +163 -64
- package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/shellCommandProcessor.js +0 -1
- package/dist/src/ui/hooks/shellCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/shellCommandProcessor.test.js +64 -35
- package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.js +2 -0
- package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.test.d.ts +6 -0
- package/dist/src/ui/hooks/slashCommandProcessor.test.js +807 -0
- package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -0
- package/dist/src/ui/hooks/useAtCompletion.js +2 -2
- package/dist/src/ui/hooks/useAtCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useAtCompletion.test.d.ts +6 -0
- package/dist/src/ui/hooks/useAtCompletion.test.js +396 -0
- package/dist/src/ui/hooks/useAtCompletion.test.js.map +1 -0
- package/dist/src/ui/hooks/useAutoAcceptIndicator.js +10 -0
- package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +1 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +32 -2
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.d.ts +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.js +5 -3
- package/dist/src/ui/hooks/useCommandCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.test.d.ts +6 -0
- package/dist/src/ui/hooks/useCommandCompletion.test.js +377 -0
- package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -0
- package/dist/src/ui/hooks/useConsoleMessages.test.d.ts +6 -0
- package/dist/src/ui/hooks/useConsoleMessages.test.js +127 -0
- package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -0
- package/dist/src/ui/hooks/useEditorSettings.test.js +40 -34
- package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.d.ts +14 -4
- package/dist/src/ui/hooks/useExtensionUpdates.js +18 -11
- package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.test.js +52 -35
- package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
- package/dist/src/ui/hooks/useFlickerDetector.test.js +9 -5
- package/dist/src/ui/hooks/useFlickerDetector.test.js.map +1 -1
- package/dist/src/ui/hooks/useFocus.test.d.ts +6 -0
- package/dist/src/ui/hooks/useFocus.test.js +131 -0
- package/dist/src/ui/hooks/useFocus.test.js.map +1 -0
- package/dist/src/ui/hooks/useFolderTrust.test.d.ts +6 -0
- package/dist/src/ui/hooks/useFolderTrust.test.js +188 -0
- package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -0
- package/dist/src/ui/hooks/useGeminiStream.js +119 -74
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.test.d.ts +6 -0
- package/dist/src/ui/hooks/useGeminiStream.test.js +1820 -0
- package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -0
- package/dist/src/ui/hooks/useGitBranchName.js +4 -0
- package/dist/src/ui/hooks/useGitBranchName.js.map +1 -1
- package/dist/src/ui/hooks/useGitBranchName.test.js +46 -34
- package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
- package/dist/src/ui/hooks/useHistoryManager.test.js +2 -1
- package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -1
- package/dist/src/ui/hooks/useIdeTrustListener.test.js +40 -9
- package/dist/src/ui/hooks/useIdeTrustListener.test.js.map +1 -1
- package/dist/src/ui/hooks/useInputHistory.test.js +2 -1
- package/dist/src/ui/hooks/useInputHistory.test.js.map +1 -1
- package/dist/src/ui/hooks/useInputHistoryStore.js +2 -1
- package/dist/src/ui/hooks/useInputHistoryStore.js.map +1 -1
- package/dist/src/ui/hooks/useInputHistoryStore.test.js +2 -1
- package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +1 -1
- package/dist/src/ui/hooks/useKeypress.test.d.ts +6 -0
- package/dist/src/ui/hooks/useKeypress.test.js +223 -0
- package/dist/src/ui/hooks/useKeypress.test.js.map +1 -0
- package/dist/src/ui/hooks/useLoadingIndicator.test.js +29 -6
- package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/useMemoryMonitor.test.js +10 -5
- package/dist/src/ui/hooks/useMemoryMonitor.test.js.map +1 -1
- package/dist/src/ui/hooks/useMessageQueue.d.ts +1 -0
- package/dist/src/ui/hooks/useMessageQueue.js +14 -0
- package/dist/src/ui/hooks/useMessageQueue.js.map +1 -1
- package/dist/src/ui/hooks/useMessageQueue.test.js +173 -35
- package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
- package/dist/src/ui/hooks/useModelCommand.test.js +21 -11
- package/dist/src/ui/hooks/useModelCommand.test.js.map +1 -1
- package/dist/src/ui/hooks/useMouse.d.ts +17 -0
- package/dist/src/ui/hooks/useMouse.js +27 -0
- package/dist/src/ui/hooks/useMouse.js.map +1 -0
- package/dist/src/ui/hooks/useMouse.test.d.ts +6 -0
- package/dist/src/ui/hooks/useMouse.test.js +57 -0
- package/dist/src/ui/hooks/useMouse.test.js.map +1 -0
- package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +2 -2
- package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.d.ts +1 -0
- package/dist/src/ui/hooks/usePhraseCycler.js +156 -5
- package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.test.d.ts +6 -0
- package/dist/src/ui/hooks/usePhraseCycler.test.js +158 -0
- package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -0
- package/dist/src/ui/hooks/usePrivacySettings.test.js +26 -6
- package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -1
- package/dist/src/ui/hooks/usePromptCompletion.js +2 -2
- package/dist/src/ui/hooks/usePromptCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useQuotaAndFallback.js +13 -14
- package/dist/src/ui/hooks/useQuotaAndFallback.js.map +1 -1
- package/dist/src/ui/hooks/useQuotaAndFallback.test.js +55 -48
- package/dist/src/ui/hooks/useQuotaAndFallback.test.js.map +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.d.ts +8 -1
- package/dist/src/ui/hooks/useReactToolScheduler.js +61 -36
- package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.test.d.ts +6 -0
- package/dist/src/ui/hooks/useReactToolScheduler.test.js +65 -0
- package/dist/src/ui/hooks/useReactToolScheduler.test.js.map +1 -0
- package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +2 -2
- package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useSelectionList.js +5 -4
- package/dist/src/ui/hooks/useSelectionList.js.map +1 -1
- package/dist/src/ui/hooks/useSelectionList.test.js +272 -183
- package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
- package/dist/src/ui/hooks/useShellHistory.test.js +52 -20
- package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -1
- package/dist/src/ui/hooks/useShowMemoryCommand.d.ts +1 -1
- package/dist/src/ui/hooks/useShowMemoryCommand.js +4 -3
- package/dist/src/ui/hooks/useShowMemoryCommand.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.js +20 -8
- package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.test.js +275 -137
- package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useThemeCommand.d.ts +2 -1
- package/dist/src/ui/hooks/useThemeCommand.js +6 -0
- package/dist/src/ui/hooks/useThemeCommand.js.map +1 -1
- package/dist/src/ui/hooks/useTimer.test.js +43 -14
- package/dist/src/ui/hooks/useTimer.test.js.map +1 -1
- package/dist/src/ui/hooks/useToolScheduler.test.js +229 -242
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
- package/dist/src/ui/hooks/vim.js +2 -1
- package/dist/src/ui/hooks/vim.js.map +1 -1
- package/dist/src/ui/hooks/vim.test.d.ts +6 -0
- package/dist/src/ui/hooks/vim.test.js +1269 -0
- package/dist/src/ui/hooks/vim.test.js.map +1 -0
- package/dist/src/ui/keyMatchers.test.js +39 -6
- package/dist/src/ui/keyMatchers.test.js.map +1 -1
- package/dist/src/ui/state/extensions.d.ts +1 -0
- package/dist/src/ui/state/extensions.js +1 -0
- package/dist/src/ui/state/extensions.js.map +1 -1
- package/dist/src/ui/themes/ansi-light.js +1 -0
- package/dist/src/ui/themes/ansi-light.js.map +1 -1
- package/dist/src/ui/themes/ansi.js +1 -0
- package/dist/src/ui/themes/ansi.js.map +1 -1
- package/dist/src/ui/themes/atom-one-dark.js +2 -0
- package/dist/src/ui/themes/atom-one-dark.js.map +1 -1
- package/dist/src/ui/themes/ayu-light.js +2 -0
- package/dist/src/ui/themes/ayu-light.js.map +1 -1
- package/dist/src/ui/themes/ayu.js +2 -0
- package/dist/src/ui/themes/ayu.js.map +1 -1
- package/dist/src/ui/themes/color-utils.d.ts +1 -0
- package/dist/src/ui/themes/color-utils.js +8 -1
- package/dist/src/ui/themes/color-utils.js.map +1 -1
- package/dist/src/ui/themes/color-utils.test.js +13 -1
- package/dist/src/ui/themes/color-utils.test.js.map +1 -1
- package/dist/src/ui/themes/dracula.js +2 -0
- package/dist/src/ui/themes/dracula.js.map +1 -1
- package/dist/src/ui/themes/github-dark.js +2 -0
- package/dist/src/ui/themes/github-dark.js.map +1 -1
- package/dist/src/ui/themes/github-light.js +2 -0
- package/dist/src/ui/themes/github-light.js.map +1 -1
- package/dist/src/ui/themes/googlecode.js +2 -0
- package/dist/src/ui/themes/googlecode.js.map +1 -1
- package/dist/src/ui/themes/no-color.js +3 -0
- package/dist/src/ui/themes/no-color.js.map +1 -1
- package/dist/src/ui/themes/semantic-tokens.d.ts +2 -0
- package/dist/src/ui/themes/semantic-tokens.js +6 -0
- package/dist/src/ui/themes/semantic-tokens.js.map +1 -1
- package/dist/src/ui/themes/shades-of-purple.js +2 -0
- package/dist/src/ui/themes/shades-of-purple.js.map +1 -1
- package/dist/src/ui/themes/theme-manager.js +8 -7
- package/dist/src/ui/themes/theme-manager.js.map +1 -1
- package/dist/src/ui/themes/theme.d.ts +3 -0
- package/dist/src/ui/themes/theme.js +14 -3
- package/dist/src/ui/themes/theme.js.map +1 -1
- package/dist/src/ui/themes/theme.test.d.ts +6 -0
- package/dist/src/ui/themes/theme.test.js +151 -0
- package/dist/src/ui/themes/theme.test.js.map +1 -0
- package/dist/src/ui/themes/xcode.js +2 -0
- package/dist/src/ui/themes/xcode.js.map +1 -1
- package/dist/src/ui/types.d.ts +3 -2
- package/dist/src/ui/types.js +2 -0
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/ui/utils/CodeColorizer.d.ts +1 -1
- package/dist/src/ui/utils/CodeColorizer.js +6 -3
- package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
- package/dist/src/ui/utils/InlineMarkdownRenderer.d.ts +1 -0
- package/dist/src/ui/utils/InlineMarkdownRenderer.js +11 -10
- 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 +19 -10
- package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
- package/dist/src/ui/utils/clipboardUtils.js +2 -2
- package/dist/src/ui/utils/clipboardUtils.js.map +1 -1
- package/dist/src/ui/utils/commandUtils.js +20 -3
- package/dist/src/ui/utils/commandUtils.js.map +1 -1
- package/dist/src/ui/utils/commandUtils.test.js +61 -6
- package/dist/src/ui/utils/commandUtils.test.js.map +1 -1
- package/dist/src/ui/utils/computeStats.js +5 -2
- package/dist/src/ui/utils/computeStats.js.map +1 -1
- package/dist/src/ui/utils/computeStats.test.d.ts +6 -0
- package/dist/src/ui/utils/computeStats.test.js +262 -0
- package/dist/src/ui/utils/computeStats.test.js.map +1 -0
- package/dist/src/ui/utils/input.d.ts +17 -0
- package/dist/src/ui/utils/input.js +51 -0
- package/dist/src/ui/utils/input.js.map +1 -0
- package/dist/src/ui/utils/input.test.d.ts +6 -0
- package/dist/src/ui/utils/input.test.js +44 -0
- package/dist/src/ui/utils/input.test.js.map +1 -0
- package/dist/src/ui/utils/kittyProtocolDetector.js +13 -4
- package/dist/src/ui/utils/kittyProtocolDetector.js.map +1 -1
- package/dist/src/ui/utils/mouse.d.ts +31 -0
- package/dist/src/ui/utils/mouse.js +164 -0
- package/dist/src/ui/utils/mouse.js.map +1 -0
- package/dist/src/ui/utils/mouse.test.d.ts +6 -0
- package/dist/src/ui/utils/mouse.test.js +131 -0
- package/dist/src/ui/utils/mouse.test.js.map +1 -0
- package/dist/src/ui/utils/terminalSetup.js +3 -2
- package/dist/src/ui/utils/terminalSetup.js.map +1 -1
- package/dist/src/ui/utils/textOutput.d.ts +25 -0
- package/dist/src/ui/utils/textOutput.js +49 -0
- package/dist/src/ui/utils/textOutput.js.map +1 -0
- package/dist/src/ui/utils/textOutput.test.d.ts +6 -0
- package/dist/src/ui/utils/textOutput.test.js +79 -0
- package/dist/src/ui/utils/textOutput.test.js.map +1 -0
- package/dist/src/ui/utils/updateCheck.d.ts +9 -2
- package/dist/src/ui/utils/updateCheck.js +38 -30
- package/dist/src/ui/utils/updateCheck.js.map +1 -1
- package/dist/src/ui/utils/updateCheck.test.js +48 -59
- package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
- package/dist/src/utils/cleanup.test.d.ts +6 -0
- package/dist/src/utils/cleanup.test.js +49 -0
- package/dist/src/utils/cleanup.test.js.map +1 -0
- package/dist/src/utils/commentJson.js +2 -2
- package/dist/src/utils/commentJson.js.map +1 -1
- package/dist/src/utils/commentJson.test.js +7 -6
- package/dist/src/utils/commentJson.test.js.map +1 -1
- package/dist/src/utils/envVarResolver.d.ts +2 -2
- package/dist/src/utils/envVarResolver.js +10 -7
- package/dist/src/utils/envVarResolver.js.map +1 -1
- package/dist/src/utils/errors.d.ts +1 -0
- package/dist/src/utils/errors.js +66 -5
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/events.d.ts +11 -2
- package/dist/src/utils/events.js +1 -0
- package/dist/src/utils/events.js.map +1 -1
- package/dist/src/utils/gitUtils.js +3 -2
- package/dist/src/utils/gitUtils.js.map +1 -1
- package/dist/src/utils/handleAutoUpdate.js +9 -3
- package/dist/src/utils/handleAutoUpdate.js.map +1 -1
- package/dist/src/utils/handleAutoUpdate.test.d.ts +6 -0
- package/dist/src/utils/handleAutoUpdate.test.js +225 -0
- package/dist/src/utils/handleAutoUpdate.test.js.map +1 -0
- package/dist/src/utils/installationInfo.js +2 -2
- package/dist/src/utils/installationInfo.js.map +1 -1
- package/dist/src/utils/installationInfo.test.js +8 -4
- package/dist/src/utils/installationInfo.test.js.map +1 -1
- package/dist/src/utils/readStdin.js +2 -1
- package/dist/src/utils/readStdin.js.map +1 -1
- package/dist/src/utils/sandbox-macos-permissive-open.sb +2 -0
- package/dist/src/utils/sandbox.js +28 -30
- package/dist/src/utils/sandbox.js.map +1 -1
- package/dist/src/utils/sessionCleanup.js +4 -4
- package/dist/src/utils/sessionCleanup.js.map +1 -1
- package/dist/src/utils/startupWarnings.test.d.ts +6 -0
- package/dist/src/utils/startupWarnings.test.js +61 -0
- package/dist/src/utils/startupWarnings.test.js.map +1 -0
- package/dist/src/utils/version.js +6 -2
- package/dist/src/utils/version.js.map +1 -1
- package/dist/src/validateNonInterActiveAuth.js +2 -2
- package/dist/src/validateNonInterActiveAuth.js.map +1 -1
- package/dist/src/zed-integration/acp.js +2 -1
- package/dist/src/zed-integration/acp.js.map +1 -1
- package/dist/src/zed-integration/schema.d.ts +4 -4
- package/dist/src/zed-integration/zedIntegration.d.ts +2 -2
- package/dist/src/zed-integration/zedIntegration.js +16 -25
- package/dist/src/zed-integration/zedIntegration.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/dist/src/config/policy.test.js +0 -336
- package/dist/src/config/policy.test.js.map +0 -1
- package/dist/src/ui/components/WorkspaceMigrationDialog.d.ts +0 -11
- package/dist/src/ui/components/WorkspaceMigrationDialog.js +0 -44
- package/dist/src/ui/components/WorkspaceMigrationDialog.js.map +0 -1
- package/dist/src/ui/hooks/useWorkspaceMigration.d.ts +0 -13
- package/dist/src/ui/hooks/useWorkspaceMigration.js +0 -59
- package/dist/src/ui/hooks/useWorkspaceMigration.js.map +0 -1
- package/dist/src/utils/package.d.ts +0 -12
- package/dist/src/utils/package.js +0 -24
- package/dist/src/utils/package.js.map +0 -1
- /package/dist/src/{config/policy.test.d.ts → commands/extensions/examples/mcp-server/example.d.ts} +0 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { act } from 'react';
|
|
3
|
+
import { renderHook } from '../../test-utils/render.js';
|
|
4
|
+
import { waitFor } from '../../test-utils/async.js';
|
|
3
5
|
import { vi } from 'vitest';
|
|
4
|
-
import { KeypressProvider, useKeypressContext, DRAG_COMPLETION_TIMEOUT_MS,
|
|
6
|
+
import { KeypressProvider, useKeypressContext, DRAG_COMPLETION_TIMEOUT_MS, KITTY_SEQUENCE_TIMEOUT_MS,
|
|
5
7
|
// CSI_END_O,
|
|
6
8
|
// SS3_END,
|
|
7
9
|
SINGLE_QUOTE, DOUBLE_QUOTE, } from './KeypressContext.js';
|
|
@@ -15,35 +17,34 @@ vi.mock('ink', async (importOriginal) => {
|
|
|
15
17
|
useStdin: vi.fn(),
|
|
16
18
|
};
|
|
17
19
|
});
|
|
20
|
+
const PASTE_START = '\x1B[200~';
|
|
21
|
+
const PASTE_END = '\x1B[201~';
|
|
22
|
+
// readline will not emit most incomplete kitty sequences but it will give
|
|
23
|
+
// up on sequences like this where the modifier (135) has more than two digits.
|
|
24
|
+
const INCOMPLETE_KITTY_SEQUENCE = '\x1b[97;135';
|
|
18
25
|
class MockStdin extends EventEmitter {
|
|
19
26
|
isTTY = true;
|
|
20
27
|
setRawMode = vi.fn();
|
|
21
28
|
on = this.addListener;
|
|
22
29
|
removeListener = super.removeListener;
|
|
23
|
-
write = vi.fn();
|
|
24
30
|
resume = vi.fn();
|
|
25
31
|
pause = vi.fn();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
this.emit('keypress', null, key);
|
|
29
|
-
}
|
|
30
|
-
// Helper to simulate a kitty protocol sequence
|
|
31
|
-
sendKittySequence(sequence) {
|
|
32
|
-
this.emit('data', Buffer.from(sequence));
|
|
33
|
-
}
|
|
34
|
-
// Helper to simulate a paste event
|
|
35
|
-
sendPaste(text) {
|
|
36
|
-
const PASTE_MODE_PREFIX = `\x1b[200~`;
|
|
37
|
-
const PASTE_MODE_SUFFIX = `\x1b[201~`;
|
|
38
|
-
this.emit('data', Buffer.from(PASTE_MODE_PREFIX));
|
|
39
|
-
this.emit('data', Buffer.from(text));
|
|
40
|
-
this.emit('data', Buffer.from(PASTE_MODE_SUFFIX));
|
|
32
|
+
write(text) {
|
|
33
|
+
this.emit('data', text);
|
|
41
34
|
}
|
|
42
35
|
}
|
|
36
|
+
// Helper function to setup keypress test with standard configuration
|
|
37
|
+
const setupKeypressTest = (kittyProtocolEnabled = true) => {
|
|
38
|
+
const keyHandler = vi.fn();
|
|
39
|
+
const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kittyProtocolEnabled, children: children }));
|
|
40
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
41
|
+
act(() => result.current.subscribe(keyHandler));
|
|
42
|
+
return { result, keyHandler };
|
|
43
|
+
};
|
|
43
44
|
describe('KeypressContext - Kitty Protocol', () => {
|
|
44
45
|
let stdin;
|
|
45
46
|
const mockSetRawMode = vi.fn();
|
|
46
|
-
const wrapper = ({ children, kittyProtocolEnabled = true, }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kittyProtocolEnabled, children: children }));
|
|
47
|
+
const wrapper = ({ children, kittyProtocolEnabled = true, }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kittyProtocolEnabled ?? false, children: children }));
|
|
47
48
|
beforeEach(() => {
|
|
48
49
|
vi.clearAllMocks();
|
|
49
50
|
stdin = new MockStdin();
|
|
@@ -53,117 +54,58 @@ describe('KeypressContext - Kitty Protocol', () => {
|
|
|
53
54
|
});
|
|
54
55
|
});
|
|
55
56
|
describe('Enter key handling', () => {
|
|
56
|
-
it(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
});
|
|
68
|
-
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
69
|
-
name: 'return',
|
|
70
|
-
kittyProtocol: true,
|
|
71
|
-
ctrl: false,
|
|
72
|
-
meta: false,
|
|
73
|
-
shift: false,
|
|
74
|
-
}));
|
|
75
|
-
});
|
|
76
|
-
it('should recognize numpad enter key (keycode 57414) in kitty protocol', async () => {
|
|
77
|
-
const keyHandler = vi.fn();
|
|
78
|
-
const { result } = renderHook(() => useKeypressContext(), {
|
|
79
|
-
wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: true }),
|
|
80
|
-
});
|
|
81
|
-
act(() => {
|
|
82
|
-
result.current.subscribe(keyHandler);
|
|
83
|
-
});
|
|
84
|
-
// Send kitty protocol sequence for numpad enter: ESC[57414u
|
|
85
|
-
act(() => {
|
|
86
|
-
stdin.sendKittySequence(`\x1b[57414u`);
|
|
87
|
-
});
|
|
88
|
-
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
89
|
-
name: 'return',
|
|
90
|
-
kittyProtocol: true,
|
|
91
|
-
ctrl: false,
|
|
92
|
-
meta: false,
|
|
93
|
-
shift: false,
|
|
94
|
-
}));
|
|
95
|
-
});
|
|
96
|
-
it('should handle numpad enter with modifiers', async () => {
|
|
97
|
-
const keyHandler = vi.fn();
|
|
98
|
-
const { result } = renderHook(() => useKeypressContext(), {
|
|
99
|
-
wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: true }),
|
|
100
|
-
});
|
|
101
|
-
act(() => {
|
|
102
|
-
result.current.subscribe(keyHandler);
|
|
103
|
-
});
|
|
104
|
-
// Send kitty protocol sequence for numpad enter with Shift (modifier 2): ESC[57414;2u
|
|
57
|
+
it.each([
|
|
58
|
+
{
|
|
59
|
+
name: 'regular enter key (keycode 13)',
|
|
60
|
+
sequence: '\x1b[13u',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'numpad enter key (keycode 57414)',
|
|
64
|
+
sequence: '\x1b[57414u',
|
|
65
|
+
},
|
|
66
|
+
])('should recognize $name in kitty protocol', async ({ sequence }) => {
|
|
67
|
+
const { keyHandler } = setupKeypressTest(true);
|
|
105
68
|
act(() => {
|
|
106
|
-
stdin.
|
|
69
|
+
stdin.write(sequence);
|
|
107
70
|
});
|
|
108
71
|
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
109
72
|
name: 'return',
|
|
110
73
|
kittyProtocol: true,
|
|
111
74
|
ctrl: false,
|
|
112
75
|
meta: false,
|
|
113
|
-
shift: true,
|
|
114
|
-
}));
|
|
115
|
-
});
|
|
116
|
-
it('should handle numpad enter with Ctrl modifier', async () => {
|
|
117
|
-
const keyHandler = vi.fn();
|
|
118
|
-
const { result } = renderHook(() => useKeypressContext(), {
|
|
119
|
-
wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: true }),
|
|
120
|
-
});
|
|
121
|
-
act(() => {
|
|
122
|
-
result.current.subscribe(keyHandler);
|
|
123
|
-
});
|
|
124
|
-
// Send kitty protocol sequence for numpad enter with Ctrl (modifier 5): ESC[57414;5u
|
|
125
|
-
act(() => {
|
|
126
|
-
stdin.sendKittySequence(`\x1b[57414;5u`);
|
|
127
|
-
});
|
|
128
|
-
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
129
|
-
name: 'return',
|
|
130
|
-
kittyProtocol: true,
|
|
131
|
-
ctrl: true,
|
|
132
|
-
meta: false,
|
|
133
76
|
shift: false,
|
|
134
77
|
}));
|
|
135
78
|
});
|
|
136
|
-
it(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
79
|
+
it.each([
|
|
80
|
+
{
|
|
81
|
+
modifier: 'Shift',
|
|
82
|
+
sequence: '\x1b[57414;2u',
|
|
83
|
+
expected: { ctrl: false, meta: false, shift: true },
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
modifier: 'Ctrl',
|
|
87
|
+
sequence: '\x1b[57414;5u',
|
|
88
|
+
expected: { ctrl: true, meta: false, shift: false },
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
modifier: 'Alt',
|
|
92
|
+
sequence: '\x1b[57414;3u',
|
|
93
|
+
expected: { ctrl: false, meta: true, shift: false },
|
|
94
|
+
},
|
|
95
|
+
])('should handle numpad enter with $modifier modifier', async ({ sequence, expected }) => {
|
|
96
|
+
const { keyHandler } = setupKeypressTest(true);
|
|
97
|
+
act(() => stdin.write(sequence));
|
|
148
98
|
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
149
99
|
name: 'return',
|
|
150
100
|
kittyProtocol: true,
|
|
151
|
-
|
|
152
|
-
meta: true,
|
|
153
|
-
shift: false,
|
|
101
|
+
...expected,
|
|
154
102
|
}));
|
|
155
103
|
});
|
|
156
104
|
it('should not process kitty sequences when kitty protocol is disabled', async () => {
|
|
157
|
-
const keyHandler =
|
|
158
|
-
const { result } = renderHook(() => useKeypressContext(), {
|
|
159
|
-
wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: false }),
|
|
160
|
-
});
|
|
161
|
-
act(() => {
|
|
162
|
-
result.current.subscribe(keyHandler);
|
|
163
|
-
});
|
|
105
|
+
const { keyHandler } = setupKeypressTest(false);
|
|
164
106
|
// Send kitty protocol sequence for numpad enter
|
|
165
107
|
act(() => {
|
|
166
|
-
stdin.
|
|
108
|
+
stdin.write(`\x1b[57414u`);
|
|
167
109
|
});
|
|
168
110
|
// When kitty protocol is disabled, the sequence should be passed through
|
|
169
111
|
// as individual keypresses, not recognized as a single enter key
|
|
@@ -175,112 +117,115 @@ describe('KeypressContext - Kitty Protocol', () => {
|
|
|
175
117
|
});
|
|
176
118
|
describe('Escape key handling', () => {
|
|
177
119
|
it('should recognize escape key (keycode 27) in kitty protocol', async () => {
|
|
178
|
-
const keyHandler =
|
|
179
|
-
const { result } = renderHook(() => useKeypressContext(), {
|
|
180
|
-
wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: true }),
|
|
181
|
-
});
|
|
182
|
-
act(() => {
|
|
183
|
-
result.current.subscribe(keyHandler);
|
|
184
|
-
});
|
|
120
|
+
const { keyHandler } = setupKeypressTest(true);
|
|
185
121
|
// Send kitty protocol sequence for escape: ESC[27u
|
|
186
122
|
act(() => {
|
|
187
|
-
stdin.
|
|
123
|
+
stdin.write('\x1b[27u');
|
|
188
124
|
});
|
|
189
125
|
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
190
126
|
name: 'escape',
|
|
191
127
|
kittyProtocol: true,
|
|
192
128
|
}));
|
|
193
129
|
});
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const keyHandler = vi.fn();
|
|
198
|
-
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
199
|
-
act(() => result.current.subscribe(keyHandler));
|
|
200
|
-
act(() => {
|
|
201
|
-
stdin.sendKittySequence(`\x1b[9u`);
|
|
202
|
-
});
|
|
203
|
-
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
204
|
-
name: 'tab',
|
|
205
|
-
kittyProtocol: true,
|
|
206
|
-
shift: false,
|
|
207
|
-
}));
|
|
208
|
-
});
|
|
209
|
-
it('should recognize Shift+Tab in kitty protocol', async () => {
|
|
210
|
-
const keyHandler = vi.fn();
|
|
211
|
-
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
212
|
-
act(() => result.current.subscribe(keyHandler));
|
|
213
|
-
// Modifier 2 is Shift
|
|
214
|
-
act(() => {
|
|
215
|
-
stdin.sendKittySequence(`\x1b[9;2u`);
|
|
216
|
-
});
|
|
217
|
-
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
218
|
-
name: 'tab',
|
|
219
|
-
kittyProtocol: true,
|
|
220
|
-
shift: true,
|
|
221
|
-
}));
|
|
222
|
-
});
|
|
223
|
-
it('should recognize Backspace key in kitty protocol', async () => {
|
|
224
|
-
const keyHandler = vi.fn();
|
|
225
|
-
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
226
|
-
act(() => result.current.subscribe(keyHandler));
|
|
227
|
-
act(() => {
|
|
228
|
-
stdin.sendKittySequence(`\x1b[127u`);
|
|
229
|
-
});
|
|
230
|
-
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
231
|
-
name: 'backspace',
|
|
232
|
-
kittyProtocol: true,
|
|
233
|
-
meta: false,
|
|
234
|
-
}));
|
|
235
|
-
});
|
|
236
|
-
it('should recognize Option+Backspace in kitty protocol', async () => {
|
|
130
|
+
it('should handle lone Escape key (keycode 27) with timeout when kitty protocol is enabled', async () => {
|
|
131
|
+
// Use real timers for this test to avoid issues with stream/buffer timing
|
|
132
|
+
vi.useRealTimers();
|
|
237
133
|
const keyHandler = vi.fn();
|
|
134
|
+
const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, children: children }));
|
|
238
135
|
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
239
136
|
act(() => result.current.subscribe(keyHandler));
|
|
240
|
-
//
|
|
137
|
+
// Send just ESC
|
|
241
138
|
act(() => {
|
|
242
|
-
stdin.
|
|
139
|
+
stdin.write('\x1b');
|
|
243
140
|
});
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
141
|
+
// Should be buffered initially
|
|
142
|
+
expect(keyHandler).not.toHaveBeenCalled();
|
|
143
|
+
// Wait for timeout
|
|
144
|
+
await waitFor(() => {
|
|
145
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
146
|
+
name: 'escape',
|
|
147
|
+
meta: true,
|
|
148
|
+
}));
|
|
149
|
+
}, { timeout: 500 });
|
|
249
150
|
});
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
151
|
+
});
|
|
152
|
+
describe('Tab and Backspace handling', () => {
|
|
153
|
+
it.each([
|
|
154
|
+
{
|
|
155
|
+
name: 'Tab key',
|
|
156
|
+
sequence: '\x1b[9u',
|
|
157
|
+
expected: { name: 'tab', shift: false },
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: 'Shift+Tab',
|
|
161
|
+
sequence: '\x1b[9;2u',
|
|
162
|
+
expected: { name: 'tab', shift: true },
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: 'Backspace',
|
|
166
|
+
sequence: '\x1b[127u',
|
|
167
|
+
expected: { name: 'backspace', meta: false },
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
name: 'Option+Backspace',
|
|
171
|
+
sequence: '\x1b[127;3u',
|
|
172
|
+
expected: { name: 'backspace', meta: true },
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: 'Ctrl+Backspace',
|
|
176
|
+
sequence: '\x1b[127;5u',
|
|
177
|
+
expected: { name: 'backspace', ctrl: true },
|
|
178
|
+
},
|
|
179
|
+
])('should recognize $name in kitty protocol', async ({ sequence, expected }) => {
|
|
180
|
+
const { keyHandler } = setupKeypressTest(true);
|
|
255
181
|
act(() => {
|
|
256
|
-
stdin.
|
|
182
|
+
stdin.write(sequence);
|
|
257
183
|
});
|
|
258
184
|
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
259
|
-
|
|
185
|
+
...expected,
|
|
260
186
|
kittyProtocol: true,
|
|
261
|
-
ctrl: true,
|
|
262
187
|
}));
|
|
263
188
|
});
|
|
264
189
|
});
|
|
265
190
|
describe('paste mode', () => {
|
|
266
|
-
it(
|
|
191
|
+
it.each([
|
|
192
|
+
{
|
|
193
|
+
name: 'handle multiline paste as a single event',
|
|
194
|
+
pastedText: 'This \n is \n a \n multiline \n paste.',
|
|
195
|
+
writeSequence: (text) => {
|
|
196
|
+
stdin.write(PASTE_START);
|
|
197
|
+
stdin.write(text);
|
|
198
|
+
stdin.write(PASTE_END);
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
name: 'handle paste start code split over multiple writes',
|
|
203
|
+
pastedText: 'pasted content',
|
|
204
|
+
writeSequence: (text) => {
|
|
205
|
+
stdin.write(PASTE_START.slice(0, 3));
|
|
206
|
+
stdin.write(PASTE_START.slice(3));
|
|
207
|
+
stdin.write(text);
|
|
208
|
+
stdin.write(PASTE_END);
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
name: 'handle paste end code split over multiple writes',
|
|
213
|
+
pastedText: 'pasted content',
|
|
214
|
+
writeSequence: (text) => {
|
|
215
|
+
stdin.write(PASTE_START);
|
|
216
|
+
stdin.write(text);
|
|
217
|
+
stdin.write(PASTE_END.slice(0, 3));
|
|
218
|
+
stdin.write(PASTE_END.slice(3));
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
])('should $name', async ({ pastedText, writeSequence }) => {
|
|
267
222
|
const keyHandler = vi.fn();
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
});
|
|
272
|
-
act(() => {
|
|
273
|
-
result.current.subscribe(keyHandler);
|
|
274
|
-
});
|
|
275
|
-
// Simulate a bracketed paste event
|
|
276
|
-
act(() => {
|
|
277
|
-
stdin.sendPaste(pastedText);
|
|
278
|
-
});
|
|
223
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
224
|
+
act(() => result.current.subscribe(keyHandler));
|
|
225
|
+
act(() => writeSequence(pastedText));
|
|
279
226
|
await waitFor(() => {
|
|
280
|
-
// Expect the handler to be called exactly once for the entire paste
|
|
281
227
|
expect(keyHandler).toHaveBeenCalledTimes(1);
|
|
282
228
|
});
|
|
283
|
-
// Verify the single event contains the full pasted text
|
|
284
229
|
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
285
230
|
paste: true,
|
|
286
231
|
sequence: pastedText,
|
|
@@ -302,12 +247,10 @@ describe('KeypressContext - Kitty Protocol', () => {
|
|
|
302
247
|
const keyHandler = vi.fn();
|
|
303
248
|
const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, debugKeystrokeLogging: false, children: children }));
|
|
304
249
|
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
305
|
-
act(() =>
|
|
306
|
-
result.current.subscribe(keyHandler);
|
|
307
|
-
});
|
|
250
|
+
act(() => result.current.subscribe(keyHandler));
|
|
308
251
|
// Send a kitty sequence
|
|
309
252
|
act(() => {
|
|
310
|
-
stdin.
|
|
253
|
+
stdin.write('\x1b[27u');
|
|
311
254
|
});
|
|
312
255
|
expect(keyHandler).toHaveBeenCalled();
|
|
313
256
|
expect(consoleLogSpy).not.toHaveBeenCalledWith(expect.stringContaining('[DEBUG] Kitty'));
|
|
@@ -316,61 +259,34 @@ describe('KeypressContext - Kitty Protocol', () => {
|
|
|
316
259
|
const keyHandler = vi.fn();
|
|
317
260
|
const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, debugKeystrokeLogging: true, children: children }));
|
|
318
261
|
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
319
|
-
act(() =>
|
|
320
|
-
result.current.subscribe(keyHandler);
|
|
321
|
-
});
|
|
262
|
+
act(() => result.current.subscribe(keyHandler));
|
|
322
263
|
// Send a complete kitty sequence for escape
|
|
323
|
-
act(() =>
|
|
324
|
-
|
|
325
|
-
});
|
|
326
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Kitty buffer accumulating:', expect.stringContaining('\x1b[27u'));
|
|
264
|
+
act(() => stdin.write('\x1b[27u'));
|
|
265
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Input buffer accumulating:', expect.stringContaining('"\\u001b[27u"'));
|
|
327
266
|
const parsedCall = consoleLogSpy.mock.calls.find((args) => typeof args[0] === 'string' &&
|
|
328
|
-
args[0].includes('[DEBUG]
|
|
267
|
+
args[0].includes('[DEBUG] Sequence parsed successfully'));
|
|
329
268
|
expect(parsedCall).toBeTruthy();
|
|
330
|
-
expect(parsedCall?.[1]).toEqual(expect.stringContaining('
|
|
269
|
+
expect(parsedCall?.[1]).toEqual(expect.stringContaining('\\u001b[27u'));
|
|
331
270
|
});
|
|
332
271
|
it('should log kitty buffer overflow when debugKeystrokeLogging is true', async () => {
|
|
333
272
|
const keyHandler = vi.fn();
|
|
334
273
|
const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, debugKeystrokeLogging: true, children: children }));
|
|
335
274
|
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
336
|
-
act(() =>
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
act(() => {
|
|
342
|
-
stdin.sendKittySequence(longInvalidSequence);
|
|
343
|
-
});
|
|
344
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Kitty buffer overflow, clearing:', expect.any(String));
|
|
275
|
+
act(() => result.current.subscribe(keyHandler));
|
|
276
|
+
// Send a long sequence starting with a valid kitty prefix to trigger overflow
|
|
277
|
+
const longSequence = '\x1b[1;' + '1'.repeat(100);
|
|
278
|
+
act(() => stdin.write(longSequence));
|
|
279
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Input buffer overflow, clearing:', expect.any(String));
|
|
345
280
|
});
|
|
346
281
|
it('should log kitty buffer clear on Ctrl+C when debugKeystrokeLogging is true', async () => {
|
|
347
282
|
const keyHandler = vi.fn();
|
|
348
283
|
const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, debugKeystrokeLogging: true, children: children }));
|
|
349
284
|
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
350
|
-
act(() =>
|
|
351
|
-
|
|
352
|
-
});
|
|
353
|
-
// Send incomplete kitty sequence
|
|
354
|
-
act(() => {
|
|
355
|
-
stdin.pressKey({
|
|
356
|
-
name: undefined,
|
|
357
|
-
ctrl: false,
|
|
358
|
-
meta: false,
|
|
359
|
-
shift: false,
|
|
360
|
-
sequence: '\x1b[1',
|
|
361
|
-
});
|
|
362
|
-
});
|
|
285
|
+
act(() => result.current.subscribe(keyHandler));
|
|
286
|
+
act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
|
|
363
287
|
// Send Ctrl+C
|
|
364
|
-
act(() =>
|
|
365
|
-
|
|
366
|
-
name: 'c',
|
|
367
|
-
ctrl: true,
|
|
368
|
-
meta: false,
|
|
369
|
-
shift: false,
|
|
370
|
-
sequence: '\x03',
|
|
371
|
-
});
|
|
372
|
-
});
|
|
373
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Kitty buffer cleared on Ctrl+C:', '\x1b[1');
|
|
288
|
+
act(() => stdin.write('\x03'));
|
|
289
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Input buffer cleared on Ctrl+C:', INCOMPLETE_KITTY_SEQUENCE);
|
|
374
290
|
// Verify Ctrl+C was handled
|
|
375
291
|
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
376
292
|
name: 'c',
|
|
@@ -381,24 +297,13 @@ describe('KeypressContext - Kitty Protocol', () => {
|
|
|
381
297
|
const keyHandler = vi.fn();
|
|
382
298
|
const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, debugKeystrokeLogging: true, children: children }));
|
|
383
299
|
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
384
|
-
act(() =>
|
|
385
|
-
result.current.subscribe(keyHandler);
|
|
386
|
-
});
|
|
300
|
+
act(() => result.current.subscribe(keyHandler));
|
|
387
301
|
// Send incomplete kitty sequence
|
|
388
|
-
|
|
389
|
-
act(() => {
|
|
390
|
-
stdin.pressKey({
|
|
391
|
-
name: undefined,
|
|
392
|
-
ctrl: false,
|
|
393
|
-
meta: false,
|
|
394
|
-
shift: false,
|
|
395
|
-
sequence,
|
|
396
|
-
});
|
|
397
|
-
});
|
|
302
|
+
act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
|
|
398
303
|
// Verify debug logging for accumulation
|
|
399
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG]
|
|
304
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Input buffer accumulating:', JSON.stringify(INCOMPLETE_KITTY_SEQUENCE));
|
|
400
305
|
// Verify warning for char codes
|
|
401
|
-
expect(consoleWarnSpy).toHaveBeenCalledWith('
|
|
306
|
+
expect(consoleWarnSpy).toHaveBeenCalledWith('Input sequence buffer has content:', JSON.stringify(INCOMPLETE_KITTY_SEQUENCE));
|
|
402
307
|
});
|
|
403
308
|
});
|
|
404
309
|
describe('Parameterized functional keys', () => {
|
|
@@ -414,6 +319,13 @@ describe('KeypressContext - Kitty Protocol', () => {
|
|
|
414
319
|
{ sequence: `\x1b[1~`, expected: { name: 'home' } },
|
|
415
320
|
{ sequence: `\x1b[4~`, expected: { name: 'end' } },
|
|
416
321
|
{ sequence: `\x1b[2~`, expected: { name: 'insert' } },
|
|
322
|
+
{ sequence: `\x1b[11~`, expected: { name: 'f1' } },
|
|
323
|
+
{ sequence: `\x1b[17~`, expected: { name: 'f6' } },
|
|
324
|
+
{ sequence: `\x1b[23~`, expected: { name: 'f11' } },
|
|
325
|
+
{ sequence: `\x1b[24~`, expected: { name: 'f12' } },
|
|
326
|
+
// Reverse tabs
|
|
327
|
+
{ sequence: `\x1b[Z`, expected: { name: 'tab', shift: true } },
|
|
328
|
+
{ sequence: `\x1b[1;2Z`, expected: { name: 'tab', shift: true } },
|
|
417
329
|
// Legacy Arrows
|
|
418
330
|
{
|
|
419
331
|
sequence: `\x1b[A`,
|
|
@@ -444,56 +356,32 @@ describe('KeypressContext - Kitty Protocol', () => {
|
|
|
444
356
|
const keyHandler = vi.fn();
|
|
445
357
|
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
446
358
|
act(() => result.current.subscribe(keyHandler));
|
|
447
|
-
act(() => stdin.
|
|
359
|
+
act(() => stdin.write(sequence));
|
|
448
360
|
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining(expected));
|
|
449
361
|
});
|
|
450
362
|
});
|
|
451
|
-
describe('Shift+Tab forms', () => {
|
|
452
|
-
it.each([
|
|
453
|
-
{ sequence: `\x1b[Z`, description: 'legacy reverse Tab' },
|
|
454
|
-
{ sequence: `\x1b[1;2Z`, description: 'parameterized reverse Tab' },
|
|
455
|
-
])('should recognize $description "$sequence" as Shift+Tab', ({ sequence }) => {
|
|
456
|
-
const keyHandler = vi.fn();
|
|
457
|
-
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
458
|
-
act(() => result.current.subscribe(keyHandler));
|
|
459
|
-
act(() => stdin.sendKittySequence(sequence));
|
|
460
|
-
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({ name: 'tab', shift: true }));
|
|
461
|
-
});
|
|
462
|
-
});
|
|
463
363
|
describe('Double-tap and batching', () => {
|
|
464
364
|
it('should emit two delete events for double-tap CSI[3~', async () => {
|
|
465
|
-
const keyHandler =
|
|
466
|
-
|
|
467
|
-
act(() =>
|
|
468
|
-
act(() => stdin.sendKittySequence(`\x1b[3~`));
|
|
469
|
-
act(() => stdin.sendKittySequence(`\x1b[3~`));
|
|
365
|
+
const { keyHandler } = setupKeypressTest(true);
|
|
366
|
+
act(() => stdin.write(`\x1b[3~`));
|
|
367
|
+
act(() => stdin.write(`\x1b[3~`));
|
|
470
368
|
expect(keyHandler).toHaveBeenNthCalledWith(1, expect.objectContaining({ name: 'delete' }));
|
|
471
369
|
expect(keyHandler).toHaveBeenNthCalledWith(2, expect.objectContaining({ name: 'delete' }));
|
|
472
370
|
});
|
|
473
371
|
it('should parse two concatenated tilde-coded sequences in one chunk', async () => {
|
|
474
|
-
const keyHandler =
|
|
475
|
-
|
|
476
|
-
act(() => result.current.subscribe(keyHandler));
|
|
477
|
-
act(() => stdin.sendKittySequence(`\x1b[3~\x1b[5~`));
|
|
372
|
+
const { keyHandler } = setupKeypressTest(true);
|
|
373
|
+
act(() => stdin.write(`\x1b[3~\x1b[5~`));
|
|
478
374
|
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({ name: 'delete' }));
|
|
479
375
|
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({ name: 'pageup' }));
|
|
480
376
|
});
|
|
481
377
|
it('should ignore incomplete CSI then parse the next complete sequence', async () => {
|
|
482
|
-
const keyHandler =
|
|
483
|
-
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
484
|
-
act(() => result.current.subscribe(keyHandler));
|
|
378
|
+
const { keyHandler } = setupKeypressTest(true);
|
|
485
379
|
// Incomplete ESC sequence then a complete Delete
|
|
486
380
|
act(() => {
|
|
487
381
|
// Provide an incomplete ESC sequence chunk with a real ESC character
|
|
488
|
-
stdin.
|
|
489
|
-
name: undefined,
|
|
490
|
-
ctrl: false,
|
|
491
|
-
meta: false,
|
|
492
|
-
shift: false,
|
|
493
|
-
sequence: '\x1b[1;',
|
|
494
|
-
});
|
|
382
|
+
stdin.write('\x1b[1;');
|
|
495
383
|
});
|
|
496
|
-
act(() => stdin.
|
|
384
|
+
act(() => stdin.write(`\x1b[3~`));
|
|
497
385
|
expect(keyHandler).toHaveBeenCalledTimes(1);
|
|
498
386
|
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({ name: 'delete' }));
|
|
499
387
|
});
|
|
@@ -502,7 +390,7 @@ describe('KeypressContext - Kitty Protocol', () => {
|
|
|
502
390
|
describe('Drag and Drop Handling', () => {
|
|
503
391
|
let stdin;
|
|
504
392
|
const mockSetRawMode = vi.fn();
|
|
505
|
-
const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled:
|
|
393
|
+
const wrapper = ({ children, kittyProtocolEnabled = true, }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kittyProtocolEnabled, children: children }));
|
|
506
394
|
beforeEach(() => {
|
|
507
395
|
vi.clearAllMocks();
|
|
508
396
|
vi.useFakeTimers();
|
|
@@ -516,254 +404,150 @@ describe('Drag and Drop Handling', () => {
|
|
|
516
404
|
vi.useRealTimers();
|
|
517
405
|
});
|
|
518
406
|
describe('drag start by quotes', () => {
|
|
519
|
-
it(
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
result.current.subscribe(keyHandler);
|
|
524
|
-
});
|
|
525
|
-
act(() => {
|
|
526
|
-
stdin.pressKey({
|
|
527
|
-
name: undefined,
|
|
528
|
-
ctrl: false,
|
|
529
|
-
meta: false,
|
|
530
|
-
shift: false,
|
|
531
|
-
paste: false,
|
|
532
|
-
sequence: SINGLE_QUOTE,
|
|
533
|
-
});
|
|
534
|
-
});
|
|
535
|
-
expect(keyHandler).not.toHaveBeenCalled();
|
|
536
|
-
});
|
|
537
|
-
it('should start collecting when double quote arrives and not broadcast immediately', async () => {
|
|
407
|
+
it.each([
|
|
408
|
+
{ name: 'single quote', quote: SINGLE_QUOTE },
|
|
409
|
+
{ name: 'double quote', quote: DOUBLE_QUOTE },
|
|
410
|
+
])('should start collecting when $name arrives and not broadcast immediately', async ({ quote }) => {
|
|
538
411
|
const keyHandler = vi.fn();
|
|
539
412
|
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
540
|
-
act(() =>
|
|
541
|
-
|
|
542
|
-
});
|
|
543
|
-
act(() => {
|
|
544
|
-
stdin.pressKey({
|
|
545
|
-
name: undefined,
|
|
546
|
-
ctrl: false,
|
|
547
|
-
meta: false,
|
|
548
|
-
shift: false,
|
|
549
|
-
paste: false,
|
|
550
|
-
sequence: DOUBLE_QUOTE,
|
|
551
|
-
});
|
|
552
|
-
});
|
|
413
|
+
act(() => result.current.subscribe(keyHandler));
|
|
414
|
+
act(() => stdin.write(quote));
|
|
553
415
|
expect(keyHandler).not.toHaveBeenCalled();
|
|
554
416
|
});
|
|
555
417
|
});
|
|
556
418
|
describe('drag collection and completion', () => {
|
|
557
|
-
it(
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
shift: false,
|
|
570
|
-
paste: false,
|
|
571
|
-
sequence: SINGLE_QUOTE,
|
|
572
|
-
});
|
|
573
|
-
});
|
|
574
|
-
// Send single character
|
|
575
|
-
act(() => {
|
|
576
|
-
stdin.pressKey({
|
|
577
|
-
name: undefined,
|
|
578
|
-
ctrl: false,
|
|
579
|
-
meta: false,
|
|
580
|
-
shift: false,
|
|
581
|
-
paste: false,
|
|
582
|
-
sequence: 'a',
|
|
583
|
-
});
|
|
584
|
-
});
|
|
585
|
-
// Character should not be immediately broadcast
|
|
586
|
-
expect(keyHandler).not.toHaveBeenCalled();
|
|
587
|
-
// Fast-forward to completion timeout
|
|
588
|
-
act(() => {
|
|
589
|
-
vi.advanceTimersByTime(DRAG_COMPLETION_TIMEOUT_MS + 10);
|
|
590
|
-
});
|
|
591
|
-
// Should broadcast the collected path as paste (includes starting quote)
|
|
592
|
-
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
593
|
-
name: '',
|
|
594
|
-
paste: true,
|
|
595
|
-
sequence: `${SINGLE_QUOTE}a`,
|
|
596
|
-
}));
|
|
597
|
-
});
|
|
598
|
-
it('should collect multiple characters and complete on timeout', async () => {
|
|
419
|
+
it.each([
|
|
420
|
+
{
|
|
421
|
+
name: 'collect single character inputs during drag mode',
|
|
422
|
+
characters: ['a'],
|
|
423
|
+
expectedText: 'a',
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
name: 'collect multiple characters and complete on timeout',
|
|
427
|
+
characters: ['p', 'a', 't', 'h'],
|
|
428
|
+
expectedText: 'path',
|
|
429
|
+
},
|
|
430
|
+
])('should $name', async ({ characters, expectedText }) => {
|
|
599
431
|
const keyHandler = vi.fn();
|
|
600
432
|
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
601
|
-
act(() =>
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
act(() => {
|
|
606
|
-
stdin.pressKey({
|
|
607
|
-
name: undefined,
|
|
608
|
-
ctrl: false,
|
|
609
|
-
meta: false,
|
|
610
|
-
shift: false,
|
|
611
|
-
paste: false,
|
|
612
|
-
sequence: SINGLE_QUOTE,
|
|
613
|
-
});
|
|
614
|
-
});
|
|
615
|
-
// Send multiple characters
|
|
616
|
-
act(() => {
|
|
617
|
-
stdin.pressKey({
|
|
618
|
-
name: undefined,
|
|
619
|
-
ctrl: false,
|
|
620
|
-
meta: false,
|
|
621
|
-
shift: false,
|
|
622
|
-
paste: false,
|
|
623
|
-
sequence: 'p',
|
|
624
|
-
});
|
|
625
|
-
});
|
|
626
|
-
act(() => {
|
|
627
|
-
stdin.pressKey({
|
|
628
|
-
name: undefined,
|
|
629
|
-
ctrl: false,
|
|
630
|
-
meta: false,
|
|
631
|
-
shift: false,
|
|
632
|
-
paste: false,
|
|
633
|
-
sequence: 'a',
|
|
634
|
-
});
|
|
635
|
-
});
|
|
636
|
-
act(() => {
|
|
637
|
-
stdin.pressKey({
|
|
638
|
-
name: undefined,
|
|
639
|
-
ctrl: false,
|
|
640
|
-
meta: false,
|
|
641
|
-
shift: false,
|
|
642
|
-
paste: false,
|
|
643
|
-
sequence: 't',
|
|
644
|
-
});
|
|
645
|
-
});
|
|
646
|
-
act(() => {
|
|
647
|
-
stdin.pressKey({
|
|
648
|
-
name: undefined,
|
|
649
|
-
ctrl: false,
|
|
650
|
-
meta: false,
|
|
651
|
-
shift: false,
|
|
652
|
-
paste: false,
|
|
653
|
-
sequence: 'h',
|
|
654
|
-
});
|
|
433
|
+
act(() => result.current.subscribe(keyHandler));
|
|
434
|
+
act(() => stdin.write(SINGLE_QUOTE));
|
|
435
|
+
characters.forEach((char) => {
|
|
436
|
+
act(() => stdin.write(char));
|
|
655
437
|
});
|
|
656
|
-
// Characters should not be immediately broadcast
|
|
657
438
|
expect(keyHandler).not.toHaveBeenCalled();
|
|
658
|
-
// Fast-forward to completion timeout
|
|
659
439
|
act(() => {
|
|
660
440
|
vi.advanceTimersByTime(DRAG_COMPLETION_TIMEOUT_MS + 10);
|
|
661
441
|
});
|
|
662
|
-
// Should broadcast the collected path as paste (includes starting quote)
|
|
663
442
|
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
664
443
|
name: '',
|
|
665
444
|
paste: true,
|
|
666
|
-
sequence: `${SINGLE_QUOTE}
|
|
445
|
+
sequence: `${SINGLE_QUOTE}${expectedText}`,
|
|
667
446
|
}));
|
|
668
447
|
});
|
|
669
448
|
});
|
|
670
449
|
});
|
|
671
|
-
describe('
|
|
450
|
+
describe('Kitty Sequence Parsing', () => {
|
|
672
451
|
let stdin;
|
|
673
452
|
const mockSetRawMode = vi.fn();
|
|
674
|
-
const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled:
|
|
453
|
+
const wrapper = ({ children, kittyProtocolEnabled = true, }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kittyProtocolEnabled, children: children }));
|
|
675
454
|
beforeEach(() => {
|
|
676
455
|
vi.clearAllMocks();
|
|
456
|
+
vi.useFakeTimers();
|
|
677
457
|
stdin = new MockStdin();
|
|
678
458
|
useStdin.mockReturnValue({
|
|
679
459
|
stdin,
|
|
680
460
|
setRawMode: mockSetRawMode,
|
|
681
461
|
});
|
|
682
462
|
});
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
463
|
+
afterEach(() => {
|
|
464
|
+
vi.useRealTimers();
|
|
465
|
+
});
|
|
466
|
+
describe('Cross-terminal Alt key handling (simulating macOS)', () => {
|
|
467
|
+
let originalPlatform;
|
|
468
|
+
beforeEach(() => {
|
|
469
|
+
originalPlatform = process.platform;
|
|
470
|
+
Object.defineProperty(process, 'platform', {
|
|
471
|
+
value: 'darwin',
|
|
472
|
+
configurable: true,
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
afterEach(() => {
|
|
476
|
+
Object.defineProperty(process, 'platform', {
|
|
477
|
+
value: originalPlatform,
|
|
478
|
+
configurable: true,
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
// Terminals to test
|
|
482
|
+
const terminals = ['iTerm2', 'Ghostty', 'MacTerminal', 'VSCodeTerminal'];
|
|
483
|
+
// Key mappings: letter -> [keycode, accented character]
|
|
484
|
+
const keys = {
|
|
485
|
+
b: [98, '\u222B'],
|
|
486
|
+
f: [102, '\u0192'],
|
|
487
|
+
m: [109, '\u00B5'],
|
|
488
|
+
};
|
|
489
|
+
it.each(terminals.flatMap((terminal) => Object.entries(keys).map(([key, [keycode, accentedChar]]) => {
|
|
490
|
+
if (terminal === 'Ghostty') {
|
|
491
|
+
// Ghostty uses kitty protocol sequences
|
|
492
|
+
return {
|
|
493
|
+
terminal,
|
|
494
|
+
key,
|
|
495
|
+
chunk: `\x1b[${keycode};3u`,
|
|
496
|
+
expected: {
|
|
497
|
+
name: key,
|
|
498
|
+
ctrl: false,
|
|
499
|
+
meta: true,
|
|
500
|
+
shift: false,
|
|
501
|
+
paste: false,
|
|
502
|
+
kittyProtocol: true,
|
|
503
|
+
},
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
else if (terminal === 'MacTerminal') {
|
|
507
|
+
// Mac Terminal sends ESC + letter
|
|
508
|
+
return {
|
|
509
|
+
terminal,
|
|
510
|
+
key,
|
|
511
|
+
kitty: false,
|
|
512
|
+
chunk: `\x1b${key}`,
|
|
513
|
+
expected: {
|
|
514
|
+
sequence: `\x1b${key}`,
|
|
515
|
+
name: key,
|
|
516
|
+
ctrl: false,
|
|
517
|
+
meta: true,
|
|
518
|
+
shift: false,
|
|
519
|
+
paste: false,
|
|
520
|
+
},
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
524
|
+
// iTerm2 and VSCode send accented characters (å, ø, µ)
|
|
525
|
+
// Note: µ (mu) is sent with meta:false on iTerm2/VSCode but
|
|
526
|
+
// gets converted to m with meta:true
|
|
527
|
+
return {
|
|
528
|
+
terminal,
|
|
529
|
+
key,
|
|
530
|
+
chunk: accentedChar,
|
|
531
|
+
expected: {
|
|
532
|
+
name: key,
|
|
533
|
+
ctrl: false,
|
|
534
|
+
meta: true, // Always expect meta:true after conversion
|
|
535
|
+
shift: false,
|
|
536
|
+
paste: false,
|
|
537
|
+
sequence: accentedChar,
|
|
538
|
+
},
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
})))('should handle Alt+$key in $terminal', ({ chunk, expected, kitty = true, }) => {
|
|
542
|
+
const keyHandler = vi.fn();
|
|
543
|
+
const testWrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kitty, children: children }));
|
|
544
|
+
const { result } = renderHook(() => useKeypressContext(), {
|
|
545
|
+
wrapper: testWrapper,
|
|
546
|
+
});
|
|
547
|
+
act(() => result.current.subscribe(keyHandler));
|
|
548
|
+
act(() => stdin.write(chunk));
|
|
549
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining(expected));
|
|
550
|
+
});
|
|
767
551
|
});
|
|
768
552
|
describe('Backslash key handling', () => {
|
|
769
553
|
beforeEach(() => {
|
|
@@ -773,17 +557,8 @@ describe('Terminal-specific Alt+key combinations', () => {
|
|
|
773
557
|
vi.useRealTimers();
|
|
774
558
|
});
|
|
775
559
|
it('should treat backslash as a regular keystroke', () => {
|
|
776
|
-
const keyHandler =
|
|
777
|
-
|
|
778
|
-
act(() => result.current.subscribe(keyHandler));
|
|
779
|
-
act(() => stdin.pressKey({
|
|
780
|
-
name: undefined,
|
|
781
|
-
ctrl: false,
|
|
782
|
-
meta: false,
|
|
783
|
-
shift: false,
|
|
784
|
-
paste: false,
|
|
785
|
-
sequence: '\\',
|
|
786
|
-
}));
|
|
560
|
+
const { keyHandler } = setupKeypressTest(true);
|
|
561
|
+
act(() => stdin.write('\\'));
|
|
787
562
|
// Advance timers to trigger the backslash timeout
|
|
788
563
|
act(() => {
|
|
789
564
|
vi.runAllTimers();
|
|
@@ -794,5 +569,349 @@ describe('Terminal-specific Alt+key combinations', () => {
|
|
|
794
569
|
}));
|
|
795
570
|
});
|
|
796
571
|
});
|
|
572
|
+
it('should timeout and flush incomplete kitty sequences after 50ms', async () => {
|
|
573
|
+
const keyHandler = vi.fn();
|
|
574
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
575
|
+
act(() => result.current.subscribe(keyHandler));
|
|
576
|
+
act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
|
|
577
|
+
// Should not broadcast immediately
|
|
578
|
+
expect(keyHandler).not.toHaveBeenCalled();
|
|
579
|
+
// Advance time just before timeout
|
|
580
|
+
act(() => vi.advanceTimersByTime(KITTY_SEQUENCE_TIMEOUT_MS - 5));
|
|
581
|
+
// Still shouldn't broadcast
|
|
582
|
+
expect(keyHandler).not.toHaveBeenCalled();
|
|
583
|
+
// Advance past timeout
|
|
584
|
+
act(() => vi.advanceTimersByTime(10));
|
|
585
|
+
// Should now broadcast the incomplete sequence as regular input
|
|
586
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
587
|
+
name: '',
|
|
588
|
+
sequence: INCOMPLETE_KITTY_SEQUENCE,
|
|
589
|
+
paste: false,
|
|
590
|
+
}));
|
|
591
|
+
});
|
|
592
|
+
it('should immediately flush non-kitty CSI sequences', async () => {
|
|
593
|
+
const keyHandler = vi.fn();
|
|
594
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
595
|
+
act(() => result.current.subscribe(keyHandler));
|
|
596
|
+
// Send a CSI sequence that doesn't match kitty patterns
|
|
597
|
+
// ESC[m is SGR reset, not a kitty sequence
|
|
598
|
+
act(() => stdin.write('\x1b[m'));
|
|
599
|
+
// Should broadcast immediately as it's not a valid kitty pattern
|
|
600
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
601
|
+
sequence: '\x1b[m',
|
|
602
|
+
paste: false,
|
|
603
|
+
}));
|
|
604
|
+
});
|
|
605
|
+
it('should parse valid kitty sequences immediately when complete', async () => {
|
|
606
|
+
const keyHandler = vi.fn();
|
|
607
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
608
|
+
act(() => result.current.subscribe(keyHandler));
|
|
609
|
+
// Send complete kitty sequence for Ctrl+A
|
|
610
|
+
act(() => stdin.write('\x1b[97;5u'));
|
|
611
|
+
// Should parse and broadcast immediately
|
|
612
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
613
|
+
name: 'a',
|
|
614
|
+
ctrl: true,
|
|
615
|
+
kittyProtocol: true,
|
|
616
|
+
}));
|
|
617
|
+
});
|
|
618
|
+
it('should handle batched kitty sequences correctly', async () => {
|
|
619
|
+
const keyHandler = vi.fn();
|
|
620
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
621
|
+
act(() => result.current.subscribe(keyHandler));
|
|
622
|
+
// Send Ctrl+a followed by Ctrl+b
|
|
623
|
+
act(() => stdin.write('\x1b[97;5u\x1b[98;5u'));
|
|
624
|
+
// Should parse both sequences
|
|
625
|
+
expect(keyHandler).toHaveBeenCalledTimes(2);
|
|
626
|
+
expect(keyHandler).toHaveBeenNthCalledWith(1, expect.objectContaining({
|
|
627
|
+
name: 'a',
|
|
628
|
+
ctrl: true,
|
|
629
|
+
kittyProtocol: true,
|
|
630
|
+
}));
|
|
631
|
+
expect(keyHandler).toHaveBeenNthCalledWith(2, expect.objectContaining({
|
|
632
|
+
name: 'b',
|
|
633
|
+
ctrl: true,
|
|
634
|
+
kittyProtocol: true,
|
|
635
|
+
}));
|
|
636
|
+
});
|
|
637
|
+
it('should clear kitty buffer and timeout on Ctrl+C', async () => {
|
|
638
|
+
const keyHandler = vi.fn();
|
|
639
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
640
|
+
act(() => result.current.subscribe(keyHandler));
|
|
641
|
+
act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
|
|
642
|
+
// Press Ctrl+C
|
|
643
|
+
act(() => stdin.write('\x03'));
|
|
644
|
+
// Advance past timeout
|
|
645
|
+
act(() => vi.advanceTimersByTime(KITTY_SEQUENCE_TIMEOUT_MS + 10));
|
|
646
|
+
// Should only have received Ctrl+C, not the incomplete sequence
|
|
647
|
+
expect(keyHandler).toHaveBeenCalledTimes(1);
|
|
648
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
649
|
+
name: 'c',
|
|
650
|
+
ctrl: true,
|
|
651
|
+
}));
|
|
652
|
+
});
|
|
653
|
+
it('should handle mixed valid and invalid sequences', async () => {
|
|
654
|
+
const keyHandler = vi.fn();
|
|
655
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
656
|
+
act(() => result.current.subscribe(keyHandler));
|
|
657
|
+
// Send valid kitty sequence followed by invalid CSI
|
|
658
|
+
// Valid enter, then invalid sequence
|
|
659
|
+
act(() => stdin.write('\x1b[13u\x1b[!'));
|
|
660
|
+
// Should parse valid sequence and flush invalid immediately
|
|
661
|
+
expect(keyHandler).toHaveBeenCalledTimes(2);
|
|
662
|
+
expect(keyHandler).toHaveBeenNthCalledWith(1, expect.objectContaining({
|
|
663
|
+
name: 'return',
|
|
664
|
+
kittyProtocol: true,
|
|
665
|
+
}));
|
|
666
|
+
expect(keyHandler).toHaveBeenNthCalledWith(2, expect.objectContaining({
|
|
667
|
+
sequence: '\x1b[!',
|
|
668
|
+
}));
|
|
669
|
+
});
|
|
670
|
+
it('should not buffer sequences when kitty protocol is disabled', async () => {
|
|
671
|
+
const keyHandler = vi.fn();
|
|
672
|
+
const { result } = renderHook(() => useKeypressContext(), {
|
|
673
|
+
wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: false }),
|
|
674
|
+
});
|
|
675
|
+
act(() => result.current.subscribe(keyHandler));
|
|
676
|
+
// Send what would be a kitty sequence
|
|
677
|
+
act(() => stdin.write('\x1b[13u'));
|
|
678
|
+
// Should pass through without parsing
|
|
679
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
680
|
+
sequence: '\x1b[13u',
|
|
681
|
+
}));
|
|
682
|
+
expect(keyHandler).not.toHaveBeenCalledWith(expect.objectContaining({
|
|
683
|
+
name: 'return',
|
|
684
|
+
kittyProtocol: true,
|
|
685
|
+
}));
|
|
686
|
+
});
|
|
687
|
+
it('should handle sequences arriving character by character', async () => {
|
|
688
|
+
vi.useRealTimers(); // Required for correct buffering timing.
|
|
689
|
+
const keyHandler = vi.fn();
|
|
690
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
691
|
+
act(() => {
|
|
692
|
+
result.current.subscribe(keyHandler);
|
|
693
|
+
});
|
|
694
|
+
// Send kitty sequence character by character
|
|
695
|
+
const sequence = '\x1b[27u'; // Escape key
|
|
696
|
+
for (const char of sequence) {
|
|
697
|
+
act(() => {
|
|
698
|
+
stdin.emit('data', Buffer.from(char));
|
|
699
|
+
});
|
|
700
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
701
|
+
}
|
|
702
|
+
// Should parse once complete
|
|
703
|
+
await waitFor(() => {
|
|
704
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
705
|
+
name: 'escape',
|
|
706
|
+
kittyProtocol: true,
|
|
707
|
+
}));
|
|
708
|
+
});
|
|
709
|
+
});
|
|
710
|
+
it('should reset timeout when new input arrives', async () => {
|
|
711
|
+
const keyHandler = vi.fn();
|
|
712
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
713
|
+
act(() => result.current.subscribe(keyHandler));
|
|
714
|
+
// Start incomplete sequence
|
|
715
|
+
act(() => stdin.write('\x1b[97;13'));
|
|
716
|
+
// Advance time partway
|
|
717
|
+
act(() => vi.advanceTimersByTime(30));
|
|
718
|
+
// Add more to sequence
|
|
719
|
+
act(() => stdin.write('5'));
|
|
720
|
+
// Advance time from the first timeout point
|
|
721
|
+
act(() => vi.advanceTimersByTime(25));
|
|
722
|
+
// Should not have timed out yet (timeout restarted)
|
|
723
|
+
expect(keyHandler).not.toHaveBeenCalled();
|
|
724
|
+
// Complete the sequence
|
|
725
|
+
act(() => stdin.write('u'));
|
|
726
|
+
// Should now parse as complete enter key
|
|
727
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
728
|
+
name: 'a',
|
|
729
|
+
kittyProtocol: true,
|
|
730
|
+
}));
|
|
731
|
+
});
|
|
732
|
+
it('should flush incomplete kitty sequence on FOCUS_IN event', async () => {
|
|
733
|
+
const keyHandler = vi.fn();
|
|
734
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
735
|
+
act(() => result.current.subscribe(keyHandler));
|
|
736
|
+
act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
|
|
737
|
+
// Incomplete sequence should be buffered, not broadcast
|
|
738
|
+
expect(keyHandler).not.toHaveBeenCalled();
|
|
739
|
+
// Send FOCUS_IN event
|
|
740
|
+
act(() => stdin.write('\x1b[I'));
|
|
741
|
+
// The buffered sequence should be flushed
|
|
742
|
+
expect(keyHandler).toHaveBeenCalledTimes(1);
|
|
743
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
744
|
+
name: '',
|
|
745
|
+
sequence: INCOMPLETE_KITTY_SEQUENCE,
|
|
746
|
+
paste: false,
|
|
747
|
+
}));
|
|
748
|
+
});
|
|
749
|
+
it('should flush incomplete kitty sequence on FOCUS_OUT event', async () => {
|
|
750
|
+
const keyHandler = vi.fn();
|
|
751
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
752
|
+
act(() => result.current.subscribe(keyHandler));
|
|
753
|
+
act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
|
|
754
|
+
// Incomplete sequence should be buffered, not broadcast
|
|
755
|
+
expect(keyHandler).not.toHaveBeenCalled();
|
|
756
|
+
// Send FOCUS_OUT event
|
|
757
|
+
act(() => stdin.write('\x1b[O'));
|
|
758
|
+
// The buffered sequence should be flushed
|
|
759
|
+
expect(keyHandler).toHaveBeenCalledTimes(1);
|
|
760
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
761
|
+
name: '',
|
|
762
|
+
sequence: INCOMPLETE_KITTY_SEQUENCE,
|
|
763
|
+
paste: false,
|
|
764
|
+
}));
|
|
765
|
+
});
|
|
766
|
+
it('should flush incomplete kitty sequence on paste event', async () => {
|
|
767
|
+
vi.useFakeTimers();
|
|
768
|
+
const keyHandler = vi.fn();
|
|
769
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
770
|
+
act(() => result.current.subscribe(keyHandler));
|
|
771
|
+
act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
|
|
772
|
+
// Incomplete sequence should be buffered, not broadcast
|
|
773
|
+
expect(keyHandler).not.toHaveBeenCalled();
|
|
774
|
+
// Send paste start sequence
|
|
775
|
+
act(() => stdin.write(`\x1b[200~`));
|
|
776
|
+
// The buffered sequence should be flushed
|
|
777
|
+
expect(keyHandler).toHaveBeenCalledTimes(1);
|
|
778
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
779
|
+
name: '',
|
|
780
|
+
sequence: INCOMPLETE_KITTY_SEQUENCE,
|
|
781
|
+
paste: false,
|
|
782
|
+
}));
|
|
783
|
+
// Now send some paste content and end paste to make sure paste still works
|
|
784
|
+
const pastedText = 'hello';
|
|
785
|
+
const PASTE_MODE_SUFFIX = `\x1b[201~`;
|
|
786
|
+
act(() => {
|
|
787
|
+
stdin.write(pastedText);
|
|
788
|
+
stdin.write(PASTE_MODE_SUFFIX);
|
|
789
|
+
});
|
|
790
|
+
act(() => vi.runAllTimers());
|
|
791
|
+
// The paste event should be broadcast
|
|
792
|
+
expect(keyHandler).toHaveBeenCalledTimes(2);
|
|
793
|
+
expect(keyHandler).toHaveBeenNthCalledWith(2, expect.objectContaining({
|
|
794
|
+
paste: true,
|
|
795
|
+
sequence: pastedText,
|
|
796
|
+
}));
|
|
797
|
+
vi.useRealTimers();
|
|
798
|
+
});
|
|
799
|
+
describe('SGR Mouse Handling', () => {
|
|
800
|
+
it('should ignore SGR mouse sequences', async () => {
|
|
801
|
+
const keyHandler = vi.fn();
|
|
802
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
803
|
+
act(() => result.current.subscribe(keyHandler));
|
|
804
|
+
// Send various SGR mouse sequences
|
|
805
|
+
act(() => {
|
|
806
|
+
stdin.write('\x1b[<0;10;20M'); // Mouse press
|
|
807
|
+
stdin.write('\x1b[<0;10;20m'); // Mouse release
|
|
808
|
+
stdin.write('\x1b[<32;30;40M'); // Mouse drag
|
|
809
|
+
stdin.write('\x1b[<64;5;5M'); // Scroll up
|
|
810
|
+
});
|
|
811
|
+
// Should not broadcast any of these as keystrokes
|
|
812
|
+
expect(keyHandler).not.toHaveBeenCalled();
|
|
813
|
+
});
|
|
814
|
+
it('should handle mixed SGR mouse and key sequences', async () => {
|
|
815
|
+
const keyHandler = vi.fn();
|
|
816
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
817
|
+
act(() => result.current.subscribe(keyHandler));
|
|
818
|
+
// Send mouse event then a key press
|
|
819
|
+
act(() => {
|
|
820
|
+
stdin.write('\x1b[<0;10;20M');
|
|
821
|
+
stdin.write('a');
|
|
822
|
+
});
|
|
823
|
+
// Should only broadcast 'a'
|
|
824
|
+
expect(keyHandler).toHaveBeenCalledTimes(1);
|
|
825
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
|
|
826
|
+
name: 'a',
|
|
827
|
+
sequence: 'a',
|
|
828
|
+
}));
|
|
829
|
+
});
|
|
830
|
+
it('should ignore X11 mouse sequences', async () => {
|
|
831
|
+
const keyHandler = vi.fn();
|
|
832
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
833
|
+
act(() => result.current.subscribe(keyHandler));
|
|
834
|
+
// Send X11 mouse sequence: ESC [ M followed by 3 bytes
|
|
835
|
+
// Space is 32. 32+0=32 (button 0), 32+33=65 ('A', col 33), 32+34=66 ('B', row 34)
|
|
836
|
+
const x11Seq = '\x1b[M AB';
|
|
837
|
+
act(() => {
|
|
838
|
+
stdin.write(x11Seq);
|
|
839
|
+
});
|
|
840
|
+
// Should not broadcast as keystrokes
|
|
841
|
+
expect(keyHandler).not.toHaveBeenCalled();
|
|
842
|
+
});
|
|
843
|
+
it('should not flush slow SGR mouse sequences as garbage', async () => {
|
|
844
|
+
vi.useFakeTimers();
|
|
845
|
+
const keyHandler = vi.fn();
|
|
846
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
847
|
+
act(() => result.current.subscribe(keyHandler));
|
|
848
|
+
// Send start of SGR sequence
|
|
849
|
+
act(() => stdin.write('\x1b[<'));
|
|
850
|
+
// Advance time past the normal kitty timeout (50ms)
|
|
851
|
+
act(() => vi.advanceTimersByTime(KITTY_SEQUENCE_TIMEOUT_MS + 10));
|
|
852
|
+
// Send the rest
|
|
853
|
+
act(() => stdin.write('0;37;25M'));
|
|
854
|
+
// Should NOT have flushed the prefix as garbage, and should have consumed the whole thing
|
|
855
|
+
expect(keyHandler).not.toHaveBeenCalled();
|
|
856
|
+
vi.useRealTimers();
|
|
857
|
+
});
|
|
858
|
+
it('should ignore specific SGR mouse sequence sandwiched between keystrokes', async () => {
|
|
859
|
+
const keyHandler = vi.fn();
|
|
860
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
861
|
+
act(() => result.current.subscribe(keyHandler));
|
|
862
|
+
act(() => {
|
|
863
|
+
stdin.write('H');
|
|
864
|
+
stdin.write('\x1b[<64;96;8M');
|
|
865
|
+
stdin.write('I');
|
|
866
|
+
});
|
|
867
|
+
expect(keyHandler).toHaveBeenCalledTimes(2);
|
|
868
|
+
expect(keyHandler).toHaveBeenNthCalledWith(1, expect.objectContaining({ name: 'h', sequence: 'H', shift: true }));
|
|
869
|
+
expect(keyHandler).toHaveBeenNthCalledWith(2, expect.objectContaining({ name: 'i', sequence: 'I', shift: true }));
|
|
870
|
+
});
|
|
871
|
+
});
|
|
872
|
+
describe('Ignored Sequences', () => {
|
|
873
|
+
describe.each([true, false])('with kittyProtocolEnabled = %s', (kittyEnabled) => {
|
|
874
|
+
it.each([
|
|
875
|
+
{ name: 'Focus In', sequence: '\x1b[I' },
|
|
876
|
+
{ name: 'Focus Out', sequence: '\x1b[O' },
|
|
877
|
+
{ name: 'SGR Mouse Release', sequence: '\u001b[<0;44;18m' },
|
|
878
|
+
{ name: 'something mouse', sequence: '\u001b[<0;53;19M' },
|
|
879
|
+
{ name: 'another mouse', sequence: '\u001b[<0;29;19m' },
|
|
880
|
+
])('should ignore $name sequence', async ({ sequence }) => {
|
|
881
|
+
vi.useFakeTimers();
|
|
882
|
+
const keyHandler = vi.fn();
|
|
883
|
+
const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kittyEnabled, children: children }));
|
|
884
|
+
const { result } = renderHook(() => useKeypressContext(), {
|
|
885
|
+
wrapper,
|
|
886
|
+
});
|
|
887
|
+
act(() => result.current.subscribe(keyHandler));
|
|
888
|
+
for (const char of sequence) {
|
|
889
|
+
act(() => {
|
|
890
|
+
stdin.write(char);
|
|
891
|
+
});
|
|
892
|
+
await act(async () => {
|
|
893
|
+
vi.advanceTimersByTime(0);
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
act(() => {
|
|
897
|
+
stdin.write('HI');
|
|
898
|
+
});
|
|
899
|
+
expect(keyHandler).toHaveBeenCalledTimes(2);
|
|
900
|
+
expect(keyHandler).toHaveBeenNthCalledWith(1, expect.objectContaining({ name: 'h', sequence: 'H', shift: true }));
|
|
901
|
+
expect(keyHandler).toHaveBeenNthCalledWith(2, expect.objectContaining({ name: 'i', sequence: 'I', shift: true }));
|
|
902
|
+
vi.useRealTimers();
|
|
903
|
+
});
|
|
904
|
+
});
|
|
905
|
+
it('should handle F12 when kittyProtocolEnabled is false', async () => {
|
|
906
|
+
const keyHandler = vi.fn();
|
|
907
|
+
const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: children }));
|
|
908
|
+
const { result } = renderHook(() => useKeypressContext(), { wrapper });
|
|
909
|
+
act(() => result.current.subscribe(keyHandler));
|
|
910
|
+
act(() => {
|
|
911
|
+
stdin.write('\u001b[24~');
|
|
912
|
+
});
|
|
913
|
+
expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({ name: 'f12', sequence: '\u001b[24~' }));
|
|
914
|
+
});
|
|
915
|
+
});
|
|
797
916
|
});
|
|
798
917
|
//# sourceMappingURL=KeypressContext.test.js.map
|