@nexus-cortex/tui 4.47.0
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/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +13 -0
- package/bin/cli-full.js +23 -0
- package/bin/cortex-ui.js +26 -0
- package/bin/ink-ui.js +108 -0
- package/bin/launcher-dev.js +266 -0
- package/bin/launcher.js +516 -0
- package/dist/commands/agent/InteractiveAgentMenu.d.ts +100 -0
- package/dist/commands/agent/InteractiveAgentMenu.d.ts.map +1 -0
- package/dist/commands/agent/InteractiveAgentMenu.js +909 -0
- package/dist/commands/agent/InteractiveAgentMenu.js.map +1 -0
- package/dist/commands/agent/index.d.ts +55 -0
- package/dist/commands/agent/index.d.ts.map +1 -0
- package/dist/commands/agent/index.js +714 -0
- package/dist/commands/agent/index.js.map +1 -0
- package/dist/commands/chat/interactive.d.ts +13 -0
- package/dist/commands/chat/interactive.d.ts.map +1 -0
- package/dist/commands/chat/interactive.js +2055 -0
- package/dist/commands/chat/interactive.js.map +1 -0
- package/dist/commands/system-message/EditorLauncher.d.ts +65 -0
- package/dist/commands/system-message/EditorLauncher.d.ts.map +1 -0
- package/dist/commands/system-message/EditorLauncher.js +143 -0
- package/dist/commands/system-message/EditorLauncher.js.map +1 -0
- package/dist/commands/system-message/InlineEditor.d.ts +23 -0
- package/dist/commands/system-message/InlineEditor.d.ts.map +1 -0
- package/dist/commands/system-message/InlineEditor.js +225 -0
- package/dist/commands/system-message/InlineEditor.js.map +1 -0
- package/dist/commands/system-message/InteractiveMenu.d.ts +76 -0
- package/dist/commands/system-message/InteractiveMenu.d.ts.map +1 -0
- package/dist/commands/system-message/InteractiveMenu.js +979 -0
- package/dist/commands/system-message/InteractiveMenu.js.map +1 -0
- package/dist/commands/system-message/index.d.ts +56 -0
- package/dist/commands/system-message/index.d.ts.map +1 -0
- package/dist/commands/system-message/index.js +694 -0
- package/dist/commands/system-message/index.js.map +1 -0
- package/dist/commands/ui/artifacts.d.ts +14 -0
- package/dist/commands/ui/artifacts.d.ts.map +1 -0
- package/dist/commands/ui/artifacts.js +22 -0
- package/dist/commands/ui/artifacts.js.map +1 -0
- package/dist/commands/ui/config.d.ts +12 -0
- package/dist/commands/ui/config.d.ts.map +1 -0
- package/dist/commands/ui/config.js +26 -0
- package/dist/commands/ui/config.js.map +1 -0
- package/dist/commands/ui/context.d.ts +16 -0
- package/dist/commands/ui/context.d.ts.map +1 -0
- package/dist/commands/ui/context.js +28 -0
- package/dist/commands/ui/context.js.map +1 -0
- package/dist/commands/ui/middleware.d.ts +14 -0
- package/dist/commands/ui/middleware.d.ts.map +1 -0
- package/dist/commands/ui/middleware.js +22 -0
- package/dist/commands/ui/middleware.js.map +1 -0
- package/dist/commands/ui/models.d.ts +14 -0
- package/dist/commands/ui/models.d.ts.map +1 -0
- package/dist/commands/ui/models.js +50 -0
- package/dist/commands/ui/models.js.map +1 -0
- package/dist/commands/ui/permissions.d.ts +14 -0
- package/dist/commands/ui/permissions.d.ts.map +1 -0
- package/dist/commands/ui/permissions.js +22 -0
- package/dist/commands/ui/permissions.js.map +1 -0
- package/dist/commands/ui/sessions.d.ts +13 -0
- package/dist/commands/ui/sessions.d.ts.map +1 -0
- package/dist/commands/ui/sessions.js +45 -0
- package/dist/commands/ui/sessions.js.map +1 -0
- package/dist/commands/ui/system-messages.d.ts +5 -0
- package/dist/commands/ui/system-messages.d.ts.map +1 -0
- package/dist/commands/ui/system-messages.js +19 -0
- package/dist/commands/ui/system-messages.js.map +1 -0
- package/dist/commands/ui/themes.d.ts +12 -0
- package/dist/commands/ui/themes.d.ts.map +1 -0
- package/dist/commands/ui/themes.js +40 -0
- package/dist/commands/ui/themes.js.map +1 -0
- package/dist/commands/ui/tmux.d.ts +5 -0
- package/dist/commands/ui/tmux.d.ts.map +1 -0
- package/dist/commands/ui/tmux.js +19 -0
- package/dist/commands/ui/tmux.js.map +1 -0
- package/dist/cortex.d.ts +12 -0
- package/dist/cortex.d.ts.map +1 -0
- package/dist/cortex.js +320 -0
- package/dist/cortex.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +112 -0
- package/dist/index.js.map +1 -0
- package/dist/ink-ui/CortexApp.d.ts +28 -0
- package/dist/ink-ui/CortexApp.d.ts.map +1 -0
- package/dist/ink-ui/CortexApp.js +2291 -0
- package/dist/ink-ui/CortexApp.js.map +1 -0
- package/dist/ink-ui/SimpleInputBuffer.d.ts +63 -0
- package/dist/ink-ui/SimpleInputBuffer.d.ts.map +1 -0
- package/dist/ink-ui/SimpleInputBuffer.js +369 -0
- package/dist/ink-ui/SimpleInputBuffer.js.map +1 -0
- package/dist/ink-ui/commands/slashCommands.d.ts +40 -0
- package/dist/ink-ui/commands/slashCommands.d.ts.map +1 -0
- package/dist/ink-ui/commands/slashCommands.js +111 -0
- package/dist/ink-ui/commands/slashCommands.js.map +1 -0
- package/dist/ink-ui/commands/types.d.ts +161 -0
- package/dist/ink-ui/commands/types.d.ts.map +1 -0
- package/dist/ink-ui/commands/types.js +12 -0
- package/dist/ink-ui/commands/types.js.map +1 -0
- package/dist/ink-ui/components/ApprovalDialog.d.ts +21 -0
- package/dist/ink-ui/components/ApprovalDialog.d.ts.map +1 -0
- package/dist/ink-ui/components/ApprovalDialog.js +81 -0
- package/dist/ink-ui/components/ApprovalDialog.js.map +1 -0
- package/dist/ink-ui/components/CommandSuggestions.d.ts +19 -0
- package/dist/ink-ui/components/CommandSuggestions.d.ts.map +1 -0
- package/dist/ink-ui/components/CommandSuggestions.js +36 -0
- package/dist/ink-ui/components/CommandSuggestions.js.map +1 -0
- package/dist/ink-ui/components/DiffPreview.d.ts +60 -0
- package/dist/ink-ui/components/DiffPreview.d.ts.map +1 -0
- package/dist/ink-ui/components/DiffPreview.js +195 -0
- package/dist/ink-ui/components/DiffPreview.js.map +1 -0
- package/dist/ink-ui/components/DocumentPreview.d.ts +50 -0
- package/dist/ink-ui/components/DocumentPreview.d.ts.map +1 -0
- package/dist/ink-ui/components/DocumentPreview.js +92 -0
- package/dist/ink-ui/components/DocumentPreview.js.map +1 -0
- package/dist/ink-ui/components/MarkdownText.d.ts +27 -0
- package/dist/ink-ui/components/MarkdownText.d.ts.map +1 -0
- package/dist/ink-ui/components/MarkdownText.js +342 -0
- package/dist/ink-ui/components/MarkdownText.js.map +1 -0
- package/dist/ink-ui/components/MenuRenderer.d.ts +26 -0
- package/dist/ink-ui/components/MenuRenderer.d.ts.map +1 -0
- package/dist/ink-ui/components/MenuRenderer.js +264 -0
- package/dist/ink-ui/components/MenuRenderer.js.map +1 -0
- package/dist/ink-ui/components/ModelPickerDialog.d.ts +33 -0
- package/dist/ink-ui/components/ModelPickerDialog.d.ts.map +1 -0
- package/dist/ink-ui/components/ModelPickerDialog.js +98 -0
- package/dist/ink-ui/components/ModelPickerDialog.js.map +1 -0
- package/dist/ink-ui/components/StreamDisplay.d.ts +31 -0
- package/dist/ink-ui/components/StreamDisplay.d.ts.map +1 -0
- package/dist/ink-ui/components/StreamDisplay.js +573 -0
- package/dist/ink-ui/components/StreamDisplay.js.map +1 -0
- package/dist/ink-ui/components/SubAgentPanel.d.ts +98 -0
- package/dist/ink-ui/components/SubAgentPanel.d.ts.map +1 -0
- package/dist/ink-ui/components/SubAgentPanel.js +155 -0
- package/dist/ink-ui/components/SubAgentPanel.js.map +1 -0
- package/dist/ink-ui/components/ThinkingDisplay.d.ts +46 -0
- package/dist/ink-ui/components/ThinkingDisplay.d.ts.map +1 -0
- package/dist/ink-ui/components/ThinkingDisplay.js +176 -0
- package/dist/ink-ui/components/ThinkingDisplay.js.map +1 -0
- package/dist/ink-ui/components/ToolCallDisplay.d.ts +51 -0
- package/dist/ink-ui/components/ToolCallDisplay.d.ts.map +1 -0
- package/dist/ink-ui/components/ToolCallDisplay.js +378 -0
- package/dist/ink-ui/components/ToolCallDisplay.js.map +1 -0
- package/dist/ink-ui/components/WritePreview.d.ts +42 -0
- package/dist/ink-ui/components/WritePreview.d.ts.map +1 -0
- package/dist/ink-ui/components/WritePreview.js +100 -0
- package/dist/ink-ui/components/WritePreview.js.map +1 -0
- package/dist/ink-ui/contexts/KeypressContext.d.ts +32 -0
- package/dist/ink-ui/contexts/KeypressContext.d.ts.map +1 -0
- package/dist/ink-ui/contexts/KeypressContext.js +529 -0
- package/dist/ink-ui/contexts/KeypressContext.js.map +1 -0
- package/dist/ink-ui/contexts/SessionContext.d.ts +46 -0
- package/dist/ink-ui/contexts/SessionContext.d.ts.map +1 -0
- package/dist/ink-ui/contexts/SessionContext.js +162 -0
- package/dist/ink-ui/contexts/SessionContext.js.map +1 -0
- package/dist/ink-ui/core-stubs.d.ts +270 -0
- package/dist/ink-ui/core-stubs.d.ts.map +1 -0
- package/dist/ink-ui/core-stubs.js +276 -0
- package/dist/ink-ui/core-stubs.js.map +1 -0
- package/dist/ink-ui/cortex-types.d.ts +214 -0
- package/dist/ink-ui/cortex-types.d.ts.map +1 -0
- package/dist/ink-ui/cortex-types.js +52 -0
- package/dist/ink-ui/cortex-types.js.map +1 -0
- package/dist/ink-ui/hooks/useCortexStream.d.ts +75 -0
- package/dist/ink-ui/hooks/useCortexStream.d.ts.map +1 -0
- package/dist/ink-ui/hooks/useCortexStream.js +518 -0
- package/dist/ink-ui/hooks/useCortexStream.js.map +1 -0
- package/dist/ink-ui/hooks/useFocus.d.ts +11 -0
- package/dist/ink-ui/hooks/useFocus.d.ts.map +1 -0
- package/dist/ink-ui/hooks/useFocus.js +51 -0
- package/dist/ink-ui/hooks/useFocus.js.map +1 -0
- package/dist/ink-ui/hooks/useHistoryManager.d.ts +23 -0
- package/dist/ink-ui/hooks/useHistoryManager.d.ts.map +1 -0
- package/dist/ink-ui/hooks/useHistoryManager.js +63 -0
- package/dist/ink-ui/hooks/useHistoryManager.js.map +1 -0
- package/dist/ink-ui/hooks/useKeypress.d.ts +18 -0
- package/dist/ink-ui/hooks/useKeypress.d.ts.map +1 -0
- package/dist/ink-ui/hooks/useKeypress.js +27 -0
- package/dist/ink-ui/hooks/useKeypress.js.map +1 -0
- package/dist/ink-ui/hooks/useReactApprovalHandler.d.ts +74 -0
- package/dist/ink-ui/hooks/useReactApprovalHandler.d.ts.map +1 -0
- package/dist/ink-ui/hooks/useReactApprovalHandler.js +83 -0
- package/dist/ink-ui/hooks/useReactApprovalHandler.js.map +1 -0
- package/dist/ink-ui/hooks/useTerminalSize.d.ts +10 -0
- package/dist/ink-ui/hooks/useTerminalSize.d.ts.map +1 -0
- package/dist/ink-ui/hooks/useTerminalSize.js +28 -0
- package/dist/ink-ui/hooks/useTerminalSize.js.map +1 -0
- package/dist/ink-ui/semantic-colors.d.ts +8 -0
- package/dist/ink-ui/semantic-colors.d.ts.map +1 -0
- package/dist/ink-ui/semantic-colors.js +24 -0
- package/dist/ink-ui/semantic-colors.js.map +1 -0
- package/dist/ink-ui/state/extensions.d.ts +68 -0
- package/dist/ink-ui/state/extensions.d.ts.map +1 -0
- package/dist/ink-ui/state/extensions.js +97 -0
- package/dist/ink-ui/state/extensions.js.map +1 -0
- package/dist/ink-ui/themes/ansi-light.d.ts +8 -0
- package/dist/ink-ui/themes/ansi-light.d.ts.map +1 -0
- package/dist/ink-ui/themes/ansi-light.js +143 -0
- package/dist/ink-ui/themes/ansi-light.js.map +1 -0
- package/dist/ink-ui/themes/ansi.d.ts +8 -0
- package/dist/ink-ui/themes/ansi.d.ts.map +1 -0
- package/dist/ink-ui/themes/ansi.js +153 -0
- package/dist/ink-ui/themes/ansi.js.map +1 -0
- package/dist/ink-ui/themes/atom-one-dark.d.ts +8 -0
- package/dist/ink-ui/themes/atom-one-dark.d.ts.map +1 -0
- package/dist/ink-ui/themes/atom-one-dark.js +140 -0
- package/dist/ink-ui/themes/atom-one-dark.js.map +1 -0
- package/dist/ink-ui/themes/ayu-light.d.ts +8 -0
- package/dist/ink-ui/themes/ayu-light.d.ts.map +1 -0
- package/dist/ink-ui/themes/ayu-light.js +132 -0
- package/dist/ink-ui/themes/ayu-light.js.map +1 -0
- package/dist/ink-ui/themes/ayu.d.ts +8 -0
- package/dist/ink-ui/themes/ayu.d.ts.map +1 -0
- package/dist/ink-ui/themes/ayu.js +106 -0
- package/dist/ink-ui/themes/ayu.js.map +1 -0
- package/dist/ink-ui/themes/color-utils.d.ts +23 -0
- package/dist/ink-ui/themes/color-utils.d.ts.map +1 -0
- package/dist/ink-ui/themes/color-utils.js +237 -0
- package/dist/ink-ui/themes/color-utils.js.map +1 -0
- package/dist/ink-ui/themes/default-light.d.ts +8 -0
- package/dist/ink-ui/themes/default-light.d.ts.map +1 -0
- package/dist/ink-ui/themes/default-light.js +100 -0
- package/dist/ink-ui/themes/default-light.js.map +1 -0
- package/dist/ink-ui/themes/default.d.ts +8 -0
- package/dist/ink-ui/themes/default.d.ts.map +1 -0
- package/dist/ink-ui/themes/default.js +143 -0
- package/dist/ink-ui/themes/default.js.map +1 -0
- package/dist/ink-ui/themes/dracula.d.ts +8 -0
- package/dist/ink-ui/themes/dracula.d.ts.map +1 -0
- package/dist/ink-ui/themes/dracula.js +117 -0
- package/dist/ink-ui/themes/dracula.js.map +1 -0
- package/dist/ink-ui/themes/github-dark.d.ts +8 -0
- package/dist/ink-ui/themes/github-dark.d.ts.map +1 -0
- package/dist/ink-ui/themes/github-dark.js +140 -0
- package/dist/ink-ui/themes/github-dark.js.map +1 -0
- package/dist/ink-ui/themes/github-light.d.ts +8 -0
- package/dist/ink-ui/themes/github-light.d.ts.map +1 -0
- package/dist/ink-ui/themes/github-light.js +142 -0
- package/dist/ink-ui/themes/github-light.js.map +1 -0
- package/dist/ink-ui/themes/googlecode.d.ts +8 -0
- package/dist/ink-ui/themes/googlecode.d.ts.map +1 -0
- package/dist/ink-ui/themes/googlecode.js +139 -0
- package/dist/ink-ui/themes/googlecode.js.map +1 -0
- package/dist/ink-ui/themes/no-color.d.ts +8 -0
- package/dist/ink-ui/themes/no-color.d.ts.map +1 -0
- package/dist/ink-ui/themes/no-color.js +118 -0
- package/dist/ink-ui/themes/no-color.js.map +1 -0
- package/dist/ink-ui/themes/semantic-tokens.d.ts +40 -0
- package/dist/ink-ui/themes/semantic-tokens.d.ts.map +1 -0
- package/dist/ink-ui/themes/semantic-tokens.js +100 -0
- package/dist/ink-ui/themes/semantic-tokens.js.map +1 -0
- package/dist/ink-ui/themes/shades-of-purple.d.ts +12 -0
- package/dist/ink-ui/themes/shades-of-purple.d.ts.map +1 -0
- package/dist/ink-ui/themes/shades-of-purple.js +306 -0
- package/dist/ink-ui/themes/shades-of-purple.js.map +1 -0
- package/dist/ink-ui/themes/theme-manager.d.ts +67 -0
- package/dist/ink-ui/themes/theme-manager.d.ts.map +1 -0
- package/dist/ink-ui/themes/theme-manager.js +263 -0
- package/dist/ink-ui/themes/theme-manager.js.map +1 -0
- package/dist/ink-ui/themes/theme.d.ts +134 -0
- package/dist/ink-ui/themes/theme.d.ts.map +1 -0
- package/dist/ink-ui/themes/theme.js +390 -0
- package/dist/ink-ui/themes/theme.js.map +1 -0
- package/dist/ink-ui/themes/xcode.d.ts +8 -0
- package/dist/ink-ui/themes/xcode.d.ts.map +1 -0
- package/dist/ink-ui/themes/xcode.js +147 -0
- package/dist/ink-ui/themes/xcode.js.map +1 -0
- package/dist/ink-ui/types.d.ts +306 -0
- package/dist/ink-ui/types.d.ts.map +1 -0
- package/dist/ink-ui/types.js +65 -0
- package/dist/ink-ui/types.js.map +1 -0
- package/dist/ink-ui/utils/input.d.ts +18 -0
- package/dist/ink-ui/utils/input.d.ts.map +1 -0
- package/dist/ink-ui/utils/input.js +51 -0
- package/dist/ink-ui/utils/input.js.map +1 -0
- package/dist/ink-ui/utils/mouse.d.ts +33 -0
- package/dist/ink-ui/utils/mouse.d.ts.map +1 -0
- package/dist/ink-ui/utils/mouse.js +182 -0
- package/dist/ink-ui/utils/mouse.js.map +1 -0
- package/dist/services/BuiltinCommandLoader.d.ts +21 -0
- package/dist/services/BuiltinCommandLoader.d.ts.map +1 -0
- package/dist/services/BuiltinCommandLoader.js +182 -0
- package/dist/services/BuiltinCommandLoader.js.map +1 -0
- package/dist/services/CommandService.d.ts +39 -0
- package/dist/services/CommandService.d.ts.map +1 -0
- package/dist/services/CommandService.js +49 -0
- package/dist/services/CommandService.js.map +1 -0
- package/dist/services/FileCommandLoader.d.ts +16 -0
- package/dist/services/FileCommandLoader.d.ts.map +1 -0
- package/dist/services/FileCommandLoader.js +19 -0
- package/dist/services/FileCommandLoader.js.map +1 -0
- package/dist/services/McpPromptLoader.d.ts +16 -0
- package/dist/services/McpPromptLoader.d.ts.map +1 -0
- package/dist/services/McpPromptLoader.js +19 -0
- package/dist/services/McpPromptLoader.js.map +1 -0
- package/dist/services/index.d.ts +8 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +8 -0
- package/dist/services/index.js.map +1 -0
- package/dist/ui/ChalkMenuRenderer.d.ts +22 -0
- package/dist/ui/ChalkMenuRenderer.d.ts.map +1 -0
- package/dist/ui/ChalkMenuRenderer.js +478 -0
- package/dist/ui/ChalkMenuRenderer.js.map +1 -0
- package/dist/ui/ChalkModelPicker.d.ts +20 -0
- package/dist/ui/ChalkModelPicker.d.ts.map +1 -0
- package/dist/ui/ChalkModelPicker.js +363 -0
- package/dist/ui/ChalkModelPicker.js.map +1 -0
- package/dist/ui/ChalkThemePicker.d.ts +20 -0
- package/dist/ui/ChalkThemePicker.d.ts.map +1 -0
- package/dist/ui/ChalkThemePicker.js +370 -0
- package/dist/ui/ChalkThemePicker.js.map +1 -0
- package/dist/ui/InkApprovalDialog.d.ts +8 -0
- package/dist/ui/InkApprovalDialog.d.ts.map +1 -0
- package/dist/ui/InkApprovalDialog.js +25 -0
- package/dist/ui/InkApprovalDialog.js.map +1 -0
- package/dist/ui/InkCommandPalette.d.ts +43 -0
- package/dist/ui/InkCommandPalette.d.ts.map +1 -0
- package/dist/ui/InkCommandPalette.js +105 -0
- package/dist/ui/InkCommandPalette.js.map +1 -0
- package/dist/ui/InkConfigMenu.d.ts +24 -0
- package/dist/ui/InkConfigMenu.d.ts.map +1 -0
- package/dist/ui/InkConfigMenu.js +259 -0
- package/dist/ui/InkConfigMenu.js.map +1 -0
- package/dist/ui/InkHelp.d.ts +25 -0
- package/dist/ui/InkHelp.d.ts.map +1 -0
- package/dist/ui/InkHelp.js +55 -0
- package/dist/ui/InkHelp.js.map +1 -0
- package/dist/ui/InkMenuPicker.d.ts +19 -0
- package/dist/ui/InkMenuPicker.d.ts.map +1 -0
- package/dist/ui/InkMenuPicker.js +33 -0
- package/dist/ui/InkMenuPicker.js.map +1 -0
- package/dist/ui/InkModelPicker.d.ts +23 -0
- package/dist/ui/InkModelPicker.d.ts.map +1 -0
- package/dist/ui/InkModelPicker.js +53 -0
- package/dist/ui/InkModelPicker.js.map +1 -0
- package/dist/ui/PersistentInput.d.ts +91 -0
- package/dist/ui/PersistentInput.d.ts.map +1 -0
- package/dist/ui/PersistentInput.js +283 -0
- package/dist/ui/PersistentInput.js.map +1 -0
- package/dist/ui/RawInput.d.ts +27 -0
- package/dist/ui/RawInput.d.ts.map +1 -0
- package/dist/ui/RawInput.js +731 -0
- package/dist/ui/RawInput.js.map +1 -0
- package/dist/ui/SlashCommandAutocomplete.d.ts +94 -0
- package/dist/ui/SlashCommandAutocomplete.d.ts.map +1 -0
- package/dist/ui/SlashCommandAutocomplete.js +274 -0
- package/dist/ui/SlashCommandAutocomplete.js.map +1 -0
- package/dist/ui/SplashScreen.d.ts +76 -0
- package/dist/ui/SplashScreen.d.ts.map +1 -0
- package/dist/ui/SplashScreen.js +316 -0
- package/dist/ui/SplashScreen.js.map +1 -0
- package/dist/ui/components/ArtifactDashboard.d.ts +16 -0
- package/dist/ui/components/ArtifactDashboard.d.ts.map +1 -0
- package/dist/ui/components/ArtifactDashboard.js +102 -0
- package/dist/ui/components/ArtifactDashboard.js.map +1 -0
- package/dist/ui/components/ChatInput.d.ts +36 -0
- package/dist/ui/components/ChatInput.d.ts.map +1 -0
- package/dist/ui/components/ChatInput.js +11 -0
- package/dist/ui/components/ChatInput.js.map +1 -0
- package/dist/ui/components/ConfigWizard.d.ts +17 -0
- package/dist/ui/components/ConfigWizard.d.ts.map +1 -0
- package/dist/ui/components/ConfigWizard.js +134 -0
- package/dist/ui/components/ConfigWizard.js.map +1 -0
- package/dist/ui/components/ContextViewer.d.ts +18 -0
- package/dist/ui/components/ContextViewer.d.ts.map +1 -0
- package/dist/ui/components/ContextViewer.js +85 -0
- package/dist/ui/components/ContextViewer.js.map +1 -0
- package/dist/ui/components/MiddlewareDashboard.d.ts +16 -0
- package/dist/ui/components/MiddlewareDashboard.d.ts.map +1 -0
- package/dist/ui/components/MiddlewareDashboard.js +98 -0
- package/dist/ui/components/MiddlewareDashboard.js.map +1 -0
- package/dist/ui/components/ModelPicker.d.ts +24 -0
- package/dist/ui/components/ModelPicker.d.ts.map +1 -0
- package/dist/ui/components/ModelPicker.js +96 -0
- package/dist/ui/components/ModelPicker.js.map +1 -0
- package/dist/ui/components/MultiLineInput.d.ts +27 -0
- package/dist/ui/components/MultiLineInput.d.ts.map +1 -0
- package/dist/ui/components/MultiLineInput.js +182 -0
- package/dist/ui/components/MultiLineInput.js.map +1 -0
- package/dist/ui/components/PermissionsBrowser.d.ts +16 -0
- package/dist/ui/components/PermissionsBrowser.d.ts.map +1 -0
- package/dist/ui/components/PermissionsBrowser.js +110 -0
- package/dist/ui/components/PermissionsBrowser.js.map +1 -0
- package/dist/ui/components/SessionBrowser.d.ts +19 -0
- package/dist/ui/components/SessionBrowser.d.ts.map +1 -0
- package/dist/ui/components/SessionBrowser.js +66 -0
- package/dist/ui/components/SessionBrowser.js.map +1 -0
- package/dist/ui/components/StatusBar.d.ts +32 -0
- package/dist/ui/components/StatusBar.d.ts.map +1 -0
- package/dist/ui/components/StatusBar.js +27 -0
- package/dist/ui/components/StatusBar.js.map +1 -0
- package/dist/ui/components/SystemMessageBrowser.d.ts +11 -0
- package/dist/ui/components/SystemMessageBrowser.d.ts.map +1 -0
- package/dist/ui/components/SystemMessageBrowser.js +106 -0
- package/dist/ui/components/SystemMessageBrowser.js.map +1 -0
- package/dist/ui/components/ThemePicker.d.ts +11 -0
- package/dist/ui/components/ThemePicker.d.ts.map +1 -0
- package/dist/ui/components/ThemePicker.js +62 -0
- package/dist/ui/components/ThemePicker.js.map +1 -0
- package/dist/ui/components/TmuxBrowser.d.ts +11 -0
- package/dist/ui/components/TmuxBrowser.d.ts.map +1 -0
- package/dist/ui/components/TmuxBrowser.js +85 -0
- package/dist/ui/components/TmuxBrowser.js.map +1 -0
- package/dist/ui/components/index.d.ts +22 -0
- package/dist/ui/components/index.d.ts.map +1 -0
- package/dist/ui/components/index.js +21 -0
- package/dist/ui/components/index.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,731 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raw Terminal Input with Persistent Status Line
|
|
3
|
+
*
|
|
4
|
+
* Provides a readline-like interface but with full control over terminal rendering,
|
|
5
|
+
* allowing us to show a status line below the input while the user types.
|
|
6
|
+
*/
|
|
7
|
+
import { renderStatusLine } from './SplashScreen.js';
|
|
8
|
+
import { slashCommandAutocomplete } from './SlashCommandAutocomplete.js';
|
|
9
|
+
// ANSI escape codes
|
|
10
|
+
const ESC = '\x1b';
|
|
11
|
+
const CSI = `${ESC}[`;
|
|
12
|
+
const ANSI = {
|
|
13
|
+
clearLine: `${CSI}2K`,
|
|
14
|
+
clearToEnd: `${CSI}0K`,
|
|
15
|
+
cursorUp: (n) => `${CSI}${n}A`,
|
|
16
|
+
cursorDown: (n) => `${CSI}${n}B`,
|
|
17
|
+
cursorForward: (n) => `${CSI}${n}C`,
|
|
18
|
+
cursorBack: (n) => `${CSI}${n}D`,
|
|
19
|
+
cursorToColumn: (n) => `${CSI}${n}G`,
|
|
20
|
+
saveCursor: `${ESC}7`,
|
|
21
|
+
restoreCursor: `${ESC}8`,
|
|
22
|
+
hideCursor: `${CSI}?25l`,
|
|
23
|
+
showCursor: `${CSI}?25h`,
|
|
24
|
+
};
|
|
25
|
+
// Bracketed paste mode markers (some terminals send these)
|
|
26
|
+
const PASTE_START = `${CSI}200~`;
|
|
27
|
+
const PASTE_END = `${CSI}201~`;
|
|
28
|
+
/**
|
|
29
|
+
* Calculate display width of a string (accounting for wide characters)
|
|
30
|
+
* Wide characters (emoji, CJK) take 2 columns
|
|
31
|
+
*/
|
|
32
|
+
function getDisplayWidth(str) {
|
|
33
|
+
let width = 0;
|
|
34
|
+
for (const char of str) {
|
|
35
|
+
const code = char.codePointAt(0) || 0;
|
|
36
|
+
// Wide characters: CJK, emoji, fullwidth
|
|
37
|
+
if ((code >= 0x1100 && code <= 0x115F) || // Hangul Jamo
|
|
38
|
+
(code >= 0x2E80 && code <= 0x9FFF) || // CJK
|
|
39
|
+
(code >= 0xAC00 && code <= 0xD7A3) || // Hangul Syllables
|
|
40
|
+
(code >= 0xF900 && code <= 0xFAFF) || // CJK Compatibility
|
|
41
|
+
(code >= 0xFE10 && code <= 0xFE1F) || // Vertical forms
|
|
42
|
+
(code >= 0xFE30 && code <= 0xFE6F) || // CJK Compatibility Forms
|
|
43
|
+
(code >= 0xFF00 && code <= 0xFF60) || // Fullwidth
|
|
44
|
+
(code >= 0xFFE0 && code <= 0xFFE6) || // Fullwidth symbols
|
|
45
|
+
(code >= 0x1F300 && code <= 0x1F9FF) || // Emoji
|
|
46
|
+
(code >= 0x20000 && code <= 0x2FFFF) // CJK Extension B+
|
|
47
|
+
) {
|
|
48
|
+
width += 2;
|
|
49
|
+
}
|
|
50
|
+
else if (code >= 0x20) {
|
|
51
|
+
width += 1;
|
|
52
|
+
}
|
|
53
|
+
// Control characters (< 0x20) have width 0
|
|
54
|
+
}
|
|
55
|
+
return width;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get display width up to a character position (for cursor positioning)
|
|
59
|
+
*/
|
|
60
|
+
function getDisplayWidthUpTo(str, charPos) {
|
|
61
|
+
return getDisplayWidth(str.slice(0, charPos));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Calculate multiline metrics for input with explicit newlines and terminal wrapping
|
|
65
|
+
* Returns info about total visual lines and cursor position
|
|
66
|
+
*/
|
|
67
|
+
function getMultilineMetrics(input, cursorPos, termWidth, prefixWidth) {
|
|
68
|
+
const lines = input.split('\n');
|
|
69
|
+
let totalVisualLines = 0;
|
|
70
|
+
let cursorVisualRow = 0;
|
|
71
|
+
let cursorVisualCol = 0;
|
|
72
|
+
let charCount = 0;
|
|
73
|
+
for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
|
74
|
+
const line = lines[lineIdx];
|
|
75
|
+
const lineDisplayWidth = getDisplayWidth(line);
|
|
76
|
+
// First line has prefix, subsequent lines start at column 0
|
|
77
|
+
const effectiveWidth = lineIdx === 0 ? prefixWidth + lineDisplayWidth : lineDisplayWidth;
|
|
78
|
+
const lineVisualRows = Math.max(1, Math.ceil(effectiveWidth / termWidth) || 1);
|
|
79
|
+
// Check if cursor is on this line
|
|
80
|
+
const lineStart = charCount;
|
|
81
|
+
const lineEnd = charCount + line.length;
|
|
82
|
+
if (cursorPos >= lineStart && cursorPos <= lineEnd) {
|
|
83
|
+
// Cursor is on this line
|
|
84
|
+
const posInLine = cursorPos - lineStart;
|
|
85
|
+
const displayPosInLine = getDisplayWidthUpTo(line, posInLine);
|
|
86
|
+
const absoluteCol = lineIdx === 0 ? prefixWidth + displayPosInLine : displayPosInLine;
|
|
87
|
+
cursorVisualRow = totalVisualLines + Math.floor(absoluteCol / termWidth);
|
|
88
|
+
cursorVisualCol = absoluteCol % termWidth;
|
|
89
|
+
}
|
|
90
|
+
totalVisualLines += lineVisualRows;
|
|
91
|
+
charCount += line.length + 1; // +1 for newline
|
|
92
|
+
}
|
|
93
|
+
return { totalVisualLines, cursorVisualRow, cursorVisualCol };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Find the character position in input that corresponds to a visual row/col
|
|
97
|
+
* Used for up/down arrow navigation in multiline input
|
|
98
|
+
*/
|
|
99
|
+
function findCharPosForVisualPosition(input, targetRow, targetCol, termWidth, prefixWidth) {
|
|
100
|
+
const lines = input.split('\n');
|
|
101
|
+
let currentVisualRow = 0;
|
|
102
|
+
let charCount = 0;
|
|
103
|
+
for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
|
104
|
+
const line = lines[lineIdx];
|
|
105
|
+
const lineDisplayWidth = getDisplayWidth(line);
|
|
106
|
+
// First line has prefix, subsequent lines start at column 0
|
|
107
|
+
const effectiveWidth = lineIdx === 0 ? prefixWidth + lineDisplayWidth : lineDisplayWidth;
|
|
108
|
+
const lineVisualRows = Math.max(1, Math.ceil(effectiveWidth / termWidth) || 1);
|
|
109
|
+
// Check if target row is within this line's visual rows
|
|
110
|
+
if (targetRow >= currentVisualRow && targetRow < currentVisualRow + lineVisualRows) {
|
|
111
|
+
// Target is on this line - find exact character position
|
|
112
|
+
const rowWithinLine = targetRow - currentVisualRow;
|
|
113
|
+
const targetDisplayPos = rowWithinLine * termWidth + targetCol - (rowWithinLine === 0 && lineIdx === 0 ? prefixWidth : 0);
|
|
114
|
+
// Find character position for this display position within the line
|
|
115
|
+
let displayWidth = 0;
|
|
116
|
+
for (let i = 0; i < line.length; i++) {
|
|
117
|
+
const charWidth = getDisplayWidth(line.charAt(i));
|
|
118
|
+
if (displayWidth >= targetDisplayPos) {
|
|
119
|
+
return charCount + i;
|
|
120
|
+
}
|
|
121
|
+
displayWidth += charWidth;
|
|
122
|
+
}
|
|
123
|
+
// If we reach end of line, return end of line position
|
|
124
|
+
return charCount + line.length;
|
|
125
|
+
}
|
|
126
|
+
currentVisualRow += lineVisualRows;
|
|
127
|
+
charCount += line.length + 1; // +1 for newline
|
|
128
|
+
}
|
|
129
|
+
// If target row is beyond input, return end of input
|
|
130
|
+
return input.length;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Check if a character is a word character (alphanumeric or underscore)
|
|
134
|
+
*/
|
|
135
|
+
function isWordChar(char) {
|
|
136
|
+
return /[\w\u00C0-\u024F\u1E00-\u1EFF]/.test(char);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Find the start of the previous word from cursor position
|
|
140
|
+
* Mimics Option+Left behavior: skip whitespace, then skip word chars
|
|
141
|
+
*/
|
|
142
|
+
function findPrevWordStart(str, pos) {
|
|
143
|
+
if (pos <= 0)
|
|
144
|
+
return 0;
|
|
145
|
+
let i = pos - 1;
|
|
146
|
+
// Skip any whitespace/non-word chars immediately before cursor
|
|
147
|
+
while (i > 0 && !isWordChar(str[i])) {
|
|
148
|
+
i--;
|
|
149
|
+
}
|
|
150
|
+
// Now skip the word characters to find the start of the word
|
|
151
|
+
while (i > 0 && isWordChar(str[i - 1])) {
|
|
152
|
+
i--;
|
|
153
|
+
}
|
|
154
|
+
return i;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Find the end of the next word from cursor position
|
|
158
|
+
* Mimics Option+Right behavior: skip current word, then skip whitespace
|
|
159
|
+
*/
|
|
160
|
+
function findNextWordEnd(str, pos) {
|
|
161
|
+
if (pos >= str.length)
|
|
162
|
+
return str.length;
|
|
163
|
+
let i = pos;
|
|
164
|
+
// Skip current word characters
|
|
165
|
+
while (i < str.length && isWordChar(str[i])) {
|
|
166
|
+
i++;
|
|
167
|
+
}
|
|
168
|
+
// Skip whitespace/non-word chars to reach the next word
|
|
169
|
+
while (i < str.length && !isWordChar(str[i])) {
|
|
170
|
+
i++;
|
|
171
|
+
}
|
|
172
|
+
return i;
|
|
173
|
+
}
|
|
174
|
+
// Track frame state for redraws
|
|
175
|
+
let lastFrameTotalLines = 0;
|
|
176
|
+
let lastCursorRowInFrame = 0; // Which row (0-indexed from top of frame) cursor is on
|
|
177
|
+
// Module-level history that persists across rawQuestion calls
|
|
178
|
+
const inputHistory = [];
|
|
179
|
+
const MAX_HISTORY_SIZE = 100;
|
|
180
|
+
/**
|
|
181
|
+
* Draw the input frame with status line below
|
|
182
|
+
*
|
|
183
|
+
* Uses explicit line counting and cursor movement (not save/restore which fails on scroll).
|
|
184
|
+
* Supports multiline input with explicit newlines and terminal wrapping.
|
|
185
|
+
*/
|
|
186
|
+
function drawInputFrame(inputLine, cursorPos, options) {
|
|
187
|
+
const theme = options.theme;
|
|
188
|
+
const termWidth = process.stdout.columns || 80;
|
|
189
|
+
const borderWidth = Math.min(70, termWidth);
|
|
190
|
+
const statusLine = renderStatusLine(options.getStatusState());
|
|
191
|
+
const shortcuts = ' / commands • ←→↑↓ nav • ⌥←→ word • ⌥↑↓ 5 lines • ⌥⌫ del word';
|
|
192
|
+
const prefixWidth = 3; // " > "
|
|
193
|
+
const prefix = theme.colors.info(' > ');
|
|
194
|
+
// Calculate multiline metrics (handles explicit newlines + terminal wrapping)
|
|
195
|
+
const metrics = getMultilineMetrics(inputLine, cursorPos, termWidth, prefixWidth);
|
|
196
|
+
const inputLinesCount = metrics.totalVisualLines;
|
|
197
|
+
// Get autocomplete popup lines (if visible)
|
|
198
|
+
const autocompleteLines = slashCommandAutocomplete.render();
|
|
199
|
+
const autocompleteLineCount = autocompleteLines.length;
|
|
200
|
+
// For redraws, move cursor back to top of previous frame
|
|
201
|
+
// Use tracked cursor position for accurate repositioning
|
|
202
|
+
if (lastFrameTotalLines > 0 && lastCursorRowInFrame > 0) {
|
|
203
|
+
// Move to start of line first
|
|
204
|
+
process.stdout.write('\r');
|
|
205
|
+
// Move up from cursor's current row to top of frame
|
|
206
|
+
process.stdout.write(ANSI.cursorUp(lastCursorRowInFrame));
|
|
207
|
+
}
|
|
208
|
+
// Calculate total lines this frame will use
|
|
209
|
+
// Frame = autocomplete popup + top border (1) + input lines + bottom border (1) + shortcuts (1) + status (1)
|
|
210
|
+
const totalFrameLines = autocompleteLineCount + 1 + inputLinesCount + 1 + 1 + 1;
|
|
211
|
+
lastFrameTotalLines = totalFrameLines;
|
|
212
|
+
// Draw autocomplete popup (if visible) - above the input box
|
|
213
|
+
for (const line of autocompleteLines) {
|
|
214
|
+
process.stdout.write(ANSI.clearLine);
|
|
215
|
+
process.stdout.write(line + '\n');
|
|
216
|
+
}
|
|
217
|
+
// Draw top border
|
|
218
|
+
process.stdout.write(ANSI.clearLine);
|
|
219
|
+
process.stdout.write(theme.dimmed('─'.repeat(borderWidth)) + '\n');
|
|
220
|
+
// Draw input line(s) - terminal handles wrapping naturally
|
|
221
|
+
// For multiline input, we need to clear each line as we go
|
|
222
|
+
const inputLines = inputLine.split('\n');
|
|
223
|
+
for (let i = 0; i < inputLines.length; i++) {
|
|
224
|
+
process.stdout.write(ANSI.clearLine);
|
|
225
|
+
if (i === 0) {
|
|
226
|
+
process.stdout.write(prefix + inputLines[i]);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
process.stdout.write(inputLines[i]);
|
|
230
|
+
}
|
|
231
|
+
process.stdout.write(ANSI.clearToEnd);
|
|
232
|
+
if (i < inputLines.length - 1) {
|
|
233
|
+
process.stdout.write('\n');
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// Move to next line after input
|
|
237
|
+
process.stdout.write('\n');
|
|
238
|
+
// Draw bottom border
|
|
239
|
+
process.stdout.write(ANSI.clearLine);
|
|
240
|
+
process.stdout.write(theme.dimmed('─'.repeat(borderWidth)) + '\n');
|
|
241
|
+
// Draw shortcuts
|
|
242
|
+
process.stdout.write(ANSI.clearLine);
|
|
243
|
+
process.stdout.write(theme.dimmed(shortcuts) + '\n');
|
|
244
|
+
// Draw status line
|
|
245
|
+
process.stdout.write(ANSI.clearLine);
|
|
246
|
+
process.stdout.write(statusLine + ANSI.clearToEnd);
|
|
247
|
+
// Clear any extra lines below (in case previous input was longer or autocomplete was visible)
|
|
248
|
+
const extraLinesToClear = 5 + (autocompleteLineCount > 0 ? 15 : 0); // Extra space for autocomplete
|
|
249
|
+
for (let i = 0; i < extraLinesToClear; i++) {
|
|
250
|
+
process.stdout.write('\n' + ANSI.clearLine);
|
|
251
|
+
}
|
|
252
|
+
// Move back up past the extra cleared lines
|
|
253
|
+
process.stdout.write(ANSI.cursorUp(extraLinesToClear));
|
|
254
|
+
// Move cursor back to input line
|
|
255
|
+
// From status line, go up: shortcuts(1) + bottom border(1) + input lines to reach first input row
|
|
256
|
+
// Then we'll move down to the correct row within input
|
|
257
|
+
const linesUp = 3 + (inputLinesCount - 1);
|
|
258
|
+
process.stdout.write(ANSI.cursorUp(linesUp));
|
|
259
|
+
// Move down to correct visual row within input
|
|
260
|
+
if (metrics.cursorVisualRow > 0) {
|
|
261
|
+
process.stdout.write(ANSI.cursorDown(metrics.cursorVisualRow));
|
|
262
|
+
}
|
|
263
|
+
// Move to correct column (1-indexed for ANSI)
|
|
264
|
+
process.stdout.write(ANSI.cursorToColumn(metrics.cursorVisualCol + 1));
|
|
265
|
+
// Track where cursor ends up (row within frame, 0-indexed from top)
|
|
266
|
+
// Cursor is at: autocomplete lines + top border (row 0) + 1 + cursorVisualRow
|
|
267
|
+
lastCursorRowInFrame = autocompleteLineCount + 1 + metrics.cursorVisualRow;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Reset frame position tracking (call when starting new input session)
|
|
271
|
+
*/
|
|
272
|
+
function resetFramePosition() {
|
|
273
|
+
lastFrameTotalLines = 0;
|
|
274
|
+
lastCursorRowInFrame = 0;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Clear the input frame completely (erase all lines)
|
|
278
|
+
* This ensures the frame doesn't appear in scrollback history
|
|
279
|
+
* Optionally echoes the submitted input text
|
|
280
|
+
*/
|
|
281
|
+
function clearInputFrame(input, theme) {
|
|
282
|
+
// Move to top of frame using tracked cursor position
|
|
283
|
+
if (lastCursorRowInFrame > 0) {
|
|
284
|
+
process.stdout.write('\r');
|
|
285
|
+
process.stdout.write(ANSI.cursorUp(lastCursorRowInFrame));
|
|
286
|
+
}
|
|
287
|
+
// Clear all lines of the frame + extra padding we added
|
|
288
|
+
const totalLinesToClear = lastFrameTotalLines + 5; // frame + padding
|
|
289
|
+
for (let i = 0; i < totalLinesToClear; i++) {
|
|
290
|
+
process.stdout.write(ANSI.clearLine);
|
|
291
|
+
if (i < totalLinesToClear - 1) {
|
|
292
|
+
process.stdout.write('\n');
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// Move back to top
|
|
296
|
+
process.stdout.write(ANSI.cursorUp(totalLinesToClear - 1));
|
|
297
|
+
process.stdout.write('\r');
|
|
298
|
+
// Reset frame position tracking
|
|
299
|
+
lastFrameTotalLines = 0;
|
|
300
|
+
lastCursorRowInFrame = 0;
|
|
301
|
+
// Echo just the user's input for history
|
|
302
|
+
if (input.trim()) {
|
|
303
|
+
process.stdout.write(theme.colors.info('> ') + input + '\n');
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Prompt for input with persistent status line below
|
|
308
|
+
*/
|
|
309
|
+
export function rawQuestion(options) {
|
|
310
|
+
return new Promise((resolve) => {
|
|
311
|
+
let input = '';
|
|
312
|
+
let cursorPos = 0;
|
|
313
|
+
let historyIndex = -1; // -1 means not browsing history
|
|
314
|
+
let drawTimeout = null;
|
|
315
|
+
// Reset frame position for new input session
|
|
316
|
+
resetFramePosition();
|
|
317
|
+
// Debounced redraw to prevent flickering during paste
|
|
318
|
+
const scheduleRedraw = () => {
|
|
319
|
+
if (drawTimeout) {
|
|
320
|
+
clearTimeout(drawTimeout);
|
|
321
|
+
}
|
|
322
|
+
drawTimeout = setTimeout(() => {
|
|
323
|
+
drawInputFrame(input, cursorPos, options);
|
|
324
|
+
drawTimeout = null;
|
|
325
|
+
}, 16); // ~60fps max
|
|
326
|
+
};
|
|
327
|
+
// Initial draw
|
|
328
|
+
drawInputFrame(input, cursorPos, options);
|
|
329
|
+
// Enable raw mode - use try-catch to prevent crashes if stdin is in unexpected state
|
|
330
|
+
if (process.stdin.isTTY) {
|
|
331
|
+
try {
|
|
332
|
+
process.stdin.setRawMode(true);
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
// Ignore errors if stdin is already closed or in unexpected state
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
process.stdin.resume();
|
|
339
|
+
// Helper to update autocomplete suggestions after input changes
|
|
340
|
+
const updateAutocomplete = async () => {
|
|
341
|
+
await slashCommandAutocomplete.update(input);
|
|
342
|
+
};
|
|
343
|
+
const handleData = (data) => {
|
|
344
|
+
const str = data.toString();
|
|
345
|
+
// Handle special keys
|
|
346
|
+
if (str === '\r' || str === '\n') {
|
|
347
|
+
// Enter - if autocomplete is visible with selection, accept it; otherwise submit
|
|
348
|
+
if (slashCommandAutocomplete.isVisible()) {
|
|
349
|
+
const newInput = slashCommandAutocomplete.accept();
|
|
350
|
+
if (newInput !== null) {
|
|
351
|
+
input = newInput + ' '; // Add space after command for arguments
|
|
352
|
+
cursorPos = input.length;
|
|
353
|
+
updateAutocomplete();
|
|
354
|
+
drawInputFrame(input, cursorPos, options);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
// Hide autocomplete before submitting
|
|
359
|
+
slashCommandAutocomplete.hide();
|
|
360
|
+
try {
|
|
361
|
+
process.stdin.removeListener('data', handleData);
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
// Ignore errors during listener removal
|
|
365
|
+
}
|
|
366
|
+
if (process.stdin.isTTY) {
|
|
367
|
+
try {
|
|
368
|
+
process.stdin.setRawMode(false);
|
|
369
|
+
}
|
|
370
|
+
catch {
|
|
371
|
+
// Ignore errors if stdin is already closed or in unexpected state
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
// Cancel any pending debounced redraw and do a final synchronous draw
|
|
375
|
+
// to ensure frame metrics are accurate before clearing
|
|
376
|
+
if (drawTimeout) {
|
|
377
|
+
clearTimeout(drawTimeout);
|
|
378
|
+
drawTimeout = null;
|
|
379
|
+
}
|
|
380
|
+
// Final draw to update lastCursorRowInFrame with current input state
|
|
381
|
+
drawInputFrame(input, cursorPos, options);
|
|
382
|
+
clearInputFrame(input, options.theme);
|
|
383
|
+
if (input.trim()) {
|
|
384
|
+
// Add to persistent history, avoiding duplicates of the last entry
|
|
385
|
+
if (inputHistory.length === 0 || inputHistory[inputHistory.length - 1] !== input) {
|
|
386
|
+
inputHistory.push(input);
|
|
387
|
+
// Trim history if it exceeds max size
|
|
388
|
+
if (inputHistory.length > MAX_HISTORY_SIZE) {
|
|
389
|
+
inputHistory.shift();
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
resolve(input);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (str === '\x03') {
|
|
397
|
+
// Ctrl+C - clean exit via signal handler
|
|
398
|
+
if (process.stdin.isTTY) {
|
|
399
|
+
try {
|
|
400
|
+
process.stdin.setRawMode(false);
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
// Ignore errors if stdin is already closed or in unexpected state
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
process.kill(process.pid, 'SIGINT');
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
if (str === '\x1b') {
|
|
410
|
+
// Escape - hide autocomplete if visible, otherwise call onEscape
|
|
411
|
+
if (slashCommandAutocomplete.isVisible()) {
|
|
412
|
+
slashCommandAutocomplete.hide();
|
|
413
|
+
drawInputFrame(input, cursorPos, options);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
if (options.onEscape) {
|
|
417
|
+
options.onEscape();
|
|
418
|
+
}
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
if (str === '\x09') {
|
|
422
|
+
// Tab - accept autocomplete if visible, otherwise toggle thinking
|
|
423
|
+
if (slashCommandAutocomplete.isVisible()) {
|
|
424
|
+
const newInput = slashCommandAutocomplete.accept();
|
|
425
|
+
if (newInput !== null) {
|
|
426
|
+
input = newInput + ' '; // Add space after command for arguments
|
|
427
|
+
cursorPos = input.length;
|
|
428
|
+
updateAutocomplete();
|
|
429
|
+
drawInputFrame(input, cursorPos, options);
|
|
430
|
+
}
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
if (options.onToggleThinking) {
|
|
434
|
+
options.onToggleThinking();
|
|
435
|
+
drawInputFrame(input, cursorPos, options);
|
|
436
|
+
}
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
if (str === '\x1b[Z') {
|
|
440
|
+
// Shift+Tab - toggle auto-approve
|
|
441
|
+
if (options.onToggleAutoApprove) {
|
|
442
|
+
options.onToggleAutoApprove();
|
|
443
|
+
drawInputFrame(input, cursorPos, options);
|
|
444
|
+
}
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
// Backspace or Ctrl+H
|
|
448
|
+
if (str === '\x7f' || str === '\b' || str === '\x08') {
|
|
449
|
+
if (cursorPos > 0) {
|
|
450
|
+
input = input.slice(0, cursorPos - 1) + input.slice(cursorPos);
|
|
451
|
+
cursorPos--;
|
|
452
|
+
historyIndex = -1; // Reset history browsing when input is modified
|
|
453
|
+
updateAutocomplete(); // Update autocomplete after deletion
|
|
454
|
+
scheduleRedraw();
|
|
455
|
+
}
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
// Left arrow or Ctrl+B (emacs style)
|
|
459
|
+
if (str === '\x1b[D' || str === '\x02') {
|
|
460
|
+
if (cursorPos > 0) {
|
|
461
|
+
cursorPos--;
|
|
462
|
+
drawInputFrame(input, cursorPos, options);
|
|
463
|
+
}
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
// Right arrow or Ctrl+F (emacs style)
|
|
467
|
+
if (str === '\x1b[C' || str === '\x06') {
|
|
468
|
+
if (cursorPos < input.length) {
|
|
469
|
+
cursorPos++;
|
|
470
|
+
drawInputFrame(input, cursorPos, options);
|
|
471
|
+
}
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
// Home key - go to start of line
|
|
475
|
+
if (str === '\x1b[H' || str === '\x1b[1~' || str === '\x1bOH') {
|
|
476
|
+
cursorPos = 0;
|
|
477
|
+
drawInputFrame(input, cursorPos, options);
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
// End key - go to end of line
|
|
481
|
+
if (str === '\x1b[F' || str === '\x1b[4~' || str === '\x1bOF') {
|
|
482
|
+
cursorPos = input.length;
|
|
483
|
+
drawInputFrame(input, cursorPos, options);
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
// Ctrl+D - delete character forward (like Delete key)
|
|
487
|
+
if (str === '\x04') {
|
|
488
|
+
if (cursorPos < input.length) {
|
|
489
|
+
input = input.slice(0, cursorPos) + input.slice(cursorPos + 1);
|
|
490
|
+
historyIndex = -1; // Reset history browsing
|
|
491
|
+
drawInputFrame(input, cursorPos, options);
|
|
492
|
+
}
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
// Option+Left or Ctrl+Left - jump to previous word
|
|
496
|
+
// Option: \x1bb (ESC b) or \x1b[1;3D
|
|
497
|
+
// Ctrl: \x1b[1;5D
|
|
498
|
+
if (str === '\x1bb' || str === '\x1b[1;3D' || str === '\x1b[1;5D') {
|
|
499
|
+
cursorPos = findPrevWordStart(input, cursorPos);
|
|
500
|
+
drawInputFrame(input, cursorPos, options);
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
// Option+Right or Ctrl+Right - jump to next word
|
|
504
|
+
// Option: \x1bf (ESC f) or \x1b[1;3C
|
|
505
|
+
// Ctrl: \x1b[1;5C
|
|
506
|
+
if (str === '\x1bf' || str === '\x1b[1;3C' || str === '\x1b[1;5C') {
|
|
507
|
+
cursorPos = findNextWordEnd(input, cursorPos);
|
|
508
|
+
drawInputFrame(input, cursorPos, options);
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
// Option+Up or Ctrl+Up - jump 5 lines up
|
|
512
|
+
// Option: \x1b[1;3A, Ctrl: \x1b[1;5A
|
|
513
|
+
if (str === '\x1b[1;3A' || str === '\x1b[1;5A') {
|
|
514
|
+
const termWidth = process.stdout.columns || 80;
|
|
515
|
+
const prefixWidth = 3;
|
|
516
|
+
const metrics = getMultilineMetrics(input, cursorPos, termWidth, prefixWidth);
|
|
517
|
+
const targetRow = Math.max(0, metrics.cursorVisualRow - 5);
|
|
518
|
+
if (targetRow !== metrics.cursorVisualRow) {
|
|
519
|
+
cursorPos = findCharPosForVisualPosition(input, targetRow, metrics.cursorVisualCol, termWidth, prefixWidth);
|
|
520
|
+
drawInputFrame(input, cursorPos, options);
|
|
521
|
+
}
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
// Option+Down or Ctrl+Down - jump 5 lines down
|
|
525
|
+
// Option: \x1b[1;3B, Ctrl: \x1b[1;5B
|
|
526
|
+
if (str === '\x1b[1;3B' || str === '\x1b[1;5B') {
|
|
527
|
+
const termWidth = process.stdout.columns || 80;
|
|
528
|
+
const prefixWidth = 3;
|
|
529
|
+
const metrics = getMultilineMetrics(input, cursorPos, termWidth, prefixWidth);
|
|
530
|
+
const targetRow = Math.min(metrics.totalVisualLines - 1, metrics.cursorVisualRow + 5);
|
|
531
|
+
if (targetRow !== metrics.cursorVisualRow) {
|
|
532
|
+
cursorPos = findCharPosForVisualPosition(input, targetRow, metrics.cursorVisualCol, termWidth, prefixWidth);
|
|
533
|
+
drawInputFrame(input, cursorPos, options);
|
|
534
|
+
}
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
// Option+Backspace - delete previous word
|
|
538
|
+
// macOS sends \x1b\x7f (ESC DEL)
|
|
539
|
+
if (str === '\x1b\x7f') {
|
|
540
|
+
const newPos = findPrevWordStart(input, cursorPos);
|
|
541
|
+
input = input.slice(0, newPos) + input.slice(cursorPos);
|
|
542
|
+
cursorPos = newPos;
|
|
543
|
+
historyIndex = -1; // Reset history browsing
|
|
544
|
+
drawInputFrame(input, cursorPos, options);
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
// Ctrl+W - delete previous word (bash-style)
|
|
548
|
+
if (str === '\x17') {
|
|
549
|
+
const newPos = findPrevWordStart(input, cursorPos);
|
|
550
|
+
input = input.slice(0, newPos) + input.slice(cursorPos);
|
|
551
|
+
cursorPos = newPos;
|
|
552
|
+
historyIndex = -1; // Reset history browsing
|
|
553
|
+
drawInputFrame(input, cursorPos, options);
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
// Option+Delete or Ctrl+Delete - delete next word
|
|
557
|
+
// Option: \x1bd (ESC d) or \x1b[3;3~
|
|
558
|
+
// Ctrl: \x1b[3;5~
|
|
559
|
+
if (str === '\x1bd' || str === '\x1b[3;3~' || str === '\x1b[3;5~') {
|
|
560
|
+
const endPos = findNextWordEnd(input, cursorPos);
|
|
561
|
+
input = input.slice(0, cursorPos) + input.slice(endPos);
|
|
562
|
+
historyIndex = -1; // Reset history browsing
|
|
563
|
+
drawInputFrame(input, cursorPos, options);
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
// Forward delete (Fn+Backspace on Mac, Delete key)
|
|
567
|
+
// Sends \x1b[3~
|
|
568
|
+
if (str === '\x1b[3~') {
|
|
569
|
+
if (cursorPos < input.length) {
|
|
570
|
+
input = input.slice(0, cursorPos) + input.slice(cursorPos + 1);
|
|
571
|
+
historyIndex = -1; // Reset history browsing
|
|
572
|
+
drawInputFrame(input, cursorPos, options);
|
|
573
|
+
}
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
if (str === '\x1b[A') {
|
|
577
|
+
// Up arrow - navigate autocomplete when visible, otherwise normal behavior
|
|
578
|
+
if (slashCommandAutocomplete.isVisible()) {
|
|
579
|
+
slashCommandAutocomplete.moveUp();
|
|
580
|
+
drawInputFrame(input, cursorPos, options);
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
// Navigate visual lines (including newlines), then jump to beginning, then history
|
|
584
|
+
const termWidth = process.stdout.columns || 80;
|
|
585
|
+
const prefixWidth = 3;
|
|
586
|
+
const metrics = getMultilineMetrics(input, cursorPos, termWidth, prefixWidth);
|
|
587
|
+
if (metrics.cursorVisualRow > 0) {
|
|
588
|
+
// Move cursor up one visual row - find char position for target row
|
|
589
|
+
const targetRow = metrics.cursorVisualRow - 1;
|
|
590
|
+
const targetCol = metrics.cursorVisualCol;
|
|
591
|
+
cursorPos = findCharPosForVisualPosition(input, targetRow, targetCol, termWidth, prefixWidth);
|
|
592
|
+
drawInputFrame(input, cursorPos, options);
|
|
593
|
+
}
|
|
594
|
+
else if (cursorPos > 0) {
|
|
595
|
+
// At first visual row but not at beginning - jump to beginning
|
|
596
|
+
cursorPos = 0;
|
|
597
|
+
drawInputFrame(input, cursorPos, options);
|
|
598
|
+
}
|
|
599
|
+
else {
|
|
600
|
+
// At first visual row AND at beginning - access history
|
|
601
|
+
if (inputHistory.length > 0 && historyIndex < inputHistory.length - 1) {
|
|
602
|
+
historyIndex++;
|
|
603
|
+
input = inputHistory[inputHistory.length - 1 - historyIndex] || '';
|
|
604
|
+
cursorPos = input.length;
|
|
605
|
+
drawInputFrame(input, cursorPos, options);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
if (str === '\x1b[B') {
|
|
611
|
+
// Down arrow - navigate autocomplete when visible, otherwise normal behavior
|
|
612
|
+
if (slashCommandAutocomplete.isVisible()) {
|
|
613
|
+
slashCommandAutocomplete.moveDown();
|
|
614
|
+
drawInputFrame(input, cursorPos, options);
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
// Navigate visual lines (including newlines), then jump to end of text
|
|
618
|
+
const termWidth = process.stdout.columns || 80;
|
|
619
|
+
const prefixWidth = 3;
|
|
620
|
+
const metrics = getMultilineMetrics(input, cursorPos, termWidth, prefixWidth);
|
|
621
|
+
if (metrics.cursorVisualRow < metrics.totalVisualLines - 1) {
|
|
622
|
+
// Move cursor down one visual row - find char position for target row
|
|
623
|
+
const targetRow = metrics.cursorVisualRow + 1;
|
|
624
|
+
const targetCol = metrics.cursorVisualCol;
|
|
625
|
+
cursorPos = findCharPosForVisualPosition(input, targetRow, targetCol, termWidth, prefixWidth);
|
|
626
|
+
drawInputFrame(input, cursorPos, options);
|
|
627
|
+
}
|
|
628
|
+
else if (cursorPos < input.length) {
|
|
629
|
+
// At last visual row but not at end - jump to end of text
|
|
630
|
+
cursorPos = input.length;
|
|
631
|
+
drawInputFrame(input, cursorPos, options);
|
|
632
|
+
}
|
|
633
|
+
// If already at end of last row, do nothing
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
if (str === '\x01') {
|
|
637
|
+
// Ctrl+A - start of line
|
|
638
|
+
cursorPos = 0;
|
|
639
|
+
drawInputFrame(input, cursorPos, options);
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
if (str === '\x05') {
|
|
643
|
+
// Ctrl+E - toggle document expand/collapse
|
|
644
|
+
if (options.onToggleDocuments) {
|
|
645
|
+
options.onToggleDocuments();
|
|
646
|
+
drawInputFrame(input, cursorPos, options);
|
|
647
|
+
}
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
if (str === '\x0b') {
|
|
651
|
+
// Ctrl+K - kill to end of line
|
|
652
|
+
input = input.slice(0, cursorPos);
|
|
653
|
+
historyIndex = -1; // Reset history browsing
|
|
654
|
+
drawInputFrame(input, cursorPos, options);
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
if (str === '\x15') {
|
|
658
|
+
// Ctrl+U - kill whole line
|
|
659
|
+
input = '';
|
|
660
|
+
cursorPos = 0;
|
|
661
|
+
historyIndex = -1; // Reset history browsing
|
|
662
|
+
drawInputFrame(input, cursorPos, options);
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
// Regular character input (handles both single chars and paste)
|
|
666
|
+
// Strip bracketed paste mode markers if present
|
|
667
|
+
let cleanStr = str;
|
|
668
|
+
if (cleanStr.includes(PASTE_START)) {
|
|
669
|
+
cleanStr = cleanStr.replace(PASTE_START, '');
|
|
670
|
+
}
|
|
671
|
+
if (cleanStr.includes(PASTE_END)) {
|
|
672
|
+
cleanStr = cleanStr.replace(PASTE_END, '');
|
|
673
|
+
}
|
|
674
|
+
// Normalize line endings: \r\n -> \n, \r -> \n
|
|
675
|
+
cleanStr = cleanStr.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
676
|
+
// Filter to printable characters and newlines (including Unicode)
|
|
677
|
+
let printable = '';
|
|
678
|
+
for (const char of cleanStr) {
|
|
679
|
+
const code = char.codePointAt(0) || 0;
|
|
680
|
+
// Accept printable ASCII, newlines, and all Unicode above ASCII
|
|
681
|
+
// Reject control characters (0x00-0x1F except newline 0x0A, and 0x7F)
|
|
682
|
+
if ((code >= 0x20 && code !== 0x7F) || code === 0x0A) {
|
|
683
|
+
printable += char;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
if (printable.length > 0) {
|
|
687
|
+
// Insert all printable characters at cursor position
|
|
688
|
+
input = input.slice(0, cursorPos) + printable + input.slice(cursorPos);
|
|
689
|
+
cursorPos += printable.length;
|
|
690
|
+
historyIndex = -1; // Reset history browsing when input is modified
|
|
691
|
+
// Update autocomplete suggestions
|
|
692
|
+
updateAutocomplete();
|
|
693
|
+
// For paste (multiple characters), do immediate redraw to keep cursor in sync
|
|
694
|
+
// For single char, use debounced redraw
|
|
695
|
+
if (printable.length > 1) {
|
|
696
|
+
if (drawTimeout) {
|
|
697
|
+
clearTimeout(drawTimeout);
|
|
698
|
+
drawTimeout = null;
|
|
699
|
+
}
|
|
700
|
+
drawInputFrame(input, cursorPos, options);
|
|
701
|
+
}
|
|
702
|
+
else {
|
|
703
|
+
scheduleRedraw();
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
};
|
|
707
|
+
process.stdin.on('data', handleData);
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Simple wrapper that mimics readline.question interface
|
|
712
|
+
*/
|
|
713
|
+
export function createRawReadline(options) {
|
|
714
|
+
return {
|
|
715
|
+
question: async (_prompt, callback) => {
|
|
716
|
+
const answer = await rawQuestion(options);
|
|
717
|
+
callback(answer);
|
|
718
|
+
},
|
|
719
|
+
close: () => {
|
|
720
|
+
if (process.stdin.isTTY) {
|
|
721
|
+
try {
|
|
722
|
+
process.stdin.setRawMode(false);
|
|
723
|
+
}
|
|
724
|
+
catch {
|
|
725
|
+
// Ignore errors if stdin is already closed or in unexpected state
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
//# sourceMappingURL=RawInput.js.map
|