@datalayer/agent-runtimes 1.0.3 → 1.0.5
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 +35 -119
- package/lib/App.js +1 -1
- package/lib/agents/AgentDetails.d.ts +22 -1
- package/lib/agents/AgentDetails.js +34 -47
- package/lib/api/index.d.ts +0 -1
- package/lib/api/index.js +4 -2
- package/lib/chat/Chat.d.ts +5 -104
- package/lib/chat/Chat.js +4 -4
- package/lib/chat/ChatFloating.d.ts +7 -140
- package/lib/chat/ChatFloating.js +2 -2
- package/lib/chat/ChatPopupStandalone.d.ts +8 -47
- package/lib/chat/ChatPopupStandalone.js +3 -3
- package/lib/chat/ChatSidebar.d.ts +4 -69
- package/lib/chat/ChatSidebar.js +2 -2
- package/lib/chat/ChatStandalone.d.ts +4 -54
- package/lib/chat/ChatStandalone.js +3 -3
- package/lib/chat/base/ChatBase.js +1118 -141
- package/lib/chat/header/ChatHeaderBase.d.ts +11 -6
- package/lib/chat/header/ChatHeaderBase.js +18 -16
- package/lib/chat/indicators/McpStatusIndicator.d.ts +7 -4
- package/lib/chat/indicators/McpStatusIndicator.js +7 -32
- package/lib/chat/indicators/SandboxStatusIndicator.d.ts +4 -1
- package/lib/chat/indicators/SandboxStatusIndicator.js +9 -9
- package/lib/chat/indicators/SkillsStatusIndicator.d.ts +7 -0
- package/lib/chat/indicators/SkillsStatusIndicator.js +88 -0
- package/lib/chat/indicators/index.d.ts +1 -0
- package/lib/chat/indicators/index.js +1 -0
- package/lib/chat/messages/ChatMessageList.d.ts +1 -1
- package/lib/chat/messages/ChatMessageList.js +110 -102
- package/lib/chat/prompt/InputFooter.d.ts +19 -6
- package/lib/chat/prompt/InputFooter.js +71 -18
- package/lib/chat/prompt/InputPrompt.d.ts +3 -1
- package/lib/chat/prompt/InputPrompt.js +4 -4
- package/lib/chat/prompt/InputPromptFooter.js +1 -1
- package/lib/chat/prompt/InputPromptLexical.d.ts +3 -1
- package/lib/chat/prompt/InputPromptLexical.js +12 -5
- package/lib/chat/prompt/InputPromptText.d.ts +3 -1
- package/lib/chat/prompt/InputPromptText.js +2 -2
- package/lib/chat/tools/ToolApprovalBanner.js +1 -1
- package/lib/chat/tools/ToolCallDisplay.d.ts +3 -1
- package/lib/chat/tools/ToolCallDisplay.js +2 -2
- package/lib/chat/usage/TokenUsageBar.js +20 -2
- package/lib/client/AgentRuntimesClientContext.d.ts +53 -0
- package/lib/client/AgentRuntimesClientContext.js +55 -0
- package/lib/client/AgentsMixin.d.ts +48 -19
- package/lib/client/AgentsMixin.js +115 -30
- package/lib/client/IAgentRuntimesClient.d.ts +215 -0
- package/lib/client/IAgentRuntimesClient.js +5 -0
- package/lib/client/SdkAgentRuntimesClient.d.ts +151 -0
- package/lib/client/SdkAgentRuntimesClient.js +134 -0
- package/lib/client/index.d.ts +4 -1
- package/lib/client/index.js +3 -1
- package/lib/components/NotificationEventCard.js +55 -26
- package/lib/components/OutputCard.js +21 -7
- package/lib/components/ToolApprovalCard.js +20 -2
- package/lib/config/AgentConfiguration.js +3 -3
- package/lib/context/ContextDistribution.d.ts +3 -1
- package/lib/context/ContextDistribution.js +8 -27
- package/lib/context/ContextInspector.d.ts +3 -1
- package/lib/context/ContextInspector.js +19 -67
- package/lib/context/ContextPanel.d.ts +3 -1
- package/lib/context/ContextPanel.js +104 -64
- package/lib/context/ContextUsage.d.ts +3 -1
- package/lib/context/ContextUsage.js +3 -3
- package/lib/context/CostTracker.d.ts +9 -3
- package/lib/context/CostTracker.js +26 -47
- package/lib/context/CostUsageChart.d.ts +12 -0
- package/lib/context/CostUsageChart.js +378 -0
- package/lib/context/GraphFlowChart.d.ts +16 -0
- package/lib/context/GraphFlowChart.js +182 -0
- package/lib/context/TokenUsageChart.d.ts +8 -1
- package/lib/context/TokenUsageChart.js +349 -211
- package/lib/context/TurnGraphChart.d.ts +39 -0
- package/lib/context/TurnGraphChart.js +538 -0
- package/lib/context/otelWsPool.d.ts +20 -0
- package/lib/context/otelWsPool.js +69 -0
- package/lib/examples/A2UiComponentGalleryExample.d.ts +0 -17
- package/lib/examples/A2UiComponentGalleryExample.js +315 -522
- package/lib/examples/A2UiContactCardExample.d.ts +0 -18
- package/lib/examples/A2UiContactCardExample.js +154 -411
- package/lib/examples/A2UiRestaurantExample.d.ts +0 -30
- package/lib/examples/A2UiRestaurantExample.js +114 -212
- package/lib/examples/A2UiViewerExample.d.ts +0 -18
- package/lib/examples/A2UiViewerExample.js +283 -532
- package/lib/examples/AgUiBackendToolRenderingExample.js +1 -1
- package/lib/examples/AgUiHaikuGenUiExample.d.ts +1 -1
- package/lib/examples/AgUiHaikuGenUiExample.js +1 -1
- package/lib/examples/AgentCheckpointsExample.js +14 -34
- package/lib/examples/AgentCodemodeExample.d.ts +4 -6
- package/lib/examples/AgentCodemodeExample.js +591 -175
- package/lib/examples/AgentEvalsExample.js +13 -23
- package/lib/examples/AgentGuardrailsExample.js +371 -71
- package/lib/examples/AgentHooksExample.d.ts +3 -0
- package/lib/examples/AgentHooksExample.js +104 -0
- package/lib/examples/AgentMCPExample.d.ts +3 -0
- package/lib/examples/AgentMCPExample.js +480 -0
- package/lib/examples/AgentMemoryExample.js +14 -24
- package/lib/examples/AgentMonitoringExample.js +261 -206
- package/lib/examples/AgentNotificationsExample.js +50 -24
- package/lib/examples/AgentOtelExample.js +2 -3
- package/lib/examples/AgentOutputsExample.d.ts +11 -6
- package/lib/examples/AgentOutputsExample.js +383 -88
- package/lib/examples/AgentParametersExample.d.ts +3 -0
- package/lib/examples/AgentParametersExample.js +246 -0
- package/lib/examples/AgentSandboxExample.d.ts +2 -2
- package/lib/examples/AgentSandboxExample.js +69 -47
- package/lib/examples/AgentSkillsExample.js +92 -106
- package/lib/examples/{AgentspecExample.js → AgentSpecsExample.js} +10 -21
- package/lib/examples/AgentSubagentsExample.d.ts +14 -0
- package/lib/examples/AgentSubagentsExample.js +228 -0
- package/lib/examples/AgentToolApprovalsExample.js +30 -493
- package/lib/examples/AgentTriggersExample.js +1067 -246
- package/lib/examples/ChatCustomExample.js +11 -24
- package/lib/examples/ChatExample.js +9 -34
- package/lib/examples/CopilotKitLexicalExample.js +2 -1
- package/lib/examples/CopilotKitNotebookExample.js +2 -1
- package/lib/examples/HomeExample.d.ts +15 -0
- package/lib/examples/HomeExample.js +77 -0
- package/lib/examples/Lexical2Example.js +4 -2
- package/lib/examples/{LexicalExample.d.ts → LexicalAgentExample.d.ts} +4 -4
- package/lib/examples/{LexicalExample.js → LexicalAgentExample.js} +65 -16
- package/lib/examples/{LexicalSidebarExample.d.ts → LexicalAgentSidebarExample.d.ts} +5 -5
- package/lib/examples/LexicalAgentSidebarExample.js +261 -0
- package/lib/examples/NotebookAgentExample.d.ts +9 -0
- package/lib/examples/NotebookAgentExample.js +192 -0
- package/lib/examples/{NotebookSidebarExample.d.ts → NotebookAgentSidebarExample.d.ts} +2 -2
- package/lib/examples/NotebookAgentSidebarExample.js +221 -0
- package/lib/examples/{DatalayerNotebookExample.d.ts → NotebookCollaborationExample.d.ts} +4 -4
- package/lib/examples/{DatalayerNotebookExample.js → NotebookCollaborationExample.js} +3 -3
- package/lib/examples/NotebookExample.d.ts +4 -7
- package/lib/examples/NotebookExample.js +14 -146
- package/lib/examples/components/AuthRequiredView.d.ts +6 -0
- package/lib/examples/components/AuthRequiredView.js +33 -0
- package/lib/examples/components/ErrorView.d.ts +14 -0
- package/lib/examples/components/ErrorView.js +20 -0
- package/lib/examples/components/ExampleWrapper.d.ts +7 -0
- package/lib/examples/components/ExampleWrapper.js +25 -6
- package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.js +1 -1
- package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.js +1 -1
- package/lib/examples/{ag-ui → components}/haiku/index.d.ts +1 -1
- package/lib/examples/{ag-ui → components}/haiku/index.js +1 -1
- package/lib/examples/components/index.d.ts +5 -0
- package/lib/examples/components/index.js +5 -0
- package/lib/examples/{ag-ui → components}/weather/index.d.ts +1 -1
- package/lib/examples/{ag-ui → components}/weather/index.js +1 -1
- package/lib/examples/example-selector.d.ts +17 -4
- package/lib/examples/example-selector.js +107 -41
- package/lib/examples/index.d.ts +9 -6
- package/lib/examples/index.js +9 -6
- package/lib/examples/main.d.ts +1 -0
- package/lib/examples/main.js +218 -27
- package/lib/examples/utils/a2ui.d.ts +18 -0
- package/lib/examples/utils/a2ui.js +69 -0
- package/lib/examples/utils/a2uiMarkdownProvider.d.ts +7 -0
- package/lib/examples/utils/a2uiMarkdownProvider.js +9 -0
- package/lib/examples/utils/agentId.d.ts +18 -0
- package/lib/examples/utils/agentId.js +54 -0
- package/lib/examples/utils/agents/earthquake-detector.json +11 -11
- package/lib/examples/utils/agents/sales-forecaster.json +11 -11
- package/lib/examples/utils/agents/social-post-generator.json +11 -11
- package/lib/examples/utils/agents/stock-market.json +11 -11
- package/lib/examples/utils/examplesStore.js +82 -27
- package/lib/hooks/index.d.ts +8 -8
- package/lib/hooks/index.js +7 -7
- package/lib/hooks/useA2A.d.ts +2 -3
- package/lib/hooks/useAIAgentsWebSocket.d.ts +43 -4
- package/lib/hooks/useAIAgentsWebSocket.js +118 -12
- package/lib/hooks/useAcp.d.ts +1 -2
- package/lib/hooks/useAgUi.d.ts +1 -1
- package/lib/hooks/{useAgents.d.ts → useAgentRuntimes.d.ts} +39 -2
- package/lib/hooks/{useAgents.js → useAgentRuntimes.js} +125 -15
- package/lib/hooks/useAgentsCatalog.js +1 -1
- package/lib/hooks/useAgentsService.d.ts +2 -2
- package/lib/hooks/useAgentsService.js +7 -7
- package/lib/hooks/useCheckpoints.js +1 -1
- package/lib/hooks/useConfig.d.ts +4 -1
- package/lib/hooks/useConfig.js +10 -3
- package/lib/hooks/useContextSnapshot.d.ts +9 -4
- package/lib/hooks/useContextSnapshot.js +9 -37
- package/lib/hooks/useMonitoring.js +3 -0
- package/lib/hooks/useSandbox.d.ts +20 -8
- package/lib/hooks/useSandbox.js +105 -40
- package/lib/hooks/useSkills.d.ts +23 -5
- package/lib/hooks/useSkills.js +94 -39
- package/lib/hooks/useToolApprovals.d.ts +60 -36
- package/lib/hooks/useToolApprovals.js +318 -69
- package/lib/hooks/useVercelAI.d.ts +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +1 -0
- package/lib/inference/index.d.ts +0 -1
- package/lib/middleware/index.d.ts +0 -1
- package/lib/protocols/AGUIAdapter.js +6 -0
- package/lib/protocols/VercelAIAdapter.d.ts +9 -0
- package/lib/protocols/VercelAIAdapter.js +144 -26
- package/lib/shims/json5.d.ts +4 -0
- package/lib/shims/json5.js +8 -0
- package/lib/specs/agents/agents.d.ts +10 -0
- package/lib/specs/agents/agents.js +752 -24
- package/lib/specs/envvars.d.ts +1 -0
- package/lib/specs/envvars.js +11 -0
- package/lib/specs/events.d.ts +1 -0
- package/lib/specs/events.js +1 -0
- package/lib/specs/index.d.ts +1 -0
- package/lib/specs/index.js +1 -0
- package/lib/specs/personas.d.ts +41 -0
- package/lib/specs/personas.js +168 -0
- package/lib/specs/skills.d.ts +2 -1
- package/lib/specs/skills.js +23 -5
- package/lib/specs/tools.js +3 -0
- package/lib/stores/agentRuntimeStore.d.ts +204 -0
- package/lib/stores/agentRuntimeStore.js +636 -0
- package/lib/stores/index.d.ts +1 -1
- package/lib/stores/index.js +1 -1
- package/lib/tools/adapters/copilotkit/lexicalHooks.d.ts +1 -2
- package/lib/tools/adapters/copilotkit/lexicalHooks.js +1 -3
- package/lib/tools/adapters/copilotkit/notebookHooks.d.ts +1 -2
- package/lib/tools/adapters/copilotkit/notebookHooks.js +1 -3
- package/lib/tools/index.d.ts +0 -2
- package/lib/tools/index.js +0 -1
- package/lib/types/agentspecs.d.ts +50 -1
- package/lib/types/chat.d.ts +309 -8
- package/lib/types/context.d.ts +27 -0
- package/lib/types/cost.d.ts +2 -2
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.js +2 -0
- package/lib/types/mcp.d.ts +8 -0
- package/lib/types/models.d.ts +2 -2
- package/lib/types/personas.d.ts +25 -0
- package/lib/types/personas.js +5 -0
- package/lib/types/skills.d.ts +43 -1
- package/lib/types/stream.d.ts +110 -0
- package/lib/types/stream.js +36 -0
- package/lib/types/tools.d.ts +2 -0
- package/lib/utils/utils.d.ts +9 -5
- package/lib/utils/utils.js +9 -5
- package/package.json +13 -9
- package/scripts/codegen/__pycache__/generate_agents.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_events.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
- package/scripts/codegen/generate_agents.py +106 -7
- package/scripts/codegen/generate_events.py +47 -17
- package/scripts/codegen/generate_personas.py +319 -0
- package/scripts/codegen/generate_skills.py +9 -9
- package/scripts/codegen/generate_tools.py +20 -0
- package/scripts/sync-jupyter.sh +26 -7
- package/style/primer-primitives.css +1 -6
- package/lib/api/tool-approvals.d.ts +0 -62
- package/lib/api/tool-approvals.js +0 -145
- package/lib/examples/LexicalSidebarExample.js +0 -163
- package/lib/examples/NotebookSidebarExample.js +0 -119
- package/lib/examples/NotebookSimpleExample.d.ts +0 -6
- package/lib/examples/NotebookSimpleExample.js +0 -22
- package/lib/examples/ag-ui/index.d.ts +0 -10
- package/lib/examples/ag-ui/index.js +0 -16
- package/lib/hooks/useAgentsRegistry.d.ts +0 -10
- package/lib/hooks/useAgentsRegistry.js +0 -20
- package/lib/stores/agentsStore.d.ts +0 -123
- package/lib/stores/agentsStore.js +0 -270
- package/scripts/codegen/__pycache__/generate_envvars.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_evals.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_guardrails.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_mcp_servers.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_memory.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_models.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_notifications.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_outputs.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_skills.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_teams.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_tools.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_triggers.cpython-313.pyc +0 -0
- /package/lib/examples/{AgentspecExample.d.ts → AgentSpecsExample.d.ts} +0 -0
- /package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.d.ts +0 -0
- /package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.d.ts +0 -0
- /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.d.ts +0 -0
- /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.js +0 -0
|
@@ -1,20 +1,27 @@
|
|
|
1
|
-
import type { BuiltinTool, ContextSnapshotData, MCPServerConfig, ModelConfig, SkillInfo } from '../../types';
|
|
1
|
+
import type { BuiltinTool, ContextSnapshotData, MCPServerConfig, McpToolsetsStatusResponse, ModelConfig, SkillInfo } from '../../types';
|
|
2
2
|
export interface InputToolbarProps {
|
|
3
3
|
input: string;
|
|
4
4
|
setInput: (value: string) => void;
|
|
5
5
|
isLoading: boolean;
|
|
6
|
+
connectionConfirmed: boolean;
|
|
6
7
|
placeholder?: string;
|
|
7
8
|
autoFocus: boolean;
|
|
8
9
|
focusTrigger?: number;
|
|
9
10
|
padding: number;
|
|
10
11
|
onSend: () => void;
|
|
11
12
|
onStop: () => void;
|
|
13
|
+
disableInputPrompt?: boolean;
|
|
12
14
|
showTokenUsage: boolean;
|
|
13
15
|
agentUsage?: ContextSnapshotData;
|
|
14
16
|
showModelSelector: boolean;
|
|
15
17
|
showToolsMenu: boolean;
|
|
16
18
|
showSkillsMenu: boolean;
|
|
17
19
|
codemodeEnabled: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Optional callback invoked when the user toggles codemode from the Tools
|
|
22
|
+
* menu. When omitted the toggle renders as read-only.
|
|
23
|
+
*/
|
|
24
|
+
onToggleCodemode?: (enabled: boolean) => void | Promise<void>;
|
|
18
25
|
isA2AProtocol: boolean;
|
|
19
26
|
hasConfigData: boolean;
|
|
20
27
|
hasSkillsData: boolean;
|
|
@@ -28,16 +35,22 @@ export interface InputToolbarProps {
|
|
|
28
35
|
enabledMcpToolCount: number;
|
|
29
36
|
onToggleMcpTool: (serverId: string, toolName: string) => void;
|
|
30
37
|
onToggleAllMcpServerTools: (serverId: string, toolNames: string[], enable: boolean) => void;
|
|
38
|
+
/** Approved MCP tools per server (default: all tools approved) */
|
|
39
|
+
approvedMcpTools: Map<string, Set<string>>;
|
|
40
|
+
onToggleMcpToolApproval: (serverId: string, toolName: string) => void;
|
|
31
41
|
skills: SkillInfo[];
|
|
32
42
|
skillsLoading: boolean;
|
|
33
43
|
enabledSkills: Set<string>;
|
|
34
44
|
onToggleSkill: (skillId: string) => void;
|
|
35
45
|
onToggleAllSkills: (skillIds: string[], enable: boolean) => void;
|
|
36
|
-
/**
|
|
46
|
+
/** Approved skills set (default: all skills approved) */
|
|
47
|
+
approvedSkills: Set<string>;
|
|
48
|
+
onToggleSkillApproval: (skillId: string) => void;
|
|
49
|
+
/** API base URL passed to MCP indicator */
|
|
37
50
|
apiBase?: string;
|
|
38
|
-
/** Auth token passed to MCP
|
|
51
|
+
/** Auth token passed to MCP indicator */
|
|
39
52
|
authToken?: string;
|
|
40
|
-
/**
|
|
41
|
-
|
|
53
|
+
/** Pre-fetched MCP status from WebSocket — bypasses REST polling */
|
|
54
|
+
mcpStatusData?: McpToolsetsStatusResponse | null;
|
|
42
55
|
}
|
|
43
|
-
export declare function InputToolbar({ input, setInput, isLoading, placeholder, autoFocus, focusTrigger, padding, onSend, onStop, showTokenUsage, agentUsage, showModelSelector, showToolsMenu, showSkillsMenu, codemodeEnabled, isA2AProtocol, hasConfigData, hasSkillsData, models, selectedModel, onModelSelect, availableTools, mcpServers, enabledMcpTools, enabledMcpToolCount, onToggleMcpTool, onToggleAllMcpServerTools, skills, skillsLoading, enabledSkills, onToggleSkill, onToggleAllSkills, apiBase, authToken,
|
|
56
|
+
export declare function InputToolbar({ input, setInput, isLoading, connectionConfirmed, placeholder, autoFocus, focusTrigger, padding, onSend, onStop, disableInputPrompt, showTokenUsage, agentUsage, showModelSelector, showToolsMenu, showSkillsMenu, codemodeEnabled, onToggleCodemode, isA2AProtocol, hasConfigData, hasSkillsData, models, selectedModel, onModelSelect, availableTools, mcpServers, enabledMcpTools, enabledMcpToolCount, onToggleMcpTool, onToggleAllMcpServerTools, approvedMcpTools, onToggleMcpToolApproval, skills, skillsLoading, enabledSkills, onToggleSkill, onToggleAllSkills, approvedSkills, onToggleSkillApproval, apiBase, authToken, mcpStatusData, }: InputToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -17,14 +17,14 @@ import { ToolsIcon, BriefcaseIcon, AiModelIcon } from '@primer/octicons-react';
|
|
|
17
17
|
import { InputPrompt } from './InputPrompt';
|
|
18
18
|
import { TokenUsageBar } from '../usage/TokenUsageBar';
|
|
19
19
|
import { McpStatusIndicator } from '../indicators/McpStatusIndicator';
|
|
20
|
-
import {
|
|
20
|
+
import { SkillsStatusIndicator } from '../indicators/SkillsStatusIndicator';
|
|
21
21
|
// ---------------------------------------------------------------------------
|
|
22
22
|
// Component
|
|
23
23
|
// ---------------------------------------------------------------------------
|
|
24
|
-
export function InputToolbar({ input, setInput, isLoading, placeholder, autoFocus, focusTrigger, padding, onSend, onStop, showTokenUsage, agentUsage, showModelSelector, showToolsMenu, showSkillsMenu, codemodeEnabled, isA2AProtocol, hasConfigData, hasSkillsData, models, selectedModel, onModelSelect, availableTools, mcpServers, enabledMcpTools, enabledMcpToolCount, onToggleMcpTool, onToggleAllMcpServerTools, skills, skillsLoading, enabledSkills, onToggleSkill, onToggleAllSkills, apiBase, authToken,
|
|
24
|
+
export function InputToolbar({ input, setInput, isLoading, connectionConfirmed, placeholder, autoFocus, focusTrigger, padding, onSend, onStop, disableInputPrompt = false, showTokenUsage, agentUsage, showModelSelector, showToolsMenu, showSkillsMenu, codemodeEnabled, onToggleCodemode, isA2AProtocol, hasConfigData, hasSkillsData, models, selectedModel, onModelSelect, availableTools, mcpServers, enabledMcpTools, enabledMcpToolCount, onToggleMcpTool, onToggleAllMcpServerTools, approvedMcpTools, onToggleMcpToolApproval, skills, skillsLoading, enabledSkills, onToggleSkill, onToggleAllSkills, approvedSkills, onToggleSkillApproval, apiBase, authToken, mcpStatusData, }) {
|
|
25
25
|
// Show token usage when we have valid context data
|
|
26
|
-
const hasContext = agentUsage && !agentUsage.error && agentUsage.totalTokens > 0;
|
|
27
|
-
return (_jsxs(Box, { children: [_jsx(InputPrompt, { placeholder: placeholder || 'Type a message...', isLoading: isLoading, onSend: onSend, onStop: onStop, autoFocus: autoFocus, focusTrigger: focusTrigger, padding: padding, value: input, onChange: setInput, footerRightContent: _jsxs(_Fragment, { children: [_jsx(
|
|
26
|
+
const hasContext = Boolean(agentUsage && !agentUsage.error && agentUsage.totalTokens > 0);
|
|
27
|
+
return (_jsxs(Box, { children: [_jsx(InputPrompt, { placeholder: placeholder || 'Type a message...', isLoading: isLoading, disabled: disableInputPrompt, readOnly: !connectionConfirmed, onSend: onSend, onStop: onStop, autoFocus: autoFocus, focusTrigger: focusTrigger, padding: padding, value: input, onChange: setInput, footerRightContent: _jsxs(_Fragment, { children: [_jsx(McpStatusIndicator, { apiBase: apiBase, authToken: authToken, data: mcpStatusData }), _jsx(SkillsStatusIndicator, { skillsCount: skills.length, enabledCount: enabledSkills.size, loading: skillsLoading })] }) }), showTokenUsage && hasContext && agentUsage && (_jsx(TokenUsageBar, { agentUsage: agentUsage, padding: padding })), (showModelSelector || showToolsMenu || showSkillsMenu) &&
|
|
28
28
|
(hasConfigData || hasSkillsData) && (_jsxs(Box, { sx: {
|
|
29
29
|
display: 'flex',
|
|
30
30
|
gap: 2,
|
|
@@ -34,13 +34,29 @@ export function InputToolbar({ input, setInput, isLoading, placeholder, autoFocu
|
|
|
34
34
|
borderColor: 'border.default',
|
|
35
35
|
alignItems: 'center',
|
|
36
36
|
bg: 'canvas.subtle',
|
|
37
|
-
}, children: [showToolsMenu && (_jsx(ToolsMenu, { codemodeEnabled: codemodeEnabled, mcpServers: mcpServers, enabledMcpTools: enabledMcpTools, enabledMcpToolCount: enabledMcpToolCount, onToggleMcpTool: onToggleMcpTool, onToggleAllMcpServerTools: onToggleAllMcpServerTools, availableTools: availableTools })), showSkillsMenu && (_jsx(SkillsMenu, { skills: skills, skillsLoading: skillsLoading, enabledSkills: enabledSkills, onToggleSkill: onToggleSkill, onToggleAllSkills: onToggleAllSkills })), showModelSelector && models.length > 0 && selectedModel && (_jsx(ModelSelector, { models: models, selectedModel: selectedModel, onModelSelect: onModelSelect, isA2AProtocol: isA2AProtocol }))] }))] }));
|
|
37
|
+
}, children: [showToolsMenu && (_jsx(ToolsMenu, { codemodeEnabled: codemodeEnabled, onToggleCodemode: onToggleCodemode, mcpServers: mcpServers, enabledMcpTools: enabledMcpTools, enabledMcpToolCount: enabledMcpToolCount, onToggleMcpTool: onToggleMcpTool, onToggleAllMcpServerTools: onToggleAllMcpServerTools, approvedMcpTools: approvedMcpTools, onToggleMcpToolApproval: onToggleMcpToolApproval, availableTools: availableTools })), showSkillsMenu && (_jsx(SkillsMenu, { skills: skills, skillsLoading: skillsLoading, enabledSkills: enabledSkills, onToggleSkill: onToggleSkill, onToggleAllSkills: onToggleAllSkills, approvedSkills: approvedSkills, onToggleSkillApproval: onToggleSkillApproval })), showModelSelector && models.length > 0 && selectedModel && (_jsx(ModelSelector, { models: models, selectedModel: selectedModel, onModelSelect: onModelSelect, isA2AProtocol: isA2AProtocol }))] }))] }));
|
|
38
38
|
}
|
|
39
39
|
// ---------------------------------------------------------------------------
|
|
40
40
|
// ToolsMenu (private sub-component)
|
|
41
41
|
// ---------------------------------------------------------------------------
|
|
42
|
-
function ToolsMenu({ codemodeEnabled, mcpServers, enabledMcpTools, enabledMcpToolCount, onToggleMcpTool, onToggleAllMcpServerTools, availableTools, }) {
|
|
43
|
-
|
|
42
|
+
function ToolsMenu({ codemodeEnabled, onToggleCodemode, mcpServers, enabledMcpTools, enabledMcpToolCount, onToggleMcpTool, onToggleAllMcpServerTools, approvedMcpTools, onToggleMcpToolApproval, availableTools: _availableTools, }) {
|
|
43
|
+
const hasUsableMcpServers = mcpServers.some(server => server.isAvailable);
|
|
44
|
+
return (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Button, { type: "button", variant: "invisible", size: "small", leadingVisual: ToolsIcon, children: _jsxs(Text, { sx: { fontSize: 0 }, children: ["Tools", enabledMcpToolCount > 0 && ` (${enabledMcpToolCount})`] }) }) }), _jsx(ActionMenu.Overlay, { side: "outside-top", align: "start", width: "large", children: _jsx(Box, { sx: { maxHeight: '60vh', overflowY: 'auto' }, children: _jsxs(ActionList, { children: [_jsx(ActionList.Group, { title: "Codemode", children: _jsxs(Box, { sx: {
|
|
45
|
+
display: 'flex',
|
|
46
|
+
alignItems: 'center',
|
|
47
|
+
justifyContent: 'space-between',
|
|
48
|
+
px: 3,
|
|
49
|
+
py: 2,
|
|
50
|
+
borderBottom: '1px solid',
|
|
51
|
+
borderColor: 'border.muted',
|
|
52
|
+
gap: 2,
|
|
53
|
+
}, children: [_jsxs(Box, { sx: { flex: 1, minWidth: 0 }, children: [_jsx(Text, { id: "toggle-codemode", sx: { fontWeight: 'semibold', display: 'block' }, children: "Enable Codemode" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: codemodeEnabled
|
|
54
|
+
? 'MCP tools accessible via meta-tools (search_tools, execute_code).'
|
|
55
|
+
: 'Expose MCP tools directly to the model.' })] }), _jsx(ToggleSwitch, { size: "small", checked: codemodeEnabled, disabled: !onToggleCodemode, onClick: () => {
|
|
56
|
+
if (onToggleCodemode) {
|
|
57
|
+
void onToggleCodemode(!codemodeEnabled);
|
|
58
|
+
}
|
|
59
|
+
}, "aria-labelledby": "toggle-codemode" })] }) }), mcpServers.length > 0 && hasUsableMcpServers ? (mcpServers.map(server => {
|
|
44
60
|
const serverTools = enabledMcpTools.get(server.id);
|
|
45
61
|
const allToolNames = server.tools.map(t => t.name);
|
|
46
62
|
const enabledCount = serverTools?.size ?? 0;
|
|
@@ -60,6 +76,10 @@ function ToolsMenu({ codemodeEnabled, mcpServers, enabledMcpTools, enabledMcpToo
|
|
|
60
76
|
color: 'fg.muted',
|
|
61
77
|
}, children: ["Enable all (", enabledCount, "/", allToolNames.length, ")"] }), _jsx(ToggleSwitch, { size: "small", checked: allEnabled, onClick: () => onToggleAllMcpServerTools(server.id, allToolNames, !allEnabled), "aria-labelledby": `toggle-all-${server.id}` })] })), server.isAvailable && server.tools.length > 0 ? (server.tools.map(tool => {
|
|
62
78
|
const isEnabled = serverTools?.has(tool.name) ?? false;
|
|
79
|
+
const serverApproved = approvedMcpTools.get(server.id);
|
|
80
|
+
// Tools default to NOT approved — user must explicitly
|
|
81
|
+
// approve each one (matches the Skills approval UX).
|
|
82
|
+
const isApproved = serverApproved?.has(tool.name) ?? false;
|
|
63
83
|
return (_jsxs(Box, { sx: {
|
|
64
84
|
display: 'flex',
|
|
65
85
|
alignItems: 'center',
|
|
@@ -76,20 +96,29 @@ function ToolsMenu({ codemodeEnabled, mcpServers, enabledMcpTools, enabledMcpToo
|
|
|
76
96
|
overflow: 'hidden',
|
|
77
97
|
textOverflow: 'ellipsis',
|
|
78
98
|
whiteSpace: 'nowrap',
|
|
79
|
-
}, children: tool.description }))] }),
|
|
99
|
+
}, children: tool.description }))] }), _jsxs(Box, { sx: {
|
|
100
|
+
display: 'flex',
|
|
101
|
+
alignItems: 'center',
|
|
102
|
+
gap: 3,
|
|
103
|
+
}, children: [_jsxs(Box, { sx: {
|
|
104
|
+
display: 'flex',
|
|
105
|
+
flexDirection: 'column',
|
|
106
|
+
alignItems: 'center',
|
|
107
|
+
gap: '2px',
|
|
108
|
+
}, children: [_jsx(Text, { sx: { fontSize: '10px', color: 'fg.muted' }, children: "Enabled" }), _jsx(ToggleSwitch, { size: "small", checked: isEnabled, onClick: () => onToggleMcpTool(server.id, tool.name), "aria-labelledby": `toggle-tool-${server.id}-${tool.name}` })] }), _jsxs(Box, { sx: {
|
|
109
|
+
display: 'flex',
|
|
110
|
+
flexDirection: 'column',
|
|
111
|
+
alignItems: 'center',
|
|
112
|
+
gap: '2px',
|
|
113
|
+
}, children: [_jsx(Text, { sx: { fontSize: '10px', color: 'fg.muted' }, children: "Approved" }), _jsx(ToggleSwitch, { size: "small", checked: isApproved, onClick: () => onToggleMcpToolApproval(server.id, tool.name), "aria-labelledby": `toggle-tool-${server.id}-${tool.name}` })] })] })] }, `${server.id}-${tool.name}`));
|
|
80
114
|
})) : server.isAvailable ? (_jsx(ActionList.Item, { disabled: true, children: _jsx(Text, { sx: { color: 'fg.muted', fontStyle: 'italic' }, children: "No tools discovered" }) })) : (_jsx(ActionList.Item, { disabled: true, children: _jsx(Text, { sx: { color: 'fg.muted', fontStyle: 'italic' }, children: "Server unavailable" }) }))] }, server.id));
|
|
81
|
-
})) : (_jsx(ActionList.Group, { title: "
|
|
82
|
-
width: 8,
|
|
83
|
-
height: 8,
|
|
84
|
-
borderRadius: '50%',
|
|
85
|
-
backgroundColor: 'success.emphasis',
|
|
86
|
-
} }) }), tool.name] }, tool.id)))) : (_jsx(ActionList.Item, { disabled: true, children: _jsx(Text, { sx: { color: 'fg.muted', fontStyle: 'italic' }, children: "No tools available" }) })) }))] }) }) })] }));
|
|
115
|
+
})) : (_jsx(ActionList.Group, { title: "No MCP Servers", children: _jsx(ActionList.Item, { disabled: true, children: _jsx(Text, { sx: { color: 'fg.muted', fontStyle: 'italic' }, children: "No MCP Servers" }) }) }))] }) }) })] }));
|
|
87
116
|
}
|
|
88
117
|
// ---------------------------------------------------------------------------
|
|
89
118
|
// SkillsMenu (private sub-component)
|
|
90
119
|
// ---------------------------------------------------------------------------
|
|
91
|
-
function SkillsMenu({ skills, skillsLoading, enabledSkills, onToggleSkill, onToggleAllSkills, }) {
|
|
92
|
-
return (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Button, { type: "button", variant: "invisible", size: "small", leadingVisual: BriefcaseIcon, children: _jsxs(Text, { sx: { fontSize: 0 }, children: ["Skills",
|
|
120
|
+
function SkillsMenu({ skills, skillsLoading, enabledSkills, onToggleSkill, onToggleAllSkills, approvedSkills, onToggleSkillApproval, }) {
|
|
121
|
+
return (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Button, { type: "button", variant: "invisible", size: "small", leadingVisual: BriefcaseIcon, children: _jsxs(Text, { sx: { fontSize: 0 }, children: ["Skills", skills.length > 0 && ` (${skills.length})`] }) }) }), _jsx(ActionMenu.Overlay, { side: "outside-top", align: "start", width: "large", children: _jsx(Box, { sx: { maxHeight: '60vh', overflowY: 'auto' }, children: _jsx(ActionList, { children: skillsLoading ? (_jsx(ActionList.Item, { disabled: true, children: _jsx(Text, { sx: { color: 'fg.muted' }, children: "Loading skills..." }) })) : skills.length > 0 ? (_jsxs(_Fragment, { children: [_jsxs(Box, { sx: {
|
|
93
122
|
display: 'flex',
|
|
94
123
|
alignItems: 'center',
|
|
95
124
|
justifyContent: 'space-between',
|
|
@@ -110,14 +139,38 @@ function SkillsMenu({ skills, skillsLoading, enabledSkills, onToggleSkill, onTog
|
|
|
110
139
|
'&:hover': {
|
|
111
140
|
backgroundColor: 'canvas.subtle',
|
|
112
141
|
},
|
|
113
|
-
}, children: [_jsxs(Box, { sx: { flex: 1, minWidth: 0 }, children: [_jsx(Text, { id: `toggle-skill-${skill.id}`, sx: { fontWeight: 'semibold' }, children: skill.name }), skill.
|
|
142
|
+
}, children: [_jsxs(Box, { sx: { flex: 1, minWidth: 0 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [_jsx(Text, { id: `toggle-skill-${skill.id}`, sx: { fontWeight: 'semibold' }, children: skill.name }), skill.status && (_jsx(Text, { sx: {
|
|
143
|
+
fontSize: '10px',
|
|
144
|
+
px: 1,
|
|
145
|
+
borderRadius: 2,
|
|
146
|
+
bg: skill.status === 'loaded'
|
|
147
|
+
? 'success.subtle'
|
|
148
|
+
: skill.status === 'enabled'
|
|
149
|
+
? 'attention.subtle'
|
|
150
|
+
: 'neutral.subtle',
|
|
151
|
+
color: skill.status === 'loaded'
|
|
152
|
+
? 'success.fg'
|
|
153
|
+
: skill.status === 'enabled'
|
|
154
|
+
? 'attention.fg'
|
|
155
|
+
: 'fg.muted',
|
|
156
|
+
}, children: skill.status }))] }), skill.description && (_jsx(Text, { sx: {
|
|
114
157
|
display: 'block',
|
|
115
158
|
fontSize: 0,
|
|
116
159
|
color: 'fg.muted',
|
|
117
160
|
overflow: 'hidden',
|
|
118
161
|
textOverflow: 'ellipsis',
|
|
119
162
|
whiteSpace: 'nowrap',
|
|
120
|
-
}, children: skill.description }))] }),
|
|
163
|
+
}, children: skill.description }))] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 3 }, children: [_jsxs(Box, { sx: {
|
|
164
|
+
display: 'flex',
|
|
165
|
+
flexDirection: 'column',
|
|
166
|
+
alignItems: 'center',
|
|
167
|
+
gap: '2px',
|
|
168
|
+
}, children: [_jsx(Text, { sx: { fontSize: '10px', color: 'fg.muted' }, children: "Enabled" }), _jsx(ToggleSwitch, { size: "small", checked: enabledSkills.has(skill.id), onClick: () => onToggleSkill(skill.id), "aria-labelledby": `toggle-skill-${skill.id}` })] }), _jsxs(Box, { sx: {
|
|
169
|
+
display: 'flex',
|
|
170
|
+
flexDirection: 'column',
|
|
171
|
+
alignItems: 'center',
|
|
172
|
+
gap: '2px',
|
|
173
|
+
}, children: [_jsx(Text, { sx: { fontSize: '10px', color: 'fg.muted' }, children: "Approved" }), _jsx(ToggleSwitch, { size: "small", checked: approvedSkills.has(skill.id), onClick: () => onToggleSkillApproval(skill.id), "aria-labelledby": `toggle-skill-${skill.id}` })] })] })] }, skill.id)))] })) : (_jsx(ActionList.Item, { disabled: true, children: _jsx(Text, { sx: { color: 'fg.muted', fontStyle: 'italic' }, children: "No skills available" }) })) }) }) })] }));
|
|
121
174
|
}
|
|
122
175
|
// ---------------------------------------------------------------------------
|
|
123
176
|
// ModelSelector (private sub-component)
|
|
@@ -40,6 +40,8 @@ export interface InputPromptProps {
|
|
|
40
40
|
padding?: number;
|
|
41
41
|
/** Whether the prompt is disabled */
|
|
42
42
|
disabled?: boolean;
|
|
43
|
+
/** Whether the prompt is read-only */
|
|
44
|
+
readOnly?: boolean;
|
|
43
45
|
/** Additional sx props for the outer container */
|
|
44
46
|
sx?: Record<string, unknown>;
|
|
45
47
|
/** Controlled input value (external state) */
|
|
@@ -56,5 +58,5 @@ export interface InputPromptProps {
|
|
|
56
58
|
/**
|
|
57
59
|
* InputPrompt — Integrated chat input with header, input area, and footer.
|
|
58
60
|
*/
|
|
59
|
-
export declare function InputPrompt({ variant, placeholder, isLoading, onSend, onStop, autoFocus, focusTrigger, showBorderTop, showBackground, padding, disabled, sx, value: controlledValue, onChange: controlledOnChange, headerContent, footerContent, footerRightContent, }: InputPromptProps): import("react/jsx-runtime").JSX.Element;
|
|
61
|
+
export declare function InputPrompt({ variant, placeholder, isLoading, onSend, onStop, autoFocus, focusTrigger, showBorderTop, showBackground, padding, disabled, readOnly, sx, value: controlledValue, onChange: controlledOnChange, headerContent, footerContent, footerRightContent, }: InputPromptProps): import("react/jsx-runtime").JSX.Element;
|
|
60
62
|
export default InputPrompt;
|
|
@@ -8,7 +8,7 @@ import { InputPromptLexical } from './InputPromptLexical';
|
|
|
8
8
|
/**
|
|
9
9
|
* InputPrompt — Integrated chat input with header, input area, and footer.
|
|
10
10
|
*/
|
|
11
|
-
export function InputPrompt({ variant = 'text', placeholder = 'Ask anything…', isLoading = false, onSend, onStop, autoFocus = false, focusTrigger, showBorderTop = true, showBackground = true, padding = 3, disabled = false, sx, value: controlledValue, onChange: controlledOnChange, headerContent, footerContent, footerRightContent, }) {
|
|
11
|
+
export function InputPrompt({ variant = 'text', placeholder = 'Ask anything…', isLoading = false, onSend, onStop, autoFocus = false, focusTrigger, showBorderTop = true, showBackground = true, padding = 3, disabled = false, readOnly = false, sx, value: controlledValue, onChange: controlledOnChange, headerContent, footerContent, footerRightContent, }) {
|
|
12
12
|
// ---- Controlled / uncontrolled state -----------------------------------
|
|
13
13
|
const [internalInput, setInternalInput] = useState('');
|
|
14
14
|
const input = controlledValue !== undefined ? controlledValue : internalInput;
|
|
@@ -46,14 +46,14 @@ export function InputPrompt({ variant = 'text', placeholder = 'Ask anything…',
|
|
|
46
46
|
}, [isLoading, variant]);
|
|
47
47
|
// ---- Send / Stop handlers ----------------------------------------------
|
|
48
48
|
const handleSend = useCallback(() => {
|
|
49
|
-
if (!input.trim() || isLoading || disabled)
|
|
49
|
+
if (!input.trim() || isLoading || disabled || readOnly)
|
|
50
50
|
return;
|
|
51
51
|
const message = input.trim();
|
|
52
52
|
if (controlledValue === undefined) {
|
|
53
53
|
setInput('');
|
|
54
54
|
}
|
|
55
55
|
onSend(message);
|
|
56
|
-
}, [input, isLoading, disabled, onSend, setInput, controlledValue]);
|
|
56
|
+
}, [input, isLoading, disabled, readOnly, onSend, setInput, controlledValue]);
|
|
57
57
|
const handleStop = useCallback(() => {
|
|
58
58
|
onStop?.();
|
|
59
59
|
}, [onStop]);
|
|
@@ -78,6 +78,6 @@ export function InputPrompt({ variant = 'text', placeholder = 'Ask anything…',
|
|
|
78
78
|
borderColor: 'accent.fg',
|
|
79
79
|
boxShadow: (t) => `0 0 0 1px ${t?.colors?.accent?.fg ?? '#0969da'}`,
|
|
80
80
|
},
|
|
81
|
-
}, children: [_jsx(InputPromptHeader, { children: headerContent }), variant === 'lexical' ? (_jsx(InputPromptLexical, { value: input, onChange: setInput, placeholder: placeholder, disabled: isLoading || disabled, onSubmit: handleSend, autoFocus: autoFocus })) : (_jsx(InputPromptText, { value: input, onChange: setInput, placeholder: placeholder, disabled: isLoading || disabled, onSubmit: handleSend, inputRef: inputRef })), _jsx(InputPromptFooter, { isLoading: isLoading, sendDisabled: !input.trim() || disabled, onSend: handleSend, onStop: handleStop, rightContent: footerRightContent, children: footerContent })] }) }) }));
|
|
81
|
+
}, children: [_jsx(InputPromptHeader, { children: headerContent }), variant === 'lexical' ? (_jsx(InputPromptLexical, { value: input, onChange: setInput, placeholder: placeholder, disabled: isLoading || disabled, readOnly: readOnly, onSubmit: handleSend, autoFocus: autoFocus })) : (_jsx(InputPromptText, { value: input, onChange: setInput, placeholder: placeholder, disabled: isLoading || disabled, readOnly: readOnly, onSubmit: handleSend, inputRef: inputRef })), _jsx(InputPromptFooter, { isLoading: isLoading, sendDisabled: !input.trim() || disabled || readOnly, onSend: handleSend, onStop: handleStop, rightContent: footerRightContent, children: footerContent })] }) }) }));
|
|
82
82
|
}
|
|
83
83
|
export default InputPrompt;
|
|
@@ -10,6 +10,6 @@ export function InputPromptFooter({ children, rightContent, isLoading = false, s
|
|
|
10
10
|
px: 2,
|
|
11
11
|
pt: 1,
|
|
12
12
|
pb: 2,
|
|
13
|
-
}, children: [_jsx(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2, flex: 1 }, children: children }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [rightContent, isLoading ? (_jsx(IconButton, { icon: SquareCircleIcon, "aria-label": "Stop", onClick: onStop, size: "small" })) : (_jsx(IconButton, { icon: PaperAirplaneIcon, "aria-label": "Send", onClick: onSend, disabled: sendDisabled, size: "small" }))] })] }));
|
|
13
|
+
}, children: [_jsx(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2, flex: 1 }, children: children }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [rightContent, isLoading ? (_jsx(IconButton, { icon: SquareCircleIcon, "aria-label": "Stop", onClick: onStop, size: "small", variant: "invisible" })) : (_jsx(IconButton, { icon: PaperAirplaneIcon, "aria-label": "Send", onClick: onSend, disabled: sendDisabled, size: "small", variant: "invisible" }))] })] }));
|
|
14
14
|
}
|
|
15
15
|
export default InputPromptFooter;
|
|
@@ -7,10 +7,12 @@ export interface InputPromptLexicalProps {
|
|
|
7
7
|
placeholder?: string;
|
|
8
8
|
/** Whether the input is disabled */
|
|
9
9
|
disabled?: boolean;
|
|
10
|
+
/** Whether the input is read-only */
|
|
11
|
+
readOnly?: boolean;
|
|
10
12
|
/** Callback when the user presses Enter (without Shift) */
|
|
11
13
|
onSubmit?: () => void;
|
|
12
14
|
/** Auto-focus the editor on mount */
|
|
13
15
|
autoFocus?: boolean;
|
|
14
16
|
}
|
|
15
|
-
export declare function InputPromptLexical({ value, onChange, placeholder, disabled, onSubmit, autoFocus, }: InputPromptLexicalProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export declare function InputPromptLexical({ value, onChange, placeholder, disabled, readOnly, onSubmit, autoFocus, }: InputPromptLexicalProps): import("react/jsx-runtime").JSX.Element;
|
|
16
18
|
export default InputPromptLexical;
|
|
@@ -38,17 +38,17 @@ const EDITOR_CONFIG = {
|
|
|
38
38
|
},
|
|
39
39
|
};
|
|
40
40
|
// ---- Enter-to-submit plugin ---------------------------------------------
|
|
41
|
-
function EnterSubmitPlugin({ onSubmit, disabled, }) {
|
|
41
|
+
function EnterSubmitPlugin({ onSubmit, disabled, readOnly, }) {
|
|
42
42
|
const [editor] = useLexicalComposerContext();
|
|
43
43
|
useEffect(() => {
|
|
44
44
|
return editor.registerCommand(KEY_ENTER_COMMAND, (event) => {
|
|
45
|
-
if (event?.shiftKey || disabled)
|
|
45
|
+
if (event?.shiftKey || disabled || readOnly)
|
|
46
46
|
return false;
|
|
47
47
|
event?.preventDefault();
|
|
48
48
|
onSubmit?.();
|
|
49
49
|
return true;
|
|
50
50
|
}, COMMAND_PRIORITY_HIGH);
|
|
51
|
-
}, [editor, onSubmit, disabled]);
|
|
51
|
+
}, [editor, onSubmit, disabled, readOnly]);
|
|
52
52
|
return null;
|
|
53
53
|
}
|
|
54
54
|
// ---- Sync plugin (controlled component bridge) --------------------------
|
|
@@ -94,7 +94,14 @@ function AutoFocusPlugin({ autoFocus }) {
|
|
|
94
94
|
}, [editor, autoFocus]);
|
|
95
95
|
return null;
|
|
96
96
|
}
|
|
97
|
-
|
|
97
|
+
function ReadOnlyPlugin({ readOnly }) {
|
|
98
|
+
const [editor] = useLexicalComposerContext();
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
editor.setEditable(!readOnly);
|
|
101
|
+
}, [editor, readOnly]);
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
export function InputPromptLexical({ value, onChange, placeholder = 'Ask anything…', disabled = false, readOnly = false, onSubmit, autoFocus = false, }) {
|
|
98
105
|
return (_jsx(Box, { sx: {
|
|
99
106
|
px: 2,
|
|
100
107
|
py: 1,
|
|
@@ -117,6 +124,6 @@ export function InputPromptLexical({ value, onChange, placeholder = 'Ask anythin
|
|
|
117
124
|
fontSize: 1,
|
|
118
125
|
pointerEvents: 'none',
|
|
119
126
|
userSelect: 'none',
|
|
120
|
-
}, children: placeholder }), ErrorBoundary: LexicalErrorBoundary }), _jsx(HistoryPlugin, {}), _jsx(SyncPlugin, { value: value, onChange: onChange }), _jsx(EnterSubmitPlugin, { onSubmit: onSubmit, disabled: disabled }), _jsx(AutoFocusPlugin, { autoFocus: autoFocus })] }) }));
|
|
127
|
+
}, children: placeholder }), ErrorBoundary: LexicalErrorBoundary }), _jsx(HistoryPlugin, {}), _jsx(SyncPlugin, { value: value, onChange: onChange }), _jsx(ReadOnlyPlugin, { readOnly: readOnly || disabled }), _jsx(EnterSubmitPlugin, { onSubmit: onSubmit, disabled: disabled, readOnly: readOnly }), _jsx(AutoFocusPlugin, { autoFocus: autoFocus })] }) }));
|
|
121
128
|
}
|
|
122
129
|
export default InputPromptLexical;
|
|
@@ -15,10 +15,12 @@ export interface InputPromptTextProps {
|
|
|
15
15
|
placeholder?: string;
|
|
16
16
|
/** Whether the input is disabled */
|
|
17
17
|
disabled?: boolean;
|
|
18
|
+
/** Whether the input is read-only */
|
|
19
|
+
readOnly?: boolean;
|
|
18
20
|
/** Callback when the user presses Enter (without Shift) */
|
|
19
21
|
onSubmit?: () => void;
|
|
20
22
|
/** Ref forwarded to the underlying textarea */
|
|
21
23
|
inputRef?: Ref<HTMLTextAreaElement>;
|
|
22
24
|
}
|
|
23
|
-
export declare function InputPromptText({ value, onChange, placeholder, disabled, onSubmit, inputRef, }: InputPromptTextProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export declare function InputPromptText({ value, onChange, placeholder, disabled, readOnly, onSubmit, inputRef, }: InputPromptTextProps): import("react/jsx-runtime").JSX.Element;
|
|
24
26
|
export default InputPromptText;
|
|
@@ -13,7 +13,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
13
13
|
import { useCallback, useEffect, } from 'react';
|
|
14
14
|
import { Textarea } from '@primer/react';
|
|
15
15
|
import { Box } from '@datalayer/primer-addons';
|
|
16
|
-
export function InputPromptText({ value, onChange, placeholder = 'Ask anything…', disabled = false, onSubmit, inputRef, }) {
|
|
16
|
+
export function InputPromptText({ value, onChange, placeholder = 'Ask anything…', disabled = false, readOnly = false, onSubmit, inputRef, }) {
|
|
17
17
|
// Auto-resize
|
|
18
18
|
const adjustHeight = useCallback(() => {
|
|
19
19
|
const el = inputRef && 'current' in inputRef
|
|
@@ -41,7 +41,7 @@ export function InputPromptText({ value, onChange, placeholder = 'Ask anything
|
|
|
41
41
|
onSubmit?.();
|
|
42
42
|
}
|
|
43
43
|
}, [onSubmit]);
|
|
44
|
-
return (_jsx(Box, { sx: { px: 2, py: 1 }, children: _jsx(Textarea, { ref: inputRef, value: value, onChange: e => onChange(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, sx: {
|
|
44
|
+
return (_jsx(Box, { sx: { px: 2, py: 1 }, children: _jsx(Textarea, { ref: inputRef, value: value, onChange: e => onChange(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, readOnly: readOnly, sx: {
|
|
45
45
|
width: '100%',
|
|
46
46
|
resize: 'none',
|
|
47
47
|
minHeight: '40px',
|
|
@@ -46,7 +46,7 @@ export function ToolApprovalBanner({ pendingApprovals, onReview, onApproveAll, o
|
|
|
46
46
|
justifyContent: 'space-between',
|
|
47
47
|
px: 3,
|
|
48
48
|
py: 2,
|
|
49
|
-
}, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(AlertIcon, { size: 16 }), _jsxs(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: [pendingApprovals.length, " tool", ' ', pendingApprovals.length === 1 ? 'approval' : 'approvals', " pending"] })] }), _jsxs(Box, { sx: { display: 'flex', gap: 1 }, children: [onApproveAll && pendingApprovals.length
|
|
49
|
+
}, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(AlertIcon, { size: 16 }), _jsxs(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: [pendingApprovals.length, " tool", ' ', pendingApprovals.length === 1 ? 'approval' : 'approvals', " pending"] })] }), _jsxs(Box, { sx: { display: 'flex', gap: 1 }, children: [onApproveAll && pendingApprovals.length >= 1 && (_jsx(Button, { size: "small", variant: "primary", leadingVisual: CheckIcon, onClick: onApproveAll, children: "Approve all" })), collapsible && (_jsx(Button, { size: "small", variant: "invisible", onClick: () => setCollapsed(true), children: "Collapse" })), onDismiss && (_jsx(Button, { size: "small", variant: "invisible", leadingVisual: XIcon, onClick: onDismiss, "aria-label": "Dismiss" }))] })] }), _jsx(Box, { sx: { px: 3, pb: 2 }, children: pendingApprovals.map(approval => (_jsxs(Box, { sx: {
|
|
50
50
|
display: 'flex',
|
|
51
51
|
alignItems: 'center',
|
|
52
52
|
justifyContent: 'space-between',
|
|
@@ -28,6 +28,8 @@ export interface ToolCallDisplayProps {
|
|
|
28
28
|
approvalRequired?: boolean;
|
|
29
29
|
/** Approval state for this tool call */
|
|
30
30
|
approvalState?: 'pending' | 'approved' | 'denied';
|
|
31
|
+
/** Where the approval decision originated */
|
|
32
|
+
approvalDecisionSource?: 'inline' | 'external';
|
|
31
33
|
/** Called when user approves this tool call */
|
|
32
34
|
onApprove?: () => void;
|
|
33
35
|
/** Called when user denies this tool call */
|
|
@@ -45,5 +47,5 @@ export interface ToolCallDisplayProps {
|
|
|
45
47
|
* - Color-coded status indicators
|
|
46
48
|
* - Rich error display distinguishing execution errors from code errors
|
|
47
49
|
*/
|
|
48
|
-
export declare function ToolCallDisplay({ toolCallId, toolName, args, result, status, error, executionResult, codeError, exitCode, executionError, approvalRequired, approvalState, onApprove, onDeny, approvalLoading, }: ToolCallDisplayProps): import("react/jsx-runtime").JSX.Element;
|
|
50
|
+
export declare function ToolCallDisplay({ toolCallId, toolName, args, result, status, error, executionResult, codeError, exitCode, executionError, approvalRequired, approvalState, approvalDecisionSource, onApprove, onDeny, approvalLoading, }: ToolCallDisplayProps): import("react/jsx-runtime").JSX.Element;
|
|
49
51
|
export default ToolCallDisplay;
|
|
@@ -124,7 +124,7 @@ function getArgsSummary(args) {
|
|
|
124
124
|
* - Color-coded status indicators
|
|
125
125
|
* - Rich error display distinguishing execution errors from code errors
|
|
126
126
|
*/
|
|
127
|
-
export function ToolCallDisplay({ toolCallId, toolName, args, result, status, error, executionResult, codeError, exitCode, executionError, approvalRequired = false, approvalState, onApprove, onDeny, approvalLoading = false, }) {
|
|
127
|
+
export function ToolCallDisplay({ toolCallId, toolName, args, result, status, error, executionResult, codeError, exitCode, executionError, approvalRequired = false, approvalState, approvalDecisionSource, onApprove, onDeny, approvalLoading = false, }) {
|
|
128
128
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
129
129
|
// Determine effective exit code from props or execution result
|
|
130
130
|
const effectiveExitCode = exitCode ?? executionResult?.exit_code;
|
|
@@ -265,7 +265,7 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
|
|
|
265
265
|
wordBreak: 'break-word',
|
|
266
266
|
}, children: typeof result === 'string'
|
|
267
267
|
? result
|
|
268
|
-
: JSON.stringify(result, null, 2) }) })] })), approvalRequired && (_jsx(Box, { sx: { mt: status === 'complete' && result !== undefined ? 3 : 0 }, children: approvalState === 'approved' ? (_jsx(Text, { sx: { color: 'success.fg', fontSize: 1 }, children: "Approved. Executing tool." })) : approvalState === 'denied' ? (_jsx(Text, { sx: { color: 'danger.fg', fontSize: 1 }, children: "Denied. Tool will not run." })) : (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 1, color: 'fg.default' }, children: "This tool requires your approval to run." }), _jsxs(Box, { sx: { mt: 2, display: 'flex', gap: 2 }, children: [_jsx(Button, { size: "small", onClick: onApprove, disabled: approvalLoading || !onApprove, children: "Approve" }), _jsx(Button, { size: "small", variant: "danger", onClick: onDeny, disabled: approvalLoading || !onDeny, children: "Deny" })] })] })) })), status === 'error' && effectiveExecutionError && (_jsxs(Box, { children: [_jsxs(Text, { sx: {
|
|
268
|
+
: JSON.stringify(result, null, 2) }) })] })), approvalRequired && (_jsx(Box, { sx: { mt: status === 'complete' && result !== undefined ? 3 : 0 }, children: approvalState === 'approved' ? (_jsxs(Box, { children: [_jsx(Text, { sx: { color: 'success.fg', fontSize: 1, display: 'block' }, children: "Approved. Executing tool." }), approvalDecisionSource === 'external' && (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 0, display: 'block' }, children: "Approved from sidebar." }))] })) : approvalState === 'denied' ? (_jsxs(Box, { children: [_jsx(Text, { sx: { color: 'danger.fg', fontSize: 1, display: 'block' }, children: "Denied. Tool will not run." }), approvalDecisionSource === 'external' && (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 0, display: 'block' }, children: "Decision came from sidebar." }))] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 1, color: 'fg.default' }, children: "This tool requires your approval to run." }), _jsxs(Box, { sx: { mt: 2, display: 'flex', gap: 2 }, children: [_jsx(Button, { size: "small", onClick: onApprove, disabled: approvalLoading || !onApprove, children: "Approve" }), _jsx(Button, { size: "small", variant: "danger", onClick: onDeny, disabled: approvalLoading || !onDeny, children: "Deny" })] })] })) })), status === 'error' && effectiveExecutionError && (_jsxs(Box, { children: [_jsxs(Text, { sx: {
|
|
269
269
|
display: 'block',
|
|
270
270
|
fontSize: 0,
|
|
271
271
|
fontWeight: 'semibold',
|
|
@@ -29,6 +29,19 @@ export function TokenUsageBar({ agentUsage, padding }) {
|
|
|
29
29
|
const hasSession = agentUsage.sessionUsage &&
|
|
30
30
|
(agentUsage.sessionUsage.inputTokens > 0 ||
|
|
31
31
|
agentUsage.sessionUsage.outputTokens > 0);
|
|
32
|
+
const hasCostUsage = !!agentUsage.costUsage &&
|
|
33
|
+
(agentUsage.costUsage.cumulativeCostUsd > 0 ||
|
|
34
|
+
agentUsage.costUsage.lastTurnCostUsd > 0);
|
|
35
|
+
const sessionUsage = agentUsage.sessionUsage;
|
|
36
|
+
const turnUsage = agentUsage.turnUsage;
|
|
37
|
+
const costUsage = agentUsage.costUsage;
|
|
38
|
+
const formatUsd = (amount) => {
|
|
39
|
+
if (amount < 0.01)
|
|
40
|
+
return `$${amount.toFixed(4)}`;
|
|
41
|
+
if (amount < 1)
|
|
42
|
+
return `$${amount.toFixed(3)}`;
|
|
43
|
+
return `$${amount.toFixed(2)}`;
|
|
44
|
+
};
|
|
32
45
|
// Build pie chart data
|
|
33
46
|
const usedTokens = agentUsage.totalTokens;
|
|
34
47
|
const windowTokens = agentUsage.contextWindow;
|
|
@@ -180,7 +193,12 @@ export function TokenUsageBar({ agentUsage, padding }) {
|
|
|
180
193
|
color: 'fg.default',
|
|
181
194
|
display: 'block',
|
|
182
195
|
mb: 2,
|
|
183
|
-
}, children: "Context Window" }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block', mb: 1 }, children: [_jsx(Text, { as: "span", sx: { fontWeight: 'semibold', color: 'fg.default' }, children: formatTokenCount(usedTokens) }), ' / ', formatTokenCount(windowTokens), ' tokens'] }), _jsxs(Text, { sx: {
|
|
196
|
+
}, children: "Context Window" }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block', mb: 1 }, children: [_jsx(Text, { as: "span", sx: { fontWeight: 'semibold', color: 'fg.default' }, children: formatTokenCount(usedTokens) }), ' / ', formatTokenCount(windowTokens), ' tokens'] }), agentUsage.costUsage && (_jsxs(Text, { sx: {
|
|
197
|
+
fontSize: 0,
|
|
198
|
+
color: 'fg.muted',
|
|
199
|
+
display: 'block',
|
|
200
|
+
mb: 2,
|
|
201
|
+
}, children: ['cost ', _jsx(Text, { as: "span", sx: { fontWeight: 'semibold', color: 'fg.default' }, children: formatUsd(agentUsage.costUsage.lastTurnCostUsd) }), ' turn · ', _jsx(Text, { as: "span", sx: { fontWeight: 'semibold', color: 'fg.default' }, children: formatUsd(agentUsage.costUsage.cumulativeCostUsd) }), ' total'] })), _jsxs(Text, { sx: {
|
|
184
202
|
fontSize: 0,
|
|
185
203
|
color: pct > 90
|
|
186
204
|
? 'danger.fg'
|
|
@@ -209,5 +227,5 @@ export function TokenUsageBar({ agentUsage, padding }) {
|
|
|
209
227
|
display: 'block',
|
|
210
228
|
mt: 2,
|
|
211
229
|
fontStyle: 'italic',
|
|
212
|
-
}, children: "Quality may decline as limit nears." }))] }))] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', flexShrink: 0 }, children: [_jsx(Text, { as: "span", sx: { fontWeight: 'semibold', color: 'fg.default', fontSize: 0 }, children: formatTokenCount(agentUsage.totalTokens) }), ' / ', formatTokenCount(agentUsage.contextWindow), ' ctx'] }), hasSession && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', flexShrink: 0 }, children: ['· ', formatTokenCount(
|
|
230
|
+
}, children: "Quality may decline as limit nears." }))] }))] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', flexShrink: 0 }, children: [_jsx(Text, { as: "span", sx: { fontWeight: 'semibold', color: 'fg.default', fontSize: 0 }, children: formatTokenCount(agentUsage.totalTokens) }), ' / ', formatTokenCount(agentUsage.contextWindow), ' ctx'] }), hasCostUsage && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', flexShrink: 0 }, children: ['· cost ', _jsx(Text, { as: "span", sx: { fontWeight: 'semibold', color: 'fg.default', fontSize: 0 }, children: formatUsd(costUsage?.lastTurnCostUsd ?? 0) }), ' turn / ', _jsx(Text, { as: "span", sx: { fontWeight: 'semibold', color: 'fg.default', fontSize: 0 }, children: formatUsd(costUsage?.cumulativeCostUsd ?? 0) })] })), hasSession && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', flexShrink: 0 }, children: ['· ', formatTokenCount(sessionUsage?.inputTokens ?? 0), _jsx(Text, { as: "span", sx: { color: 'success.fg', fontSize: 0 }, children: '▲' }), ' ', formatTokenCount(sessionUsage?.outputTokens ?? 0), _jsx(Text, { as: "span", sx: { color: 'attention.fg', fontSize: 0 }, children: '▼' })] })), hasTurn && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', flexShrink: 0 }, children: ['· turn ', formatTokenCount(turnUsage?.inputTokens ?? 0), _jsx(Text, { as: "span", sx: { color: 'success.fg', fontSize: 0 }, children: '▲' }), ' ', formatTokenCount(turnUsage?.outputTokens ?? 0), _jsx(Text, { as: "span", sx: { color: 'attention.fg', fontSize: 0 }, children: '▼' })] }))] }));
|
|
213
231
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React context and hook for injecting an {@link IAgentRuntimesClient}
|
|
3
|
+
* implementation into the chat component tree.
|
|
4
|
+
*
|
|
5
|
+
* Consumers wrap the `<Chat>` component with `<AgentRuntimesClientProvider>`
|
|
6
|
+
* and pass the implementation of their choice — the default
|
|
7
|
+
* `SdkAgentRuntimesClient` for browser / Node, or a bridge
|
|
8
|
+
* implementation in the VSCode webview sandbox. Components and hooks inside
|
|
9
|
+
* the tree call {@link useAgentRuntimesClient} to retrieve the current client
|
|
10
|
+
* without knowing anything about how it talks to the backend.
|
|
11
|
+
*
|
|
12
|
+
* @module client/AgentRuntimesClientContext
|
|
13
|
+
*/
|
|
14
|
+
import type { ReactNode } from 'react';
|
|
15
|
+
import type { IAgentRuntimesClient } from './IAgentRuntimesClient';
|
|
16
|
+
/** Props for {@link AgentRuntimesClientProvider}. */
|
|
17
|
+
export interface AgentRuntimesClientProviderProps {
|
|
18
|
+
/** Client implementation to make available to descendants. */
|
|
19
|
+
client: IAgentRuntimesClient;
|
|
20
|
+
/** Descendants that should see the provided client. */
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Provides an {@link IAgentRuntimesClient} instance to every descendant.
|
|
25
|
+
*
|
|
26
|
+
* @param props - Provider props.
|
|
27
|
+
*
|
|
28
|
+
* @returns A React element that exposes `props.client` to descendants.
|
|
29
|
+
*/
|
|
30
|
+
export declare function AgentRuntimesClientProvider(props: AgentRuntimesClientProviderProps): JSX.Element;
|
|
31
|
+
/**
|
|
32
|
+
* Reads the active {@link IAgentRuntimesClient} from context.
|
|
33
|
+
*
|
|
34
|
+
* @returns The active client.
|
|
35
|
+
*
|
|
36
|
+
* @throws When called outside an {@link AgentRuntimesClientProvider}. Prefer a
|
|
37
|
+
* loud failure to silently falling back to a default client, because a
|
|
38
|
+
* missing provider usually indicates a wiring bug (especially in the VSCode
|
|
39
|
+
* webview where the default client would make forbidden direct HTTP calls).
|
|
40
|
+
*/
|
|
41
|
+
export declare function useAgentRuntimesClient(): IAgentRuntimesClient;
|
|
42
|
+
/**
|
|
43
|
+
* Reads the current {@link IAgentRuntimesClient} from context without
|
|
44
|
+
* throwing.
|
|
45
|
+
*
|
|
46
|
+
* Use this variant in code paths that want to fall back to some other behavior
|
|
47
|
+
* when no provider is mounted (for example, legacy hook implementations that
|
|
48
|
+
* currently still make direct network calls and are being migrated
|
|
49
|
+
* incrementally).
|
|
50
|
+
*
|
|
51
|
+
* @returns The active client, or `null` when no provider is mounted.
|
|
52
|
+
*/
|
|
53
|
+
export declare function useOptionalAgentRuntimesClient(): IAgentRuntimesClient | null;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useMemo } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* React context carrying the active {@link IAgentRuntimesClient}. `null` when
|
|
5
|
+
* no provider is mounted — in that case {@link useAgentRuntimesClient} throws
|
|
6
|
+
* so callers fail loudly rather than silently making no-op HTTP calls.
|
|
7
|
+
*/
|
|
8
|
+
const AgentRuntimesClientContext = createContext(null);
|
|
9
|
+
/**
|
|
10
|
+
* Provides an {@link IAgentRuntimesClient} instance to every descendant.
|
|
11
|
+
*
|
|
12
|
+
* @param props - Provider props.
|
|
13
|
+
*
|
|
14
|
+
* @returns A React element that exposes `props.client` to descendants.
|
|
15
|
+
*/
|
|
16
|
+
export function AgentRuntimesClientProvider(props) {
|
|
17
|
+
const { client, children } = props;
|
|
18
|
+
// Memoize the context value so identity only changes when the client
|
|
19
|
+
// reference itself changes.
|
|
20
|
+
const value = useMemo(() => client, [client]);
|
|
21
|
+
return (_jsx(AgentRuntimesClientContext.Provider, { value: value, children: children }));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Reads the active {@link IAgentRuntimesClient} from context.
|
|
25
|
+
*
|
|
26
|
+
* @returns The active client.
|
|
27
|
+
*
|
|
28
|
+
* @throws When called outside an {@link AgentRuntimesClientProvider}. Prefer a
|
|
29
|
+
* loud failure to silently falling back to a default client, because a
|
|
30
|
+
* missing provider usually indicates a wiring bug (especially in the VSCode
|
|
31
|
+
* webview where the default client would make forbidden direct HTTP calls).
|
|
32
|
+
*/
|
|
33
|
+
export function useAgentRuntimesClient() {
|
|
34
|
+
const client = useContext(AgentRuntimesClientContext);
|
|
35
|
+
if (client === null) {
|
|
36
|
+
throw new Error('useAgentRuntimesClient must be called inside an <AgentRuntimesClientProvider>. ' +
|
|
37
|
+
'Wrap your <Chat> component (or the subtree that uses agent-runtimes hooks) ' +
|
|
38
|
+
'with <AgentRuntimesClientProvider client={...}>.');
|
|
39
|
+
}
|
|
40
|
+
return client;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Reads the current {@link IAgentRuntimesClient} from context without
|
|
44
|
+
* throwing.
|
|
45
|
+
*
|
|
46
|
+
* Use this variant in code paths that want to fall back to some other behavior
|
|
47
|
+
* when no provider is mounted (for example, legacy hook implementations that
|
|
48
|
+
* currently still make direct network calls and are being migrated
|
|
49
|
+
* incrementally).
|
|
50
|
+
*
|
|
51
|
+
* @returns The active client, or `null` when no provider is mounted.
|
|
52
|
+
*/
|
|
53
|
+
export function useOptionalAgentRuntimesClient() {
|
|
54
|
+
return useContext(AgentRuntimesClientContext);
|
|
55
|
+
}
|