@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,909 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Interactive Agent Menu
|
|
4
|
+
*
|
|
5
|
+
* Ink-based terminal UI for managing Task Agent profiles.
|
|
6
|
+
* Provides list view, navigation, CRUD operations, and AI-powered agent creation.
|
|
7
|
+
*/
|
|
8
|
+
import { useState, useEffect, useMemo } from 'react';
|
|
9
|
+
import { Box, Text, useInput, useApp } from 'ink';
|
|
10
|
+
import TextInput from 'ink-text-input';
|
|
11
|
+
import Spinner from 'ink-spinner';
|
|
12
|
+
import { InlineEditor } from '../system-message/InlineEditor.js';
|
|
13
|
+
/**
|
|
14
|
+
* Interactive Agent Menu Component
|
|
15
|
+
*/
|
|
16
|
+
export const InteractiveAgentMenu = ({ store, initialAgentName, currentModel = 'sonnet', generateAgentProfile, conversationalCreator, listModels, editAssistant, onExit, }) => {
|
|
17
|
+
const { exit: inkExit } = useApp();
|
|
18
|
+
// Use onExit callback if provided (for graceful return to CLI), otherwise fall back to Ink's exit
|
|
19
|
+
const handleExit = () => {
|
|
20
|
+
if (onExit) {
|
|
21
|
+
onExit();
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
inkExit();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const [agents, setAgents] = useState([]);
|
|
28
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
29
|
+
const [menuState, setMenuState] = useState('list');
|
|
30
|
+
const [confirmAction, setConfirmAction] = useState(null);
|
|
31
|
+
const [statusMessage, setStatusMessage] = useState('');
|
|
32
|
+
const [errorMessage, setErrorMessage] = useState('');
|
|
33
|
+
// Editing state
|
|
34
|
+
const [editingAgent, setEditingAgent] = useState(null);
|
|
35
|
+
const [editingContent, setEditingContent] = useState('');
|
|
36
|
+
const [editingFilePath, setEditingFilePath] = useState('');
|
|
37
|
+
// Edit choice state (direct vs AI-assisted)
|
|
38
|
+
const [editChoiceIndex, setEditChoiceIndex] = useState(0);
|
|
39
|
+
const [selectedAgentForEdit, setSelectedAgentForEdit] = useState(null);
|
|
40
|
+
// AI edit state
|
|
41
|
+
const [aiEditRequest, setAiEditRequest] = useState('');
|
|
42
|
+
const [aiEditResult, setAiEditResult] = useState(null);
|
|
43
|
+
const [aiEditOriginalContent, setAiEditOriginalContent] = useState('');
|
|
44
|
+
// Viewing state
|
|
45
|
+
const [viewingAgent, setViewingAgent] = useState(null);
|
|
46
|
+
// Model registry state
|
|
47
|
+
const [availableModels, setAvailableModels] = useState([]);
|
|
48
|
+
const [modelsLoading, setModelsLoading] = useState(false);
|
|
49
|
+
const [modelFilter, setModelFilter] = useState('');
|
|
50
|
+
const [modelSelectIndex, setModelSelectIndex] = useState(0);
|
|
51
|
+
// Creation wizard state
|
|
52
|
+
const [createSelectedModel, setCreateSelectedModel] = useState('');
|
|
53
|
+
const [createDescription, setCreateDescription] = useState('');
|
|
54
|
+
const [generatingMessage, setGeneratingMessage] = useState('');
|
|
55
|
+
// Conversation state for multi-turn agent creation
|
|
56
|
+
const [conversationMessages, setConversationMessages] = useState([]);
|
|
57
|
+
const [conversationInput, setConversationInput] = useState('');
|
|
58
|
+
const [conversationThinking, setConversationThinking] = useState(false);
|
|
59
|
+
// For editing agent model
|
|
60
|
+
const [editingAgentForModel, setEditingAgentForModel] = useState(null);
|
|
61
|
+
// Load agents on mount
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
loadAgents();
|
|
64
|
+
// Subscribe to store changes for hot-reload
|
|
65
|
+
const listener = () => {
|
|
66
|
+
loadAgents();
|
|
67
|
+
};
|
|
68
|
+
store.onChange(listener);
|
|
69
|
+
return () => {
|
|
70
|
+
store.removeChangeListener(listener);
|
|
71
|
+
};
|
|
72
|
+
}, []);
|
|
73
|
+
// Set initial selection
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (initialAgentName && agents.length > 0) {
|
|
76
|
+
const index = agents.findIndex((a) => a.name === initialAgentName);
|
|
77
|
+
if (index !== -1) {
|
|
78
|
+
setSelectedIndex(index);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}, [agents, initialAgentName]);
|
|
82
|
+
// Load models when entering model selection mode
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if ((menuState === 'create-model' || menuState === 'edit-model') && listModels && availableModels.length === 0) {
|
|
85
|
+
setModelsLoading(true);
|
|
86
|
+
listModels()
|
|
87
|
+
.then((models) => {
|
|
88
|
+
setAvailableModels(models);
|
|
89
|
+
setModelsLoading(false);
|
|
90
|
+
})
|
|
91
|
+
.catch((err) => {
|
|
92
|
+
setErrorMessage(`Failed to load models: ${err.message}`);
|
|
93
|
+
setModelsLoading(false);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}, [menuState, listModels]);
|
|
97
|
+
// Reset model selection index when filter changes
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
setModelSelectIndex(0);
|
|
100
|
+
}, [modelFilter]);
|
|
101
|
+
// Compute filtered models based on filter text
|
|
102
|
+
const filteredModels = useMemo(() => {
|
|
103
|
+
// Add "inherit" option at the top
|
|
104
|
+
const inheritOption = {
|
|
105
|
+
id: 'inherit',
|
|
106
|
+
displayName: `Inherit (${currentModel})`,
|
|
107
|
+
owned_by: 'session',
|
|
108
|
+
};
|
|
109
|
+
const allModels = [inheritOption, ...availableModels];
|
|
110
|
+
if (!modelFilter.trim()) {
|
|
111
|
+
return allModels;
|
|
112
|
+
}
|
|
113
|
+
const lowerFilter = modelFilter.toLowerCase();
|
|
114
|
+
return allModels.filter((m) => {
|
|
115
|
+
const idMatch = m.id.toLowerCase().includes(lowerFilter);
|
|
116
|
+
const nameMatch = m.displayName?.toLowerCase().includes(lowerFilter);
|
|
117
|
+
const providerMatch = m.owned_by?.toLowerCase().includes(lowerFilter);
|
|
118
|
+
return idMatch || nameMatch || providerMatch;
|
|
119
|
+
});
|
|
120
|
+
}, [availableModels, modelFilter, currentModel]);
|
|
121
|
+
// Max visible models in the list (for scrolling)
|
|
122
|
+
const MAX_VISIBLE_MODELS = 15;
|
|
123
|
+
/**
|
|
124
|
+
* Load agents from store
|
|
125
|
+
*/
|
|
126
|
+
const loadAgents = () => {
|
|
127
|
+
const allAgents = store.getAll();
|
|
128
|
+
// Sort by location (project first), then by name
|
|
129
|
+
allAgents.sort((a, b) => {
|
|
130
|
+
if (a.location !== b.location) {
|
|
131
|
+
return a.location === 'project' ? -1 : 1;
|
|
132
|
+
}
|
|
133
|
+
return a.name.localeCompare(b.name);
|
|
134
|
+
});
|
|
135
|
+
setAgents(allAgents);
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Get currently selected agent
|
|
139
|
+
*/
|
|
140
|
+
const selectedAgent = agents[selectedIndex];
|
|
141
|
+
/**
|
|
142
|
+
* Handle keyboard input
|
|
143
|
+
*/
|
|
144
|
+
useInput((input, key) => {
|
|
145
|
+
// Loading/generating state - block all input
|
|
146
|
+
if (menuState === 'loading' || menuState === 'create-generating') {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// Viewing mode - any key returns to list
|
|
150
|
+
if (menuState === 'viewing') {
|
|
151
|
+
setMenuState('list');
|
|
152
|
+
setViewingAgent(null);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
// Model selection step (for creation or editing)
|
|
156
|
+
if (menuState === 'create-model' || menuState === 'edit-model') {
|
|
157
|
+
// Model selection uses TextInput for filtering, so only handle navigation keys here
|
|
158
|
+
// TextInput handles text entry
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// Confirmation prompt state
|
|
162
|
+
if (menuState === 'confirm' && confirmAction) {
|
|
163
|
+
if (input.toLowerCase() === 'y') {
|
|
164
|
+
executeConfirmedAction(confirmAction);
|
|
165
|
+
setMenuState('list');
|
|
166
|
+
setConfirmAction(null);
|
|
167
|
+
}
|
|
168
|
+
else if (input.toLowerCase() === 'n' || key.escape) {
|
|
169
|
+
setMenuState('list');
|
|
170
|
+
setConfirmAction(null);
|
|
171
|
+
setStatusMessage('Action cancelled');
|
|
172
|
+
}
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
// List navigation state
|
|
176
|
+
if (menuState === 'list') {
|
|
177
|
+
// Navigation
|
|
178
|
+
if (key.upArrow) {
|
|
179
|
+
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
180
|
+
setStatusMessage('');
|
|
181
|
+
setErrorMessage('');
|
|
182
|
+
}
|
|
183
|
+
else if (key.downArrow) {
|
|
184
|
+
setSelectedIndex((prev) => Math.min(agents.length - 1, prev + 1));
|
|
185
|
+
setStatusMessage('');
|
|
186
|
+
setErrorMessage('');
|
|
187
|
+
}
|
|
188
|
+
// Actions
|
|
189
|
+
else if (key.return && selectedAgent) {
|
|
190
|
+
// Start edit flow - first confirm/change model
|
|
191
|
+
setEditingAgentForModel(selectedAgent);
|
|
192
|
+
setSelectedAgentForEdit(selectedAgent);
|
|
193
|
+
setModelFilter('');
|
|
194
|
+
setModelSelectIndex(0);
|
|
195
|
+
setMenuState('edit-model');
|
|
196
|
+
}
|
|
197
|
+
else if (input === ' ' && selectedAgent) {
|
|
198
|
+
// View details
|
|
199
|
+
handleView(selectedAgent.name);
|
|
200
|
+
}
|
|
201
|
+
else if (input === '+' || input.toLowerCase() === 'n') {
|
|
202
|
+
// Start creation wizard
|
|
203
|
+
setModelFilter('');
|
|
204
|
+
setModelSelectIndex(0);
|
|
205
|
+
setCreateSelectedModel('');
|
|
206
|
+
setCreateDescription('');
|
|
207
|
+
setMenuState('create-model');
|
|
208
|
+
}
|
|
209
|
+
else if (input.toLowerCase() === 'm' && selectedAgent) {
|
|
210
|
+
// Edit agent's model
|
|
211
|
+
setEditingAgentForModel(selectedAgent);
|
|
212
|
+
setModelFilter('');
|
|
213
|
+
setModelSelectIndex(0);
|
|
214
|
+
setMenuState('edit-model');
|
|
215
|
+
}
|
|
216
|
+
else if (input.toLowerCase() === 'd' && selectedAgent) {
|
|
217
|
+
// Delete agent
|
|
218
|
+
setConfirmAction({ type: 'delete', agentName: selectedAgent.name });
|
|
219
|
+
setMenuState('confirm');
|
|
220
|
+
}
|
|
221
|
+
else if (input.toLowerCase() === 'q' || key.escape) {
|
|
222
|
+
// Quit - use handleExit for graceful return to CLI
|
|
223
|
+
handleExit();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}, { isActive: menuState !== 'editing' && menuState !== 'create-description' && menuState !== 'create-model' && menuState !== 'edit-model' && menuState !== 'create-conversation' && menuState !== 'edit-choice' && menuState !== 'ai-edit-request' && menuState !== 'ai-edit-processing' && menuState !== 'ai-edit-confirm' });
|
|
227
|
+
/**
|
|
228
|
+
* Handle keyboard input for model selection (arrow keys and escape)
|
|
229
|
+
*/
|
|
230
|
+
useInput((_input, key) => {
|
|
231
|
+
if (key.upArrow) {
|
|
232
|
+
setModelSelectIndex((prev) => Math.max(0, prev - 1));
|
|
233
|
+
}
|
|
234
|
+
else if (key.downArrow) {
|
|
235
|
+
setModelSelectIndex((prev) => Math.min(filteredModels.length - 1, prev + 1));
|
|
236
|
+
}
|
|
237
|
+
else if (key.escape) {
|
|
238
|
+
handleModelSelectionCancel();
|
|
239
|
+
}
|
|
240
|
+
}, { isActive: menuState === 'create-model' || menuState === 'edit-model' });
|
|
241
|
+
/**
|
|
242
|
+
* Handle keyboard input for conversation mode (escape to cancel)
|
|
243
|
+
*/
|
|
244
|
+
useInput((_input, key) => {
|
|
245
|
+
if (key.escape && !conversationThinking) {
|
|
246
|
+
handleConversationCancel();
|
|
247
|
+
}
|
|
248
|
+
}, { isActive: menuState === 'create-conversation' });
|
|
249
|
+
/**
|
|
250
|
+
* Handle keyboard input for edit choice state
|
|
251
|
+
*/
|
|
252
|
+
useInput((_input, key) => {
|
|
253
|
+
if (key.upArrow || key.downArrow) {
|
|
254
|
+
setEditChoiceIndex((prev) => (prev === 0 ? 1 : 0));
|
|
255
|
+
}
|
|
256
|
+
else if (key.return) {
|
|
257
|
+
if (editChoiceIndex === 0 && selectedAgentForEdit) {
|
|
258
|
+
// Direct edit
|
|
259
|
+
handleDirectEdit(selectedAgentForEdit.name);
|
|
260
|
+
}
|
|
261
|
+
else if (editChoiceIndex === 1 && selectedAgentForEdit) {
|
|
262
|
+
// AI-assisted edit
|
|
263
|
+
handleAiEditStart(selectedAgentForEdit.name);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
else if (key.escape) {
|
|
267
|
+
setSelectedAgentForEdit(null);
|
|
268
|
+
setMenuState('list');
|
|
269
|
+
}
|
|
270
|
+
}, { isActive: menuState === 'edit-choice' });
|
|
271
|
+
/**
|
|
272
|
+
* Handle keyboard input for AI edit request state (escape to cancel)
|
|
273
|
+
*/
|
|
274
|
+
useInput((_input, key) => {
|
|
275
|
+
if (key.escape) {
|
|
276
|
+
handleAiEditCancel();
|
|
277
|
+
}
|
|
278
|
+
}, { isActive: menuState === 'ai-edit-request' });
|
|
279
|
+
/**
|
|
280
|
+
* Handle keyboard input for AI edit confirm state
|
|
281
|
+
*/
|
|
282
|
+
useInput((input, key) => {
|
|
283
|
+
if (input.toLowerCase() === 'y' || key.return) {
|
|
284
|
+
handleAiEditConfirm();
|
|
285
|
+
}
|
|
286
|
+
else if (input.toLowerCase() === 'n' || key.escape) {
|
|
287
|
+
handleAiEditReject();
|
|
288
|
+
}
|
|
289
|
+
}, { isActive: menuState === 'ai-edit-confirm' });
|
|
290
|
+
/**
|
|
291
|
+
* Handle description submission - starts conversation or generates directly
|
|
292
|
+
*/
|
|
293
|
+
const handleDescriptionSubmit = async () => {
|
|
294
|
+
if (!createDescription.trim()) {
|
|
295
|
+
setErrorMessage('Please enter a description for your agent');
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
setErrorMessage('');
|
|
299
|
+
// If conversational creator is available, start the conversation flow
|
|
300
|
+
if (conversationalCreator) {
|
|
301
|
+
const initialMessage = {
|
|
302
|
+
role: 'user',
|
|
303
|
+
content: createDescription,
|
|
304
|
+
};
|
|
305
|
+
setConversationMessages([initialMessage]);
|
|
306
|
+
setConversationThinking(true);
|
|
307
|
+
setMenuState('create-conversation');
|
|
308
|
+
// Get first AI response (likely a clarifying question)
|
|
309
|
+
try {
|
|
310
|
+
const response = await conversationalCreator([initialMessage], createSelectedModel);
|
|
311
|
+
setConversationThinking(false);
|
|
312
|
+
if (response.type === 'profile' && response.profile) {
|
|
313
|
+
// AI generated profile directly without questions
|
|
314
|
+
await createAgentFromProfile(response.profile);
|
|
315
|
+
}
|
|
316
|
+
else if (response.type === 'question' && response.question) {
|
|
317
|
+
// AI is asking a clarifying question
|
|
318
|
+
const questionText = response.question; // Capture as string
|
|
319
|
+
setConversationMessages((prev) => [
|
|
320
|
+
...prev,
|
|
321
|
+
{ role: 'assistant', content: questionText },
|
|
322
|
+
]);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
catch (error) {
|
|
326
|
+
setConversationThinking(false);
|
|
327
|
+
setErrorMessage(`AI error: ${error.message}`);
|
|
328
|
+
setMenuState('list');
|
|
329
|
+
}
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
// Fallback to legacy one-shot generation
|
|
333
|
+
setMenuState('create-generating');
|
|
334
|
+
setGeneratingMessage('Generating agent profile...');
|
|
335
|
+
try {
|
|
336
|
+
let profile;
|
|
337
|
+
if (generateAgentProfile) {
|
|
338
|
+
// Use AI to generate the profile
|
|
339
|
+
profile = await generateAgentProfile(createDescription, createSelectedModel);
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
// Fallback: Create a basic profile
|
|
343
|
+
const safeName = createDescription
|
|
344
|
+
.toLowerCase()
|
|
345
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
346
|
+
.replace(/^-|-$/g, '')
|
|
347
|
+
.slice(0, 32) || `agent-${Date.now()}`;
|
|
348
|
+
profile = {
|
|
349
|
+
name: safeName,
|
|
350
|
+
description: createDescription.slice(0, 200),
|
|
351
|
+
tools: ['Read', 'Glob', 'Grep', 'Write', 'Edit', 'Bash'],
|
|
352
|
+
systemPrompt: `# ${safeName}\n\n${createDescription}\n\n## Your Role\n\nYou are a specialized agent. Follow the user's instructions carefully.\n\n## Guidelines\n\n- Be thorough and methodical\n- Explain your reasoning\n- Ask for clarification if needed`,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
await createAgentFromProfile(profile);
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
setErrorMessage(`Failed to create agent: ${error.message}`);
|
|
359
|
+
setMenuState('list');
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
/**
|
|
363
|
+
* Handle user response in conversation flow
|
|
364
|
+
*/
|
|
365
|
+
const handleConversationSubmit = async () => {
|
|
366
|
+
if (!conversationInput.trim() || !conversationalCreator) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
// Add user message to conversation
|
|
370
|
+
const userMessage = {
|
|
371
|
+
role: 'user',
|
|
372
|
+
content: conversationInput,
|
|
373
|
+
};
|
|
374
|
+
const updatedMessages = [...conversationMessages, userMessage];
|
|
375
|
+
setConversationMessages(updatedMessages);
|
|
376
|
+
setConversationInput('');
|
|
377
|
+
setConversationThinking(true);
|
|
378
|
+
setErrorMessage('');
|
|
379
|
+
try {
|
|
380
|
+
const response = await conversationalCreator(updatedMessages, createSelectedModel);
|
|
381
|
+
setConversationThinking(false);
|
|
382
|
+
if (response.type === 'profile' && response.profile) {
|
|
383
|
+
// AI generated the final profile
|
|
384
|
+
await createAgentFromProfile(response.profile);
|
|
385
|
+
}
|
|
386
|
+
else if (response.type === 'question' && response.question) {
|
|
387
|
+
// AI is asking another clarifying question
|
|
388
|
+
const questionText = response.question; // Capture as string
|
|
389
|
+
setConversationMessages((prev) => [
|
|
390
|
+
...prev,
|
|
391
|
+
{ role: 'assistant', content: questionText },
|
|
392
|
+
]);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
setConversationThinking(false);
|
|
397
|
+
setErrorMessage(`AI error: ${error.message}`);
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
/**
|
|
401
|
+
* Create agent from generated profile
|
|
402
|
+
*/
|
|
403
|
+
const createAgentFromProfile = async (profile) => {
|
|
404
|
+
setMenuState('create-generating');
|
|
405
|
+
setGeneratingMessage('Saving agent...');
|
|
406
|
+
try {
|
|
407
|
+
await store.createAgent({
|
|
408
|
+
name: profile.name,
|
|
409
|
+
description: profile.description,
|
|
410
|
+
tools: profile.tools,
|
|
411
|
+
model: createSelectedModel,
|
|
412
|
+
systemPrompt: profile.systemPrompt,
|
|
413
|
+
location: 'project',
|
|
414
|
+
});
|
|
415
|
+
setStatusMessage(`Created agent '${profile.name}' successfully!`);
|
|
416
|
+
loadAgents();
|
|
417
|
+
// Select the new agent
|
|
418
|
+
setTimeout(() => {
|
|
419
|
+
const newIndex = store.getAll().findIndex((a) => a.name === profile.name);
|
|
420
|
+
if (newIndex !== -1) {
|
|
421
|
+
setSelectedIndex(newIndex);
|
|
422
|
+
}
|
|
423
|
+
}, 100);
|
|
424
|
+
// Reset all creation state
|
|
425
|
+
resetCreationState();
|
|
426
|
+
setMenuState('list');
|
|
427
|
+
}
|
|
428
|
+
catch (error) {
|
|
429
|
+
setErrorMessage(`Failed to create agent: ${error.message}`);
|
|
430
|
+
setMenuState('list');
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
/**
|
|
434
|
+
* Reset all creation-related state
|
|
435
|
+
*/
|
|
436
|
+
const resetCreationState = () => {
|
|
437
|
+
setModelFilter('');
|
|
438
|
+
setModelSelectIndex(0);
|
|
439
|
+
setCreateSelectedModel('');
|
|
440
|
+
setCreateDescription('');
|
|
441
|
+
setConversationMessages([]);
|
|
442
|
+
setConversationInput('');
|
|
443
|
+
setConversationThinking(false);
|
|
444
|
+
setGeneratingMessage('');
|
|
445
|
+
};
|
|
446
|
+
/**
|
|
447
|
+
* Cancel conversation and return to list
|
|
448
|
+
*/
|
|
449
|
+
const handleConversationCancel = () => {
|
|
450
|
+
resetCreationState();
|
|
451
|
+
setMenuState('list');
|
|
452
|
+
};
|
|
453
|
+
/**
|
|
454
|
+
* Handle model selection for creation
|
|
455
|
+
*/
|
|
456
|
+
const handleModelSelect = (modelId) => {
|
|
457
|
+
const resolvedModel = modelId === 'inherit' ? currentModel : modelId;
|
|
458
|
+
setCreateSelectedModel(resolvedModel);
|
|
459
|
+
setModelFilter('');
|
|
460
|
+
setModelSelectIndex(0);
|
|
461
|
+
setMenuState('create-description');
|
|
462
|
+
};
|
|
463
|
+
/**
|
|
464
|
+
* Handle model change for existing agent
|
|
465
|
+
*/
|
|
466
|
+
const handleAgentModelChange = async (modelId) => {
|
|
467
|
+
if (!editingAgentForModel)
|
|
468
|
+
return;
|
|
469
|
+
const resolvedModel = modelId === 'inherit' ? currentModel : modelId;
|
|
470
|
+
const isEditFlow = selectedAgentForEdit !== null;
|
|
471
|
+
try {
|
|
472
|
+
// Read current content and update model in frontmatter
|
|
473
|
+
const content = await store.getAgentContent(editingAgentForModel.name);
|
|
474
|
+
// Replace model in YAML frontmatter
|
|
475
|
+
const updatedContent = content.replace(/^(model:\s*).+$/m, `$1${resolvedModel}`);
|
|
476
|
+
await store.updateAgent(editingAgentForModel.name, updatedContent);
|
|
477
|
+
setStatusMessage(`Model ${isEditFlow ? 'confirmed' : 'changed'}: '${resolvedModel}'`);
|
|
478
|
+
loadAgents();
|
|
479
|
+
}
|
|
480
|
+
catch (error) {
|
|
481
|
+
setErrorMessage(`Failed to update model: ${error.message}`);
|
|
482
|
+
}
|
|
483
|
+
// Reset model selection state
|
|
484
|
+
setEditingAgentForModel(null);
|
|
485
|
+
setModelFilter('');
|
|
486
|
+
setModelSelectIndex(0);
|
|
487
|
+
// If in edit flow, proceed to edit choice; otherwise return to list
|
|
488
|
+
if (isEditFlow) {
|
|
489
|
+
setEditChoiceIndex(0);
|
|
490
|
+
setMenuState('edit-choice');
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
setMenuState('list');
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
/**
|
|
497
|
+
* Handle model filter input change
|
|
498
|
+
*/
|
|
499
|
+
const handleModelFilterChange = (value) => {
|
|
500
|
+
setModelFilter(value);
|
|
501
|
+
};
|
|
502
|
+
/**
|
|
503
|
+
* Handle model filter submit (Enter key)
|
|
504
|
+
*/
|
|
505
|
+
const handleModelFilterSubmit = () => {
|
|
506
|
+
// If filter matches exactly one model or user typed full ID, select it
|
|
507
|
+
const exactMatch = filteredModels.find((m) => m.id.toLowerCase() === modelFilter.toLowerCase());
|
|
508
|
+
if (exactMatch) {
|
|
509
|
+
if (menuState === 'create-model') {
|
|
510
|
+
handleModelSelect(exactMatch.id);
|
|
511
|
+
}
|
|
512
|
+
else if (menuState === 'edit-model') {
|
|
513
|
+
handleAgentModelChange(exactMatch.id);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
else if (filteredModels.length > 0 && modelSelectIndex < filteredModels.length) {
|
|
517
|
+
// Select the highlighted model
|
|
518
|
+
const selected = filteredModels[modelSelectIndex];
|
|
519
|
+
if (selected) {
|
|
520
|
+
if (menuState === 'create-model') {
|
|
521
|
+
handleModelSelect(selected.id);
|
|
522
|
+
}
|
|
523
|
+
else if (menuState === 'edit-model') {
|
|
524
|
+
handleAgentModelChange(selected.id);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
setErrorMessage('No matching model found');
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
/**
|
|
533
|
+
* Cancel model selection
|
|
534
|
+
*/
|
|
535
|
+
const handleModelSelectionCancel = () => {
|
|
536
|
+
setModelFilter('');
|
|
537
|
+
setModelSelectIndex(0);
|
|
538
|
+
setEditingAgentForModel(null);
|
|
539
|
+
setSelectedAgentForEdit(null); // Clear edit flow state
|
|
540
|
+
setMenuState('list');
|
|
541
|
+
};
|
|
542
|
+
/**
|
|
543
|
+
* Execute confirmed action
|
|
544
|
+
*/
|
|
545
|
+
const executeConfirmedAction = async (action) => {
|
|
546
|
+
setMenuState('loading');
|
|
547
|
+
setStatusMessage('');
|
|
548
|
+
setErrorMessage('');
|
|
549
|
+
try {
|
|
550
|
+
switch (action.type) {
|
|
551
|
+
case 'edit':
|
|
552
|
+
await handleEdit(action.agentName);
|
|
553
|
+
break;
|
|
554
|
+
case 'delete':
|
|
555
|
+
await handleDelete(action.agentName);
|
|
556
|
+
break;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
catch (error) {
|
|
560
|
+
setErrorMessage(error.message);
|
|
561
|
+
}
|
|
562
|
+
finally {
|
|
563
|
+
setMenuState('list');
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
/**
|
|
567
|
+
* Handle edit action - opens inline editor (legacy, used by confirmation flow)
|
|
568
|
+
*/
|
|
569
|
+
const handleEdit = async (agentName) => {
|
|
570
|
+
const agent = store.getAgent(agentName);
|
|
571
|
+
if (!agent) {
|
|
572
|
+
setErrorMessage(`Agent '${agentName}' not found`);
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
try {
|
|
576
|
+
const content = await store.getAgentContent(agentName);
|
|
577
|
+
// Set editing state and open inline editor
|
|
578
|
+
setEditingAgent(agent);
|
|
579
|
+
setEditingContent(content);
|
|
580
|
+
setEditingFilePath(agent.filePath);
|
|
581
|
+
setMenuState('editing');
|
|
582
|
+
}
|
|
583
|
+
catch (error) {
|
|
584
|
+
setErrorMessage(`Failed to load agent: ${error.message}`);
|
|
585
|
+
}
|
|
586
|
+
};
|
|
587
|
+
/**
|
|
588
|
+
* Handle direct edit action - opens inline editor
|
|
589
|
+
*/
|
|
590
|
+
const handleDirectEdit = async (agentName) => {
|
|
591
|
+
const agent = store.getAgent(agentName);
|
|
592
|
+
if (!agent) {
|
|
593
|
+
setErrorMessage(`Agent '${agentName}' not found`);
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
try {
|
|
597
|
+
const content = await store.getAgentContent(agentName);
|
|
598
|
+
// Clear edit choice state
|
|
599
|
+
setSelectedAgentForEdit(null);
|
|
600
|
+
// Set editing state and open inline editor
|
|
601
|
+
setEditingAgent(agent);
|
|
602
|
+
setEditingContent(content);
|
|
603
|
+
setEditingFilePath(agent.filePath);
|
|
604
|
+
setMenuState('editing');
|
|
605
|
+
}
|
|
606
|
+
catch (error) {
|
|
607
|
+
setErrorMessage(`Failed to load agent: ${error.message}`);
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
/**
|
|
611
|
+
* Handle AI edit start - shows the request input
|
|
612
|
+
*/
|
|
613
|
+
const handleAiEditStart = async (agentName) => {
|
|
614
|
+
const agent = store.getAgent(agentName);
|
|
615
|
+
if (!agent) {
|
|
616
|
+
setErrorMessage(`Agent '${agentName}' not found`);
|
|
617
|
+
setMenuState('list');
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
if (!editAssistant) {
|
|
621
|
+
setErrorMessage('AI edit assistant not available');
|
|
622
|
+
setMenuState('list');
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
try {
|
|
626
|
+
const content = await store.getAgentContent(agentName);
|
|
627
|
+
// Store original content for AI edit flow
|
|
628
|
+
setAiEditOriginalContent(content);
|
|
629
|
+
setAiEditRequest('');
|
|
630
|
+
setAiEditResult(null);
|
|
631
|
+
setMenuState('ai-edit-request');
|
|
632
|
+
}
|
|
633
|
+
catch (error) {
|
|
634
|
+
setErrorMessage(`Failed to load agent: ${error.message}`);
|
|
635
|
+
setMenuState('list');
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
/**
|
|
639
|
+
* Handle AI edit request submission
|
|
640
|
+
*/
|
|
641
|
+
const handleAiEditSubmit = async () => {
|
|
642
|
+
if (!aiEditRequest.trim() || !selectedAgentForEdit || !editAssistant) {
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
setErrorMessage('');
|
|
646
|
+
setMenuState('ai-edit-processing');
|
|
647
|
+
try {
|
|
648
|
+
const result = await editAssistant(aiEditOriginalContent, aiEditRequest, selectedAgentForEdit.name);
|
|
649
|
+
setAiEditResult(result);
|
|
650
|
+
setMenuState('ai-edit-confirm');
|
|
651
|
+
}
|
|
652
|
+
catch (error) {
|
|
653
|
+
setErrorMessage(`AI edit failed: ${error.message}`);
|
|
654
|
+
setMenuState('ai-edit-request');
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
/**
|
|
658
|
+
* Handle AI edit confirmation - save the changes
|
|
659
|
+
*/
|
|
660
|
+
const handleAiEditConfirm = async () => {
|
|
661
|
+
if (!aiEditResult || !selectedAgentForEdit) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
try {
|
|
665
|
+
await store.updateAgent(selectedAgentForEdit.name, aiEditResult.content);
|
|
666
|
+
setStatusMessage(`Agent '${selectedAgentForEdit.name}' updated: ${aiEditResult.summary}`);
|
|
667
|
+
loadAgents();
|
|
668
|
+
// Reset state
|
|
669
|
+
handleAiEditReset();
|
|
670
|
+
setMenuState('list');
|
|
671
|
+
}
|
|
672
|
+
catch (error) {
|
|
673
|
+
setErrorMessage(`Failed to save: ${error.message}`);
|
|
674
|
+
setMenuState('ai-edit-confirm');
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
/**
|
|
678
|
+
* Handle AI edit rejection - discard changes
|
|
679
|
+
*/
|
|
680
|
+
const handleAiEditReject = () => {
|
|
681
|
+
setAiEditResult(null);
|
|
682
|
+
setMenuState('ai-edit-request');
|
|
683
|
+
setStatusMessage('Changes discarded. Try a different edit request.');
|
|
684
|
+
};
|
|
685
|
+
/**
|
|
686
|
+
* Handle AI edit cancel - return to list
|
|
687
|
+
*/
|
|
688
|
+
const handleAiEditCancel = () => {
|
|
689
|
+
handleAiEditReset();
|
|
690
|
+
setMenuState('list');
|
|
691
|
+
};
|
|
692
|
+
/**
|
|
693
|
+
* Reset all AI edit state
|
|
694
|
+
*/
|
|
695
|
+
const handleAiEditReset = () => {
|
|
696
|
+
setSelectedAgentForEdit(null);
|
|
697
|
+
setAiEditRequest('');
|
|
698
|
+
setAiEditResult(null);
|
|
699
|
+
setAiEditOriginalContent('');
|
|
700
|
+
};
|
|
701
|
+
/**
|
|
702
|
+
* Handle view action - show agent details
|
|
703
|
+
*/
|
|
704
|
+
const handleView = async (agentName) => {
|
|
705
|
+
const agent = store.getAgent(agentName);
|
|
706
|
+
if (!agent) {
|
|
707
|
+
setErrorMessage(`Agent '${agentName}' not found`);
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
setViewingAgent(agent);
|
|
711
|
+
setMenuState('viewing');
|
|
712
|
+
};
|
|
713
|
+
/**
|
|
714
|
+
* Handle save from inline editor
|
|
715
|
+
*/
|
|
716
|
+
const handleEditorSave = async (newContent) => {
|
|
717
|
+
if (!editingFilePath || !editingAgent) {
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
try {
|
|
721
|
+
await store.updateAgent(editingAgent.name, newContent);
|
|
722
|
+
setStatusMessage(`Agent '${editingAgent.name}' saved successfully`);
|
|
723
|
+
setMenuState('list');
|
|
724
|
+
// Clear editing state
|
|
725
|
+
setEditingAgent(null);
|
|
726
|
+
setEditingContent('');
|
|
727
|
+
setEditingFilePath('');
|
|
728
|
+
// Reload agents
|
|
729
|
+
loadAgents();
|
|
730
|
+
}
|
|
731
|
+
catch (error) {
|
|
732
|
+
setErrorMessage(`Failed to save: ${error.message}`);
|
|
733
|
+
setMenuState('list');
|
|
734
|
+
}
|
|
735
|
+
};
|
|
736
|
+
/**
|
|
737
|
+
* Handle cancel from inline editor
|
|
738
|
+
*/
|
|
739
|
+
const handleEditorCancel = () => {
|
|
740
|
+
setMenuState('list');
|
|
741
|
+
// Clear editing state
|
|
742
|
+
setEditingAgent(null);
|
|
743
|
+
setEditingContent('');
|
|
744
|
+
setEditingFilePath('');
|
|
745
|
+
};
|
|
746
|
+
/**
|
|
747
|
+
* Handle delete action
|
|
748
|
+
*/
|
|
749
|
+
const handleDelete = async (agentName) => {
|
|
750
|
+
try {
|
|
751
|
+
await store.deleteAgent(agentName);
|
|
752
|
+
setStatusMessage(`Agent '${agentName}' deleted`);
|
|
753
|
+
loadAgents();
|
|
754
|
+
// Adjust selection if needed
|
|
755
|
+
if (selectedIndex >= agents.length - 1) {
|
|
756
|
+
setSelectedIndex(Math.max(0, agents.length - 2));
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
catch (error) {
|
|
760
|
+
setErrorMessage(error.message);
|
|
761
|
+
}
|
|
762
|
+
};
|
|
763
|
+
/**
|
|
764
|
+
* Render model selection step (for both creation and editing)
|
|
765
|
+
*/
|
|
766
|
+
const renderModelSelection = () => {
|
|
767
|
+
const isEditing = menuState === 'edit-model';
|
|
768
|
+
const title = isEditing
|
|
769
|
+
? `Change Model for '${editingAgentForModel?.name}'`
|
|
770
|
+
: 'Step 1: Select Model';
|
|
771
|
+
// Calculate visible range for scrolling
|
|
772
|
+
const startIndex = Math.max(0, modelSelectIndex - Math.floor(MAX_VISIBLE_MODELS / 2));
|
|
773
|
+
const endIndex = Math.min(filteredModels.length, startIndex + MAX_VISIBLE_MODELS);
|
|
774
|
+
const visibleModels = filteredModels.slice(startIndex, endIndex);
|
|
775
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: title }) }), modelsLoading && (_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { children: " Loading models..." })] })), !modelsLoading && (_jsxs(_Fragment, { children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "Type to filter or enter model ID:" }) }), _jsxs(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, marginBottom: 1, children: [_jsxs(Text, { color: "cyan", children: ['>', " "] }), _jsx(TextInput, { value: modelFilter, onChange: handleModelFilterChange, onSubmit: handleModelFilterSubmit, placeholder: "e.g., sonnet, opus, gemini, grok..." })] }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { dimColor: true, children: ["Showing ", filteredModels.length, " model", filteredModels.length !== 1 ? 's' : '', modelFilter && ` matching "${modelFilter}"`, filteredModels.length > MAX_VISIBLE_MODELS && ` (scroll with arrow keys)`] }) }), _jsx(Box, { flexDirection: "column", marginBottom: 1, children: visibleModels.length === 0 ? (_jsx(Box, { children: _jsx(Text, { color: "yellow", children: "No models match your filter" }) })) : (visibleModels.map((model, displayIndex) => {
|
|
776
|
+
const actualIndex = startIndex + displayIndex;
|
|
777
|
+
const isSelected = actualIndex === modelSelectIndex;
|
|
778
|
+
const providerLabel = model.owned_by ? `[${model.owned_by}]` : '';
|
|
779
|
+
const displayName = model.displayName || model.id;
|
|
780
|
+
const contextInfo = model.contextWindow
|
|
781
|
+
? `${Math.round(model.contextWindow / 1000)}k ctx`
|
|
782
|
+
: '';
|
|
783
|
+
const costInfo = model.inputCostPer1M !== undefined
|
|
784
|
+
? `$${model.inputCostPer1M.toFixed(2)}/$${model.outputCostPer1M?.toFixed(2) || '?'}`
|
|
785
|
+
: '';
|
|
786
|
+
const reasoningBadge = model.reasoning?.supported ? ' [R]' : '';
|
|
787
|
+
return (_jsxs(Box, { paddingLeft: isSelected ? 0 : 2, children: [isSelected && _jsx(Text, { color: "cyan", bold: true, children: '> ' }), _jsxs(Text, { dimColor: true, children: [providerLabel, " "] }), _jsx(Text, { bold: isSelected, color: isSelected ? 'cyan' : undefined, children: displayName }), _jsx(Text, { color: "yellow", children: reasoningBadge }), contextInfo && _jsxs(Text, { dimColor: true, children: [" (", contextInfo, ")"] }), costInfo && _jsxs(Text, { dimColor: true, children: [" ", costInfo] })] }, model.id));
|
|
788
|
+
})) }), filteredModels.length > MAX_VISIBLE_MODELS && (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { dimColor: true, children: [startIndex > 0 ? '↑ more above ' : '', endIndex < filteredModels.length ? '↓ more below' : ''] }) })), errorMessage && (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: "red", children: ['!', " ", errorMessage] }) })), _jsx(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Type: Filter | \u2191/\u2193: Navigate | Enter: Select | Esc: Cancel" }) })] }))] }));
|
|
789
|
+
};
|
|
790
|
+
/**
|
|
791
|
+
* Render description input step
|
|
792
|
+
*/
|
|
793
|
+
const renderDescriptionInput = () => {
|
|
794
|
+
// Find the selected model info
|
|
795
|
+
const selectedModelInfo = availableModels.find((m) => m.id === createSelectedModel);
|
|
796
|
+
const modelDisplayName = selectedModelInfo?.displayName || createSelectedModel;
|
|
797
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: "Step 2: Describe Your Agent" }) }), _jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { dimColor: true, children: "Model: " }), _jsx(Text, { color: "green", children: modelDisplayName })] }), _jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [_jsx(Text, { children: "Please describe your new agent. Be as descriptive as possible:" }), _jsx(Text, { dimColor: true, children: "(What should it do? What's its specialty? How should it behave?)" })] }), _jsx(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, paddingY: 0, children: _jsx(TextInput, { value: createDescription, onChange: setCreateDescription, onSubmit: handleDescriptionSubmit, placeholder: "E.g., A security auditor that reviews code for vulnerabilities, checks for OWASP top 10 issues, and provides remediation advice..." }) }), errorMessage && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ['!', " ", errorMessage] }) })), _jsx(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Enter: Generate Agent | Esc: Cancel" }) })] }));
|
|
798
|
+
};
|
|
799
|
+
/**
|
|
800
|
+
* Render generating state
|
|
801
|
+
*/
|
|
802
|
+
const renderGenerating = () => {
|
|
803
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: "Creating Your Agent" }) }), _jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsxs(Text, { children: [" ", generatingMessage] })] }), _jsx(Box, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1, children: _jsx(Text, { dimColor: true, children: "The AI is generating a detailed agent profile based on your description..." }) })] }));
|
|
804
|
+
};
|
|
805
|
+
/**
|
|
806
|
+
* Render conversation mode - multi-turn agent creation
|
|
807
|
+
*/
|
|
808
|
+
const renderConversation = () => {
|
|
809
|
+
// Find the selected model info
|
|
810
|
+
const selectedModelInfo = availableModels.find((m) => m.id === createSelectedModel);
|
|
811
|
+
const modelDisplayName = selectedModelInfo?.displayName || createSelectedModel;
|
|
812
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: "Creating Agent - Conversation" }) }), _jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { dimColor: true, children: "Model: " }), _jsx(Text, { color: "green", children: modelDisplayName }), _jsx(Text, { dimColor: true, children: " | Answer the AI's questions to refine your agent" })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "gray", paddingX: 1, paddingY: 1, marginBottom: 1, children: [conversationMessages.map((msg, index) => (_jsx(Box, { marginBottom: index < conversationMessages.length - 1 ? 1 : 0, children: msg.role === 'user' ? (_jsxs(Box, { children: [_jsx(Text, { color: "blue", bold: true, children: "You: " }), _jsx(Text, { children: msg.content })] })) : (_jsxs(Box, { children: [_jsx(Text, { color: "magenta", bold: true, children: "AI: " }), _jsx(Text, { children: msg.content })] })) }, index))), conversationThinking && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { dimColor: true, children: " AI is thinking..." })] }))] }), !conversationThinking && (_jsxs(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, children: [_jsxs(Text, { color: "cyan", children: ['>', " "] }), _jsx(TextInput, { value: conversationInput, onChange: setConversationInput, onSubmit: handleConversationSubmit, placeholder: "Type your response..." })] })), errorMessage && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ['!', " ", errorMessage] }) })), _jsx(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Enter: Submit response | Esc: Cancel creation" }) })] }));
|
|
813
|
+
};
|
|
814
|
+
/**
|
|
815
|
+
* Render confirmation prompt
|
|
816
|
+
*/
|
|
817
|
+
const renderConfirmation = () => {
|
|
818
|
+
if (!confirmAction)
|
|
819
|
+
return null;
|
|
820
|
+
let promptText = '';
|
|
821
|
+
let warningText = '';
|
|
822
|
+
switch (confirmAction.type) {
|
|
823
|
+
case 'edit':
|
|
824
|
+
promptText = `Edit agent '${confirmAction.agentName}'?`;
|
|
825
|
+
break;
|
|
826
|
+
case 'delete':
|
|
827
|
+
promptText = `Delete agent '${confirmAction.agentName}'?`;
|
|
828
|
+
warningText = 'This action cannot be undone.';
|
|
829
|
+
break;
|
|
830
|
+
}
|
|
831
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "yellow", children: "Confirmation Required" }) }), _jsx(Box, { marginBottom: warningText ? 1 : 0, children: _jsx(Text, { children: promptText }) }), warningText && (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: warningText }) })), _jsx(Box, { children: _jsxs(Text, { children: ["Press ", _jsx(Text, { bold: true, color: "green", children: "Y" }), " to confirm, ", _jsx(Text, { bold: true, color: "red", children: "N" }), " to cancel"] }) })] }));
|
|
832
|
+
};
|
|
833
|
+
/**
|
|
834
|
+
* Render edit choice dialog
|
|
835
|
+
*/
|
|
836
|
+
const renderEditChoice = () => {
|
|
837
|
+
if (!selectedAgentForEdit)
|
|
838
|
+
return null;
|
|
839
|
+
const choices = [
|
|
840
|
+
{ label: 'Edit directly', description: 'Open in text editor' },
|
|
841
|
+
{ label: 'AI-assisted edit', description: 'Describe changes in natural language' },
|
|
842
|
+
];
|
|
843
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, color: "cyan", children: ["Edit Agent: ", selectedAgentForEdit.name] }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "How would you like to edit this agent?" }) }), _jsx(Box, { flexDirection: "column", marginBottom: 1, children: choices.map((choice, index) => {
|
|
844
|
+
const isSelected = index === editChoiceIndex;
|
|
845
|
+
return (_jsxs(Box, { paddingLeft: isSelected ? 0 : 2, children: [isSelected && _jsx(Text, { color: "cyan", bold: true, children: '> ' }), _jsx(Text, { bold: isSelected, color: isSelected ? 'cyan' : undefined, children: choice.label }), _jsxs(Text, { dimColor: true, children: [" - ", choice.description] })] }, index));
|
|
846
|
+
}) }), !editAssistant && editChoiceIndex === 1 && (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: "yellow", children: ['!', " AI assistant not available"] }) })), _jsx(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, children: _jsx(Text, { dimColor: true, children: "\u2191/\u2193: Select | Enter: Confirm | Esc: Cancel" }) })] }));
|
|
847
|
+
};
|
|
848
|
+
/**
|
|
849
|
+
* Render AI edit request input
|
|
850
|
+
*/
|
|
851
|
+
const renderAiEditRequest = () => {
|
|
852
|
+
if (!selectedAgentForEdit)
|
|
853
|
+
return null;
|
|
854
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, color: "cyan", children: ["AI-Assisted Edit: ", selectedAgentForEdit.name] }) }), _jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [_jsx(Text, { children: "Describe the changes you'd like to make:" }), _jsx(Text, { dimColor: true, children: "(e.g., \"add error handling guidelines\", \"make it focus on TypeScript\", \"add a code review checklist\")" })] }), _jsxs(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, children: [_jsxs(Text, { color: "cyan", children: ['>', " "] }), _jsx(TextInput, { value: aiEditRequest, onChange: setAiEditRequest, onSubmit: handleAiEditSubmit, placeholder: "Describe your changes..." })] }), errorMessage && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ['!', " ", errorMessage] }) })), statusMessage && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "green", children: ['>', " ", statusMessage] }) })), _jsx(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Enter: Submit | Esc: Cancel" }) })] }));
|
|
855
|
+
};
|
|
856
|
+
/**
|
|
857
|
+
* Render AI edit processing state
|
|
858
|
+
*/
|
|
859
|
+
const renderAiEditProcessing = () => {
|
|
860
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: "AI-Assisted Edit" }) }), _jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { children: " Processing your edit request..." })] }), _jsx(Box, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1, children: _jsx(Text, { dimColor: true, children: "The AI is updating the agent based on your description..." }) })] }));
|
|
861
|
+
};
|
|
862
|
+
/**
|
|
863
|
+
* Render AI edit confirmation
|
|
864
|
+
*/
|
|
865
|
+
const renderAiEditConfirm = () => {
|
|
866
|
+
if (!aiEditResult || !selectedAgentForEdit)
|
|
867
|
+
return null;
|
|
868
|
+
// Show a preview of the changes (first ~500 chars of content)
|
|
869
|
+
const preview = aiEditResult.content.slice(0, 500);
|
|
870
|
+
const truncated = aiEditResult.content.length > 500;
|
|
871
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, color: "cyan", children: ["Review AI Changes: ", selectedAgentForEdit.name] }) }), _jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "green", children: "Summary: " }), _jsx(Text, { children: aiEditResult.summary })] }), _jsxs(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, paddingY: 1, marginBottom: 1, flexDirection: "column", children: [_jsx(Text, { bold: true, dimColor: true, children: "Updated Content Preview:" }), _jsx(Text, { children: preview }), truncated && _jsx(Text, { dimColor: true, children: "... (truncated)" })] }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Accept these changes?" }) }), _jsx(Box, { children: _jsxs(Text, { children: ["Press ", _jsx(Text, { bold: true, color: "green", children: "Y" }), " to save, ", _jsx(Text, { bold: true, color: "red", children: "N" }), " to try again"] }) }), errorMessage && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ['!', " ", errorMessage] }) }))] }));
|
|
872
|
+
};
|
|
873
|
+
/**
|
|
874
|
+
* Render agent list
|
|
875
|
+
*/
|
|
876
|
+
const renderList = () => {
|
|
877
|
+
if (agents.length === 0) {
|
|
878
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { dimColor: true, children: "No agents found" }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { children: ["Press ", _jsx(Text, { bold: true, color: "cyan", children: "+" }), " or ", _jsx(Text, { bold: true, color: "cyan", children: "N" }), " to create a new agent"] }) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Agents directory: ", store.getProjectDir()] }) })] }));
|
|
879
|
+
}
|
|
880
|
+
return (_jsx(Box, { flexDirection: "column", marginTop: 1, children: agents.map((agent, index) => {
|
|
881
|
+
const isSelected = index === selectedIndex;
|
|
882
|
+
const locationIcon = agent.location === 'project' ? '[P]' : '[G]';
|
|
883
|
+
const toolsInfo = agent.tools === 'all' ? 'all tools' : `${agent.tools.length} tools`;
|
|
884
|
+
return (_jsxs(Box, { paddingLeft: isSelected ? 0 : 2, children: [isSelected && _jsx(Text, { color: "cyan", bold: true, children: '> ' }), _jsx(Text, { dimColor: true, children: locationIcon }), _jsx(Text, { children: " " }), _jsx(Text, { bold: isSelected, color: isSelected ? 'cyan' : undefined, children: agent.name }), _jsxs(Text, { dimColor: true, children: [" (", agent.model, ", ", toolsInfo, ")"] })] }, agent.name));
|
|
885
|
+
}) }));
|
|
886
|
+
};
|
|
887
|
+
/**
|
|
888
|
+
* Render agent detail view
|
|
889
|
+
*/
|
|
890
|
+
const renderDetail = () => {
|
|
891
|
+
if (!viewingAgent)
|
|
892
|
+
return null;
|
|
893
|
+
const toolsList = viewingAgent.tools === 'all'
|
|
894
|
+
? 'All tools'
|
|
895
|
+
: viewingAgent.tools.join(', ');
|
|
896
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: viewingAgent.name }), _jsxs(Text, { dimColor: true, children: [" (", viewingAgent.location, ")"] })] }), _jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, children: "Description: " }), _jsx(Text, { children: viewingAgent.description })] }), _jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, children: "Model: " }), _jsx(Text, { children: viewingAgent.model })] }), _jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, children: "Tools: " }), _jsx(Text, { children: toolsList })] }), _jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, children: "File: " }), _jsx(Text, { dimColor: true, children: viewingAgent.filePath })] }), _jsx(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, marginTop: 1, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, dimColor: true, children: "System Prompt Preview:" }), _jsxs(Text, { children: [viewingAgent.systemPrompt.slice(0, 500), viewingAgent.systemPrompt.length > 500 ? '...' : ''] })] }) })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press any key to return to list" }) })] }));
|
|
897
|
+
};
|
|
898
|
+
/**
|
|
899
|
+
* Render status bar
|
|
900
|
+
*/
|
|
901
|
+
const renderStatusBar = () => {
|
|
902
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1, children: [_jsx(Box, { justifyContent: "space-between", children: _jsx(Text, { dimColor: true, children: "\u2191/\u2193: Navigate | Enter: Edit | Space: View | +/N: New | M: Model | D: Delete | Q: Quit" }) }), statusMessage && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "green", children: ['>', " ", statusMessage] }) })), errorMessage && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ['!', " ", errorMessage] }) })), selectedAgent && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Selected: ", selectedAgent.name, " | Location: ", selectedAgent.location, " |", ' ', "Model: ", selectedAgent.model] }) }))] }));
|
|
903
|
+
};
|
|
904
|
+
/**
|
|
905
|
+
* Main render
|
|
906
|
+
*/
|
|
907
|
+
return (_jsxs(Box, { flexDirection: "column", padding: menuState === 'editing' ? 0 : 1, children: [menuState === 'editing' && editingContent && editingFilePath && (_jsx(InlineEditor, { content: editingContent, filePath: editingFilePath, onSave: handleEditorSave, onCancel: handleEditorCancel })), menuState !== 'editing' && (_jsxs(_Fragment, { children: [_jsxs(Box, { borderStyle: "bold", borderColor: "cyan", paddingX: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "Task Agent Manager" }), _jsx(Text, { children: " " }), _jsxs(Text, { dimColor: true, children: ["(", agents.length, " agents)"] })] }), menuState === 'loading' && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { children: " Processing..." })] })), menuState === 'create-model' && renderModelSelection(), menuState === 'edit-model' && renderModelSelection(), menuState === 'create-description' && renderDescriptionInput(), menuState === 'create-conversation' && renderConversation(), menuState === 'create-generating' && renderGenerating(), menuState === 'confirm' && renderConfirmation(), menuState === 'edit-choice' && renderEditChoice(), menuState === 'ai-edit-request' && renderAiEditRequest(), menuState === 'ai-edit-processing' && renderAiEditProcessing(), menuState === 'ai-edit-confirm' && renderAiEditConfirm(), menuState === 'viewing' && renderDetail(), menuState === 'list' && renderList(), menuState === 'list' && renderStatusBar()] }))] }));
|
|
908
|
+
};
|
|
909
|
+
//# sourceMappingURL=InteractiveAgentMenu.js.map
|