@datalayer/agent-runtimes 1.0.2 → 1.0.4
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 +14 -132
- package/lib/Agent.js +2 -2
- package/lib/AgentLexical.d.ts +1 -12
- package/lib/AgentLexical.js +3 -14
- package/lib/AgentNotebook.js +3 -3
- package/lib/App.js +2 -2
- package/lib/{components/chat/components → agents}/AgentDetails.d.ts +13 -2
- package/lib/{components/chat/components → agents}/AgentDetails.js +6 -12
- package/lib/api/agents.d.ts +47 -0
- package/lib/api/agents.js +106 -0
- package/lib/api/context.d.ts +17 -0
- package/lib/api/context.js +45 -0
- package/lib/api/evals.d.ts +27 -0
- package/lib/api/evals.js +63 -0
- package/lib/api/events.d.ts +17 -0
- package/lib/api/events.js +93 -0
- package/lib/{components/chat → api}/handler.js +1 -1
- package/lib/api/index.d.ts +15 -0
- package/lib/api/index.js +20 -0
- package/lib/api/notifications.d.ts +39 -0
- package/lib/api/notifications.js +103 -0
- package/lib/api/output.d.ts +28 -0
- package/lib/api/output.js +64 -0
- package/lib/api/tool-approvals.d.ts +62 -0
- package/lib/api/tool-approvals.js +145 -0
- package/lib/{components/chat/components → chat}/Chat.d.ts +26 -15
- package/lib/{components/chat/components → chat}/Chat.js +16 -16
- package/lib/{components/chat/components → chat}/ChatFloating.d.ts +17 -9
- package/lib/{components/chat/components → chat}/ChatFloating.js +17 -9
- package/lib/{components/chat/components → chat}/ChatInline.d.ts +2 -2
- package/lib/{components/chat/components → chat}/ChatInline.js +8 -6
- package/lib/{components/chat/components → chat}/ChatPopupStandalone.d.ts +3 -4
- package/lib/{components/chat/components → chat}/ChatPopupStandalone.js +6 -6
- package/lib/{components/chat/components → chat}/ChatSidebar.d.ts +14 -5
- package/lib/{components/chat/components → chat}/ChatSidebar.js +48 -26
- package/lib/{components/chat/components → chat}/ChatStandalone.d.ts +3 -4
- package/lib/{components/chat/components → chat}/ChatStandalone.js +5 -5
- package/lib/chat/base/ChatBase.d.ts +6 -0
- package/lib/chat/base/ChatBase.js +1338 -0
- package/lib/chat/display/EmptyState.d.ts +27 -0
- package/lib/chat/display/EmptyState.js +41 -0
- package/lib/{components/chat/components/elements → chat/display}/FloatingBrandButton.d.ts +1 -1
- package/lib/{components/chat/components/elements → chat/display}/FloatingBrandButton.js +1 -1
- package/lib/{components/chat/components/elements → chat/display}/PoweredByTag.d.ts +1 -1
- package/lib/{components/chat/components/elements → chat/header}/ChatHeader.d.ts +1 -4
- package/lib/{components/chat/components/elements → chat/header}/ChatHeader.js +1 -1
- package/lib/chat/header/ChatHeaderBase.d.ts +38 -0
- package/lib/chat/header/ChatHeaderBase.js +83 -0
- package/lib/chat/index.d.ts +66 -0
- package/lib/chat/index.js +74 -0
- package/lib/chat/indicators/McpStatusIndicator.d.ts +9 -0
- package/lib/chat/indicators/McpStatusIndicator.js +128 -0
- package/lib/chat/indicators/SandboxStatusIndicator.d.ts +10 -0
- package/lib/chat/indicators/SandboxStatusIndicator.js +175 -0
- package/lib/chat/indicators/index.d.ts +17 -0
- package/lib/chat/indicators/index.js +19 -0
- package/lib/chat/messages/ChatMessageList.d.ts +49 -0
- package/lib/chat/messages/ChatMessageList.js +332 -0
- package/lib/{components/chat/components/elements → chat/messages}/ChatMessages.d.ts +2 -2
- package/lib/{components/chat/components/elements → chat/messages}/ChatMessages.js +6 -4
- package/lib/{components/chat/components → chat}/parts/DynamicToolPart.d.ts +1 -1
- package/lib/{components/chat/components/elements → chat/parts}/MessagePart.d.ts +1 -1
- package/lib/{components/chat/components/elements → chat/parts}/MessagePart.js +4 -4
- package/lib/{components/chat/components → chat}/parts/ReasoningPart.js +1 -1
- package/lib/{components/chat/components → chat}/parts/TextPart.d.ts +1 -1
- package/lib/{components/chat/components → chat}/parts/ToolPart.js +1 -1
- package/lib/{components/chat/components → chat}/parts/index.d.ts +2 -1
- package/lib/{components/chat/components → chat}/parts/index.js +2 -1
- package/lib/chat/prompt/InputFooter.d.ts +43 -0
- package/lib/chat/prompt/InputFooter.js +135 -0
- package/lib/chat/prompt/InputPrompt.d.ts +60 -0
- package/lib/chat/prompt/InputPrompt.js +83 -0
- package/lib/chat/prompt/InputPromptFooter.d.ts +25 -0
- package/lib/chat/prompt/InputPromptFooter.js +15 -0
- package/lib/chat/prompt/InputPromptHeader.d.ts +15 -0
- package/lib/chat/prompt/InputPromptHeader.js +15 -0
- package/lib/chat/prompt/InputPromptLexical.d.ts +16 -0
- package/lib/chat/prompt/InputPromptLexical.js +122 -0
- package/lib/chat/prompt/InputPromptText.d.ts +24 -0
- package/lib/chat/prompt/InputPromptText.js +66 -0
- package/lib/chat/prompt/index.d.ts +11 -0
- package/lib/chat/prompt/index.js +15 -0
- package/lib/{components/chat/components → chat}/styles/streamdownStyles.d.ts +1 -1
- package/lib/chat/tools/ToolApprovalBanner.d.ts +31 -0
- package/lib/chat/tools/ToolApprovalBanner.js +62 -0
- package/lib/{components/chat/components/elements → chat/tools}/ToolApprovalDialog.js +1 -1
- package/lib/{components/chat/components/display → chat/tools}/ToolCallDisplay.d.ts +13 -4
- package/lib/{components/chat/components/display → chat/tools}/ToolCallDisplay.js +18 -8
- package/lib/chat/tools/index.d.ts +8 -0
- package/lib/{components/chat/components/display → chat/tools}/index.js +3 -1
- package/lib/chat/usage/TokenUsageBar.d.ts +8 -0
- package/lib/chat/usage/TokenUsageBar.js +213 -0
- package/lib/client/AgentsMixin.d.ts +216 -0
- package/lib/client/AgentsMixin.js +388 -0
- package/lib/client/index.d.ts +6 -0
- package/lib/client/index.js +10 -0
- package/lib/components/NotificationEventCard.d.ts +8 -0
- package/lib/components/NotificationEventCard.js +177 -0
- package/lib/components/OutputCard.d.ts +8 -0
- package/lib/components/OutputCard.js +94 -0
- package/lib/components/ToolApprovalCard.d.ts +33 -0
- package/lib/components/ToolApprovalCard.js +78 -0
- package/lib/components/index.d.ts +3 -7
- package/lib/components/index.js +3 -4
- package/lib/{components → config}/AgentConfiguration.d.ts +43 -21
- package/lib/{components → config}/AgentConfiguration.js +48 -28
- package/lib/config/index.d.ts +2 -0
- package/lib/config/index.js +1 -0
- package/lib/{components/chat/components → context}/ContextInspector.js +38 -8
- package/lib/{components/chat/components → context}/ContextPanel.js +27 -6
- package/lib/context/CostTracker.d.ts +37 -0
- package/lib/context/CostTracker.js +124 -0
- package/lib/context/TokenUsageChart.d.ts +10 -0
- package/lib/context/TokenUsageChart.js +288 -0
- package/lib/examples/A2UiComponentGalleryExample.d.ts +20 -0
- package/lib/examples/A2UiComponentGalleryExample.js +568 -0
- package/lib/examples/A2UiContactCardExample.d.ts +21 -0
- package/lib/examples/A2UiContactCardExample.js +432 -0
- package/lib/examples/A2UiRestaurantExample.d.ts +11 -3
- package/lib/examples/A2UiRestaurantExample.js +63 -98
- package/lib/examples/A2UiViewerExample.d.ts +21 -0
- package/lib/examples/A2UiViewerExample.js +563 -0
- package/lib/examples/AgUiAgenticExample.js +3 -3
- package/lib/examples/AgUiBackendToolRenderingExample.js +3 -3
- package/lib/examples/{AgUiHaikuGenUIExample.d.ts → AgUiHaikuGenUiExample.d.ts} +4 -4
- package/lib/examples/{AgUiHaikuGenUIExample.js → AgUiHaikuGenUiExample.js} +7 -7
- package/lib/examples/AgUiHumanInTheLoopExample.js +3 -3
- package/lib/examples/AgUiSharedStateExample.js +3 -3
- package/lib/examples/{AgUiToolsBasedGenUIExample.d.ts → AgUiToolsBasedGenUiExample.d.ts} +4 -4
- package/lib/examples/{AgUiToolsBasedGenUIExample.js → AgUiToolsBasedGenUiExample.js} +7 -7
- package/lib/examples/AgentCheckpointsExample.d.ts +19 -0
- package/lib/examples/AgentCheckpointsExample.js +500 -0
- package/lib/examples/AgentCodemodeExample.d.ts +14 -0
- package/lib/examples/AgentCodemodeExample.js +256 -0
- package/lib/examples/AgentEvalsExample.d.ts +14 -0
- package/lib/examples/AgentEvalsExample.js +210 -0
- package/lib/examples/AgentGuardrailsExample.d.ts +14 -0
- package/lib/examples/AgentGuardrailsExample.js +212 -0
- package/lib/examples/AgentMemoryExample.d.ts +14 -0
- package/lib/examples/AgentMemoryExample.js +228 -0
- package/lib/examples/AgentMonitoringExample.d.ts +13 -0
- package/lib/examples/AgentMonitoringExample.js +305 -0
- package/lib/examples/AgentNotificationsExample.d.ts +14 -0
- package/lib/examples/AgentNotificationsExample.js +267 -0
- package/lib/examples/AgentOtelExample.d.ts +25 -0
- package/lib/examples/AgentOtelExample.js +281 -0
- package/lib/examples/AgentOutputsExample.d.ts +14 -0
- package/lib/examples/AgentOutputsExample.js +205 -0
- package/lib/examples/AgentSandboxExample.d.ts +17 -0
- package/lib/examples/AgentSandboxExample.js +490 -0
- package/lib/examples/AgentSkillsExample.d.ts +3 -0
- package/lib/examples/AgentSkillsExample.js +284 -0
- package/lib/examples/AgentToolApprovalsExample.d.ts +3 -0
- package/lib/examples/AgentToolApprovalsExample.js +737 -0
- package/lib/examples/AgentTriggersExample.d.ts +14 -0
- package/lib/examples/AgentTriggersExample.js +1090 -0
- package/lib/examples/{AgentRuntimeFormExample.d.ts → AgentspecExample.d.ts} +3 -4
- package/lib/examples/{AgentRuntimeFormExample.js → AgentspecExample.js} +92 -34
- package/lib/examples/{JupyterCellExample.js → CellSimpleExample.js} +1 -1
- package/lib/examples/{AgentRuntimeCustomExample.js → ChatCustomExample.js} +3 -3
- package/lib/examples/{AgentRuntimeChatExample.js → ChatExample.js} +6 -14
- package/lib/examples/{AgentRuntimeStandaloneExample.js → ChatStandaloneExample.js} +2 -2
- package/lib/examples/CopilotKitLexicalExample.d.ts +3 -14
- package/lib/examples/CopilotKitLexicalExample.js +4 -15
- package/lib/examples/CopilotKitNotebookExample.js +4 -6
- package/lib/examples/DatalayerNotebookExample.js +2 -2
- package/lib/examples/{AgentRuntimeLexical2Example.d.ts → Lexical2Example.d.ts} +2 -13
- package/lib/examples/{AgentRuntimeLexical2Example.js → Lexical2Example.js} +8 -17
- package/lib/examples/{AgentRuntimeLexicalExample.d.ts → LexicalExample.d.ts} +1 -12
- package/lib/examples/{AgentRuntimeLexicalExample.js → LexicalExample.js} +28 -27
- package/lib/examples/{AgentRuntimeLexicalSidebarExample.d.ts → LexicalSidebarExample.d.ts} +2 -13
- package/lib/examples/{AgentRuntimeLexicalSidebarExample.js → LexicalSidebarExample.js} +6 -18
- package/lib/examples/{AgentRuntimeNotebookExample.js → NotebookExample.js} +14 -10
- package/lib/examples/{AgentRuntimeNotebookSidebarExample.js → NotebookSidebarExample.js} +5 -8
- package/lib/examples/{JupyterNotebookExample.js → NotebookSimpleExample.js} +2 -2
- package/lib/examples/ag-ui/weather/InlineWeatherCard.js +1 -1
- package/lib/examples/components/ErrorView.d.ts +14 -0
- package/lib/examples/components/ErrorView.js +20 -0
- package/lib/examples/components/ExampleWrapper.d.ts +12 -0
- package/lib/examples/components/ExampleWrapper.js +16 -0
- package/lib/examples/components/Header.d.ts +2 -2
- package/lib/examples/components/HeaderControls.js +1 -1
- package/lib/examples/components/LexicalEditor.d.ts +1 -12
- package/lib/examples/components/LexicalEditor.js +1 -12
- package/lib/examples/components/MainContent.d.ts +4 -11
- package/lib/examples/components/MainContent.js +6 -60
- package/lib/examples/components/index.d.ts +3 -0
- package/lib/examples/components/index.js +2 -0
- package/lib/examples/example-selector.d.ts +1 -1
- package/lib/examples/example-selector.js +35 -22
- package/lib/examples/index.d.ts +26 -13
- package/lib/examples/index.js +26 -12
- package/lib/examples/main.d.ts +7 -0
- package/lib/examples/main.js +21 -43
- package/lib/examples/utils/examplesStore.d.ts +4 -0
- package/lib/examples/{stores → utils}/examplesStore.js +1 -1
- package/lib/examples/utils/notebooks/Empty.ipynb.json +33 -0
- package/lib/examples/utils/notebooks/NotebookExample2.ipynb.json +48 -0
- package/lib/examples/utils/themeStore.d.ts +8 -0
- package/lib/examples/utils/themeStore.js +14 -0
- package/lib/extensions/A2UIExtension.d.ts +65 -0
- package/lib/extensions/A2UIExtension.js +202 -0
- package/lib/{components/chat/extensions → extensions}/ExtensionRegistry.d.ts +2 -3
- package/lib/{components/chat/extensions → extensions}/ExtensionRegistry.js +0 -2
- package/lib/{components/chat/extensions → extensions}/MCPUIExtension.d.ts +2 -2
- package/lib/{components/chat/extensions → extensions}/MCPUIExtension.js +1 -1
- package/lib/extensions/index.d.ts +9 -0
- package/lib/{components/chat/extensions → extensions}/index.js +2 -2
- package/lib/hooks/index.d.ts +33 -16
- package/lib/hooks/index.js +33 -16
- package/lib/hooks/useAIAgentsWebSocket.d.ts +29 -0
- package/lib/hooks/useAIAgentsWebSocket.js +136 -0
- package/lib/hooks/{useAGUI.d.ts → useAgUi.d.ts} +2 -2
- package/lib/hooks/{useAGUI.js → useAgUi.js} +2 -2
- package/lib/hooks/useAgents.d.ts +150 -11
- package/lib/hooks/useAgents.js +623 -61
- package/lib/hooks/{useAgentStore.d.ts → useAgentsCatalog.d.ts} +3 -8
- package/lib/hooks/{useAgentStore.js → useAgentsCatalog.js} +9 -3
- package/lib/hooks/useAgentsRegistry.d.ts +10 -0
- package/lib/hooks/useAgentsRegistry.js +20 -0
- package/lib/hooks/useAgentsService.d.ts +22 -0
- package/lib/hooks/useAgentsService.js +146 -0
- package/lib/hooks/useChat.d.ts +2 -2
- package/lib/hooks/useChat.js +14 -8
- package/lib/hooks/useCheckpoints.d.ts +176 -0
- package/lib/hooks/useCheckpoints.js +466 -0
- package/lib/hooks/useConfig.d.ts +11 -0
- package/lib/hooks/useConfig.js +46 -0
- package/lib/hooks/useContextSnapshot.d.ts +11 -0
- package/lib/hooks/useContextSnapshot.js +44 -0
- package/lib/hooks/useMonitoring.d.ts +24 -0
- package/lib/hooks/useMonitoring.js +111 -0
- package/lib/hooks/useNotifications.d.ts +67 -0
- package/lib/hooks/useNotifications.js +208 -0
- package/lib/hooks/useSandbox.d.ts +12 -0
- package/lib/hooks/useSandbox.js +49 -0
- package/lib/hooks/useSkills.d.ts +13 -0
- package/lib/hooks/useSkills.js +46 -0
- package/lib/hooks/useToolApprovals.d.ts +45 -0
- package/lib/hooks/useToolApprovals.js +126 -0
- package/lib/hooks/useTools.d.ts +4 -4
- package/lib/hooks/useTools.js +2 -2
- package/lib/hooks/{useVercelChat.d.ts → useVercelAI.d.ts} +3 -3
- package/lib/hooks/{useVercelChat.js → useVercelAI.js} +2 -2
- package/lib/{components/chat/components → identity}/AgentIdentity.d.ts +1 -1
- package/lib/{components/chat/components → identity}/AgentIdentity.js +4 -3
- package/lib/identity/index.d.ts +1 -0
- package/lib/identity/index.js +2 -0
- package/lib/index.d.ts +4 -3
- package/lib/index.js +3 -2
- package/lib/{components/chat/inference → inference}/BaseInferenceProvider.d.ts +3 -3
- package/lib/{components/chat/inference → inference}/DatalayerInferenceProvider.d.ts +3 -3
- package/lib/{components/chat/inference → inference}/DatalayerInferenceProvider.js +1 -1
- package/lib/{components/chat/inference → inference}/SelfHostedInferenceProvider.d.ts +2 -2
- package/lib/{components/chat/inference → inference}/SelfHostedInferenceProvider.js +1 -1
- package/lib/{components/chat/inference → inference}/index.d.ts +1 -1
- package/lib/{components/chat/inference → inference}/index.js +1 -1
- package/lib/lexical/ChatInlinePlugin.d.ts +1 -1
- package/lib/lexical/ChatInlinePlugin.js +1 -1
- package/lib/{components → mcp}/McpServerManager.d.ts +1 -2
- package/lib/mcp/index.d.ts +1 -0
- package/lib/{specs/agents/codeai → mcp}/index.js +1 -1
- package/lib/{components/chat/middleware → middleware}/MiddlewarePipeline.d.ts +3 -3
- package/lib/{components/chat/middleware → middleware}/index.d.ts +1 -1
- package/lib/{components/chat/middleware → middleware}/index.js +1 -1
- package/lib/{components/chat/protocols → protocols}/A2AAdapter.d.ts +6 -6
- package/lib/{components/chat/protocols → protocols}/A2AAdapter.js +3 -3
- package/lib/{components/chat/protocols → protocols}/ACPAdapter.d.ts +6 -6
- package/lib/{components/chat/protocols → protocols}/ACPAdapter.js +4 -4
- package/lib/{components/chat/protocols → protocols}/AGUIAdapter.d.ts +14 -6
- package/lib/{components/chat/protocols → protocols}/AGUIAdapter.js +72 -10
- package/lib/{components/chat/protocols → protocols}/BaseProtocolAdapter.d.ts +6 -6
- package/lib/{components/chat/protocols → protocols}/BaseProtocolAdapter.js +1 -1
- package/lib/{components/chat/protocols → protocols}/VercelAIAdapter.d.ts +33 -7
- package/lib/protocols/VercelAIAdapter.js +748 -0
- package/lib/{components/chat/protocols → protocols}/index.d.ts +1 -2
- package/lib/{components/chat/protocols → protocols}/index.js +1 -1
- package/lib/shims/json5.d.ts +4 -0
- package/lib/shims/json5.js +8 -0
- package/lib/specs/agents/agents.d.ts +54 -0
- package/lib/specs/agents/agents.js +1489 -0
- package/lib/specs/agents/index.js +15 -12
- package/lib/specs/envvars.d.ts +11 -19
- package/lib/specs/envvars.js +52 -38
- package/lib/specs/evals.d.ts +20 -0
- package/lib/specs/evals.js +133 -0
- package/lib/specs/events.d.ts +26 -0
- package/lib/specs/events.js +140 -0
- package/lib/specs/frontendTools.d.ts +14 -0
- package/lib/specs/frontendTools.js +53 -0
- package/lib/specs/guardrails.d.ts +29 -0
- package/lib/specs/guardrails.js +310 -0
- package/lib/specs/index.d.ts +15 -2
- package/lib/specs/index.js +15 -2
- package/lib/specs/mcpServers.d.ts +13 -11
- package/lib/specs/mcpServers.js +75 -50
- package/lib/specs/memory.d.ts +36 -0
- package/lib/specs/memory.js +112 -0
- package/lib/specs/models.d.ts +21 -34
- package/lib/specs/models.js +66 -66
- package/lib/specs/notifications.d.ts +17 -0
- package/lib/specs/notifications.js +103 -0
- package/lib/specs/outputs.d.ts +19 -0
- package/lib/specs/outputs.js +106 -0
- package/lib/specs/skills.d.ts +7 -16
- package/lib/specs/skills.js +95 -18
- package/lib/specs/teams/index.d.ts +17 -0
- package/lib/specs/teams/index.js +35 -0
- package/lib/specs/teams/teams.d.ts +27 -0
- package/lib/specs/teams/teams.js +1000 -0
- package/lib/specs/tools.d.ts +15 -0
- package/lib/specs/tools.js +86 -0
- package/lib/specs/triggers.d.ts +15 -0
- package/lib/specs/triggers.js +67 -0
- package/lib/stores/agentsStore.d.ts +123 -0
- package/lib/stores/agentsStore.js +270 -0
- package/lib/{components/chat/store → stores}/chatStore.d.ts +3 -2
- package/lib/{components/chat/store → stores}/chatStore.js +2 -2
- package/lib/{components/chat/store → stores}/conversationStore.d.ts +1 -1
- package/lib/{components/chat/store → stores}/conversationStore.js +1 -1
- package/lib/{components/chat/store → stores}/index.d.ts +3 -2
- package/lib/{components/chat/store → stores}/index.js +3 -2
- package/lib/{components/chat/tools → tools}/ToolExecutor.d.ts +2 -2
- package/lib/{components/chat/tools → tools}/ToolExecutor.js +1 -1
- package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.d.ts +1 -1
- package/lib/tools/adapters/agent-runtimes/lexicalHooks.d.ts +14 -10
- package/lib/tools/adapters/agent-runtimes/lexicalHooks.js +31 -21
- package/lib/tools/adapters/agent-runtimes/notebookHooks.d.ts +1 -1
- package/lib/tools/index.d.ts +3 -0
- package/lib/tools/index.js +3 -7
- package/lib/types/a2a.d.ts +39 -0
- package/lib/types/acp.d.ts +21 -0
- package/lib/types/ag-ui.d.ts +25 -0
- package/lib/types/agents-lifecycle.d.ts +36 -0
- package/lib/types/agents.d.ts +80 -0
- package/lib/types/agents.js +22 -0
- package/lib/types/agentspecs.d.ts +90 -0
- package/lib/{components/chat/components/base/ChatBase.d.ts → types/chat.d.ts} +59 -99
- package/lib/types/checkpoints.d.ts +32 -0
- package/lib/types/checkpoints.js +5 -0
- package/lib/types/config.d.ts +67 -0
- package/lib/{runtime/types.js → types/config.js} +2 -2
- package/lib/types/connection.d.ts +31 -0
- package/lib/types/connection.js +5 -0
- package/lib/types/context.d.ts +67 -0
- package/lib/types/context.js +5 -0
- package/lib/types/cost.d.ts +42 -0
- package/lib/types/cost.js +5 -0
- package/lib/types/envvars.d.ts +21 -0
- package/lib/types/envvars.js +5 -0
- package/lib/types/evals.d.ts +66 -0
- package/lib/types/evals.js +5 -0
- package/lib/types/events.d.ts +49 -0
- package/lib/types/events.js +5 -0
- package/lib/types/eventspecs.d.ts +39 -0
- package/lib/types/eventspecs.js +5 -0
- package/lib/types/examples.d.ts +31 -0
- package/lib/types/examples.js +5 -0
- package/lib/{components/chat/types → types}/execution.d.ts +10 -1
- package/lib/{components/chat/types/extension.d.ts → types/extensions.d.ts} +3 -3
- package/lib/types/guardrails.d.ts +106 -0
- package/lib/types/guardrails.js +5 -0
- package/lib/types/index.d.ts +36 -2
- package/lib/types/index.js +35 -2
- package/lib/{components/chat/types → types}/inference.d.ts +3 -3
- package/lib/types/inference.js +5 -0
- package/lib/types/mcp.d.ts +117 -0
- package/lib/types/mcp.js +27 -0
- package/lib/types/memory.d.ts +23 -0
- package/lib/types/memory.js +5 -0
- package/lib/{components/chat/types/message.d.ts → types/messages.d.ts} +20 -1
- package/lib/{components/chat/types → types}/middleware.d.ts +3 -3
- package/lib/types/models.d.ts +63 -0
- package/lib/types/models.js +5 -0
- package/lib/types/notifications.d.ts +85 -0
- package/lib/types/notifications.js +5 -0
- package/lib/types/outputs.d.ts +51 -0
- package/lib/types/outputs.js +5 -0
- package/lib/{components/chat/types → types}/protocol.d.ts +37 -99
- package/lib/types/protocol.js +5 -0
- package/lib/types/sandbox.d.ts +27 -0
- package/lib/types/sandbox.js +24 -0
- package/lib/types/skills.d.ts +74 -0
- package/lib/types/skills.js +5 -0
- package/lib/types/teams.d.ts +133 -0
- package/lib/types/teams.js +5 -0
- package/lib/types/tool-approvals.d.ts +39 -0
- package/lib/types/tool-approvals.js +5 -0
- package/lib/{components/chat/types/tool.d.ts → types/tools.d.ts} +61 -4
- package/lib/types/triggers.d.ts +48 -0
- package/lib/types/triggers.js +5 -0
- package/lib/types/usage.d.ts +36 -0
- package/lib/types/usage.js +5 -0
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +5 -0
- package/lib/utils/utils.d.ts +60 -0
- package/lib/utils/utils.js +205 -0
- package/package.json +13 -14
- package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
- package/scripts/codegen/generate_agents.py +377 -61
- package/scripts/codegen/generate_envvars.py +36 -35
- package/scripts/codegen/generate_evals.py +279 -0
- package/scripts/codegen/generate_events.py +320 -0
- package/scripts/codegen/generate_frontend_tools.py +266 -0
- package/scripts/codegen/generate_guardrails.py +475 -0
- package/scripts/codegen/generate_mcp_servers.py +36 -9
- package/scripts/codegen/generate_memory.py +468 -0
- package/scripts/codegen/generate_models.py +22 -46
- package/scripts/codegen/generate_notifications.py +309 -0
- package/scripts/codegen/generate_outputs.py +267 -0
- package/scripts/codegen/generate_skills.py +108 -51
- package/scripts/codegen/generate_teams.py +922 -0
- package/scripts/codegen/generate_tools.py +346 -0
- package/scripts/codegen/generate_triggers.py +295 -0
- package/scripts/codegen/versioning.py +53 -0
- package/style/primer-primitives.css +1 -6
- package/lib/components/chat/components/base/ChatBase.js +0 -2242
- package/lib/components/chat/components/base/InputPrompt.d.ts +0 -42
- package/lib/components/chat/components/base/InputPrompt.js +0 -131
- package/lib/components/chat/components/display/index.d.ts +0 -6
- package/lib/components/chat/components/index.d.ts +0 -26
- package/lib/components/chat/components/index.js +0 -39
- package/lib/components/chat/extensions/A2UIExtension.d.ts +0 -87
- package/lib/components/chat/extensions/A2UIExtension.js +0 -312
- package/lib/components/chat/extensions/index.d.ts +0 -10
- package/lib/components/chat/index.d.ts +0 -61
- package/lib/components/chat/index.js +0 -76
- package/lib/components/chat/protocols/VercelAIAdapter.js +0 -315
- package/lib/components/chat/tools/index.d.ts +0 -8
- package/lib/components/chat/tools/index.js +0 -11
- package/lib/components/chat/types/index.d.ts +0 -12
- package/lib/components/chat/types/index.js +0 -17
- package/lib/components/sparklines/Sparklines.d.ts +0 -16
- package/lib/components/sparklines/Sparklines.js +0 -65
- package/lib/components/sparklines/SparklinesLine.d.ts +0 -8
- package/lib/components/sparklines/SparklinesLine.js +0 -37
- package/lib/components/sparklines/dataProcessing.d.ts +0 -25
- package/lib/components/sparklines/dataProcessing.js +0 -35
- package/lib/components/sparklines/index.d.ts +0 -4
- package/lib/components/sparklines/index.js +0 -7
- package/lib/components/sparklines/types.d.ts +0 -36
- package/lib/examples/stores/examplesStore.d.ts +0 -5
- package/lib/examples/stores/notebooks/Empty.ipynb.json +0 -33
- package/lib/examples/stores/notebooks/NotebookExample2.ipynb.json +0 -48
- package/lib/examples/stores/themeStore.d.ts +0 -33
- package/lib/examples/stores/themeStore.js +0 -38
- package/lib/hooks/useAgentRuntimes.d.ts +0 -350
- package/lib/hooks/useAgentRuntimes.js +0 -78
- package/lib/hooks/useKeyboardShortcuts.d.ts +0 -47
- package/lib/hooks/useKeyboardShortcuts.js +0 -153
- package/lib/hooks/useMobile.d.ts +0 -1
- package/lib/hooks/useMobile.js +0 -19
- package/lib/hooks/useNotebookAIAgent.d.ts +0 -8
- package/lib/hooks/useNotebookAIAgent.js +0 -73
- package/lib/renderers/a2ui/components/A2UIRenderer.d.ts +0 -7
- package/lib/renderers/a2ui/components/A2UIRenderer.js +0 -102
- package/lib/renderers/a2ui/components/SurfaceRenderer.d.ts +0 -7
- package/lib/renderers/a2ui/components/SurfaceRenderer.js +0 -101
- package/lib/renderers/a2ui/components/content/AudioPlayer.d.ts +0 -9
- package/lib/renderers/a2ui/components/content/AudioPlayer.js +0 -38
- package/lib/renderers/a2ui/components/content/Divider.d.ts +0 -9
- package/lib/renderers/a2ui/components/content/Divider.js +0 -35
- package/lib/renderers/a2ui/components/content/Icon.d.ts +0 -9
- package/lib/renderers/a2ui/components/content/Icon.js +0 -110
- package/lib/renderers/a2ui/components/content/Image.d.ts +0 -9
- package/lib/renderers/a2ui/components/content/Image.js +0 -61
- package/lib/renderers/a2ui/components/content/Text.d.ts +0 -9
- package/lib/renderers/a2ui/components/content/Text.js +0 -64
- package/lib/renderers/a2ui/components/content/Video.d.ts +0 -9
- package/lib/renderers/a2ui/components/content/Video.js +0 -37
- package/lib/renderers/a2ui/components/content/index.d.ts +0 -6
- package/lib/renderers/a2ui/components/content/index.js +0 -25
- package/lib/renderers/a2ui/components/index.d.ts +0 -5
- package/lib/renderers/a2ui/components/index.js +0 -24
- package/lib/renderers/a2ui/components/interactive/Button.d.ts +0 -11
- package/lib/renderers/a2ui/components/interactive/Button.js +0 -71
- package/lib/renderers/a2ui/components/interactive/CheckBox.d.ts +0 -9
- package/lib/renderers/a2ui/components/interactive/CheckBox.js +0 -48
- package/lib/renderers/a2ui/components/interactive/DateTimeInput.d.ts +0 -9
- package/lib/renderers/a2ui/components/interactive/DateTimeInput.js +0 -62
- package/lib/renderers/a2ui/components/interactive/MultipleChoice.d.ts +0 -9
- package/lib/renderers/a2ui/components/interactive/MultipleChoice.js +0 -73
- package/lib/renderers/a2ui/components/interactive/Slider.d.ts +0 -9
- package/lib/renderers/a2ui/components/interactive/Slider.js +0 -53
- package/lib/renderers/a2ui/components/interactive/TextField.d.ts +0 -9
- package/lib/renderers/a2ui/components/interactive/TextField.js +0 -72
- package/lib/renderers/a2ui/components/interactive/index.d.ts +0 -6
- package/lib/renderers/a2ui/components/interactive/index.js +0 -25
- package/lib/renderers/a2ui/components/layout/Card.d.ts +0 -11
- package/lib/renderers/a2ui/components/layout/Card.js +0 -30
- package/lib/renderers/a2ui/components/layout/Column.d.ts +0 -11
- package/lib/renderers/a2ui/components/layout/Column.js +0 -65
- package/lib/renderers/a2ui/components/layout/List.d.ts +0 -11
- package/lib/renderers/a2ui/components/layout/List.js +0 -55
- package/lib/renderers/a2ui/components/layout/Modal.d.ts +0 -11
- package/lib/renderers/a2ui/components/layout/Modal.js +0 -58
- package/lib/renderers/a2ui/components/layout/Row.d.ts +0 -11
- package/lib/renderers/a2ui/components/layout/Row.js +0 -65
- package/lib/renderers/a2ui/components/layout/Tabs.d.ts +0 -11
- package/lib/renderers/a2ui/components/layout/Tabs.js +0 -48
- package/lib/renderers/a2ui/components/layout/index.d.ts +0 -6
- package/lib/renderers/a2ui/components/layout/index.js +0 -25
- package/lib/renderers/a2ui/context/A2UIContext.d.ts +0 -17
- package/lib/renderers/a2ui/context/A2UIContext.js +0 -54
- package/lib/renderers/a2ui/context/ThemeContext.d.ts +0 -20
- package/lib/renderers/a2ui/context/ThemeContext.js +0 -333
- package/lib/renderers/a2ui/hooks/useA2UI.d.ts +0 -36
- package/lib/renderers/a2ui/hooks/useA2UI.js +0 -62
- package/lib/renderers/a2ui/hooks/useDataBinding.d.ts +0 -8
- package/lib/renderers/a2ui/hooks/useDataBinding.js +0 -83
- package/lib/renderers/a2ui/index.d.ts +0 -9
- package/lib/renderers/a2ui/index.js +0 -28
- package/lib/renderers/a2ui/lib/utils.d.ts +0 -11
- package/lib/renderers/a2ui/lib/utils.js +0 -38
- package/lib/renderers/a2ui/types/index.d.ts +0 -17
- package/lib/runtime/index.d.ts +0 -38
- package/lib/runtime/index.js +0 -40
- package/lib/runtime/runtimeStore.d.ts +0 -76
- package/lib/runtime/runtimeStore.js +0 -184
- package/lib/runtime/types.d.ts +0 -84
- package/lib/runtime/useAgentConnection.d.ts +0 -45
- package/lib/runtime/useAgentConnection.js +0 -112
- package/lib/runtime/useAgentRuntime.d.ts +0 -93
- package/lib/runtime/useAgentRuntime.js +0 -125
- package/lib/specs/agents/codeai/agents.d.ts +0 -28
- package/lib/specs/agents/codeai/agents.js +0 -179
- package/lib/specs/agents/codeai/index.d.ts +0 -1
- package/lib/specs/agents/codemode-paper/agents.d.ts +0 -31
- package/lib/specs/agents/codemode-paper/agents.js +0 -378
- package/lib/specs/agents/codemode-paper/index.d.ts +0 -1
- package/lib/specs/agents/codemode-paper/index.js +0 -5
- package/lib/specs/agents/datalayer-ai/agents.d.ts +0 -31
- package/lib/specs/agents/datalayer-ai/agents.js +0 -352
- package/lib/specs/agents/datalayer-ai/index.d.ts +0 -1
- package/lib/specs/agents/datalayer-ai/index.js +0 -5
- package/lib/specs/agents/mocks/agents.d.ts +0 -43
- package/lib/specs/agents/mocks/agents.js +0 -2293
- package/lib/specs/agents/mocks/index.d.ts +0 -1
- package/lib/specs/agents/mocks/index.js +0 -5
- package/lib/state/index.d.ts +0 -1
- package/lib/state/index.js +0 -5
- package/lib/state/substates/AIAgentState.d.ts +0 -80
- package/lib/state/substates/AIAgentState.js +0 -108
- package/lib/state/substates/index.d.ts +0 -1
- package/lib/state/substates/index.js +0 -5
- package/lib/types/AIAgent.d.ts +0 -17
- package/lib/types/Types.d.ts +0 -217
- /package/lib/{components/chat → api}/handler.d.ts +0 -0
- /package/lib/{renderers/index.d.ts → api/utils.d.ts} +0 -0
- /package/lib/{renderers/index.js → api/utils.js} +0 -0
- /package/lib/{components/chat/components/elements → chat/display}/PoweredByTag.js +0 -0
- /package/lib/{components/chat/components → chat}/parts/DynamicToolPart.js +0 -0
- /package/lib/{components/chat/components → chat}/parts/ReasoningPart.d.ts +0 -0
- /package/lib/{components/chat/components → chat}/parts/TextPart.js +0 -0
- /package/lib/{components/chat/components → chat}/parts/ToolPart.d.ts +0 -0
- /package/lib/{components/chat/components → chat}/styles/streamdownStyles.js +0 -0
- /package/lib/{components/chat/components/elements → chat/tools}/ToolApprovalDialog.d.ts +0 -0
- /package/lib/{components/chat/components → context}/ContextDistribution.d.ts +0 -0
- /package/lib/{components/chat/components → context}/ContextDistribution.js +0 -0
- /package/lib/{components/chat/components → context}/ContextInspector.d.ts +0 -0
- /package/lib/{components/chat/components → context}/ContextPanel.d.ts +0 -0
- /package/lib/{components/chat/components → context}/ContextUsage.d.ts +0 -0
- /package/lib/{components/chat/components → context}/ContextUsage.js +0 -0
- /package/lib/examples/{JupyterCellExample.d.ts → CellSimpleExample.d.ts} +0 -0
- /package/lib/examples/{AgentRuntimeCustomExample.d.ts → ChatCustomExample.d.ts} +0 -0
- /package/lib/examples/{AgentRuntimeChatExample.d.ts → ChatExample.d.ts} +0 -0
- /package/lib/examples/{AgentRuntimeStandaloneExample.d.ts → ChatStandaloneExample.d.ts} +0 -0
- /package/lib/examples/{AgentRuntimeNotebookExample.d.ts → NotebookExample.d.ts} +0 -0
- /package/lib/examples/{AgentRuntimeNotebookSidebarExample.d.ts → NotebookSidebarExample.d.ts} +0 -0
- /package/lib/examples/{JupyterNotebookExample.d.ts → NotebookSimpleExample.d.ts} +0 -0
- /package/lib/examples/{stores → utils}/agents/earthquake-detector.ipynb.json +0 -0
- /package/lib/examples/{stores → utils}/agents/earthquake-detector.json +0 -0
- /package/lib/examples/{stores → utils}/agents/earthquake-detector.lexical.json +0 -0
- /package/lib/examples/{stores → utils}/agents/sales-forecaster.ipynb.json +0 -0
- /package/lib/examples/{stores → utils}/agents/sales-forecaster.json +0 -0
- /package/lib/examples/{stores → utils}/agents/sales-forecaster.lexical.json +0 -0
- /package/lib/examples/{stores → utils}/agents/social-post-generator.ipynb.json +0 -0
- /package/lib/examples/{stores → utils}/agents/social-post-generator.json +0 -0
- /package/lib/examples/{stores → utils}/agents/social-post-generator.lexical.json +0 -0
- /package/lib/examples/{stores → utils}/agents/stock-market.ipynb.json +0 -0
- /package/lib/examples/{stores → utils}/agents/stock-market.json +0 -0
- /package/lib/examples/{stores → utils}/agents/stock-market.lexical.json +0 -0
- /package/lib/examples/{stores → utils}/notebooks/IPyWidgetsExample.ipynb.json +0 -0
- /package/lib/examples/{stores → utils}/notebooks/IPyWidgetsExampleWithState.ipynb.json +0 -0
- /package/lib/examples/{stores → utils}/notebooks/Lite.ipynb.json +0 -0
- /package/lib/examples/{stores → utils}/notebooks/Matplotlib.ipynb.json +0 -0
- /package/lib/examples/{stores → utils}/notebooks/NotebookExample1.ipynb.json +0 -0
- /package/lib/examples/{stores → utils}/notebooks/NotebookOutputs.ipynb.json +0 -0
- /package/lib/examples/{stores → utils}/notebooks/NotebookToCExample.ipynb.json +0 -0
- /package/lib/examples/{stores → utils}/notebooks/OutputIPyWidgetsExample.d.ts +0 -0
- /package/lib/examples/{stores → utils}/notebooks/OutputIPyWidgetsExample.js +0 -0
- /package/lib/examples/{stores → utils}/notebooks/PyGWalker.ipynb.json +0 -0
- /package/lib/examples/{stores → utils}/themedProvider.d.ts +0 -0
- /package/lib/examples/{stores → utils}/themedProvider.js +0 -0
- /package/lib/{components/chat/inference → inference}/BaseInferenceProvider.js +0 -0
- /package/lib/{components → mcp}/McpServerManager.js +0 -0
- /package/lib/{components/chat/middleware → middleware}/MiddlewarePipeline.js +0 -0
- /package/lib/{components/chat/types/inference.js → types/a2a.js} +0 -0
- /package/lib/{components/chat/types/protocol.js → types/acp.js} +0 -0
- /package/lib/{components/sparklines/types.js → types/ag-ui.js} +0 -0
- /package/lib/{renderers/a2ui/types/index.js → types/agents-lifecycle.js} +0 -0
- /package/lib/types/{AIAgent.js → agentspecs.js} +0 -0
- /package/lib/types/{Types.js → chat.js} +0 -0
- /package/lib/{components/chat/types → types}/execution.js +0 -0
- /package/lib/{components/chat/types/extension.js → types/extensions.js} +0 -0
- /package/lib/{components/chat/types/message.js → types/messages.js} +0 -0
- /package/lib/{components/chat/types → types}/middleware.js +0 -0
- /package/lib/{components/chat/types/tool.js → types/tools.js} +0 -0
|
@@ -0,0 +1,1338 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Main ChatBase component.
|
|
8
|
+
* Provides a full chat interface with messages and input.
|
|
9
|
+
* This is the base component used by all other chat container components.
|
|
10
|
+
*
|
|
11
|
+
* Supports multiple modes:
|
|
12
|
+
* 1. Store mode: Uses Zustand store for state management (default)
|
|
13
|
+
* 2. Protocol mode: Connects to backend via AG-UI, A2A, Vercel AI, or ACP protocols
|
|
14
|
+
* 3. Custom mode: Uses onSendMessage prop for custom message handling
|
|
15
|
+
*
|
|
16
|
+
* @module chat/base/ChatBase
|
|
17
|
+
*/
|
|
18
|
+
import { useContext } from 'react';
|
|
19
|
+
import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
20
|
+
import { Text, Spinner } from '@primer/react';
|
|
21
|
+
import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
|
|
22
|
+
import { AlertIcon, PersonIcon } from '@primer/octicons-react';
|
|
23
|
+
import { AiAgentIcon } from '@datalayer/icons-react';
|
|
24
|
+
import { QueryClientProvider, QueryClientContext } from '@tanstack/react-query';
|
|
25
|
+
import { useChatStore } from '../../stores/chatStore';
|
|
26
|
+
import { useConversationStore } from '../../stores/conversationStore';
|
|
27
|
+
import { generateMessageId, createUserMessage, createAssistantMessage, } from '../../types/messages';
|
|
28
|
+
import { internalQueryClient, isToolCallMessage, convertHistoryToDisplayItems, createProtocolAdapter, getApiBaseFromConfig, sanitizeAssistantContent, } from '../../utils';
|
|
29
|
+
import { useConfig, useSkills, useContextSnapshot, useSandbox, } from '../../hooks';
|
|
30
|
+
import { ChatBaseHeader } from '../header/ChatHeaderBase';
|
|
31
|
+
import { ChatEmptyState } from '../display/EmptyState';
|
|
32
|
+
import { PoweredByTag } from '../display/PoweredByTag';
|
|
33
|
+
import { ChatMessageList, } from '../messages/ChatMessageList';
|
|
34
|
+
import { InputToolbar } from '../prompt/InputFooter';
|
|
35
|
+
// Tracks pending prompts already auto-sent for a given conversation scope.
|
|
36
|
+
// This prevents layout-driven unmount/remount cycles from re-sending prompts.
|
|
37
|
+
const sentPendingPromptKeys = new Set();
|
|
38
|
+
function isToolCallOnlyPrompt(content) {
|
|
39
|
+
const normalized = content.toLowerCase();
|
|
40
|
+
return (/tool\s*call\s*only/.test(normalized) ||
|
|
41
|
+
/use\s+(?:a\s+)?tool\s+call\s+only/.test(normalized));
|
|
42
|
+
}
|
|
43
|
+
function formatToolResultFallback(result) {
|
|
44
|
+
if (typeof result === 'string') {
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
if (typeof result === 'number' ||
|
|
48
|
+
typeof result === 'boolean' ||
|
|
49
|
+
result === null) {
|
|
50
|
+
return String(result);
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const serialized = JSON.stringify(result, null, 2);
|
|
54
|
+
return serialized.length > 2000
|
|
55
|
+
? `${serialized.slice(0, 2000)}\n...`
|
|
56
|
+
: serialized;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return 'Tool completed successfully.';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// ChatBase (outer wrapper — ensures QueryClient is available)
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
/**
|
|
66
|
+
* ChatBase component — Universal chat panel supporting store, protocol, and custom modes.
|
|
67
|
+
*/
|
|
68
|
+
export function ChatBase(props) {
|
|
69
|
+
const { agentRuntimeConfig, protocol: protocolProp, useStore: useStoreMode = true, } = props;
|
|
70
|
+
// Resolve protocol: string Protocol overrides type in agentRuntimeConfig or
|
|
71
|
+
// is combined with a full ProtocolConfig object.
|
|
72
|
+
const protocolType = typeof protocolProp === 'string' ? protocolProp : undefined;
|
|
73
|
+
const protocolConfigProp = typeof protocolProp === 'object' ? protocolProp : undefined;
|
|
74
|
+
const protocol = agentRuntimeConfig
|
|
75
|
+
? {
|
|
76
|
+
type: protocolType || agentRuntimeConfig.protocol || 'vercel-ai',
|
|
77
|
+
endpoint: agentRuntimeConfig.url,
|
|
78
|
+
authToken: agentRuntimeConfig.authToken,
|
|
79
|
+
agentId: agentRuntimeConfig.agentId,
|
|
80
|
+
enableConfigQuery: true,
|
|
81
|
+
configEndpoint: `${agentRuntimeConfig.url}/api/v1/config`,
|
|
82
|
+
}
|
|
83
|
+
: protocolConfigProp;
|
|
84
|
+
// If agentRuntimeConfig is provided, force protocol mode
|
|
85
|
+
const effectiveUseStoreMode = agentRuntimeConfig ? false : useStoreMode;
|
|
86
|
+
// Check if QueryClientProvider is already available
|
|
87
|
+
const existingQueryClient = useContext(QueryClientContext);
|
|
88
|
+
const innerProps = {
|
|
89
|
+
...props,
|
|
90
|
+
// Protocol is resolved to ProtocolConfig | undefined by the outer wrapper.
|
|
91
|
+
// Force the type to satisfy ChatBaseProps (which accepts the union).
|
|
92
|
+
protocol: protocol,
|
|
93
|
+
useStore: effectiveUseStoreMode,
|
|
94
|
+
};
|
|
95
|
+
if (!existingQueryClient) {
|
|
96
|
+
return (_jsx(QueryClientProvider, { client: internalQueryClient, children: _jsx(ChatBaseInner, { ...innerProps }) }));
|
|
97
|
+
}
|
|
98
|
+
return _jsx(ChatBaseInner, { ...innerProps });
|
|
99
|
+
}
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// ChatBaseInner — contains all actual logic
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
function ChatBaseInner({ title, showHeader = false, showTokenUsage = true, showLoadingIndicator = true, showErrors = true, showInput = true, showModelSelector = false, showToolsMenu = false, showSkillsMenu = false, codemodeEnabled = false, initialModel, availableModels, mcpServers, initialSkills, className, loadingState, headerActions, chatViewMode, onChatViewModeChange,
|
|
104
|
+
// Mode selection
|
|
105
|
+
useStore: useStoreMode = true, protocol: protocolRaw, onSendMessage, enableStreaming = false,
|
|
106
|
+
// Extended props
|
|
107
|
+
brandIcon, avatarConfig, headerButtons, showPoweredBy = false, poweredByProps, emptyState, renderToolResult, footerContent, showInformation = false, onInformationClick, headerContent, children, borderRadius, backgroundColor, border, boxShadow, compact = false, placeholder, description = 'Start a conversation with the AI agent.', onStateUpdate, onNewChat, onClear, onMessagesChange, autoFocus = false, suggestions, submitOnSuggestionClick = true, hideMessagesAfterToolUI = false, focusTrigger, frontendTools,
|
|
108
|
+
// Identity/Authorization props
|
|
109
|
+
onAuthorizationRequired, connectedIdentities,
|
|
110
|
+
// Conversation persistence
|
|
111
|
+
runtimeId, historyEndpoint, historyAuthToken,
|
|
112
|
+
// Pending prompt
|
|
113
|
+
pendingPrompt, }) {
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
setupPrimerPortals();
|
|
116
|
+
}, []);
|
|
117
|
+
// The outer ChatBase wrapper always resolves a string Protocol to a full
|
|
118
|
+
// ProtocolConfig (or undefined). Narrow the type for internal use.
|
|
119
|
+
const protocol = typeof protocolRaw === 'object' ? protocolRaw : undefined;
|
|
120
|
+
// Stabilize the protocol reference so that the adapter-init effect only
|
|
121
|
+
// re-runs when the protocol *contents* actually change.
|
|
122
|
+
const protocolKey = protocol ? JSON.stringify(protocol) : '';
|
|
123
|
+
// Store (optional for message persistence)
|
|
124
|
+
const clearStoreMessages = useChatStore(state => state.clearMessages);
|
|
125
|
+
// Check if protocol is A2A (doesn't support per-request model override)
|
|
126
|
+
const isA2AProtocol = protocol?.type === 'a2a';
|
|
127
|
+
// ---- Component state ----
|
|
128
|
+
const [displayItems, setDisplayItems] = useState([]);
|
|
129
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
130
|
+
const [isStreaming, setIsStreaming] = useState(false);
|
|
131
|
+
const [error, setError] = useState(null);
|
|
132
|
+
const [input, setInput] = useState('');
|
|
133
|
+
// History-loaded flag — true immediately when there is nothing to fetch
|
|
134
|
+
const [historyLoaded, setHistoryLoaded] = useState(!runtimeId);
|
|
135
|
+
// Adapter-ready flag — flipped to true once the protocol adapter is initialised
|
|
136
|
+
const [adapterReady, setAdapterReady] = useState(false);
|
|
137
|
+
// Guard so the pending prompt is sent at most once
|
|
138
|
+
const pendingPromptSentRef = useRef(false);
|
|
139
|
+
const pendingPromptKey = pendingPrompt &&
|
|
140
|
+
[
|
|
141
|
+
runtimeId || historyEndpoint || protocol?.endpoint || protocol?.agentId,
|
|
142
|
+
pendingPrompt,
|
|
143
|
+
]
|
|
144
|
+
.filter(Boolean)
|
|
145
|
+
.join('::');
|
|
146
|
+
const [selectedModel, setSelectedModel] = useState('');
|
|
147
|
+
// enabledTools tracks which MCP server tools are enabled
|
|
148
|
+
// Format: Map<serverId, Set<toolName>>
|
|
149
|
+
const [enabledMcpTools, setEnabledMcpTools] = useState(new Map());
|
|
150
|
+
// Note: legacy _enabledTools for backend-defined tools from config query
|
|
151
|
+
const [_enabledTools, setEnabledTools] = useState([]);
|
|
152
|
+
// Skills state
|
|
153
|
+
const [enabledSkills, setEnabledSkills] = useState(new Set());
|
|
154
|
+
// ---- Data queries ----
|
|
155
|
+
const configQuery = useConfig(Boolean(protocol?.enableConfigQuery), protocol?.configEndpoint, protocol?.authToken);
|
|
156
|
+
const skillsQuery = useSkills(Boolean(protocol?.enableConfigQuery) && showSkillsMenu, protocol?.configEndpoint, protocol?.authToken);
|
|
157
|
+
const contextSnapshotQuery = useContextSnapshot(Boolean(protocol?.enableConfigQuery) && showTokenUsage, protocol?.configEndpoint, protocol?.agentId, protocol?.authToken);
|
|
158
|
+
const agentUsage = contextSnapshotQuery.data;
|
|
159
|
+
const sandboxStatusQuery = useSandbox(Boolean(protocol?.enableConfigQuery) && codemodeEnabled && showHeader, protocol?.configEndpoint, protocol?.authToken);
|
|
160
|
+
const sandboxStatus = sandboxStatusQuery.data;
|
|
161
|
+
// ---- Refs ----
|
|
162
|
+
const adapterRef = useRef(null);
|
|
163
|
+
const unsubscribeRef = useRef(null);
|
|
164
|
+
const toolCallsRef = useRef(new Map());
|
|
165
|
+
const pendingToolExecutionsRef = useRef(0);
|
|
166
|
+
const currentAssistantMessageRef = useRef(null);
|
|
167
|
+
const suppressAssistantTextForToolOnlyRef = useRef(false);
|
|
168
|
+
const hideMessagesAfterToolUIRef = useRef(hideMessagesAfterToolUI);
|
|
169
|
+
hideMessagesAfterToolUIRef.current = hideMessagesAfterToolUI;
|
|
170
|
+
const threadIdRef = useRef(generateMessageId());
|
|
171
|
+
const messagesEndRef = useRef(null);
|
|
172
|
+
const inputRef = useRef(null);
|
|
173
|
+
const abortControllerRef = useRef(null);
|
|
174
|
+
/** Set to true by handleStop so in-flight / about-to-run tool executions
|
|
175
|
+
* can bail out early. Reset to false at the start of each handleSend. */
|
|
176
|
+
const stoppedRef = useRef(false);
|
|
177
|
+
const connectedIdentitiesRef = useRef(connectedIdentities);
|
|
178
|
+
connectedIdentitiesRef.current = connectedIdentities;
|
|
179
|
+
// Keep a ref to frontendTools so the event listener closure (which is NOT
|
|
180
|
+
// re-created when frontendTools changes) always accesses the latest value.
|
|
181
|
+
const frontendToolsRef = useRef(frontendTools);
|
|
182
|
+
frontendToolsRef.current = frontendTools;
|
|
183
|
+
// ---- Helpers ----
|
|
184
|
+
const isServerSelected = useCallback((server) => {
|
|
185
|
+
if (!mcpServers)
|
|
186
|
+
return true;
|
|
187
|
+
const origin = server.isConfig === false ? 'catalog' : 'config';
|
|
188
|
+
return mcpServers.some(s => s.id === server.id && s.origin === origin);
|
|
189
|
+
}, [mcpServers]);
|
|
190
|
+
// ---- Focus management ----
|
|
191
|
+
useEffect(() => {
|
|
192
|
+
if (autoFocus && inputRef.current) {
|
|
193
|
+
const timeoutId = setTimeout(() => inputRef.current?.focus(), 100);
|
|
194
|
+
return () => clearTimeout(timeoutId);
|
|
195
|
+
}
|
|
196
|
+
}, [autoFocus]);
|
|
197
|
+
useEffect(() => {
|
|
198
|
+
if (focusTrigger !== undefined && focusTrigger > 0 && inputRef.current) {
|
|
199
|
+
const timeoutId = setTimeout(() => inputRef.current?.focus(), 150);
|
|
200
|
+
return () => clearTimeout(timeoutId);
|
|
201
|
+
}
|
|
202
|
+
}, [focusTrigger]);
|
|
203
|
+
const wasLoadingRef = useRef(false);
|
|
204
|
+
useEffect(() => {
|
|
205
|
+
if (wasLoadingRef.current && !isLoading && inputRef.current) {
|
|
206
|
+
const timeoutId = setTimeout(() => inputRef.current?.focus(), 50);
|
|
207
|
+
return () => clearTimeout(timeoutId);
|
|
208
|
+
}
|
|
209
|
+
wasLoadingRef.current = isLoading;
|
|
210
|
+
}, [isLoading]);
|
|
211
|
+
// ---- Auto-resize textarea ----
|
|
212
|
+
const adjustTextareaHeight = useCallback(() => {
|
|
213
|
+
const textarea = inputRef.current;
|
|
214
|
+
if (textarea) {
|
|
215
|
+
textarea.style.height = 'auto';
|
|
216
|
+
const maxHeight = 120;
|
|
217
|
+
const minHeight = 40;
|
|
218
|
+
const newHeight = Math.min(Math.max(textarea.scrollHeight, minHeight), maxHeight);
|
|
219
|
+
textarea.style.height = `${newHeight}px`;
|
|
220
|
+
textarea.style.overflowY =
|
|
221
|
+
textarea.scrollHeight > maxHeight ? 'auto' : 'hidden';
|
|
222
|
+
}
|
|
223
|
+
}, []);
|
|
224
|
+
useEffect(() => {
|
|
225
|
+
adjustTextareaHeight();
|
|
226
|
+
}, [input, adjustTextareaHeight]);
|
|
227
|
+
useEffect(() => {
|
|
228
|
+
const timer = setTimeout(adjustTextareaHeight, 0);
|
|
229
|
+
return () => clearTimeout(timer);
|
|
230
|
+
}, [adjustTextareaHeight]);
|
|
231
|
+
// ---- Initialize model and tools when config is available ----
|
|
232
|
+
useEffect(() => {
|
|
233
|
+
if ((configQuery.data || availableModels) && !selectedModel) {
|
|
234
|
+
const modelsList = availableModels || configQuery.data?.models || [];
|
|
235
|
+
const preferredModel = initialModel || configQuery.data?.defaultModel;
|
|
236
|
+
if (preferredModel) {
|
|
237
|
+
const modelExists = modelsList.some(m => m.id === preferredModel);
|
|
238
|
+
if (modelExists) {
|
|
239
|
+
setSelectedModel(preferredModel);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
const firstAvailableModel = modelsList.find(m => m.isAvailable !== false);
|
|
243
|
+
const firstModel = firstAvailableModel || modelsList[0];
|
|
244
|
+
if (firstModel)
|
|
245
|
+
setSelectedModel(firstModel.id);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
const firstAvailableModel = modelsList.find(m => m.isAvailable !== false);
|
|
250
|
+
const firstModel = firstAvailableModel || modelsList[0];
|
|
251
|
+
if (firstModel)
|
|
252
|
+
setSelectedModel(firstModel.id);
|
|
253
|
+
}
|
|
254
|
+
const allToolIds = configQuery.data?.builtinTools?.map(tool => tool.id) || [];
|
|
255
|
+
setEnabledTools(allToolIds);
|
|
256
|
+
if (configQuery.data?.mcpServers) {
|
|
257
|
+
const newEnabledMcpTools = new Map();
|
|
258
|
+
for (const server of configQuery.data.mcpServers) {
|
|
259
|
+
if (server.isAvailable && server.enabled) {
|
|
260
|
+
const shouldEnableServer = isServerSelected(server);
|
|
261
|
+
if (shouldEnableServer) {
|
|
262
|
+
const enabledToolNames = new Set(server.tools.filter(t => t.enabled).map(t => t.name));
|
|
263
|
+
newEnabledMcpTools.set(server.id, enabledToolNames);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
setEnabledMcpTools(newEnabledMcpTools);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}, [
|
|
271
|
+
configQuery.data,
|
|
272
|
+
selectedModel,
|
|
273
|
+
initialModel,
|
|
274
|
+
availableModels,
|
|
275
|
+
mcpServers,
|
|
276
|
+
isServerSelected,
|
|
277
|
+
]);
|
|
278
|
+
// Update enabled MCP servers when mcpServers prop changes
|
|
279
|
+
useEffect(() => {
|
|
280
|
+
if (!configQuery.data?.mcpServers || !mcpServers)
|
|
281
|
+
return;
|
|
282
|
+
setEnabledMcpTools(prev => {
|
|
283
|
+
const newMap = new Map();
|
|
284
|
+
for (const server of configQuery.data?.mcpServers ?? []) {
|
|
285
|
+
if (isServerSelected(server) && prev.has(server.id)) {
|
|
286
|
+
newMap.set(server.id, prev.get(server.id));
|
|
287
|
+
}
|
|
288
|
+
else if (isServerSelected(server) &&
|
|
289
|
+
server.isAvailable &&
|
|
290
|
+
server.enabled) {
|
|
291
|
+
const enabledToolNames = new Set(server.tools.filter(t => t.enabled).map(t => t.name));
|
|
292
|
+
newMap.set(server.id, enabledToolNames);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return newMap;
|
|
296
|
+
});
|
|
297
|
+
}, [mcpServers, configQuery.data?.mcpServers, isServerSelected]);
|
|
298
|
+
// Initialize enabled skills from initialSkills prop
|
|
299
|
+
useEffect(() => {
|
|
300
|
+
if (initialSkills && initialSkills.length > 0) {
|
|
301
|
+
setEnabledSkills(new Set(initialSkills));
|
|
302
|
+
}
|
|
303
|
+
}, [initialSkills]);
|
|
304
|
+
// ---- Toggle helpers ----
|
|
305
|
+
const toggleMcpTool = useCallback((serverId, toolName) => {
|
|
306
|
+
setEnabledMcpTools(prev => {
|
|
307
|
+
const newMap = new Map(prev);
|
|
308
|
+
const serverTools = new Set(prev.get(serverId) || []);
|
|
309
|
+
if (serverTools.has(toolName)) {
|
|
310
|
+
serverTools.delete(toolName);
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
serverTools.add(toolName);
|
|
314
|
+
}
|
|
315
|
+
newMap.set(serverId, serverTools);
|
|
316
|
+
return newMap;
|
|
317
|
+
});
|
|
318
|
+
}, []);
|
|
319
|
+
const toggleAllMcpServerTools = useCallback((serverId, allToolNames, enable) => {
|
|
320
|
+
setEnabledMcpTools(prev => {
|
|
321
|
+
const newMap = new Map(prev);
|
|
322
|
+
if (enable) {
|
|
323
|
+
newMap.set(serverId, new Set(allToolNames));
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
newMap.set(serverId, new Set());
|
|
327
|
+
}
|
|
328
|
+
return newMap;
|
|
329
|
+
});
|
|
330
|
+
}, []);
|
|
331
|
+
const toggleSkill = useCallback((skillId) => {
|
|
332
|
+
setEnabledSkills(prev => {
|
|
333
|
+
const newSet = new Set(prev);
|
|
334
|
+
if (newSet.has(skillId)) {
|
|
335
|
+
newSet.delete(skillId);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
newSet.add(skillId);
|
|
339
|
+
}
|
|
340
|
+
return newSet;
|
|
341
|
+
});
|
|
342
|
+
}, []);
|
|
343
|
+
const toggleAllSkills = useCallback((allSkillIds, enable) => {
|
|
344
|
+
setEnabledSkills(enable ? new Set(allSkillIds) : new Set());
|
|
345
|
+
}, []);
|
|
346
|
+
const getEnabledMcpToolNames = useCallback(() => {
|
|
347
|
+
const toolNames = [];
|
|
348
|
+
enabledMcpTools.forEach((tools, serverId) => {
|
|
349
|
+
if (!mcpServers || mcpServers.some(s => s.id === serverId)) {
|
|
350
|
+
tools.forEach(toolName => toolNames.push(toolName));
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
return toolNames;
|
|
354
|
+
}, [enabledMcpTools, mcpServers]);
|
|
355
|
+
const getEnabledSkillIds = useCallback(() => {
|
|
356
|
+
return Array.from(enabledSkills);
|
|
357
|
+
}, [enabledSkills]);
|
|
358
|
+
// ---- Load messages from store on mount ----
|
|
359
|
+
useEffect(() => {
|
|
360
|
+
if (useStoreMode) {
|
|
361
|
+
const storeMessages = useChatStore.getState().messages;
|
|
362
|
+
if (storeMessages.length > 0) {
|
|
363
|
+
setDisplayItems(storeMessages);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}, [useStoreMode]);
|
|
367
|
+
// ---- Conversation history loading ----
|
|
368
|
+
const prevRuntimeIdRef = useRef(undefined);
|
|
369
|
+
useEffect(() => {
|
|
370
|
+
if (runtimeId !== prevRuntimeIdRef.current) {
|
|
371
|
+
prevRuntimeIdRef.current = runtimeId;
|
|
372
|
+
setDisplayItems([]);
|
|
373
|
+
toolCallsRef.current.clear();
|
|
374
|
+
if (!runtimeId)
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
const store = useConversationStore.getState();
|
|
381
|
+
if (!store.needsFetch(runtimeId)) {
|
|
382
|
+
const storedMessages = store.getMessages(runtimeId);
|
|
383
|
+
if (storedMessages.length > 0) {
|
|
384
|
+
setDisplayItems(storedMessages);
|
|
385
|
+
}
|
|
386
|
+
setHistoryLoaded(true);
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
store.setFetching(runtimeId, true);
|
|
390
|
+
let endpoint = historyEndpoint ||
|
|
391
|
+
(protocol?.endpoint ? `${protocol.endpoint}/api/v1/history` : null);
|
|
392
|
+
if (!endpoint) {
|
|
393
|
+
console.warn('[ChatBase] No history endpoint available for runtimeId:', runtimeId);
|
|
394
|
+
store.markFetched(runtimeId);
|
|
395
|
+
setHistoryLoaded(true);
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
if (protocol?.agentId && !endpoint.includes('agent_id=')) {
|
|
399
|
+
const separator = endpoint.includes('?') ? '&' : '?';
|
|
400
|
+
endpoint = `${endpoint}${separator}agent_id=${encodeURIComponent(protocol.agentId)}`;
|
|
401
|
+
}
|
|
402
|
+
const fetchHistory = async () => {
|
|
403
|
+
try {
|
|
404
|
+
const authToken = historyAuthToken || protocol?.authToken;
|
|
405
|
+
const headers = {
|
|
406
|
+
'Content-Type': 'application/json',
|
|
407
|
+
};
|
|
408
|
+
if (authToken) {
|
|
409
|
+
headers['Authorization'] = `Bearer ${authToken}`;
|
|
410
|
+
}
|
|
411
|
+
const response = await fetch(endpoint, {
|
|
412
|
+
method: 'GET',
|
|
413
|
+
headers,
|
|
414
|
+
credentials: 'include',
|
|
415
|
+
});
|
|
416
|
+
if (!response.ok) {
|
|
417
|
+
throw new Error(`Failed to fetch history: ${response.status} ${response.statusText}`);
|
|
418
|
+
}
|
|
419
|
+
const data = await response.json();
|
|
420
|
+
const messages = (data.messages || []).map((msg) => {
|
|
421
|
+
if (msg.toolCalls && Array.isArray(msg.toolCalls)) {
|
|
422
|
+
msg.toolCalls = msg.toolCalls.map((tc) => {
|
|
423
|
+
if (tc.toolCallId && tc.toolName)
|
|
424
|
+
return tc;
|
|
425
|
+
let parsedArgs = tc.args ?? tc.arguments ?? {};
|
|
426
|
+
if (typeof parsedArgs === 'string') {
|
|
427
|
+
try {
|
|
428
|
+
parsedArgs = JSON.parse(parsedArgs);
|
|
429
|
+
}
|
|
430
|
+
catch {
|
|
431
|
+
parsedArgs = {};
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return {
|
|
435
|
+
type: 'tool-call',
|
|
436
|
+
toolCallId: tc.toolCallId ?? tc.id ?? tc.tool_call_id ?? '',
|
|
437
|
+
toolName: tc.toolName ?? tc.name ?? tc.tool_name ?? '',
|
|
438
|
+
args: parsedArgs,
|
|
439
|
+
status: tc.status ?? 'completed',
|
|
440
|
+
};
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
return msg;
|
|
444
|
+
});
|
|
445
|
+
if (messages.length > 0) {
|
|
446
|
+
store.setMessages(runtimeId, messages);
|
|
447
|
+
const items = convertHistoryToDisplayItems(messages);
|
|
448
|
+
setDisplayItems(items);
|
|
449
|
+
}
|
|
450
|
+
store.markFetched(runtimeId);
|
|
451
|
+
setHistoryLoaded(true);
|
|
452
|
+
}
|
|
453
|
+
catch (err) {
|
|
454
|
+
console.error('[ChatBase] Failed to fetch conversation history:', err);
|
|
455
|
+
store.markFetched(runtimeId);
|
|
456
|
+
setHistoryLoaded(true);
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
fetchHistory();
|
|
460
|
+
}, [
|
|
461
|
+
runtimeId,
|
|
462
|
+
historyEndpoint,
|
|
463
|
+
historyAuthToken,
|
|
464
|
+
protocol?.endpoint,
|
|
465
|
+
protocol?.authToken,
|
|
466
|
+
]);
|
|
467
|
+
// Keep in-memory store in sync with displayItems
|
|
468
|
+
useEffect(() => {
|
|
469
|
+
if (runtimeId && displayItems.length > 0) {
|
|
470
|
+
const messagesToSave = displayItems.filter((item) => !isToolCallMessage(item));
|
|
471
|
+
if (messagesToSave.length > 0) {
|
|
472
|
+
useConversationStore.getState().setMessages(runtimeId, messagesToSave);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}, [runtimeId, displayItems]);
|
|
476
|
+
// ---- Derived state ----
|
|
477
|
+
const messages = displayItems.filter((item) => !isToolCallMessage(item));
|
|
478
|
+
const ready = true;
|
|
479
|
+
const prevMessageCountRef = useRef(0);
|
|
480
|
+
useEffect(() => {
|
|
481
|
+
const currentCount = messages.length;
|
|
482
|
+
if (currentCount !== prevMessageCountRef.current) {
|
|
483
|
+
prevMessageCountRef.current = currentCount;
|
|
484
|
+
onMessagesChange?.(messages);
|
|
485
|
+
}
|
|
486
|
+
}, [displayItems, onMessagesChange]);
|
|
487
|
+
const padding = compact ? 2 : 3;
|
|
488
|
+
// Derive approval config from protocol for built-in tool approval support
|
|
489
|
+
const approvalConfig = useMemo(() => {
|
|
490
|
+
if (!protocol?.configEndpoint)
|
|
491
|
+
return undefined;
|
|
492
|
+
return {
|
|
493
|
+
apiBaseUrl: getApiBaseFromConfig(protocol.configEndpoint),
|
|
494
|
+
authToken: protocol.authToken,
|
|
495
|
+
};
|
|
496
|
+
}, [protocol?.configEndpoint, protocol?.authToken]);
|
|
497
|
+
const defaultAvatarConfig = {
|
|
498
|
+
userAvatar: _jsx(PersonIcon, { size: 16 }),
|
|
499
|
+
assistantAvatar: _jsx(AiAgentIcon, { size: 16 }),
|
|
500
|
+
showAvatars: true,
|
|
501
|
+
avatarSize: 32,
|
|
502
|
+
userAvatarBg: 'neutral.muted',
|
|
503
|
+
assistantAvatarBg: 'accent.emphasis',
|
|
504
|
+
...avatarConfig,
|
|
505
|
+
};
|
|
506
|
+
// ========================================================================
|
|
507
|
+
// Protocol adapter subscription
|
|
508
|
+
// ========================================================================
|
|
509
|
+
useEffect(() => {
|
|
510
|
+
if (!protocol)
|
|
511
|
+
return;
|
|
512
|
+
const adapter = createProtocolAdapter(protocol);
|
|
513
|
+
if (!adapter)
|
|
514
|
+
return;
|
|
515
|
+
adapterRef.current = adapter;
|
|
516
|
+
setAdapterReady(true);
|
|
517
|
+
unsubscribeRef.current = adapter.subscribe((event) => {
|
|
518
|
+
switch (event.type) {
|
|
519
|
+
case 'message':
|
|
520
|
+
if (suppressAssistantTextForToolOnlyRef.current) {
|
|
521
|
+
const suppressedMessageId = currentAssistantMessageRef.current?.id;
|
|
522
|
+
if (suppressedMessageId) {
|
|
523
|
+
setDisplayItems(prev => prev.filter(item => isToolCallMessage(item) || item.id !== suppressedMessageId));
|
|
524
|
+
if (useStoreMode) {
|
|
525
|
+
useChatStore.getState().deleteMessage(suppressedMessageId);
|
|
526
|
+
}
|
|
527
|
+
currentAssistantMessageRef.current = null;
|
|
528
|
+
}
|
|
529
|
+
break;
|
|
530
|
+
}
|
|
531
|
+
if (event.message) {
|
|
532
|
+
const incomingId = event.message.id;
|
|
533
|
+
const currentId = currentAssistantMessageRef.current?.id;
|
|
534
|
+
const isNewMessage = !currentId || (incomingId && incomingId !== currentId);
|
|
535
|
+
if (currentAssistantMessageRef.current && !isNewMessage) {
|
|
536
|
+
setDisplayItems(prev => {
|
|
537
|
+
const newItems = [...prev];
|
|
538
|
+
const idx = newItems.findIndex(item => !isToolCallMessage(item) &&
|
|
539
|
+
item.id === currentAssistantMessageRef.current?.id);
|
|
540
|
+
if (idx >= 0 && !isToolCallMessage(newItems[idx])) {
|
|
541
|
+
const rawContent = event.message?.content;
|
|
542
|
+
const sanitizedContent = typeof rawContent === 'string'
|
|
543
|
+
? sanitizeAssistantContent(rawContent)
|
|
544
|
+
: (rawContent ?? '');
|
|
545
|
+
newItems[idx] = {
|
|
546
|
+
...newItems[idx],
|
|
547
|
+
content: sanitizedContent,
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
return newItems;
|
|
551
|
+
});
|
|
552
|
+
if (useStoreMode && currentAssistantMessageRef.current) {
|
|
553
|
+
const rawContent = event.message?.content;
|
|
554
|
+
const sanitizedContent = typeof rawContent === 'string'
|
|
555
|
+
? sanitizeAssistantContent(rawContent)
|
|
556
|
+
: (rawContent ?? '');
|
|
557
|
+
useChatStore
|
|
558
|
+
.getState()
|
|
559
|
+
.updateMessage(currentAssistantMessageRef.current.id, {
|
|
560
|
+
content: sanitizedContent,
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
else {
|
|
565
|
+
const content = event.message.content;
|
|
566
|
+
const contentStr = typeof content === 'string' ? content : (content ?? '');
|
|
567
|
+
const sanitizedContent = typeof contentStr === 'string'
|
|
568
|
+
? sanitizeAssistantContent(contentStr)
|
|
569
|
+
: '';
|
|
570
|
+
const newMessage = createAssistantMessage(sanitizedContent);
|
|
571
|
+
newMessage.id = event.message.id || newMessage.id;
|
|
572
|
+
currentAssistantMessageRef.current = newMessage;
|
|
573
|
+
setDisplayItems(prev => {
|
|
574
|
+
const existingIdx = prev.findIndex(item => !isToolCallMessage(item) && item.id === newMessage.id);
|
|
575
|
+
if (existingIdx >= 0) {
|
|
576
|
+
const newItems = [...prev];
|
|
577
|
+
newItems[existingIdx] = {
|
|
578
|
+
...newItems[existingIdx],
|
|
579
|
+
content: sanitizedContent,
|
|
580
|
+
};
|
|
581
|
+
return newItems;
|
|
582
|
+
}
|
|
583
|
+
return [...prev, newMessage];
|
|
584
|
+
});
|
|
585
|
+
if (useStoreMode) {
|
|
586
|
+
const existingInStore = useChatStore
|
|
587
|
+
.getState()
|
|
588
|
+
.messages.find(m => m.id === newMessage.id);
|
|
589
|
+
if (existingInStore) {
|
|
590
|
+
useChatStore.getState().updateMessage(newMessage.id, {
|
|
591
|
+
content: sanitizedContent,
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
else {
|
|
595
|
+
useChatStore.getState().addMessage(newMessage);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
break;
|
|
601
|
+
case 'tool-call':
|
|
602
|
+
if (event.toolCall && !stoppedRef.current) {
|
|
603
|
+
const toolCallId = event.toolCall.toolCallId || generateMessageId();
|
|
604
|
+
const toolName = event.toolCall.toolName;
|
|
605
|
+
const args = event.toolCall.args || {};
|
|
606
|
+
if (toolCallsRef.current.has(toolCallId)) {
|
|
607
|
+
const existingToolCall = toolCallsRef.current.get(toolCallId);
|
|
608
|
+
if (existingToolCall) {
|
|
609
|
+
const updatedToolCall = {
|
|
610
|
+
...existingToolCall,
|
|
611
|
+
args: { ...existingToolCall.args, ...args },
|
|
612
|
+
};
|
|
613
|
+
toolCallsRef.current.set(toolCallId, updatedToolCall);
|
|
614
|
+
setDisplayItems(prev => prev.map(item => isToolCallMessage(item) && item.toolCallId === toolCallId
|
|
615
|
+
? updatedToolCall
|
|
616
|
+
: item));
|
|
617
|
+
const frontendTool = frontendToolsRef.current?.find(t => t.name === toolName);
|
|
618
|
+
const toolHandler = frontendTool?.handler;
|
|
619
|
+
if (toolHandler &&
|
|
620
|
+
existingToolCall.status === 'executing' &&
|
|
621
|
+
Object.keys(args).length > 0) {
|
|
622
|
+
pendingToolExecutionsRef.current++;
|
|
623
|
+
executeFrontendTool(toolHandler, updatedToolCall, toolCallId);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
else {
|
|
628
|
+
const toolCallMsg = {
|
|
629
|
+
id: `tool-${toolCallId}`,
|
|
630
|
+
type: 'tool-call',
|
|
631
|
+
toolCallId,
|
|
632
|
+
toolName,
|
|
633
|
+
args,
|
|
634
|
+
status: 'executing',
|
|
635
|
+
};
|
|
636
|
+
toolCallsRef.current.set(toolCallId, toolCallMsg);
|
|
637
|
+
setDisplayItems(prev => [...prev, toolCallMsg]);
|
|
638
|
+
const frontendTool = frontendToolsRef.current?.find(t => t.name === toolName);
|
|
639
|
+
const toolHandler = frontendTool?.handler;
|
|
640
|
+
// Only execute when we have actual args. AG-UI emits an
|
|
641
|
+
// initial tool-call with empty args on TOOL_CALL_START;
|
|
642
|
+
// the real args arrive on TOOL_CALL_END. Skip execution
|
|
643
|
+
// here and let the update branch (above) handle it once
|
|
644
|
+
// the full args are available.
|
|
645
|
+
if (toolHandler && Object.keys(args).length > 0) {
|
|
646
|
+
pendingToolExecutionsRef.current++;
|
|
647
|
+
executeFrontendTool(toolHandler, toolCallMsg, toolCallId);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
break;
|
|
652
|
+
case 'tool-result':
|
|
653
|
+
if (event.toolResult) {
|
|
654
|
+
const toolCallId = event.toolResult.toolCallId;
|
|
655
|
+
if (toolCallId && toolCallsRef.current.has(toolCallId)) {
|
|
656
|
+
const existingToolCall = toolCallsRef.current.get(toolCallId);
|
|
657
|
+
if (existingToolCall) {
|
|
658
|
+
const isHumanInTheLoop = existingToolCall.args &&
|
|
659
|
+
'steps' in existingToolCall.args &&
|
|
660
|
+
Array.isArray(existingToolCall.args.steps);
|
|
661
|
+
const resultData = event.toolResult.result;
|
|
662
|
+
let executionError;
|
|
663
|
+
let codeError;
|
|
664
|
+
let exitCode;
|
|
665
|
+
let isPendingApproval = false;
|
|
666
|
+
let hasError = !!event.toolResult.error;
|
|
667
|
+
if (resultData && typeof resultData === 'object') {
|
|
668
|
+
if ('pending_approval' in resultData &&
|
|
669
|
+
resultData.pending_approval === true) {
|
|
670
|
+
isPendingApproval = true;
|
|
671
|
+
}
|
|
672
|
+
if (resultData.execution_error &&
|
|
673
|
+
typeof resultData.execution_error === 'string') {
|
|
674
|
+
executionError = resultData.execution_error;
|
|
675
|
+
hasError = true;
|
|
676
|
+
}
|
|
677
|
+
if (resultData.code_error &&
|
|
678
|
+
typeof resultData.code_error === 'object') {
|
|
679
|
+
const ce = resultData.code_error;
|
|
680
|
+
codeError = {
|
|
681
|
+
name: ce.name || 'Error',
|
|
682
|
+
value: ce.value || 'Unknown error',
|
|
683
|
+
traceback: ce.traceback,
|
|
684
|
+
};
|
|
685
|
+
hasError = true;
|
|
686
|
+
}
|
|
687
|
+
if ('exit_code' in resultData) {
|
|
688
|
+
const ec = resultData.exit_code;
|
|
689
|
+
exitCode = typeof ec === 'number' ? ec : null;
|
|
690
|
+
if (exitCode != null && exitCode !== 0)
|
|
691
|
+
hasError = true;
|
|
692
|
+
}
|
|
693
|
+
if ('execution_ok' in resultData &&
|
|
694
|
+
resultData.execution_ok === false) {
|
|
695
|
+
hasError = true;
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
const updatedToolCall = {
|
|
699
|
+
...existingToolCall,
|
|
700
|
+
result: event.toolResult.result,
|
|
701
|
+
status: hasError
|
|
702
|
+
? 'error'
|
|
703
|
+
: isPendingApproval
|
|
704
|
+
? 'inProgress'
|
|
705
|
+
: isHumanInTheLoop
|
|
706
|
+
? 'executing'
|
|
707
|
+
: 'complete',
|
|
708
|
+
error: event.toolResult.error,
|
|
709
|
+
executionError,
|
|
710
|
+
codeError,
|
|
711
|
+
exitCode,
|
|
712
|
+
};
|
|
713
|
+
toolCallsRef.current.set(toolCallId, updatedToolCall);
|
|
714
|
+
setDisplayItems(prev => prev.map(item => isToolCallMessage(item) && item.toolCallId === toolCallId
|
|
715
|
+
? updatedToolCall
|
|
716
|
+
: item));
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
break;
|
|
721
|
+
case 'state-update':
|
|
722
|
+
onStateUpdate?.(event.data);
|
|
723
|
+
if (event.data) {
|
|
724
|
+
const executingToolCalls = Array.from(toolCallsRef.current.entries()).filter(([_, tc]) => tc.status === 'executing');
|
|
725
|
+
if (executingToolCalls.length > 0) {
|
|
726
|
+
const [lastToolCallId, existingToolCall] = executingToolCalls[executingToolCalls.length - 1];
|
|
727
|
+
const isHumanInTheLoop = existingToolCall.args &&
|
|
728
|
+
'steps' in existingToolCall.args &&
|
|
729
|
+
Array.isArray(existingToolCall.args.steps);
|
|
730
|
+
if (!isHumanInTheLoop) {
|
|
731
|
+
const stateData = event.data;
|
|
732
|
+
const result = stateData.weather ??
|
|
733
|
+
stateData.result ??
|
|
734
|
+
stateData.toolResult ??
|
|
735
|
+
stateData;
|
|
736
|
+
const updatedToolCall = {
|
|
737
|
+
...existingToolCall,
|
|
738
|
+
result,
|
|
739
|
+
status: 'complete',
|
|
740
|
+
};
|
|
741
|
+
toolCallsRef.current.set(lastToolCallId, updatedToolCall);
|
|
742
|
+
setDisplayItems(prev => prev.map(item => isToolCallMessage(item) &&
|
|
743
|
+
item.toolCallId === lastToolCallId
|
|
744
|
+
? updatedToolCall
|
|
745
|
+
: item));
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
break;
|
|
750
|
+
case 'done':
|
|
751
|
+
// The adapter signals the entire multi-turn conversation
|
|
752
|
+
// (including all continuations) has finished.
|
|
753
|
+
if (suppressAssistantTextForToolOnlyRef.current &&
|
|
754
|
+
hideMessagesAfterToolUIRef.current) {
|
|
755
|
+
setDisplayItems(prev => {
|
|
756
|
+
const hasAssistantContent = prev.some(item => !isToolCallMessage(item) &&
|
|
757
|
+
item.role === 'assistant' &&
|
|
758
|
+
String(item.content || '').trim().length > 0);
|
|
759
|
+
if (hasAssistantContent) {
|
|
760
|
+
return prev;
|
|
761
|
+
}
|
|
762
|
+
const latestCompletedTool = [...prev]
|
|
763
|
+
.reverse()
|
|
764
|
+
.find(item => isToolCallMessage(item) &&
|
|
765
|
+
item.status === 'complete' &&
|
|
766
|
+
item.result !== undefined);
|
|
767
|
+
if (!latestCompletedTool ||
|
|
768
|
+
!isToolCallMessage(latestCompletedTool)) {
|
|
769
|
+
return prev;
|
|
770
|
+
}
|
|
771
|
+
const fallbackMessage = createAssistantMessage(formatToolResultFallback(latestCompletedTool.result));
|
|
772
|
+
if (useStoreMode) {
|
|
773
|
+
useChatStore.getState().addMessage(fallbackMessage);
|
|
774
|
+
}
|
|
775
|
+
return [...prev, fallbackMessage];
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
suppressAssistantTextForToolOnlyRef.current = false;
|
|
779
|
+
pendingToolExecutionsRef.current = 0;
|
|
780
|
+
setIsLoading(false);
|
|
781
|
+
setIsStreaming(false);
|
|
782
|
+
break;
|
|
783
|
+
case 'error':
|
|
784
|
+
console.error('[ChatBase] Protocol error:', event.error);
|
|
785
|
+
if (event.error?.message &&
|
|
786
|
+
/exceeded maximum retries/i.test(event.error.message) &&
|
|
787
|
+
hideMessagesAfterToolUIRef.current) {
|
|
788
|
+
setDisplayItems(prev => {
|
|
789
|
+
const hasAssistantContent = prev.some(item => !isToolCallMessage(item) &&
|
|
790
|
+
item.role === 'assistant' &&
|
|
791
|
+
String(item.content || '').trim().length > 0);
|
|
792
|
+
if (hasAssistantContent) {
|
|
793
|
+
return prev;
|
|
794
|
+
}
|
|
795
|
+
const latestCompletedTool = [...prev]
|
|
796
|
+
.reverse()
|
|
797
|
+
.find(item => isToolCallMessage(item) &&
|
|
798
|
+
item.status === 'complete' &&
|
|
799
|
+
item.result !== undefined);
|
|
800
|
+
if (!latestCompletedTool ||
|
|
801
|
+
!isToolCallMessage(latestCompletedTool)) {
|
|
802
|
+
return prev;
|
|
803
|
+
}
|
|
804
|
+
const fallbackMessage = createAssistantMessage(formatToolResultFallback(latestCompletedTool.result));
|
|
805
|
+
if (useStoreMode) {
|
|
806
|
+
useChatStore.getState().addMessage(fallbackMessage);
|
|
807
|
+
}
|
|
808
|
+
return [...prev, fallbackMessage];
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
suppressAssistantTextForToolOnlyRef.current = false;
|
|
812
|
+
setError(event.error || new Error('Unknown error'));
|
|
813
|
+
pendingToolExecutionsRef.current = 0;
|
|
814
|
+
setIsLoading(false);
|
|
815
|
+
setIsStreaming(false);
|
|
816
|
+
break;
|
|
817
|
+
}
|
|
818
|
+
});
|
|
819
|
+
adapter.connect().catch(console.error);
|
|
820
|
+
return () => {
|
|
821
|
+
unsubscribeRef.current?.();
|
|
822
|
+
adapterRef.current?.disconnect();
|
|
823
|
+
};
|
|
824
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
825
|
+
}, [protocolKey, onStateUpdate, useStoreMode]);
|
|
826
|
+
// Helper to run a frontend tool and send result back via adapter
|
|
827
|
+
function executeFrontendTool(toolHandler, toolCallMsg, toolCallId) {
|
|
828
|
+
(async () => {
|
|
829
|
+
// If the user clicked Stop, skip executing this tool entirely.
|
|
830
|
+
if (stoppedRef.current) {
|
|
831
|
+
pendingToolExecutionsRef.current--;
|
|
832
|
+
if (pendingToolExecutionsRef.current < 0) {
|
|
833
|
+
pendingToolExecutionsRef.current = 0;
|
|
834
|
+
}
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
try {
|
|
838
|
+
const result = await toolHandler(toolCallMsg.args);
|
|
839
|
+
if (adapterRef.current) {
|
|
840
|
+
await adapterRef.current.sendToolResult(toolCallId, {
|
|
841
|
+
toolCallId,
|
|
842
|
+
success: true,
|
|
843
|
+
result,
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
const completedToolCall = {
|
|
847
|
+
...toolCallMsg,
|
|
848
|
+
result,
|
|
849
|
+
status: 'complete',
|
|
850
|
+
};
|
|
851
|
+
toolCallsRef.current.set(toolCallId, completedToolCall);
|
|
852
|
+
setDisplayItems(prev => prev.map(item => isToolCallMessage(item) && item.toolCallId === toolCallId
|
|
853
|
+
? completedToolCall
|
|
854
|
+
: item));
|
|
855
|
+
}
|
|
856
|
+
catch (err) {
|
|
857
|
+
console.error('[ChatBase] Frontend tool execution error:', err);
|
|
858
|
+
const errorToolCall = {
|
|
859
|
+
...toolCallMsg,
|
|
860
|
+
status: 'error',
|
|
861
|
+
error: err.message,
|
|
862
|
+
};
|
|
863
|
+
toolCallsRef.current.set(toolCallId, errorToolCall);
|
|
864
|
+
setDisplayItems(prev => prev.map(item => isToolCallMessage(item) && item.toolCallId === toolCallId
|
|
865
|
+
? errorToolCall
|
|
866
|
+
: item));
|
|
867
|
+
}
|
|
868
|
+
finally {
|
|
869
|
+
pendingToolExecutionsRef.current--;
|
|
870
|
+
if (pendingToolExecutionsRef.current < 0) {
|
|
871
|
+
pendingToolExecutionsRef.current = 0;
|
|
872
|
+
}
|
|
873
|
+
// NOTE: Do NOT reset isLoading here. The adapter's 'done' event
|
|
874
|
+
// is the sole authority for ending the loading state — it fires
|
|
875
|
+
// only when RUN_FINISHED arrives with no pending tool calls,
|
|
876
|
+
// meaning the entire multi-turn conversation is truly complete.
|
|
877
|
+
}
|
|
878
|
+
})();
|
|
879
|
+
}
|
|
880
|
+
// ---- Auto-scroll to bottom ----
|
|
881
|
+
useEffect(() => {
|
|
882
|
+
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
|
883
|
+
}, [displayItems]);
|
|
884
|
+
// ========================================================================
|
|
885
|
+
// handleSend
|
|
886
|
+
// ========================================================================
|
|
887
|
+
const handleSend = useCallback(async (messageOverride) => {
|
|
888
|
+
const messageContent = (messageOverride ?? input).trim();
|
|
889
|
+
if (!messageContent || isLoading)
|
|
890
|
+
return;
|
|
891
|
+
if (!adapterRef.current && !onSendMessage)
|
|
892
|
+
return;
|
|
893
|
+
stoppedRef.current = false;
|
|
894
|
+
suppressAssistantTextForToolOnlyRef.current =
|
|
895
|
+
isToolCallOnlyPrompt(messageContent);
|
|
896
|
+
const userMessage = createUserMessage(messageContent);
|
|
897
|
+
const currentMessages = displayItems.filter((item) => !isToolCallMessage(item));
|
|
898
|
+
const allMessages = [...currentMessages, userMessage];
|
|
899
|
+
setDisplayItems(prev => [...prev, userMessage]);
|
|
900
|
+
setInput('');
|
|
901
|
+
setIsLoading(true);
|
|
902
|
+
setIsStreaming(true);
|
|
903
|
+
setError(null);
|
|
904
|
+
currentAssistantMessageRef.current = null;
|
|
905
|
+
if (useStoreMode) {
|
|
906
|
+
useChatStore.getState().addMessage(userMessage);
|
|
907
|
+
}
|
|
908
|
+
try {
|
|
909
|
+
if (onSendMessage) {
|
|
910
|
+
if (enableStreaming) {
|
|
911
|
+
const assistantMessageId = generateMessageId();
|
|
912
|
+
const assistantMessage = createAssistantMessage('');
|
|
913
|
+
assistantMessage.id = assistantMessageId;
|
|
914
|
+
setDisplayItems(prev => [...prev, assistantMessage]);
|
|
915
|
+
currentAssistantMessageRef.current = assistantMessage;
|
|
916
|
+
if (useStoreMode) {
|
|
917
|
+
useChatStore.getState().addMessage(assistantMessage);
|
|
918
|
+
useChatStore.getState().startStreaming(assistantMessageId);
|
|
919
|
+
}
|
|
920
|
+
abortControllerRef.current = new AbortController();
|
|
921
|
+
await onSendMessage(messageContent, allMessages, {
|
|
922
|
+
onChunk: (chunk) => {
|
|
923
|
+
setDisplayItems(prev => prev.map(item => item.id === assistantMessageId
|
|
924
|
+
? {
|
|
925
|
+
...item,
|
|
926
|
+
content: item.content + chunk,
|
|
927
|
+
}
|
|
928
|
+
: item));
|
|
929
|
+
if (useStoreMode) {
|
|
930
|
+
useChatStore
|
|
931
|
+
.getState()
|
|
932
|
+
.appendToStream(assistantMessageId, chunk);
|
|
933
|
+
}
|
|
934
|
+
},
|
|
935
|
+
onComplete: (fullResponse) => {
|
|
936
|
+
setDisplayItems(prev => prev.map(item => item.id === assistantMessageId
|
|
937
|
+
? { ...item, content: fullResponse }
|
|
938
|
+
: item));
|
|
939
|
+
if (useStoreMode) {
|
|
940
|
+
useChatStore.getState().updateMessage(assistantMessageId, {
|
|
941
|
+
content: fullResponse,
|
|
942
|
+
});
|
|
943
|
+
useChatStore.getState().stopStreaming();
|
|
944
|
+
}
|
|
945
|
+
},
|
|
946
|
+
onError: (error) => {
|
|
947
|
+
const errorContent = `Error: ${error.message}`;
|
|
948
|
+
setDisplayItems(prev => prev.map(item => item.id === assistantMessageId
|
|
949
|
+
? { ...item, content: errorContent }
|
|
950
|
+
: item));
|
|
951
|
+
if (useStoreMode) {
|
|
952
|
+
useChatStore.getState().updateMessage(assistantMessageId, {
|
|
953
|
+
content: errorContent,
|
|
954
|
+
});
|
|
955
|
+
useChatStore.getState().stopStreaming();
|
|
956
|
+
}
|
|
957
|
+
setError(error);
|
|
958
|
+
},
|
|
959
|
+
signal: abortControllerRef.current.signal,
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
else {
|
|
963
|
+
const response = await onSendMessage(messageContent, allMessages);
|
|
964
|
+
if (response) {
|
|
965
|
+
const assistantMessage = createAssistantMessage(response);
|
|
966
|
+
setDisplayItems(prev => [...prev, assistantMessage]);
|
|
967
|
+
if (useStoreMode) {
|
|
968
|
+
useChatStore.getState().addMessage(assistantMessage);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
else if (adapterRef.current) {
|
|
974
|
+
const toolsForRequest = (frontendTools || []).map(tool => ({
|
|
975
|
+
name: tool.name,
|
|
976
|
+
description: tool.description,
|
|
977
|
+
parameters: tool.parameters || { type: 'object', properties: {} },
|
|
978
|
+
}));
|
|
979
|
+
console.log('[ChatBase] frontendTools count:', frontendTools?.length ?? 0, 'toolsForRequest:', toolsForRequest.map(t => t.name));
|
|
980
|
+
const enabledMcpToolNames = getEnabledMcpToolNames();
|
|
981
|
+
const enabledSkillIds = getEnabledSkillIds();
|
|
982
|
+
await adapterRef.current.sendMessage(userMessage, {
|
|
983
|
+
threadId: threadIdRef.current,
|
|
984
|
+
messages: allMessages,
|
|
985
|
+
...(selectedModel && { model: selectedModel }),
|
|
986
|
+
tools: toolsForRequest,
|
|
987
|
+
builtinTools: enabledMcpToolNames,
|
|
988
|
+
skills: enabledSkillIds,
|
|
989
|
+
identities: connectedIdentitiesRef.current,
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
catch (err) {
|
|
994
|
+
if (err.name !== 'AbortError') {
|
|
995
|
+
console.error('[ChatBase] Send error:', err);
|
|
996
|
+
const errorMessage = createAssistantMessage(`Error: ${err.message}`);
|
|
997
|
+
setDisplayItems(prev => [...prev, errorMessage]);
|
|
998
|
+
setError(err);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
finally {
|
|
1002
|
+
// NOTE: Do NOT reset isLoading here. The adapter's 'done' event
|
|
1003
|
+
// handles this — it fires only after the entire multi-turn
|
|
1004
|
+
// conversation (including all tool-call continuations) completes.
|
|
1005
|
+
// For the non-adapter path (onSendMessage), 'done' is never
|
|
1006
|
+
// emitted so we reset when no adapter is present.
|
|
1007
|
+
if (!adapterRef.current) {
|
|
1008
|
+
setIsLoading(false);
|
|
1009
|
+
setIsStreaming(false);
|
|
1010
|
+
}
|
|
1011
|
+
suppressAssistantTextForToolOnlyRef.current = false;
|
|
1012
|
+
currentAssistantMessageRef.current = null;
|
|
1013
|
+
abortControllerRef.current = null;
|
|
1014
|
+
}
|
|
1015
|
+
}, [
|
|
1016
|
+
input,
|
|
1017
|
+
isLoading,
|
|
1018
|
+
displayItems,
|
|
1019
|
+
selectedModel,
|
|
1020
|
+
frontendTools,
|
|
1021
|
+
useStoreMode,
|
|
1022
|
+
onSendMessage,
|
|
1023
|
+
enableStreaming,
|
|
1024
|
+
getEnabledMcpToolNames,
|
|
1025
|
+
getEnabledSkillIds,
|
|
1026
|
+
]);
|
|
1027
|
+
// Send pending prompt once history loaded and adapter/handler available
|
|
1028
|
+
useEffect(() => {
|
|
1029
|
+
if (!pendingPrompt || pendingPromptSentRef.current)
|
|
1030
|
+
return;
|
|
1031
|
+
if (pendingPromptKey && sentPendingPromptKeys.has(pendingPromptKey)) {
|
|
1032
|
+
pendingPromptSentRef.current = true;
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
if (!historyLoaded)
|
|
1036
|
+
return;
|
|
1037
|
+
if (!adapterReady && !onSendMessage)
|
|
1038
|
+
return;
|
|
1039
|
+
pendingPromptSentRef.current = true;
|
|
1040
|
+
if (pendingPromptKey) {
|
|
1041
|
+
sentPendingPromptKeys.add(pendingPromptKey);
|
|
1042
|
+
}
|
|
1043
|
+
queueMicrotask(() => handleSend(pendingPrompt));
|
|
1044
|
+
}, [
|
|
1045
|
+
pendingPrompt,
|
|
1046
|
+
pendingPromptKey,
|
|
1047
|
+
historyLoaded,
|
|
1048
|
+
adapterReady,
|
|
1049
|
+
handleSend,
|
|
1050
|
+
onSendMessage,
|
|
1051
|
+
]);
|
|
1052
|
+
// ---- handleStop ----
|
|
1053
|
+
const handleStop = useCallback(() => {
|
|
1054
|
+
stoppedRef.current = true;
|
|
1055
|
+
abortControllerRef.current?.abort();
|
|
1056
|
+
// Best-effort cancellation without tearing down adapter/session.
|
|
1057
|
+
const adapter = adapterRef.current;
|
|
1058
|
+
if (adapter) {
|
|
1059
|
+
// Abort the client-side SSE / fetch stream (if the adapter exposes it).
|
|
1060
|
+
if (typeof adapter.stopGeneration === 'function') {
|
|
1061
|
+
adapter.stopGeneration();
|
|
1062
|
+
}
|
|
1063
|
+
// Also tell the backend to stop (server-side cancellation).
|
|
1064
|
+
if (typeof adapter.terminateSession === 'function') {
|
|
1065
|
+
void adapter.terminateSession().catch(() => { });
|
|
1066
|
+
}
|
|
1067
|
+
else if (typeof adapter.terminateAgent === 'function') {
|
|
1068
|
+
void adapter.terminateAgent().catch(() => { });
|
|
1069
|
+
}
|
|
1070
|
+
else if (typeof adapter.terminateTask === 'function') {
|
|
1071
|
+
void adapter.terminateTask().catch(() => { });
|
|
1072
|
+
}
|
|
1073
|
+
else if (typeof adapter.terminateRequest === 'function') {
|
|
1074
|
+
void adapter.terminateRequest().catch(() => { });
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
// Mark in-flight tool calls as interrupted so UI doesn't remain "Executing".
|
|
1078
|
+
for (const [toolCallId, toolCall] of toolCallsRef.current.entries()) {
|
|
1079
|
+
if (toolCall.status === 'executing' || toolCall.status === 'inProgress') {
|
|
1080
|
+
toolCallsRef.current.set(toolCallId, {
|
|
1081
|
+
...toolCall,
|
|
1082
|
+
status: 'error',
|
|
1083
|
+
error: 'Interrupted by user',
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
setDisplayItems(prev => prev.map(item => {
|
|
1088
|
+
if (!isToolCallMessage(item))
|
|
1089
|
+
return item;
|
|
1090
|
+
if (item.status !== 'executing' && item.status !== 'inProgress') {
|
|
1091
|
+
return item;
|
|
1092
|
+
}
|
|
1093
|
+
return {
|
|
1094
|
+
...item,
|
|
1095
|
+
status: 'error',
|
|
1096
|
+
error: 'Interrupted by user',
|
|
1097
|
+
};
|
|
1098
|
+
}));
|
|
1099
|
+
if (useStoreMode) {
|
|
1100
|
+
useChatStore.getState().stopStreaming();
|
|
1101
|
+
}
|
|
1102
|
+
pendingToolExecutionsRef.current = 0;
|
|
1103
|
+
setIsLoading(false);
|
|
1104
|
+
setIsStreaming(false);
|
|
1105
|
+
suppressAssistantTextForToolOnlyRef.current = false;
|
|
1106
|
+
currentAssistantMessageRef.current = null;
|
|
1107
|
+
// Also interrupt any code running in the sandbox (best-effort).
|
|
1108
|
+
if (protocol?.configEndpoint) {
|
|
1109
|
+
const query = protocol.agentId
|
|
1110
|
+
? `?agent_id=${encodeURIComponent(protocol.agentId)}`
|
|
1111
|
+
: '';
|
|
1112
|
+
const interruptUrl = `${getApiBaseFromConfig(protocol.configEndpoint)}/configure/sandbox/interrupt${query}`;
|
|
1113
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
1114
|
+
if (protocol.authToken) {
|
|
1115
|
+
headers['Authorization'] = `Bearer ${protocol.authToken}`;
|
|
1116
|
+
}
|
|
1117
|
+
fetch(interruptUrl, { method: 'POST', headers }).catch(() => { });
|
|
1118
|
+
}
|
|
1119
|
+
}, [
|
|
1120
|
+
useStoreMode,
|
|
1121
|
+
protocol?.configEndpoint,
|
|
1122
|
+
protocol?.authToken,
|
|
1123
|
+
protocol?.agentId,
|
|
1124
|
+
]);
|
|
1125
|
+
// ---- handleNewChat ----
|
|
1126
|
+
const handleNewChat = useCallback(() => {
|
|
1127
|
+
setDisplayItems([]);
|
|
1128
|
+
toolCallsRef.current.clear();
|
|
1129
|
+
pendingToolExecutionsRef.current = 0;
|
|
1130
|
+
setInput('');
|
|
1131
|
+
threadIdRef.current = generateMessageId();
|
|
1132
|
+
if (useStoreMode)
|
|
1133
|
+
clearStoreMessages();
|
|
1134
|
+
if (runtimeId)
|
|
1135
|
+
useConversationStore.getState().clearMessages(runtimeId);
|
|
1136
|
+
onNewChat?.();
|
|
1137
|
+
headerButtons?.onNewChat?.();
|
|
1138
|
+
}, [clearStoreMessages, onNewChat, headerButtons, useStoreMode, runtimeId]);
|
|
1139
|
+
// ---- handleClear ----
|
|
1140
|
+
const handleClear = useCallback(() => {
|
|
1141
|
+
if (window.confirm('Clear all messages?')) {
|
|
1142
|
+
setDisplayItems([]);
|
|
1143
|
+
toolCallsRef.current.clear();
|
|
1144
|
+
if (useStoreMode)
|
|
1145
|
+
clearStoreMessages();
|
|
1146
|
+
if (runtimeId)
|
|
1147
|
+
useConversationStore.getState().clearMessages(runtimeId);
|
|
1148
|
+
onClear?.();
|
|
1149
|
+
headerButtons?.onClear?.();
|
|
1150
|
+
}
|
|
1151
|
+
}, [clearStoreMessages, onClear, headerButtons, useStoreMode, runtimeId]);
|
|
1152
|
+
// ---- handleSandboxInterrupt ----
|
|
1153
|
+
const handleSandboxInterrupt = useCallback(async () => {
|
|
1154
|
+
if (!protocol?.configEndpoint)
|
|
1155
|
+
return;
|
|
1156
|
+
const interruptUrl = `${getApiBaseFromConfig(protocol.configEndpoint)}/configure/sandbox/interrupt`;
|
|
1157
|
+
try {
|
|
1158
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
1159
|
+
if (protocol.authToken) {
|
|
1160
|
+
headers['Authorization'] = `Bearer ${protocol.authToken}`;
|
|
1161
|
+
}
|
|
1162
|
+
await fetch(interruptUrl, { method: 'POST', headers });
|
|
1163
|
+
sandboxStatusQuery.refetch();
|
|
1164
|
+
}
|
|
1165
|
+
catch {
|
|
1166
|
+
// Interrupt is best-effort
|
|
1167
|
+
}
|
|
1168
|
+
}, [protocol?.configEndpoint, protocol?.authToken, sandboxStatusQuery]);
|
|
1169
|
+
// ---- HITL respond handler (passed to MessageList) ----
|
|
1170
|
+
const handleRespond = useCallback(async (toolCallId, result) => {
|
|
1171
|
+
const existingToolCall = toolCallsRef.current.get(toolCallId);
|
|
1172
|
+
if (existingToolCall &&
|
|
1173
|
+
(existingToolCall.status === 'executing' ||
|
|
1174
|
+
existingToolCall.status === 'inProgress')) {
|
|
1175
|
+
const isApprovalDecision = !!result &&
|
|
1176
|
+
typeof result === 'object' &&
|
|
1177
|
+
result.type === 'tool-approval-decision' &&
|
|
1178
|
+
typeof result.approved === 'boolean';
|
|
1179
|
+
if (isApprovalDecision && adapterRef.current) {
|
|
1180
|
+
const approved = Boolean(result.approved);
|
|
1181
|
+
const updatedToolCall = {
|
|
1182
|
+
...existingToolCall,
|
|
1183
|
+
result,
|
|
1184
|
+
status: approved ? 'complete' : 'error',
|
|
1185
|
+
error: approved ? undefined : 'Tool approval rejected by user',
|
|
1186
|
+
};
|
|
1187
|
+
toolCallsRef.current.set(toolCallId, updatedToolCall);
|
|
1188
|
+
setDisplayItems(prev => prev.map(item => isToolCallMessage(item) && item.toolCallId === toolCallId
|
|
1189
|
+
? updatedToolCall
|
|
1190
|
+
: item));
|
|
1191
|
+
setIsLoading(true);
|
|
1192
|
+
setIsStreaming(true);
|
|
1193
|
+
try {
|
|
1194
|
+
const approvalId = typeof result === 'object' &&
|
|
1195
|
+
result !== null &&
|
|
1196
|
+
typeof result.approvalId === 'string'
|
|
1197
|
+
? result.approvalId
|
|
1198
|
+
: undefined;
|
|
1199
|
+
await adapterRef.current.sendToolResult(toolCallId, {
|
|
1200
|
+
toolCallId,
|
|
1201
|
+
success: approved,
|
|
1202
|
+
result: approved
|
|
1203
|
+
? {
|
|
1204
|
+
approved: true,
|
|
1205
|
+
message: 'Tool call approved by user.',
|
|
1206
|
+
...(approvalId ? { approvalId } : {}),
|
|
1207
|
+
}
|
|
1208
|
+
: {
|
|
1209
|
+
approved: false,
|
|
1210
|
+
message: 'Tool call rejected by user.',
|
|
1211
|
+
...(approvalId ? { approvalId } : {}),
|
|
1212
|
+
},
|
|
1213
|
+
...(approved
|
|
1214
|
+
? {}
|
|
1215
|
+
: { error: 'Tool approval rejected by user' }),
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
catch (err) {
|
|
1219
|
+
console.error('[ChatBase] Approval continuation error:', err);
|
|
1220
|
+
setError(err);
|
|
1221
|
+
}
|
|
1222
|
+
return;
|
|
1223
|
+
}
|
|
1224
|
+
const updatedToolCall = {
|
|
1225
|
+
...existingToolCall,
|
|
1226
|
+
result,
|
|
1227
|
+
status: 'complete',
|
|
1228
|
+
};
|
|
1229
|
+
toolCallsRef.current.set(toolCallId, updatedToolCall);
|
|
1230
|
+
setDisplayItems(prev => prev.map(item => isToolCallMessage(item) && item.toolCallId === toolCallId
|
|
1231
|
+
? updatedToolCall
|
|
1232
|
+
: item));
|
|
1233
|
+
if (adapterRef.current) {
|
|
1234
|
+
let responseText;
|
|
1235
|
+
if (typeof result === 'string') {
|
|
1236
|
+
responseText = result;
|
|
1237
|
+
}
|
|
1238
|
+
else if (result &&
|
|
1239
|
+
typeof result === 'object' &&
|
|
1240
|
+
'accepted' in result) {
|
|
1241
|
+
const hitlResult = result;
|
|
1242
|
+
if (hitlResult.accepted) {
|
|
1243
|
+
const stepDescriptions = hitlResult.steps?.map(s => s.description).join(', ') || '';
|
|
1244
|
+
responseText = stepDescriptions
|
|
1245
|
+
? `I confirm and approve the following steps: ${stepDescriptions}`
|
|
1246
|
+
: 'I confirm and approve the plan.';
|
|
1247
|
+
}
|
|
1248
|
+
else {
|
|
1249
|
+
responseText =
|
|
1250
|
+
'I reject this plan. Please suggest something else.';
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
else {
|
|
1254
|
+
responseText = JSON.stringify(result, null, 2);
|
|
1255
|
+
}
|
|
1256
|
+
const userMessage = {
|
|
1257
|
+
id: generateMessageId(),
|
|
1258
|
+
role: 'user',
|
|
1259
|
+
content: responseText,
|
|
1260
|
+
createdAt: new Date(),
|
|
1261
|
+
};
|
|
1262
|
+
setIsLoading(true);
|
|
1263
|
+
setIsStreaming(true);
|
|
1264
|
+
try {
|
|
1265
|
+
const allMessages = displayItems.filter((item) => !isToolCallMessage(item));
|
|
1266
|
+
await adapterRef.current.sendMessage(userMessage, {
|
|
1267
|
+
threadId: threadIdRef.current,
|
|
1268
|
+
messages: [...allMessages, userMessage],
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1271
|
+
catch (err) {
|
|
1272
|
+
console.error('[ChatBase] HITL respond error:', err);
|
|
1273
|
+
}
|
|
1274
|
+
// NOTE: Do NOT reset isLoading here — the adapter's 'done'
|
|
1275
|
+
// event will handle it when the run truly completes.
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
}, [displayItems]);
|
|
1279
|
+
// ---- Suggestion handlers (for EmptyState) ----
|
|
1280
|
+
const handleSuggestionSubmit = useCallback((suggestion) => {
|
|
1281
|
+
void handleSend(suggestion.message);
|
|
1282
|
+
}, [handleSend]);
|
|
1283
|
+
const handleSuggestionFill = useCallback((message) => {
|
|
1284
|
+
setInput(message);
|
|
1285
|
+
setTimeout(() => inputRef.current?.focus(), 0);
|
|
1286
|
+
}, []);
|
|
1287
|
+
// ---- Not ready ----
|
|
1288
|
+
if (!ready) {
|
|
1289
|
+
return (_jsx(Box, { className: className, sx: {
|
|
1290
|
+
display: 'flex',
|
|
1291
|
+
flexDirection: 'column',
|
|
1292
|
+
alignItems: 'center',
|
|
1293
|
+
justifyContent: 'center',
|
|
1294
|
+
height: '100%',
|
|
1295
|
+
p: 4,
|
|
1296
|
+
borderRadius,
|
|
1297
|
+
bg: backgroundColor || 'canvas.default',
|
|
1298
|
+
border,
|
|
1299
|
+
boxShadow,
|
|
1300
|
+
}, children: loadingState || (_jsxs(_Fragment, { children: [_jsx(Spinner, { size: "large" }), _jsx(Text, { sx: { mt: 3, color: 'fg.muted' }, children: "Initializing chat..." })] })) }));
|
|
1301
|
+
}
|
|
1302
|
+
// ---- apiBase for indicators (derived from configEndpoint) ----
|
|
1303
|
+
// Indicators (McpStatusIndicator, SandboxStatusIndicator) prepend
|
|
1304
|
+
// "/api/v1/configure/…" themselves, so we need the raw base URL
|
|
1305
|
+
// (without "/api/v1") rather than getApiBaseFromConfig() which keeps it.
|
|
1306
|
+
const indicatorApiBase = protocol?.configEndpoint
|
|
1307
|
+
? protocol.configEndpoint.replace(/\/api\/v1\/(config|configure)\/?$/, '')
|
|
1308
|
+
: undefined;
|
|
1309
|
+
// ---- Compute data for InputToolbar ----
|
|
1310
|
+
const filteredMcpServers = (configQuery.data?.mcpServers || []).filter(server => !mcpServers || isServerSelected(server));
|
|
1311
|
+
// ========================================================================
|
|
1312
|
+
// Render
|
|
1313
|
+
// ========================================================================
|
|
1314
|
+
return (_jsxs(Box, { className: className, sx: {
|
|
1315
|
+
display: 'flex',
|
|
1316
|
+
flexDirection: 'column',
|
|
1317
|
+
height: '100%',
|
|
1318
|
+
bg: backgroundColor || 'canvas.default',
|
|
1319
|
+
borderRadius,
|
|
1320
|
+
border,
|
|
1321
|
+
boxShadow,
|
|
1322
|
+
overflow: 'hidden',
|
|
1323
|
+
}, children: [showHeader && (_jsx(ChatBaseHeader, { title: title, brandIcon: brandIcon, headerContent: headerContent, headerActions: headerActions, showInformation: showInformation, onInformationClick: onInformationClick, padding: padding, sandboxStatus: sandboxStatus, onSandboxInterrupt: handleSandboxInterrupt, headerButtons: headerButtons, messageCount: messages.length, onNewChat: handleNewChat, onClear: handleClear, chatViewMode: chatViewMode, onChatViewModeChange: onChatViewModeChange })), showErrors && error && (_jsxs(Box, { sx: {
|
|
1324
|
+
display: 'flex',
|
|
1325
|
+
alignItems: 'center',
|
|
1326
|
+
gap: 2,
|
|
1327
|
+
p: padding,
|
|
1328
|
+
bg: 'danger.subtle',
|
|
1329
|
+
borderBottom: '1px solid',
|
|
1330
|
+
borderColor: 'danger.muted',
|
|
1331
|
+
}, children: [_jsx(AlertIcon, { size: 16 }), _jsx(Text, { sx: { color: 'danger.fg', fontSize: 1 }, children: error.message })] })), _jsx(Box, { sx: { flex: 1, flexGrow: 1, overflow: 'auto', bg: 'canvas.default' }, children: children ? (children) : (_jsx(Box, { sx: {
|
|
1332
|
+
display: 'flex',
|
|
1333
|
+
flexDirection: 'column',
|
|
1334
|
+
minHeight: '100%',
|
|
1335
|
+
bg: 'canvas.default',
|
|
1336
|
+
}, children: _jsx(ChatMessageList, { displayItems: displayItems, isLoading: isLoading, isStreaming: isStreaming, showLoadingIndicator: showLoadingIndicator, hideMessagesAfterToolUI: hideMessagesAfterToolUI, avatarConfig: defaultAvatarConfig, padding: padding, renderToolResult: renderToolResult, approvalConfig: approvalConfig, messagesEndRef: messagesEndRef, onRespond: handleRespond, emptyContent: _jsx(ChatEmptyState, { emptyState: emptyState, brandIcon: brandIcon, description: description, suggestions: suggestions, submitOnSuggestionClick: submitOnSuggestionClick, onSuggestionSubmit: handleSuggestionSubmit, onSuggestionFill: handleSuggestionFill }) }) })) }), footerContent, showInput && (_jsx(InputToolbar, { input: input, setInput: setInput, isLoading: isLoading, placeholder: placeholder, autoFocus: autoFocus, focusTrigger: focusTrigger, padding: padding, onSend: () => handleSend(), onStop: handleStop, showTokenUsage: showTokenUsage, agentUsage: agentUsage, showModelSelector: showModelSelector, showToolsMenu: showToolsMenu, showSkillsMenu: showSkillsMenu, codemodeEnabled: codemodeEnabled, isA2AProtocol: isA2AProtocol, hasConfigData: !!configQuery.data, hasSkillsData: !!skillsQuery.data, models: availableModels || configQuery.data?.models || [], selectedModel: selectedModel, onModelSelect: setSelectedModel, availableTools: configQuery.data?.builtinTools || [], mcpServers: filteredMcpServers, enabledMcpTools: enabledMcpTools, enabledMcpToolCount: getEnabledMcpToolNames().length, onToggleMcpTool: toggleMcpTool, onToggleAllMcpServerTools: toggleAllMcpServerTools, skills: skillsQuery.data?.skills || [], skillsLoading: !!skillsQuery.isLoading, enabledSkills: enabledSkills, onToggleSkill: toggleSkill, onToggleAllSkills: toggleAllSkills, apiBase: indicatorApiBase, authToken: protocol?.authToken, agentId: protocol?.agentId })), showPoweredBy && _jsx(PoweredByTag, { ...poweredByProps })] }));
|
|
1337
|
+
}
|
|
1338
|
+
export default ChatBase;
|