dexto 1.3.0 → 1.5.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/README.md +87 -22
- package/dist/agents/agent-registry.json +9 -0
- package/dist/agents/agent-template.yml +2 -2
- package/dist/agents/coding-agent/coding-agent.yml +27 -16
- package/dist/agents/database-agent/database-agent.yml +2 -2
- package/dist/agents/default-agent.yml +9 -7
- package/dist/agents/github-agent/github-agent.yml +2 -2
- package/dist/agents/product-name-researcher/product-name-researcher.yml +2 -2
- package/dist/agents/talk2pdf-agent/talk2pdf-agent.yml +2 -2
- package/dist/analytics/events.d.ts +13 -6
- package/dist/analytics/events.d.ts.map +1 -1
- package/dist/analytics/index.d.ts +1 -1
- package/dist/analytics/index.d.ts.map +1 -1
- package/dist/analytics/index.js +6 -2
- package/dist/api/server-hono.d.ts.map +1 -1
- package/dist/api/server-hono.js +65 -9
- package/dist/cli/cli-subscriber.d.ts +4 -0
- package/dist/cli/cli-subscriber.d.ts.map +1 -1
- package/dist/cli/cli-subscriber.js +47 -3
- package/dist/cli/commands/create-app.d.ts +16 -14
- package/dist/cli/commands/create-app.d.ts.map +1 -1
- package/dist/cli/commands/create-app.js +626 -102
- package/dist/cli/commands/create-image.d.ts +7 -0
- package/dist/cli/commands/create-image.d.ts.map +1 -0
- package/dist/cli/commands/create-image.js +201 -0
- package/dist/cli/commands/helpers/formatters.d.ts.map +1 -1
- package/dist/cli/commands/helpers/formatters.js +9 -8
- package/dist/cli/commands/index.d.ts +2 -1
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +2 -1
- package/dist/cli/commands/init-app.js +7 -7
- package/dist/cli/commands/install.d.ts +0 -3
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +19 -70
- package/dist/cli/commands/interactive-commands/command-parser.d.ts +17 -14
- package/dist/cli/commands/interactive-commands/command-parser.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/command-parser.js +7 -22
- package/dist/cli/commands/interactive-commands/commands.d.ts +4 -4
- package/dist/cli/commands/interactive-commands/commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/commands.js +34 -42
- package/dist/cli/commands/interactive-commands/documentation-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/documentation-commands.js +4 -7
- package/dist/cli/commands/interactive-commands/general-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/general-commands.js +159 -117
- package/dist/cli/commands/interactive-commands/mcp/index.d.ts +9 -3
- package/dist/cli/commands/interactive-commands/mcp/index.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/mcp/index.js +18 -3
- package/dist/cli/commands/interactive-commands/model/index.d.ts +8 -6
- package/dist/cli/commands/interactive-commands/model/index.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/model/index.js +18 -6
- package/dist/cli/commands/interactive-commands/prompt-commands.d.ts +3 -2
- package/dist/cli/commands/interactive-commands/prompt-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/prompt-commands.js +77 -60
- package/dist/cli/commands/interactive-commands/session/index.d.ts +7 -12
- package/dist/cli/commands/interactive-commands/session/index.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/session/index.js +7 -14
- package/dist/cli/commands/interactive-commands/session/session-commands.d.ts +10 -24
- package/dist/cli/commands/interactive-commands/session/session-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/session/session-commands.js +16 -371
- package/dist/cli/commands/interactive-commands/system/system-commands.d.ts +1 -0
- package/dist/cli/commands/interactive-commands/system/system-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/system/system-commands.js +106 -77
- package/dist/cli/commands/interactive-commands/tool-commands.d.ts +1 -1
- package/dist/cli/commands/interactive-commands/tool-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/tool-commands.js +5 -62
- package/dist/cli/commands/interactive-commands/utils/command-output.d.ts +13 -17
- package/dist/cli/commands/interactive-commands/utils/command-output.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/utils/command-output.js +18 -37
- package/dist/cli/commands/list-agents.d.ts +2 -2
- package/dist/cli/commands/list-agents.d.ts.map +1 -1
- package/dist/cli/commands/list-agents.js +38 -34
- package/dist/cli/commands/session-commands.js +16 -16
- package/dist/cli/commands/setup.d.ts +13 -5
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +860 -65
- package/dist/cli/commands/uninstall.d.ts.map +1 -1
- package/dist/cli/commands/uninstall.js +4 -6
- package/dist/cli/commands/which.d.ts.map +1 -1
- package/dist/cli/commands/which.js +18 -4
- package/dist/cli/ink-cli/InkCLIRefactored.d.ts +9 -22
- package/dist/cli/ink-cli/InkCLIRefactored.d.ts.map +1 -1
- package/dist/cli/ink-cli/InkCLIRefactored.js +50 -133
- package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts +26 -3
- package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ApprovalPrompt.js +182 -45
- package/dist/cli/ink-cli/components/CustomInput.js +1 -1
- package/dist/cli/ink-cli/components/EditableMultiLineInput.js +4 -4
- package/dist/cli/ink-cli/components/ElicitationForm.d.ts +22 -0
- package/dist/cli/ink-cli/components/ElicitationForm.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/ElicitationForm.js +358 -0
- package/dist/cli/ink-cli/components/ErrorBoundary.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ErrorBoundary.js +1 -1
- package/dist/cli/ink-cli/components/Footer.d.ts +16 -0
- package/dist/cli/ink-cli/components/Footer.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/Footer.js +27 -0
- package/dist/cli/ink-cli/components/HistorySearchBar.d.ts +17 -0
- package/dist/cli/ink-cli/components/HistorySearchBar.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/HistorySearchBar.js +8 -0
- package/dist/cli/ink-cli/components/MultiLineInput.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/MultiLineInput.js +3 -3
- package/dist/cli/ink-cli/components/ResourceAutocomplete.d.ts +15 -2
- package/dist/cli/ink-cli/components/ResourceAutocomplete.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ResourceAutocomplete.js +126 -82
- package/dist/cli/ink-cli/components/SlashCommandAutocomplete.d.ts +15 -2
- package/dist/cli/ink-cli/components/SlashCommandAutocomplete.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/SlashCommandAutocomplete.js +228 -122
- package/dist/cli/ink-cli/components/StatusBar.d.ts +15 -2
- package/dist/cli/ink-cli/components/StatusBar.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/StatusBar.js +50 -10
- package/dist/cli/ink-cli/components/TextBufferInput.d.ts +52 -0
- package/dist/cli/ink-cli/components/TextBufferInput.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/TextBufferInput.js +471 -0
- package/dist/cli/ink-cli/components/base/BaseAutocomplete.js +4 -4
- package/dist/cli/ink-cli/components/base/BaseSelector.d.ts +11 -1
- package/dist/cli/ink-cli/components/base/BaseSelector.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/base/BaseSelector.js +90 -49
- package/dist/cli/ink-cli/components/chat/Footer.js +1 -1
- package/dist/cli/ink-cli/components/chat/Header.d.ts +1 -0
- package/dist/cli/ink-cli/components/chat/Header.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/Header.js +6 -3
- package/dist/cli/ink-cli/components/chat/MessageItem.d.ts +3 -0
- package/dist/cli/ink-cli/components/chat/MessageItem.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/MessageItem.js +95 -9
- package/dist/cli/ink-cli/components/chat/MessageList.js +1 -1
- package/dist/cli/ink-cli/components/chat/QueuedMessagesDisplay.d.ts +16 -0
- package/dist/cli/ink-cli/components/chat/QueuedMessagesDisplay.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/chat/QueuedMessagesDisplay.js +27 -0
- package/dist/cli/ink-cli/components/chat/ToolIcon.d.ts +5 -3
- package/dist/cli/ink-cli/components/chat/ToolIcon.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/ToolIcon.js +21 -7
- package/dist/cli/ink-cli/components/chat/styled-boxes/ConfigBox.d.ts +10 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/ConfigBox.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/ConfigBox.js +6 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/HelpBox.d.ts +10 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/HelpBox.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/HelpBox.js +15 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.d.ts +10 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.js +9 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/SessionHistoryBox.d.ts +10 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/SessionHistoryBox.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/SessionHistoryBox.js +37 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/SessionListBox.d.ts +10 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/SessionListBox.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/SessionListBox.js +9 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/ShortcutsBox.d.ts +10 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/ShortcutsBox.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/ShortcutsBox.js +6 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/StatsBox.d.ts +10 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/StatsBox.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/StatsBox.js +29 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/StyledBox.d.ts +45 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/StyledBox.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/StyledBox.js +38 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/SyspromptBox.d.ts +10 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/SyspromptBox.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/SyspromptBox.js +6 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/index.d.ts +13 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/index.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/chat/styled-boxes/index.js +12 -0
- package/dist/cli/ink-cli/components/input/InputArea.d.ts +36 -8
- package/dist/cli/ink-cli/components/input/InputArea.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/input/InputArea.js +3 -3
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.d.ts +25 -0
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.js +166 -0
- package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts +27 -0
- package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/modes/StaticCLI.js +95 -0
- package/dist/cli/ink-cli/components/modes/index.d.ts +10 -0
- package/dist/cli/ink-cli/components/modes/index.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/modes/index.js +9 -0
- package/dist/cli/ink-cli/components/overlays/ApiKeyInput.d.ts +26 -0
- package/dist/cli/ink-cli/components/overlays/ApiKeyInput.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/ApiKeyInput.js +92 -0
- package/dist/cli/ink-cli/components/overlays/CustomModelWizard.d.ts +29 -0
- package/dist/cli/ink-cli/components/overlays/CustomModelWizard.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/CustomModelWizard.js +286 -0
- package/dist/cli/ink-cli/components/overlays/LogLevelSelector.d.ts +22 -0
- package/dist/cli/ink-cli/components/overlays/LogLevelSelector.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/LogLevelSelector.js +59 -0
- package/dist/cli/ink-cli/components/overlays/McpAddChoice.d.ts +22 -0
- package/dist/cli/ink-cli/components/overlays/McpAddChoice.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/McpAddChoice.js +59 -0
- package/dist/cli/ink-cli/components/overlays/McpAddSelector.d.ts +26 -0
- package/dist/cli/ink-cli/components/overlays/McpAddSelector.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/McpAddSelector.js +73 -0
- package/dist/cli/ink-cli/components/overlays/McpCustomTypeSelector.d.ts +21 -0
- package/dist/cli/ink-cli/components/overlays/McpCustomTypeSelector.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/McpCustomTypeSelector.js +51 -0
- package/dist/cli/ink-cli/components/overlays/McpCustomWizard.d.ts +29 -0
- package/dist/cli/ink-cli/components/overlays/McpCustomWizard.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/McpCustomWizard.js +215 -0
- package/dist/cli/ink-cli/components/overlays/McpRemoveSelector.d.ts +22 -0
- package/dist/cli/ink-cli/components/overlays/McpRemoveSelector.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/McpRemoveSelector.js +74 -0
- package/dist/cli/ink-cli/components/overlays/McpSelector.d.ts +21 -0
- package/dist/cli/ink-cli/components/overlays/McpSelector.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/McpSelector.js +52 -0
- package/dist/cli/ink-cli/components/overlays/McpServerActions.d.ts +28 -0
- package/dist/cli/ink-cli/components/overlays/McpServerActions.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/McpServerActions.js +84 -0
- package/dist/cli/ink-cli/components/overlays/McpServerList.d.ts +29 -0
- package/dist/cli/ink-cli/components/overlays/McpServerList.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/McpServerList.js +109 -0
- package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.d.ts +15 -8
- package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.js +400 -23
- package/dist/cli/ink-cli/components/overlays/PromptAddChoice.d.ts +22 -0
- package/dist/cli/ink-cli/components/overlays/PromptAddChoice.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/PromptAddChoice.js +52 -0
- package/dist/cli/ink-cli/components/overlays/PromptAddWizard.d.ts +29 -0
- package/dist/cli/ink-cli/components/overlays/PromptAddWizard.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/PromptAddWizard.js +166 -0
- package/dist/cli/ink-cli/components/overlays/PromptDeleteSelector.d.ts +27 -0
- package/dist/cli/ink-cli/components/overlays/PromptDeleteSelector.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/PromptDeleteSelector.js +119 -0
- package/dist/cli/ink-cli/components/overlays/PromptList.d.ts +33 -0
- package/dist/cli/ink-cli/components/overlays/PromptList.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/PromptList.js +144 -0
- package/dist/cli/ink-cli/components/overlays/SearchOverlay.d.ts +23 -0
- package/dist/cli/ink-cli/components/overlays/SearchOverlay.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/SearchOverlay.js +189 -0
- package/dist/cli/ink-cli/components/overlays/SessionSelectorRefactored.d.ts +7 -2
- package/dist/cli/ink-cli/components/overlays/SessionSelectorRefactored.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/SessionSelectorRefactored.js +19 -5
- package/dist/cli/ink-cli/components/overlays/SessionSubcommandSelector.d.ts +21 -0
- package/dist/cli/ink-cli/components/overlays/SessionSubcommandSelector.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/SessionSubcommandSelector.js +42 -0
- package/dist/cli/ink-cli/components/overlays/StreamSelector.d.ts +20 -0
- package/dist/cli/ink-cli/components/overlays/StreamSelector.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/StreamSelector.js +58 -0
- package/dist/cli/ink-cli/components/overlays/ToolBrowser.d.ts +25 -0
- package/dist/cli/ink-cli/components/overlays/ToolBrowser.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/ToolBrowser.js +400 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.d.ts +25 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.js +609 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/index.d.ts +15 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/index.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/index.js +14 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.d.ts +33 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.js +419 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/ApiKeyStep.d.ts +25 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/ApiKeyStep.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/ApiKeyStep.js +29 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/ProviderSelector.d.ts +17 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/ProviderSelector.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/ProviderSelector.js +11 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/SetupInfoBanner.d.ts +20 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/SetupInfoBanner.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/SetupInfoBanner.js +10 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/WizardStepInput.d.ts +30 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/WizardStepInput.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/WizardStepInput.js +13 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/index.d.ts +8 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/index.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/index.js +7 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/types.d.ts +79 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/types.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/types.js +38 -0
- package/dist/cli/ink-cli/components/renderers/DiffRenderer.d.ts +21 -0
- package/dist/cli/ink-cli/components/renderers/DiffRenderer.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/renderers/DiffRenderer.js +65 -0
- package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.d.ts +28 -0
- package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.js +66 -0
- package/dist/cli/ink-cli/components/renderers/FileRenderer.d.ts +19 -0
- package/dist/cli/ink-cli/components/renderers/FileRenderer.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/renderers/FileRenderer.js +26 -0
- package/dist/cli/ink-cli/components/renderers/GenericRenderer.d.ts +21 -0
- package/dist/cli/ink-cli/components/renderers/GenericRenderer.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/renderers/GenericRenderer.js +26 -0
- package/dist/cli/ink-cli/components/renderers/SearchRenderer.d.ts +20 -0
- package/dist/cli/ink-cli/components/renderers/SearchRenderer.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/renderers/SearchRenderer.js +12 -0
- package/dist/cli/ink-cli/components/renderers/ShellRenderer.d.ts +21 -0
- package/dist/cli/ink-cli/components/renderers/ShellRenderer.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/renderers/ShellRenderer.js +25 -0
- package/dist/cli/ink-cli/components/renderers/diff-shared.d.ts +61 -0
- package/dist/cli/ink-cli/components/renderers/diff-shared.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/renderers/diff-shared.js +158 -0
- package/dist/cli/ink-cli/components/renderers/index.d.ts +28 -0
- package/dist/cli/ink-cli/components/renderers/index.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/renderers/index.js +36 -0
- package/dist/cli/ink-cli/components/shared/MarkdownText.d.ts +38 -0
- package/dist/cli/ink-cli/components/shared/MarkdownText.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/shared/MarkdownText.js +362 -0
- package/dist/cli/ink-cli/components/shared/VirtualizedList.d.ts +44 -0
- package/dist/cli/ink-cli/components/shared/VirtualizedList.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/shared/VirtualizedList.js +300 -0
- package/dist/cli/ink-cli/components/shared/text-buffer.d.ts +185 -0
- package/dist/cli/ink-cli/components/shared/text-buffer.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/shared/text-buffer.js +1338 -0
- package/dist/cli/ink-cli/constants/processingPhrases.d.ts +10 -0
- package/dist/cli/ink-cli/constants/processingPhrases.d.ts.map +1 -0
- package/dist/cli/ink-cli/constants/processingPhrases.js +64 -0
- package/dist/cli/ink-cli/constants/tips.d.ts +15 -0
- package/dist/cli/ink-cli/constants/tips.d.ts.map +1 -0
- package/dist/cli/ink-cli/constants/tips.js +53 -0
- package/dist/cli/ink-cli/containers/InputContainer.d.ts +42 -8
- package/dist/cli/ink-cli/containers/InputContainer.d.ts.map +1 -1
- package/dist/cli/ink-cli/containers/InputContainer.js +513 -85
- package/dist/cli/ink-cli/containers/OverlayContainer.d.ts +23 -5
- package/dist/cli/ink-cli/containers/OverlayContainer.d.ts.map +1 -1
- package/dist/cli/ink-cli/containers/OverlayContainer.js +1214 -132
- package/dist/cli/ink-cli/containers/index.d.ts +1 -1
- package/dist/cli/ink-cli/containers/index.d.ts.map +1 -1
- package/dist/cli/ink-cli/contexts/KeypressContext.d.ts +36 -0
- package/dist/cli/ink-cli/contexts/KeypressContext.d.ts.map +1 -0
- package/dist/cli/ink-cli/contexts/KeypressContext.js +461 -0
- package/dist/cli/ink-cli/contexts/MouseContext.d.ts +27 -0
- package/dist/cli/ink-cli/contexts/MouseContext.d.ts.map +1 -0
- package/dist/cli/ink-cli/contexts/MouseContext.js +102 -0
- package/dist/cli/ink-cli/contexts/ScrollProvider.d.ts +33 -0
- package/dist/cli/ink-cli/contexts/ScrollProvider.d.ts.map +1 -0
- package/dist/cli/ink-cli/contexts/ScrollProvider.js +170 -0
- package/dist/cli/ink-cli/contexts/index.d.ts +7 -0
- package/dist/cli/ink-cli/contexts/index.d.ts.map +1 -0
- package/dist/cli/ink-cli/contexts/index.js +6 -0
- package/dist/cli/ink-cli/hooks/index.d.ts +5 -0
- package/dist/cli/ink-cli/hooks/index.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/index.js +6 -1
- package/dist/cli/ink-cli/hooks/useAgentEvents.d.ts +26 -9
- package/dist/cli/ink-cli/hooks/useAgentEvents.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useAgentEvents.js +90 -198
- package/dist/cli/ink-cli/hooks/useBatchedScroll.d.ts +14 -0
- package/dist/cli/ink-cli/hooks/useBatchedScroll.d.ts.map +1 -0
- package/dist/cli/ink-cli/hooks/useBatchedScroll.js +25 -0
- package/dist/cli/ink-cli/hooks/useCLIState.d.ts +50 -0
- package/dist/cli/ink-cli/hooks/useCLIState.d.ts.map +1 -0
- package/dist/cli/ink-cli/hooks/useCLIState.js +190 -0
- package/dist/cli/ink-cli/hooks/useElapsedTime.d.ts +24 -0
- package/dist/cli/ink-cli/hooks/useElapsedTime.d.ts.map +1 -0
- package/dist/cli/ink-cli/hooks/useElapsedTime.js +69 -0
- package/dist/cli/ink-cli/hooks/useHistorySearch.d.ts +61 -0
- package/dist/cli/ink-cli/hooks/useHistorySearch.d.ts.map +1 -0
- package/dist/cli/ink-cli/hooks/useHistorySearch.js +210 -0
- package/dist/cli/ink-cli/hooks/useInputOrchestrator.d.ts +136 -0
- package/dist/cli/ink-cli/hooks/useInputOrchestrator.d.ts.map +1 -0
- package/dist/cli/ink-cli/hooks/useInputOrchestrator.js +663 -0
- package/dist/cli/ink-cli/hooks/useKeyboardShortcuts.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useKeyboardShortcuts.js +7 -26
- package/dist/cli/ink-cli/hooks/useKeypress.d.ts +18 -0
- package/dist/cli/ink-cli/hooks/useKeypress.d.ts.map +1 -0
- package/dist/cli/ink-cli/hooks/useKeypress.js +26 -0
- package/dist/cli/ink-cli/hooks/usePhraseCycler.d.ts +30 -0
- package/dist/cli/ink-cli/hooks/usePhraseCycler.d.ts.map +1 -0
- package/dist/cli/ink-cli/hooks/usePhraseCycler.js +68 -0
- package/dist/cli/ink-cli/hooks/useStreaming.d.ts +19 -0
- package/dist/cli/ink-cli/hooks/useStreaming.d.ts.map +1 -0
- package/dist/cli/ink-cli/hooks/useStreaming.js +26 -0
- package/dist/cli/ink-cli/hooks/useTerminalSize.d.ts +14 -0
- package/dist/cli/ink-cli/hooks/useTerminalSize.d.ts.map +1 -0
- package/dist/cli/ink-cli/hooks/useTerminalSize.js +31 -0
- package/dist/cli/ink-cli/hooks/useTokenCounter.d.ts +42 -0
- package/dist/cli/ink-cli/hooks/useTokenCounter.d.ts.map +1 -0
- package/dist/cli/ink-cli/hooks/useTokenCounter.js +96 -0
- package/dist/cli/ink-cli/services/CommandService.d.ts +32 -1
- package/dist/cli/ink-cli/services/CommandService.d.ts.map +1 -1
- package/dist/cli/ink-cli/services/CommandService.js +36 -5
- package/dist/cli/ink-cli/services/InputService.d.ts +1 -5
- package/dist/cli/ink-cli/services/InputService.d.ts.map +1 -1
- package/dist/cli/ink-cli/services/InputService.js +1 -8
- package/dist/cli/ink-cli/services/index.d.ts +2 -1
- package/dist/cli/ink-cli/services/index.d.ts.map +1 -1
- package/dist/cli/ink-cli/services/index.js +2 -1
- package/dist/cli/ink-cli/services/processStream.d.ts +69 -0
- package/dist/cli/ink-cli/services/processStream.d.ts.map +1 -0
- package/dist/cli/ink-cli/services/processStream.js +742 -0
- package/dist/cli/ink-cli/state/actions.d.ts +30 -60
- package/dist/cli/ink-cli/state/actions.d.ts.map +1 -1
- package/dist/cli/ink-cli/state/actions.js +3 -0
- package/dist/cli/ink-cli/state/index.d.ts +5 -3
- package/dist/cli/ink-cli/state/index.d.ts.map +1 -1
- package/dist/cli/ink-cli/state/index.js +4 -3
- package/dist/cli/ink-cli/state/initialState.d.ts +4 -3
- package/dist/cli/ink-cli/state/initialState.d.ts.map +1 -1
- package/dist/cli/ink-cli/state/initialState.js +20 -4
- package/dist/cli/ink-cli/state/reducer.d.ts +3 -0
- package/dist/cli/ink-cli/state/reducer.d.ts.map +1 -1
- package/dist/cli/ink-cli/state/reducer.js +62 -168
- package/dist/cli/ink-cli/state/streaming-state.d.ts +27 -0
- package/dist/cli/ink-cli/state/streaming-state.d.ts.map +1 -0
- package/dist/cli/ink-cli/state/streaming-state.js +39 -0
- package/dist/cli/ink-cli/state/types.d.ts +223 -6
- package/dist/cli/ink-cli/state/types.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/bracketedPaste.d.ts +22 -0
- package/dist/cli/ink-cli/utils/bracketedPaste.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/bracketedPaste.js +27 -0
- package/dist/cli/ink-cli/utils/clipboardUtils.d.ts +49 -0
- package/dist/cli/ink-cli/utils/clipboardUtils.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/clipboardUtils.js +356 -0
- package/dist/cli/ink-cli/utils/commandOverlays.d.ts +33 -0
- package/dist/cli/ink-cli/utils/commandOverlays.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/commandOverlays.js +78 -0
- package/dist/cli/ink-cli/utils/debugLog.d.ts +38 -0
- package/dist/cli/ink-cli/utils/debugLog.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/debugLog.js +66 -0
- package/dist/cli/ink-cli/utils/index.d.ts +2 -1
- package/dist/cli/ink-cli/utils/index.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/index.js +3 -1
- package/dist/cli/ink-cli/utils/input.d.ts +25 -0
- package/dist/cli/ink-cli/utils/input.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/input.js +56 -0
- package/dist/cli/ink-cli/utils/inputParsing.d.ts +0 -9
- package/dist/cli/ink-cli/utils/inputParsing.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/inputParsing.js +0 -27
- package/dist/cli/ink-cli/utils/messageFormatting.d.ts +59 -3
- package/dist/cli/ink-cli/utils/messageFormatting.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/messageFormatting.js +348 -20
- package/dist/cli/ink-cli/utils/mouse.d.ts +61 -0
- package/dist/cli/ink-cli/utils/mouse.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/mouse.js +209 -0
- package/dist/cli/ink-cli/utils/streamSplitter.d.ts +44 -0
- package/dist/cli/ink-cli/utils/streamSplitter.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/streamSplitter.js +154 -0
- package/dist/cli/ink-cli/utils/textUtils.d.ts +63 -0
- package/dist/cli/ink-cli/utils/textUtils.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/textUtils.js +248 -0
- package/dist/cli/ink-cli/utils/toolUtils.d.ts +9 -0
- package/dist/cli/ink-cli/utils/toolUtils.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/toolUtils.js +15 -0
- package/dist/cli/utils/api-key-setup.d.ts +54 -4
- package/dist/cli/utils/api-key-setup.d.ts.map +1 -1
- package/dist/cli/utils/api-key-setup.js +433 -107
- package/dist/cli/utils/api-key-verification.d.ts +17 -0
- package/dist/cli/utils/api-key-verification.d.ts.map +1 -0
- package/dist/cli/utils/api-key-verification.js +211 -0
- package/dist/cli/utils/config-validation.d.ts +22 -2
- package/dist/cli/utils/config-validation.d.ts.map +1 -1
- package/dist/cli/utils/config-validation.js +354 -25
- package/dist/cli/utils/local-model-setup.d.ts +46 -0
- package/dist/cli/utils/local-model-setup.d.ts.map +1 -0
- package/dist/cli/utils/local-model-setup.js +662 -0
- package/dist/cli/utils/options.d.ts.map +1 -1
- package/dist/cli/utils/options.js +1 -3
- package/dist/cli/utils/prompt-helpers.d.ts +47 -0
- package/dist/cli/utils/prompt-helpers.d.ts.map +1 -0
- package/dist/cli/utils/prompt-helpers.js +66 -0
- package/dist/cli/utils/provider-setup.d.ts +66 -8
- package/dist/cli/utils/provider-setup.d.ts.map +1 -1
- package/dist/cli/utils/provider-setup.js +324 -84
- package/dist/cli/utils/scaffolding-utils.d.ts +76 -0
- package/dist/cli/utils/scaffolding-utils.d.ts.map +1 -0
- package/dist/cli/utils/scaffolding-utils.js +246 -0
- package/dist/cli/utils/setup-utils.d.ts +16 -0
- package/dist/cli/utils/setup-utils.d.ts.map +1 -1
- package/dist/cli/utils/setup-utils.js +72 -21
- package/dist/cli/utils/template-engine.d.ts +65 -0
- package/dist/cli/utils/template-engine.d.ts.map +1 -0
- package/dist/cli/utils/template-engine.js +1089 -0
- package/dist/config/cli-overrides.d.ts +45 -2
- package/dist/config/cli-overrides.d.ts.map +1 -1
- package/dist/config/cli-overrides.js +107 -10
- package/dist/index.js +379 -99
- package/dist/utils/agent-helpers.d.ts +95 -0
- package/dist/utils/agent-helpers.d.ts.map +1 -0
- package/dist/utils/agent-helpers.js +117 -0
- package/dist/webui/assets/index-8j-KMkX1.js +2054 -0
- package/dist/webui/assets/index-c_AX24V4.css +1 -0
- package/dist/webui/assets/{tanstack-DgxBONJY.js → tanstack-Br79RQ-n.js} +1 -1
- package/dist/webui/index.html +4 -10
- package/dist/webui/logos/aws-color.svg +1 -0
- package/dist/webui/logos/dexto/dexto_logo.svg +1 -1
- package/dist/webui/logos/dexto/dexto_logo_light.svg +6 -6
- package/dist/webui/logos/glama.svg +7 -0
- package/dist/webui/logos/litellm.svg +7 -0
- package/dist/webui/logos/openrouter.svg +1 -0
- package/package.json +18 -15
- package/dist/cli/commands/interactive-commands/index.d.ts +0 -63
- package/dist/cli/commands/interactive-commands/index.d.ts.map +0 -1
- package/dist/cli/commands/interactive-commands/index.js +0 -73
- package/dist/cli/commands/interactive-commands/mcp/mcp-add-utils.d.ts +0 -34
- package/dist/cli/commands/interactive-commands/mcp/mcp-add-utils.d.ts.map +0 -1
- package/dist/cli/commands/interactive-commands/mcp/mcp-add-utils.js +0 -178
- package/dist/cli/commands/interactive-commands/mcp/mcp-commands.d.ts +0 -9
- package/dist/cli/commands/interactive-commands/mcp/mcp-commands.d.ts.map +0 -1
- package/dist/cli/commands/interactive-commands/mcp/mcp-commands.js +0 -325
- package/dist/cli/commands/interactive-commands/model/model-commands.d.ts +0 -21
- package/dist/cli/commands/interactive-commands/model/model-commands.d.ts.map +0 -1
- package/dist/cli/commands/interactive-commands/model/model-commands.js +0 -190
- package/dist/cli/ink-cli/components/MultiLineTextInput.d.ts +0 -26
- package/dist/cli/ink-cli/components/MultiLineTextInput.d.ts.map +0 -1
- package/dist/cli/ink-cli/components/MultiLineTextInput.js +0 -220
- package/dist/discord/bot.d.ts +0 -4
- package/dist/discord/bot.d.ts.map +0 -1
- package/dist/discord/bot.js +0 -193
- package/dist/telegram/bot.d.ts +0 -5
- package/dist/telegram/bot.d.ts.map +0 -1
- package/dist/telegram/bot.js +0 -251
- package/dist/webui/assets/index-DKq5Xng1.js +0 -687
- package/dist/webui/assets/index-D_0_GBu5.css +0 -1
|
@@ -0,0 +1,742 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process Stream Service
|
|
3
|
+
*
|
|
4
|
+
* Processes the async iterator from agent.stream() and updates UI state.
|
|
5
|
+
* This replaces the event bus subscriptions for streaming events,
|
|
6
|
+
* providing direct, synchronous control over the streaming lifecycle.
|
|
7
|
+
*
|
|
8
|
+
* Architecture:
|
|
9
|
+
* - Messages being streamed are tracked in `pendingMessages` (rendered dynamically)
|
|
10
|
+
* - Only finalized messages are added to `messages` (rendered in <Static>)
|
|
11
|
+
* - Progressive finalization: large streaming content is split at safe markdown
|
|
12
|
+
* boundaries, moving completed paragraphs to Static to reduce flickering
|
|
13
|
+
* - This prevents duplicate output in static terminal mode
|
|
14
|
+
*
|
|
15
|
+
* IMPORTANT: React batching fix (see commit history for race condition details)
|
|
16
|
+
* - We use a local `localPending` array that mirrors React state synchronously
|
|
17
|
+
* - This allows us to flatten nested setState calls (which caused ordering bugs)
|
|
18
|
+
* - Nested setState: inner setMessages inside setPendingMessages callback gets
|
|
19
|
+
* queued and runs AFTER other setMessages calls in the same batch
|
|
20
|
+
* - Flattened: setMessages and setPendingMessages are sibling calls, processed in order
|
|
21
|
+
*/
|
|
22
|
+
import { createDebugLogger } from '../utils/debugLog.js';
|
|
23
|
+
import { ApprovalType as ApprovalTypeEnum, ApprovalStatus } from '@dexto/core';
|
|
24
|
+
import { generateMessageId } from '../utils/idGenerator.js';
|
|
25
|
+
import { checkForSplit } from '../utils/streamSplitter.js';
|
|
26
|
+
import { getToolDisplayName, formatToolArgsForDisplay, getToolTypeBadge, } from '../utils/messageFormatting.js';
|
|
27
|
+
import { isEditWriteTool } from '../utils/toolUtils.js';
|
|
28
|
+
import { capture } from '../../../analytics/index.js';
|
|
29
|
+
import chalk from 'chalk';
|
|
30
|
+
/**
|
|
31
|
+
* Build error message with recovery guidance if available
|
|
32
|
+
*/
|
|
33
|
+
function buildErrorContent(error, prefix) {
|
|
34
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
35
|
+
let errorContent = `${prefix}${errorMessage}`;
|
|
36
|
+
// Add recovery guidance if available (for DextoRuntimeError)
|
|
37
|
+
if (error instanceof Error && 'recovery' in error && error.recovery) {
|
|
38
|
+
const recoveryMessages = Array.isArray(error.recovery) ? error.recovery : [error.recovery];
|
|
39
|
+
errorContent += '\n\n' + recoveryMessages.map((msg) => `💡 ${msg}`).join('\n');
|
|
40
|
+
}
|
|
41
|
+
return errorContent;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Processes the async iterator from agent.stream() and updates UI state.
|
|
45
|
+
*
|
|
46
|
+
* For static mode compatibility:
|
|
47
|
+
* - Streaming content goes to `pendingMessages` (rendered dynamically)
|
|
48
|
+
* - Finalized content is moved to `messages` (rendered in <Static>)
|
|
49
|
+
*
|
|
50
|
+
* @param iterator - The async iterator from agent.stream()
|
|
51
|
+
* @param setters - State setters for updating UI
|
|
52
|
+
* @param options - Configuration options
|
|
53
|
+
*/
|
|
54
|
+
export async function processStream(iterator, setters, options) {
|
|
55
|
+
const { setMessages, setPendingMessages, setDequeuedBuffer, setUi, setQueuedMessages, setApproval, setApprovalQueue, } = setters;
|
|
56
|
+
const useStreaming = options?.useStreaming ?? true;
|
|
57
|
+
// Track streaming state (synchronous, not React state)
|
|
58
|
+
const state = {
|
|
59
|
+
messageId: null,
|
|
60
|
+
content: '',
|
|
61
|
+
outputTokens: 0,
|
|
62
|
+
finalizedContent: '',
|
|
63
|
+
splitCounter: 0,
|
|
64
|
+
textFinalizedBeforeTool: false,
|
|
65
|
+
nonStreamingAccumulatedText: '',
|
|
66
|
+
};
|
|
67
|
+
// LOCAL PENDING TRACKING - mirrors React state synchronously
|
|
68
|
+
// This allows us to flatten nested setState calls (which caused ordering bugs).
|
|
69
|
+
// See: https://github.com/facebook/react/issues/8132 - nested setState not supported
|
|
70
|
+
let localPending = [];
|
|
71
|
+
/**
|
|
72
|
+
* Extract text content from ContentPart array
|
|
73
|
+
*/
|
|
74
|
+
const extractTextContent = (content) => {
|
|
75
|
+
return content
|
|
76
|
+
.filter((part) => part.type === 'text')
|
|
77
|
+
.map((part) => part.text)
|
|
78
|
+
.join('\n');
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Move a message from pending to finalized.
|
|
82
|
+
* FLATTENED: Uses localPending to avoid nested setState (which breaks ordering).
|
|
83
|
+
*/
|
|
84
|
+
const finalizeMessage = (messageId, updates = {}) => {
|
|
85
|
+
const msg = localPending.find((m) => m.id === messageId);
|
|
86
|
+
if (msg) {
|
|
87
|
+
// Add to messages FIRST (sibling call, not nested)
|
|
88
|
+
setMessages((prev) => [...prev, { ...msg, ...updates }]);
|
|
89
|
+
}
|
|
90
|
+
// Update local tracking
|
|
91
|
+
localPending = localPending.filter((m) => m.id !== messageId);
|
|
92
|
+
// Then update React state (sibling call)
|
|
93
|
+
setPendingMessages(localPending);
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Move all pending messages to finalized (used at run:complete and message:dequeued).
|
|
97
|
+
* FLATTENED: Uses localPending to avoid nested setState.
|
|
98
|
+
*/
|
|
99
|
+
const finalizeAllPending = () => {
|
|
100
|
+
if (localPending.length > 0) {
|
|
101
|
+
// Add to messages FIRST (sibling call, not nested)
|
|
102
|
+
const toFinalize = [...localPending];
|
|
103
|
+
setMessages((prev) => [...prev, ...toFinalize]);
|
|
104
|
+
}
|
|
105
|
+
// Update local tracking
|
|
106
|
+
localPending = [];
|
|
107
|
+
// Then update React state (sibling call)
|
|
108
|
+
setPendingMessages([]);
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Move dequeued buffer to messages (called at start of new run)
|
|
112
|
+
* This ensures user messages appear in correct order after previous response
|
|
113
|
+
* NOTE: This still uses nested setState but dequeuedBuffer is separate from
|
|
114
|
+
* the main message flow and only flushed at llm:thinking (start of run)
|
|
115
|
+
*/
|
|
116
|
+
const flushDequeuedBuffer = () => {
|
|
117
|
+
setDequeuedBuffer((buffer) => {
|
|
118
|
+
if (buffer.length > 0) {
|
|
119
|
+
setMessages((prev) => [...prev, ...buffer]);
|
|
120
|
+
}
|
|
121
|
+
return [];
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Add message to pending (updates both local tracking and React state)
|
|
126
|
+
*/
|
|
127
|
+
const addToPending = (msg) => {
|
|
128
|
+
localPending = [...localPending, msg];
|
|
129
|
+
setPendingMessages(localPending);
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Update a message in pending (updates both local tracking and React state)
|
|
133
|
+
*/
|
|
134
|
+
const updatePending = (messageId, updates) => {
|
|
135
|
+
localPending = localPending.map((m) => (m.id === messageId ? { ...m, ...updates } : m));
|
|
136
|
+
setPendingMessages(localPending);
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* Remove a message from pending without finalizing (updates both local and React state)
|
|
140
|
+
*/
|
|
141
|
+
const removeFromPending = (messageId) => {
|
|
142
|
+
localPending = localPending.filter((m) => m.id !== messageId);
|
|
143
|
+
setPendingMessages(localPending);
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Clear all pending (updates both local tracking and React state)
|
|
147
|
+
*/
|
|
148
|
+
const clearPending = () => {
|
|
149
|
+
localPending = [];
|
|
150
|
+
setPendingMessages([]);
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Update toolStatus for a pending message by ID
|
|
154
|
+
* Used for tool status transitions: pending → pending_approval → running → finished
|
|
155
|
+
*/
|
|
156
|
+
const updatePendingStatus = (messageId, status) => {
|
|
157
|
+
localPending = localPending.map((msg) => msg.id === messageId ? { ...msg, toolStatus: status } : msg);
|
|
158
|
+
setPendingMessages(localPending);
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* Progressive finalization: split large streaming content at safe markdown
|
|
162
|
+
* boundaries and move completed portions to Static to reduce flickering.
|
|
163
|
+
*
|
|
164
|
+
* Safe to use with message queueing because dequeued user messages are
|
|
165
|
+
* rendered in a separate buffer AFTER pendingMessages, guaranteeing
|
|
166
|
+
* correct visual order regardless of React batching timing.
|
|
167
|
+
*
|
|
168
|
+
* RACE CONDITION FIX: We clear the pending message content BEFORE adding
|
|
169
|
+
* the split, then restore with afterContent. This ensures any intermediate
|
|
170
|
+
* render sees empty pending (not stale full content), avoiding duplication.
|
|
171
|
+
*/
|
|
172
|
+
const progressiveFinalize = (content) => {
|
|
173
|
+
const splitResult = checkForSplit(content);
|
|
174
|
+
if (splitResult.shouldSplit && splitResult.before && splitResult.after !== undefined) {
|
|
175
|
+
// Add the completed portion directly to finalized messages
|
|
176
|
+
state.splitCounter++;
|
|
177
|
+
const splitId = `${state.messageId}-split-${state.splitCounter}`;
|
|
178
|
+
const beforeContent = splitResult.before;
|
|
179
|
+
const afterContent = splitResult.after;
|
|
180
|
+
const isFirstSplit = state.splitCounter === 1;
|
|
181
|
+
// STEP 1: Clear pending message content to avoid showing stale content
|
|
182
|
+
// during React's batched render cycle
|
|
183
|
+
if (state.messageId) {
|
|
184
|
+
localPending = localPending.map((m) => m.id === state.messageId ? { ...m, content: '', isContinuation: true } : m);
|
|
185
|
+
setPendingMessages(localPending);
|
|
186
|
+
}
|
|
187
|
+
// STEP 2: Add split message to finalized
|
|
188
|
+
setMessages((prev) => [
|
|
189
|
+
...prev,
|
|
190
|
+
{
|
|
191
|
+
id: splitId,
|
|
192
|
+
role: 'assistant',
|
|
193
|
+
content: beforeContent,
|
|
194
|
+
timestamp: new Date(),
|
|
195
|
+
isStreaming: false,
|
|
196
|
+
// First split shows the indicator, subsequent splits are continuations
|
|
197
|
+
isContinuation: !isFirstSplit,
|
|
198
|
+
},
|
|
199
|
+
]);
|
|
200
|
+
// STEP 3: Restore pending with afterContent
|
|
201
|
+
if (state.messageId) {
|
|
202
|
+
localPending = localPending.map((m) => m.id === state.messageId ? { ...m, content: afterContent } : m);
|
|
203
|
+
setPendingMessages(localPending);
|
|
204
|
+
}
|
|
205
|
+
// Track total finalized content for final message assembly
|
|
206
|
+
state.finalizedContent += beforeContent;
|
|
207
|
+
// Return only the remaining content for pending
|
|
208
|
+
return afterContent;
|
|
209
|
+
}
|
|
210
|
+
return content;
|
|
211
|
+
};
|
|
212
|
+
// Debug logging: enable via DEXTO_DEBUG_STREAM=true
|
|
213
|
+
const debug = createDebugLogger('stream');
|
|
214
|
+
debug.reset();
|
|
215
|
+
debug.log('CONFIG', { useStreaming });
|
|
216
|
+
try {
|
|
217
|
+
for await (const event of iterator) {
|
|
218
|
+
debug.log(`EVENT: ${event.name}`, {
|
|
219
|
+
...(event.name === 'llm:chunk' &&
|
|
220
|
+
'chunkType' in event && {
|
|
221
|
+
chunkType: event.chunkType,
|
|
222
|
+
contentLen: event.content?.length,
|
|
223
|
+
}),
|
|
224
|
+
...(event.name === 'llm:tool-call' &&
|
|
225
|
+
'toolName' in event && {
|
|
226
|
+
toolName: event.toolName,
|
|
227
|
+
}),
|
|
228
|
+
});
|
|
229
|
+
switch (event.name) {
|
|
230
|
+
case 'llm:thinking': {
|
|
231
|
+
debug.log('THINKING: resetting state', {
|
|
232
|
+
prevMessageId: state.messageId,
|
|
233
|
+
prevContentLen: state.content.length,
|
|
234
|
+
});
|
|
235
|
+
// Flush dequeued buffer to messages at start of new run
|
|
236
|
+
// This ensures user messages appear after the previous response
|
|
237
|
+
flushDequeuedBuffer();
|
|
238
|
+
// Start thinking state, reset streaming state
|
|
239
|
+
setUi((prev) => ({ ...prev, isThinking: true }));
|
|
240
|
+
state.messageId = null;
|
|
241
|
+
state.content = '';
|
|
242
|
+
state.outputTokens = 0;
|
|
243
|
+
state.finalizedContent = '';
|
|
244
|
+
state.splitCounter = 0;
|
|
245
|
+
state.textFinalizedBeforeTool = false;
|
|
246
|
+
state.nonStreamingAccumulatedText = '';
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
case 'llm:chunk': {
|
|
250
|
+
// In non-streaming mode, accumulate text but don't update UI
|
|
251
|
+
// We need to track text so we can add it BEFORE tool calls (ordering fix)
|
|
252
|
+
if (!useStreaming) {
|
|
253
|
+
if (event.chunkType === 'text') {
|
|
254
|
+
state.nonStreamingAccumulatedText += event.content;
|
|
255
|
+
debug.log('CHUNK (non-stream): accumulated', {
|
|
256
|
+
chunkLen: event.content?.length,
|
|
257
|
+
totalLen: state.nonStreamingAccumulatedText.length,
|
|
258
|
+
preview: state.nonStreamingAccumulatedText.slice(0, 50),
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
// End thinking state when first chunk arrives
|
|
264
|
+
setUi((prev) => ({ ...prev, isThinking: false }));
|
|
265
|
+
if (event.chunkType === 'text') {
|
|
266
|
+
debug.log('CHUNK (stream): text', {
|
|
267
|
+
hasMessageId: !!state.messageId,
|
|
268
|
+
chunkLen: event.content?.length,
|
|
269
|
+
currentContentLen: state.content.length,
|
|
270
|
+
preview: event.content?.slice(0, 30),
|
|
271
|
+
});
|
|
272
|
+
// Create streaming message on first text chunk
|
|
273
|
+
if (!state.messageId) {
|
|
274
|
+
const newId = generateMessageId('assistant');
|
|
275
|
+
state.messageId = newId;
|
|
276
|
+
state.content = event.content;
|
|
277
|
+
state.finalizedContent = '';
|
|
278
|
+
state.splitCounter = 0;
|
|
279
|
+
// Add to PENDING (not messages) - renders dynamically
|
|
280
|
+
addToPending({
|
|
281
|
+
id: newId,
|
|
282
|
+
role: 'assistant',
|
|
283
|
+
content: event.content,
|
|
284
|
+
timestamp: new Date(),
|
|
285
|
+
isStreaming: true,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
// Accumulate content
|
|
290
|
+
state.content += event.content;
|
|
291
|
+
// Check for progressive finalization (move completed paragraphs to Static)
|
|
292
|
+
// progressiveFinalize updates pending message internally when split occurs
|
|
293
|
+
const pendingContent = progressiveFinalize(state.content);
|
|
294
|
+
const splitOccurred = pendingContent !== state.content;
|
|
295
|
+
// Update state with remaining content
|
|
296
|
+
state.content = pendingContent;
|
|
297
|
+
// Only update pending if no split occurred (split already handled by progressiveFinalize)
|
|
298
|
+
if (!splitOccurred) {
|
|
299
|
+
const messageId = state.messageId;
|
|
300
|
+
// Mark as continuation if we've had any splits
|
|
301
|
+
const isContinuation = state.splitCounter > 0;
|
|
302
|
+
updatePending(messageId, {
|
|
303
|
+
content: pendingContent,
|
|
304
|
+
isContinuation,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
case 'llm:response': {
|
|
312
|
+
// In non-streaming mode, end thinking state when response arrives
|
|
313
|
+
// (In streaming mode, thinking ends when first chunk arrives)
|
|
314
|
+
if (!useStreaming) {
|
|
315
|
+
setUi((prev) => ({ ...prev, isThinking: false }));
|
|
316
|
+
}
|
|
317
|
+
// Accumulate token usage
|
|
318
|
+
if (event.tokenUsage?.outputTokens) {
|
|
319
|
+
state.outputTokens += event.tokenUsage.outputTokens;
|
|
320
|
+
}
|
|
321
|
+
// Track token usage analytics
|
|
322
|
+
if (event.tokenUsage &&
|
|
323
|
+
(event.tokenUsage.inputTokens || event.tokenUsage.outputTokens)) {
|
|
324
|
+
capture('dexto_llm_tokens_consumed', {
|
|
325
|
+
source: 'cli',
|
|
326
|
+
sessionId: event.sessionId,
|
|
327
|
+
provider: event.provider,
|
|
328
|
+
model: event.model,
|
|
329
|
+
inputTokens: event.tokenUsage.inputTokens,
|
|
330
|
+
outputTokens: event.tokenUsage.outputTokens,
|
|
331
|
+
reasoningTokens: event.tokenUsage.reasoningTokens,
|
|
332
|
+
totalTokens: event.tokenUsage.totalTokens,
|
|
333
|
+
cacheReadTokens: event.tokenUsage.cacheReadTokens,
|
|
334
|
+
cacheWriteTokens: event.tokenUsage.cacheWriteTokens,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
const finalContent = event.content || '';
|
|
338
|
+
if (state.messageId) {
|
|
339
|
+
// Finalize existing streaming message (streaming mode)
|
|
340
|
+
const messageId = state.messageId;
|
|
341
|
+
const content = state.content || finalContent;
|
|
342
|
+
// Move from pending to finalized
|
|
343
|
+
finalizeMessage(messageId, { content, isStreaming: false });
|
|
344
|
+
// Reset for potential next response (multi-step)
|
|
345
|
+
state.messageId = null;
|
|
346
|
+
state.content = '';
|
|
347
|
+
}
|
|
348
|
+
else if (finalContent && !state.textFinalizedBeforeTool) {
|
|
349
|
+
// No streaming message exists - add directly to finalized
|
|
350
|
+
// This handles: non-streaming mode, or multi-step turns after tool calls
|
|
351
|
+
// Skip if text was already finalized before tools (avoid duplication)
|
|
352
|
+
setMessages((prev) => [
|
|
353
|
+
...prev,
|
|
354
|
+
{
|
|
355
|
+
id: generateMessageId('assistant'),
|
|
356
|
+
role: 'assistant',
|
|
357
|
+
content: finalContent,
|
|
358
|
+
timestamp: new Date(),
|
|
359
|
+
isStreaming: false,
|
|
360
|
+
},
|
|
361
|
+
]);
|
|
362
|
+
}
|
|
363
|
+
// Reset the flag for this response (new text after tools will create new message)
|
|
364
|
+
state.textFinalizedBeforeTool = false;
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
case 'llm:tool-call': {
|
|
368
|
+
debug.log('TOOL-CALL: state check', {
|
|
369
|
+
toolName: event.toolName,
|
|
370
|
+
hasMessageId: !!state.messageId,
|
|
371
|
+
contentLen: state.content.length,
|
|
372
|
+
nonStreamAccumLen: state.nonStreamingAccumulatedText.length,
|
|
373
|
+
contentPreview: state.content.slice(0, 50),
|
|
374
|
+
nonStreamPreview: state.nonStreamingAccumulatedText.slice(0, 50),
|
|
375
|
+
useStreaming,
|
|
376
|
+
});
|
|
377
|
+
// ORDERING FIX: Add any accumulated text BEFORE adding tool
|
|
378
|
+
// This ensures text appears before tools in the message list.
|
|
379
|
+
// Streaming mode: handle pending assistant message before tool
|
|
380
|
+
if (state.messageId) {
|
|
381
|
+
if (state.content) {
|
|
382
|
+
// Finalize pending message with content
|
|
383
|
+
const messageId = state.messageId;
|
|
384
|
+
const content = state.content;
|
|
385
|
+
const isContinuation = state.splitCounter > 0;
|
|
386
|
+
debug.log('TOOL-CALL: finalizing pending message', {
|
|
387
|
+
messageId,
|
|
388
|
+
contentLen: content.length,
|
|
389
|
+
});
|
|
390
|
+
finalizeMessage(messageId, {
|
|
391
|
+
content,
|
|
392
|
+
isStreaming: false,
|
|
393
|
+
isContinuation,
|
|
394
|
+
});
|
|
395
|
+
// Mark that we finalized text early - prevents duplicate in llm:response
|
|
396
|
+
state.textFinalizedBeforeTool = true;
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
// Empty pending message (first chunk had no content) - remove it
|
|
400
|
+
// This prevents empty bullets when LLM/SDK sends empty initial chunk
|
|
401
|
+
debug.log('TOOL-CALL: removing empty pending message', {
|
|
402
|
+
messageId: state.messageId,
|
|
403
|
+
});
|
|
404
|
+
removeFromPending(state.messageId);
|
|
405
|
+
}
|
|
406
|
+
state.messageId = null;
|
|
407
|
+
state.content = '';
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
debug.log('TOOL-CALL: no pending message to finalize');
|
|
411
|
+
}
|
|
412
|
+
// Non-streaming mode: add accumulated text as finalized message
|
|
413
|
+
if (!useStreaming && state.nonStreamingAccumulatedText) {
|
|
414
|
+
debug.log('TOOL-CALL: adding non-stream accumulated text', {
|
|
415
|
+
len: state.nonStreamingAccumulatedText.length,
|
|
416
|
+
});
|
|
417
|
+
setMessages((prev) => [
|
|
418
|
+
...prev,
|
|
419
|
+
{
|
|
420
|
+
id: generateMessageId('assistant'),
|
|
421
|
+
role: 'assistant',
|
|
422
|
+
content: state.nonStreamingAccumulatedText,
|
|
423
|
+
timestamp: new Date(),
|
|
424
|
+
isStreaming: false,
|
|
425
|
+
},
|
|
426
|
+
]);
|
|
427
|
+
state.nonStreamingAccumulatedText = '';
|
|
428
|
+
// Mark that we finalized text early - prevents duplicate in llm:response
|
|
429
|
+
state.textFinalizedBeforeTool = true;
|
|
430
|
+
}
|
|
431
|
+
const toolMessageId = event.callId
|
|
432
|
+
? `tool-${event.callId}`
|
|
433
|
+
: generateMessageId('tool');
|
|
434
|
+
// Get friendly display name, format args, and tool type badge
|
|
435
|
+
const displayName = getToolDisplayName(event.toolName);
|
|
436
|
+
const argsFormatted = formatToolArgsForDisplay(event.toolName, event.args || {});
|
|
437
|
+
const badge = getToolTypeBadge(event.toolName);
|
|
438
|
+
// Extract description if present
|
|
439
|
+
const description = event.args?.description;
|
|
440
|
+
// Format: toolName(args) [badge]
|
|
441
|
+
// If description exists, add it on a new line with dim styling
|
|
442
|
+
let toolContent = argsFormatted
|
|
443
|
+
? `${displayName}(${argsFormatted}) [${badge}]`
|
|
444
|
+
: `${displayName}() [${badge}]`;
|
|
445
|
+
if (description && typeof description === 'string') {
|
|
446
|
+
toolContent += `\n${chalk.dim(description)}`;
|
|
447
|
+
}
|
|
448
|
+
// Tool calls start in 'pending' state (don't know if approval needed yet)
|
|
449
|
+
// Status transitions: pending → pending_approval (if approval needed) → running → finished
|
|
450
|
+
// Or for pre-approved: pending → running → finished
|
|
451
|
+
addToPending({
|
|
452
|
+
id: toolMessageId,
|
|
453
|
+
role: 'tool',
|
|
454
|
+
content: toolContent,
|
|
455
|
+
timestamp: new Date(),
|
|
456
|
+
toolStatus: 'pending',
|
|
457
|
+
});
|
|
458
|
+
// Track tool called analytics
|
|
459
|
+
capture('dexto_tool_called', {
|
|
460
|
+
source: 'cli',
|
|
461
|
+
sessionId: event.sessionId,
|
|
462
|
+
toolName: event.toolName,
|
|
463
|
+
});
|
|
464
|
+
break;
|
|
465
|
+
}
|
|
466
|
+
case 'llm:tool-result': {
|
|
467
|
+
// Extract structured display data and content from sanitized result
|
|
468
|
+
const sanitized = event.sanitized;
|
|
469
|
+
const toolDisplayData = sanitized?.meta?.display;
|
|
470
|
+
const toolContent = sanitized?.content;
|
|
471
|
+
// Generate text preview for fallback display
|
|
472
|
+
let resultPreview = '';
|
|
473
|
+
try {
|
|
474
|
+
const result = event.sanitized || event.rawResult;
|
|
475
|
+
if (result) {
|
|
476
|
+
let resultStr = '';
|
|
477
|
+
if (typeof result === 'string') {
|
|
478
|
+
resultStr = result;
|
|
479
|
+
}
|
|
480
|
+
else if (result && typeof result === 'object') {
|
|
481
|
+
const resultObj = result;
|
|
482
|
+
if (Array.isArray(resultObj.content)) {
|
|
483
|
+
resultStr = resultObj.content
|
|
484
|
+
.filter((item) => typeof item === 'object' &&
|
|
485
|
+
item !== null &&
|
|
486
|
+
'type' in item &&
|
|
487
|
+
item.type === 'text')
|
|
488
|
+
.map((item) => item.text || '')
|
|
489
|
+
.join('\n');
|
|
490
|
+
}
|
|
491
|
+
else if (resultObj.text) {
|
|
492
|
+
resultStr = resultObj.text;
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
resultStr = JSON.stringify(result, null, 2);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
const maxChars = 400;
|
|
499
|
+
if (resultStr.length > maxChars) {
|
|
500
|
+
resultPreview = resultStr.slice(0, maxChars) + '\n...';
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
resultPreview = resultStr;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
catch {
|
|
508
|
+
resultPreview = '';
|
|
509
|
+
}
|
|
510
|
+
if (event.callId) {
|
|
511
|
+
const toolMessageId = `tool-${event.callId}`;
|
|
512
|
+
// Finalize tool message - move to messages with result and display data
|
|
513
|
+
finalizeMessage(toolMessageId, {
|
|
514
|
+
toolResult: resultPreview,
|
|
515
|
+
toolStatus: 'finished',
|
|
516
|
+
isError: !event.success,
|
|
517
|
+
...(toolDisplayData && { toolDisplayData }),
|
|
518
|
+
...(toolContent && { toolContent }),
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
// Track tool result analytics
|
|
522
|
+
capture('dexto_tool_result', {
|
|
523
|
+
source: 'cli',
|
|
524
|
+
sessionId: event.sessionId,
|
|
525
|
+
toolName: event.toolName || 'unknown',
|
|
526
|
+
success: event.success !== false,
|
|
527
|
+
});
|
|
528
|
+
break;
|
|
529
|
+
}
|
|
530
|
+
case 'llm:error': {
|
|
531
|
+
const errorContent = buildErrorContent(event.error, '❌ Error: ');
|
|
532
|
+
// Add error message to finalized
|
|
533
|
+
setMessages((prev) => [
|
|
534
|
+
...prev,
|
|
535
|
+
{
|
|
536
|
+
id: generateMessageId('error'),
|
|
537
|
+
role: 'system',
|
|
538
|
+
content: errorContent,
|
|
539
|
+
timestamp: new Date(),
|
|
540
|
+
},
|
|
541
|
+
]);
|
|
542
|
+
// Only stop processing for non-recoverable errors (fatal)
|
|
543
|
+
// Tool errors are recoverable - agent continues after them
|
|
544
|
+
if (event.recoverable !== true) {
|
|
545
|
+
// Cancel any streaming message in pending
|
|
546
|
+
if (state.messageId) {
|
|
547
|
+
removeFromPending(state.messageId);
|
|
548
|
+
state.messageId = null;
|
|
549
|
+
state.content = '';
|
|
550
|
+
}
|
|
551
|
+
// Clear any remaining pending messages
|
|
552
|
+
clearPending();
|
|
553
|
+
setUi((prev) => ({
|
|
554
|
+
...prev,
|
|
555
|
+
isProcessing: false,
|
|
556
|
+
isCancelling: false,
|
|
557
|
+
isThinking: false,
|
|
558
|
+
}));
|
|
559
|
+
}
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
562
|
+
case 'llm:unsupported-input': {
|
|
563
|
+
// Show warning for unsupported features (e.g., model doesn't support tool calling)
|
|
564
|
+
const warningContent = '⚠️ ' + event.errors.join('\n⚠️ ');
|
|
565
|
+
setMessages((prev) => [
|
|
566
|
+
...prev,
|
|
567
|
+
{
|
|
568
|
+
id: generateMessageId('warning'),
|
|
569
|
+
role: 'system',
|
|
570
|
+
content: warningContent,
|
|
571
|
+
timestamp: new Date(),
|
|
572
|
+
},
|
|
573
|
+
]);
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
case 'run:complete': {
|
|
577
|
+
const { durationMs } = event;
|
|
578
|
+
const { outputTokens } = state;
|
|
579
|
+
// Ensure any remaining pending messages are finalized
|
|
580
|
+
finalizeAllPending();
|
|
581
|
+
// Add run summary message at the END (not inserted in middle)
|
|
582
|
+
// IMPORTANT: Ink's <Static> tracks rendered items by array position, not key.
|
|
583
|
+
// Inserting in the middle shifts existing items, causing them to re-render.
|
|
584
|
+
// Always append to avoid duplicate rendering.
|
|
585
|
+
if (durationMs > 0 || outputTokens > 0) {
|
|
586
|
+
const summaryMessage = {
|
|
587
|
+
id: generateMessageId('summary'),
|
|
588
|
+
role: 'system',
|
|
589
|
+
content: '', // Content rendered via styledType
|
|
590
|
+
timestamp: new Date(),
|
|
591
|
+
styledType: 'run-summary',
|
|
592
|
+
styledData: {
|
|
593
|
+
durationMs,
|
|
594
|
+
outputTokens,
|
|
595
|
+
},
|
|
596
|
+
};
|
|
597
|
+
setMessages((prev) => [...prev, summaryMessage]);
|
|
598
|
+
}
|
|
599
|
+
setUi((prev) => ({
|
|
600
|
+
...prev,
|
|
601
|
+
isProcessing: false,
|
|
602
|
+
isCancelling: false,
|
|
603
|
+
isThinking: false,
|
|
604
|
+
}));
|
|
605
|
+
break;
|
|
606
|
+
}
|
|
607
|
+
case 'message:dequeued': {
|
|
608
|
+
// Queued message is being processed
|
|
609
|
+
// NOTE: llm:thinking only fires ONCE at the start of execute(),
|
|
610
|
+
// NOT when each queued message starts. So we must finalize here.
|
|
611
|
+
// 1. Finalize any pending from previous response
|
|
612
|
+
// This ensures the previous assistant response is in messages
|
|
613
|
+
// before we add the next user message
|
|
614
|
+
finalizeAllPending();
|
|
615
|
+
// 2. Add user message directly to messages (not buffer)
|
|
616
|
+
// The buffer approach doesn't work because llm:thinking
|
|
617
|
+
// doesn't fire between queued message runs
|
|
618
|
+
const textContent = extractTextContent(event.content);
|
|
619
|
+
if (textContent || event.content.length > 0) {
|
|
620
|
+
setMessages((prev) => [
|
|
621
|
+
...prev,
|
|
622
|
+
{
|
|
623
|
+
id: generateMessageId('user'),
|
|
624
|
+
role: 'user',
|
|
625
|
+
content: textContent || '[attachment]',
|
|
626
|
+
timestamp: new Date(),
|
|
627
|
+
},
|
|
628
|
+
]);
|
|
629
|
+
}
|
|
630
|
+
// Clear queue state - message was consumed
|
|
631
|
+
setQueuedMessages([]);
|
|
632
|
+
// Set processing state for the queued message run
|
|
633
|
+
setUi((prev) => ({ ...prev, isProcessing: true }));
|
|
634
|
+
break;
|
|
635
|
+
}
|
|
636
|
+
case 'tool:running': {
|
|
637
|
+
// Tool execution actually started (after approval if needed)
|
|
638
|
+
// Update status from 'pending' or 'pending_approval' to 'running'
|
|
639
|
+
const runningToolId = `tool-${event.toolCallId}`;
|
|
640
|
+
updatePendingStatus(runningToolId, 'running');
|
|
641
|
+
break;
|
|
642
|
+
}
|
|
643
|
+
case 'approval:request': {
|
|
644
|
+
// Handle approval requests in processStream (NOT useAgentEvents) to ensure
|
|
645
|
+
// proper ordering - text messages must be added BEFORE approval UI shows.
|
|
646
|
+
// This fixes a race condition where direct event bus subscription in
|
|
647
|
+
// useAgentEvents fired before the iterator processed llm:tool-call.
|
|
648
|
+
// Check for auto-approval of edit/write tools FIRST
|
|
649
|
+
// Read from ref to get latest value (may have changed mid-stream)
|
|
650
|
+
const autoApproveEdits = options.autoApproveEditsRef.current;
|
|
651
|
+
const { eventBus } = options;
|
|
652
|
+
if (autoApproveEdits && event.type === ApprovalTypeEnum.TOOL_CONFIRMATION) {
|
|
653
|
+
// Type is narrowed - metadata is now ToolConfirmationMetadata
|
|
654
|
+
const { toolName } = event.metadata;
|
|
655
|
+
if (isEditWriteTool(toolName)) {
|
|
656
|
+
// Auto-approve immediately - emit response and let tool:running handle status
|
|
657
|
+
eventBus.emit('approval:response', {
|
|
658
|
+
approvalId: event.approvalId,
|
|
659
|
+
status: ApprovalStatus.APPROVED,
|
|
660
|
+
sessionId: event.sessionId,
|
|
661
|
+
data: {},
|
|
662
|
+
});
|
|
663
|
+
break;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
// Manual approval needed - update tool status to 'pending_approval'
|
|
667
|
+
// Extract toolCallId based on approval type
|
|
668
|
+
const toolCallId = event.type === ApprovalTypeEnum.TOOL_CONFIRMATION
|
|
669
|
+
? event.metadata.toolCallId
|
|
670
|
+
: undefined;
|
|
671
|
+
if (toolCallId) {
|
|
672
|
+
updatePendingStatus(`tool-${toolCallId}`, 'pending_approval');
|
|
673
|
+
}
|
|
674
|
+
// Show approval UI (moved from useAgentEvents for ordering)
|
|
675
|
+
if (event.type === ApprovalTypeEnum.TOOL_CONFIRMATION ||
|
|
676
|
+
event.type === ApprovalTypeEnum.COMMAND_CONFIRMATION ||
|
|
677
|
+
event.type === ApprovalTypeEnum.ELICITATION ||
|
|
678
|
+
event.type === ApprovalTypeEnum.DIRECTORY_ACCESS) {
|
|
679
|
+
const newApproval = {
|
|
680
|
+
approvalId: event.approvalId,
|
|
681
|
+
type: event.type,
|
|
682
|
+
timestamp: event.timestamp,
|
|
683
|
+
metadata: event.metadata,
|
|
684
|
+
};
|
|
685
|
+
if (event.sessionId !== undefined) {
|
|
686
|
+
newApproval.sessionId = event.sessionId;
|
|
687
|
+
}
|
|
688
|
+
if (event.timeout !== undefined) {
|
|
689
|
+
newApproval.timeout = event.timeout;
|
|
690
|
+
}
|
|
691
|
+
// Queue if there's already an approval, otherwise show immediately
|
|
692
|
+
setApproval((current) => {
|
|
693
|
+
if (current !== null) {
|
|
694
|
+
setApprovalQueue((queue) => [...queue, newApproval]);
|
|
695
|
+
return current;
|
|
696
|
+
}
|
|
697
|
+
setUi((prev) => ({ ...prev, activeOverlay: 'approval' }));
|
|
698
|
+
return newApproval;
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
break;
|
|
702
|
+
}
|
|
703
|
+
// Ignore other events
|
|
704
|
+
default:
|
|
705
|
+
break;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
catch (error) {
|
|
710
|
+
// Handle iterator errors (e.g., aborted)
|
|
711
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
712
|
+
// Expected when cancelled, clean up UI state
|
|
713
|
+
clearPending();
|
|
714
|
+
setUi((prev) => ({
|
|
715
|
+
...prev,
|
|
716
|
+
isProcessing: false,
|
|
717
|
+
isCancelling: false,
|
|
718
|
+
isThinking: false,
|
|
719
|
+
}));
|
|
720
|
+
}
|
|
721
|
+
else {
|
|
722
|
+
// Unexpected error, show to user
|
|
723
|
+
clearPending();
|
|
724
|
+
const errorContent = buildErrorContent(error, '❌ Stream error: ');
|
|
725
|
+
setMessages((prev) => [
|
|
726
|
+
...prev,
|
|
727
|
+
{
|
|
728
|
+
id: generateMessageId('error'),
|
|
729
|
+
role: 'system',
|
|
730
|
+
content: errorContent,
|
|
731
|
+
timestamp: new Date(),
|
|
732
|
+
},
|
|
733
|
+
]);
|
|
734
|
+
setUi((prev) => ({
|
|
735
|
+
...prev,
|
|
736
|
+
isProcessing: false,
|
|
737
|
+
isCancelling: false,
|
|
738
|
+
isThinking: false,
|
|
739
|
+
}));
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|