@datalayer/agent-runtimes 1.3.75 → 1.3.79

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.
Files changed (110) hide show
  1. package/lib/agents/AgentDetails.d.ts +16 -2
  2. package/lib/agents/AgentDetails.js +381 -272
  3. package/lib/chat/ChatFloating.d.ts +12 -2
  4. package/lib/chat/ChatFloating.js +48 -11
  5. package/lib/chat/assistant/AgentDetailsDialog.d.ts +21 -0
  6. package/lib/chat/assistant/AgentDetailsDialog.js +19 -0
  7. package/lib/chat/assistant/AssistantStage.d.ts +51 -5
  8. package/lib/chat/assistant/AssistantStage.js +60 -10
  9. package/lib/chat/assistant/BalloonParts.d.ts +18 -4
  10. package/lib/chat/assistant/BalloonParts.js +46 -41
  11. package/lib/chat/assistant/BalloonVisual.js +2 -1
  12. package/lib/chat/assistant/SandboxDetailsDialog.d.ts +44 -0
  13. package/lib/chat/assistant/SandboxDetailsDialog.js +214 -0
  14. package/lib/chat/assistant/SpeechBalloon.d.ts +8 -6
  15. package/lib/chat/assistant/SpeechBalloon.js +29 -30
  16. package/lib/chat/assistant/assistantDetails.d.ts +84 -0
  17. package/lib/chat/assistant/assistantDetails.js +140 -0
  18. package/lib/chat/assistant/formats/files.d.ts +23 -0
  19. package/lib/chat/assistant/formats/files.js +48 -0
  20. package/lib/chat/assistant/formats/index.d.ts +2 -0
  21. package/lib/chat/assistant/formats/index.js +1 -0
  22. package/lib/chat/assistant/state.d.ts +7 -14
  23. package/lib/chat/assistant/state.js +21 -20
  24. package/lib/chat/assistant/toolLine.d.ts +16 -0
  25. package/lib/chat/assistant/toolLine.js +46 -0
  26. package/lib/chat/base/ChatBase.js +20 -0
  27. package/lib/chat/base/loopMessage.d.ts +37 -0
  28. package/lib/chat/base/loopMessage.js +37 -0
  29. package/lib/chat/messages/ChatMarkdown.d.ts +16 -0
  30. package/lib/chat/messages/ChatMarkdown.js +18 -0
  31. package/lib/chat/messages/ChatMessageList.d.ts +8 -1
  32. package/lib/chat/messages/ChatMessageList.js +24 -18
  33. package/lib/chat/styles/streamdownStyles.js +3 -1
  34. package/lib/chat/tools/ToolCallDisplay.d.ts +8 -1
  35. package/lib/chat/tools/ToolCallDisplay.js +8 -7
  36. package/lib/components/code-sandboxes/CodeSandboxCellVariablesDialog.js +5 -11
  37. package/lib/components/code-sandboxes/CodeSandboxVariables.d.ts +8 -0
  38. package/lib/components/code-sandboxes/CodeSandboxVariables.js +17 -11
  39. package/lib/components/teams/A2ATeamGraph.d.ts +30 -3
  40. package/lib/components/teams/A2ATeamGraph.js +264 -41
  41. package/lib/components/teams/TeamNotebookView.js +15 -0
  42. package/lib/components/teams/teamNotebookKernel.d.ts +3 -0
  43. package/lib/components/teams/teamNotebookKernel.js +17 -0
  44. package/lib/components/teams/useA2ATeam.d.ts +10 -6
  45. package/lib/components/teams/useA2ATeam.js +29 -8
  46. package/lib/examples/AgentA2ATeamExample.js +6 -0
  47. package/lib/examples/AssistantExample.js +3 -24
  48. package/lib/examples/AssistantGalleryExample.js +2 -1
  49. package/lib/examples/exampleGroups.d.ts +1 -1
  50. package/lib/examples/exampleGroups.js +1 -1
  51. package/lib/examples/utils/assistantGallery.d.ts +7 -6
  52. package/lib/examples/utils/assistantGallery.js +23 -8
  53. package/lib/jupyter/exec/Python.d.ts +0 -1
  54. package/lib/jupyter/exec/Python.js +0 -32
  55. package/lib/jupyter/exec/Snippets.d.ts +4 -12
  56. package/lib/jupyter/exec/Snippets.js +0 -8
  57. package/lib/loop/apps/AppFeedback.js +3 -1
  58. package/lib/loop/apps/AppKept.d.ts +22 -0
  59. package/lib/loop/apps/AppKept.js +36 -0
  60. package/lib/loop/apps/AppRenderer.d.ts +11 -1
  61. package/lib/loop/apps/AppRenderer.js +21 -3
  62. package/lib/loop/apps/checks.d.ts +7 -0
  63. package/lib/loop/apps/checks.js +39 -0
  64. package/lib/loop/apps/index.d.ts +3 -0
  65. package/lib/loop/apps/index.js +3 -0
  66. package/lib/loop/apps/kept.d.ts +30 -0
  67. package/lib/loop/apps/kept.js +52 -0
  68. package/lib/loop/apps/records.d.ts +12 -4
  69. package/lib/loop/apps/records.js +13 -5
  70. package/lib/loop/apps/saved.d.ts +30 -0
  71. package/lib/loop/apps/saved.js +40 -0
  72. package/lib/loop/embed/AppEmbed.d.ts +8 -1
  73. package/lib/loop/embed/AppEmbed.js +4 -4
  74. package/lib/loop/embed/LoopEmbed.d.ts +6 -1
  75. package/lib/loop/embed/LoopEmbed.js +4 -2
  76. package/lib/loop/embed/element.js +1 -1
  77. package/lib/loop/plugins/agents/DatalayerAgentBridge.js +12 -6
  78. package/lib/loop/plugins/agents/browserService.d.ts +7 -1
  79. package/lib/loop/plugins/agents/browserService.js +4 -0
  80. package/lib/loop/plugins/agents/plugin.d.ts +16 -0
  81. package/lib/loop/plugins/agents/switchable.d.ts +3 -0
  82. package/lib/loop/plugins/agents/switchable.js +1 -0
  83. package/lib/loop/plugins/app-activity/index.js +3 -0
  84. package/lib/loop/plugins/app-computer/index.js +3 -0
  85. package/lib/loop/plugins/app-rules/AppRulesCard.d.ts +5 -0
  86. package/lib/loop/plugins/app-rules/AppRulesCard.js +25 -6
  87. package/lib/loop/plugins/app-rules/index.js +3 -0
  88. package/lib/loop/plugins/assistant/index.d.ts +7 -2
  89. package/lib/loop/plugins/assistant/index.js +53 -4
  90. package/lib/loop/plugins/assistant-characters/index.d.ts +7 -0
  91. package/lib/loop/plugins/assistant-characters/index.js +17 -0
  92. package/lib/loop/plugins/chat/ChatView.js +4 -1
  93. package/lib/loop/plugins/page-layout/SplitLayout.d.ts +2 -1
  94. package/lib/loop/plugins/page-layout/SplitLayout.js +4 -0
  95. package/lib/loop/presets.d.ts +4 -0
  96. package/lib/loop/presets.js +3 -1
  97. package/lib/loop/shell/LoopWorkspace.d.ts +7 -0
  98. package/lib/loop/shell/LoopWorkspace.js +5 -4
  99. package/lib/loop/shell/SidebarRail.d.ts +53 -0
  100. package/lib/loop/shell/SidebarRail.js +74 -0
  101. package/lib/loop/shell/index.d.ts +2 -0
  102. package/lib/loop/shell/index.js +2 -0
  103. package/lib/loop/shell/paneMotion.d.ts +21 -0
  104. package/lib/loop/shell/paneMotion.js +37 -0
  105. package/lib/specs/apps.js +8 -5
  106. package/lib/specs/uiPlugins.js +529 -0
  107. package/lib/types/agentspecs.d.ts +5 -3
  108. package/lib/types/chat.d.ts +5 -0
  109. package/package.json +2 -2
  110. package/scripts/codegen/generate_ui_plugins.py +112 -2
@@ -26,6 +26,7 @@ import { type PresenceState } from './presence/presenceStatus';
26
26
  import type { AgentInspectorSink } from '../components/inspector/agentInspector';
27
27
  import type { AssistantMenuItem } from './assistant/AssistantContextMenu';
28
28
  import type { AssistantAbout } from './assistant/AssistantStage';
29
+ import { type AssistantSandbox } from './assistant/assistantDetails';
29
30
  import type { ChatCommonProps, ChatViewMode, ThemeOverrides } from '../types';
30
31
  /**
31
32
  * A conversation the host draws in the floating window, in place of the
@@ -184,8 +185,17 @@ export interface ChatFloatingProps extends ChatCommonProps {
184
185
  onBalloonDisplayChange?: (display: BalloonDisplay) => void;
185
186
  /** Opens the host's character picker, from the assistant's menu. */
186
187
  onChangeCharacter?: () => void;
187
- /** What the assistant's menu's *About* says. */
188
+ /**
189
+ * What the assistant's menu's *About* and *Agent Details…* say. The
190
+ * chat's own agent (its id and runtime, from `endpoint`) is described
191
+ * without it.
192
+ */
188
193
  about?: AssistantAbout;
194
+ /**
195
+ * The agent's code sandbox, for *Code Sandbox Details…*. Without it, the
196
+ * sandbox the agent's runtime reports (its codemode status), if any.
197
+ */
198
+ sandbox?: AssistantSandbox;
189
199
  /** The host's own entries of the assistant's menu. */
190
200
  contextMenu?: readonly AssistantMenuItem[];
191
201
  /**
@@ -200,5 +210,5 @@ export interface ChatFloatingProps extends ChatCommonProps {
200
210
  * ChatFloating component
201
211
  * A floating chat window built on ChatBase
202
212
  */
203
- export declare function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode, title, description, position, defaultOpen, width, height, showHeader, showButton, showNewChatButton, showClearButton, showSettingsButton, enableKeyboardShortcuts, toggleShortcut, showPoweredBy, promptVariant, mentionableAgents, poweredByProps, clickOutsideToClose, escapeToClose, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip, brandColor, buttonGlow, offset, animationDuration, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick, hideMessagesAfterToolUI, defaultViewMode, onViewModeChange, sidebarMountPoint, showPanelBackdrop, availableModels, showModelSelector, showToolsMenu, showSkillsMenu, showTokenUsage, showContextRing, themeVariant, themeOverrides, colorMode, runtimeId, historyEndpoint, authToken, historyAuthToken, pendingPrompt, showInformation, onInformationClick, onToolCallStart, onToolCallComplete, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, panelProps, launching, launchingMessage, assistantCharacter, balloonDisplay: balloonDisplayGiven, expandTarget, conversation, decisions, voice, inspector, onBalloonDisplayChange, onChangeCharacter, about, contextMenu, }: ChatFloatingProps): React.JSX.Element;
213
+ export declare function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode, title, description, position, defaultOpen, width, height, showHeader, showButton, showNewChatButton, showClearButton, showSettingsButton, enableKeyboardShortcuts, toggleShortcut, showPoweredBy, promptVariant, mentionableAgents, poweredByProps, clickOutsideToClose, escapeToClose, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip, brandColor, buttonGlow, offset, animationDuration, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick, hideMessagesAfterToolUI, defaultViewMode, onViewModeChange, sidebarMountPoint, showPanelBackdrop, availableModels, showModelSelector, showToolsMenu, showSkillsMenu, showTokenUsage, showContextRing, themeVariant, themeOverrides, colorMode, runtimeId, historyEndpoint, authToken, historyAuthToken, pendingPrompt, showInformation, onInformationClick, onToolCallStart, onToolCallComplete, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, panelProps, launching, launchingMessage, assistantCharacter, balloonDisplay: balloonDisplayGiven, expandTarget, conversation, decisions, voice, inspector, onBalloonDisplayChange, onChangeCharacter, about, sandbox, contextMenu, }: ChatFloatingProps): React.JSX.Element;
204
214
  export default ChatFloating;
@@ -40,10 +40,12 @@ import { ConversationBalloonHeader, CurrentBalloonBody, } from './assistant/Ball
40
40
  import { DEFAULT_BALLOON_DISPLAY, conversationCount, newestToolLine, toolLineText, } from './assistant/toolLine';
41
41
  import { SpeechBalloon } from './assistant/SpeechBalloon';
42
42
  import { DEFAULT_ASSISTANT_CHARACTER, } from './assistant/characters';
43
- import { assistantStateOf, balloonHistoryOf, latestSaying, newestIsAnswer, keepAway, keptAway, ASSISTANT_WORDS, } from './assistant/state';
43
+ import { assistantStateOf, latestSaying, newestIsAnswer, keepAway, keptAway, ASSISTANT_WORDS, } from './assistant/state';
44
44
  import { presenceState, presenceToolOf, } from './presence/presenceStatus';
45
45
  import { useChatOpen, useChatMessages, useChatStore, } from '../stores/chatStore';
46
46
  import { useChatKeyboardShortcuts, getShortcutDisplay, } from '@datalayer/core/lib/hooks';
47
+ import { assistantSandboxOf, } from './assistant/assistantDetails';
48
+ import { useAgentRuntimeCodemodeStatus } from '../stores/agentRuntimeStore';
47
49
  /**
48
50
  * Hook to detect mobile viewport
49
51
  */
@@ -70,7 +72,7 @@ const clamp = (value, max) => Math.max(8, Math.min(value, Math.max(8, max)));
70
72
  * ChatFloating component
71
73
  * A floating chat window built on ChatBase
72
74
  */
73
- export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode = true, title = 'Chat', description = 'Start a conversation with the AI agent.', position = 'bottom-right', defaultOpen = false, width = 400, height = 550, showHeader = true, showButton = true, showNewChatButton = true, showClearButton = true, showSettingsButton = false, enableKeyboardShortcuts = true, toggleShortcut = '/', showPoweredBy = true, promptVariant, mentionableAgents, poweredByProps, clickOutsideToClose = false, escapeToClose = true, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip = 'Chat with AI', brandColor, buttonGlow = true, offset = 20, animationDuration = 200, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick = true, hideMessagesAfterToolUI = false, defaultViewMode = 'floating', onViewModeChange, sidebarMountPoint = null, showPanelBackdrop = false, availableModels, showModelSelector = false, showToolsMenu = false, showSkillsMenu = false, showTokenUsage = true, showContextRing = false, themeVariant, themeOverrides, colorMode, runtimeId, historyEndpoint, authToken, historyAuthToken, pendingPrompt, showInformation = false, onInformationClick, onToolCallStart, onToolCallComplete, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, panelProps, launching = false, launchingMessage, assistantCharacter = DEFAULT_ASSISTANT_CHARACTER, balloonDisplay: balloonDisplayGiven = DEFAULT_BALLOON_DISPLAY, expandTarget, conversation, decisions, voice, inspector, onBalloonDisplayChange, onChangeCharacter, about, contextMenu, }) {
75
+ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode = true, title = 'Chat', description = 'Start a conversation with the AI agent.', position = 'bottom-right', defaultOpen = false, width = 400, height = 550, showHeader = true, showButton = true, showNewChatButton = true, showClearButton = true, showSettingsButton = false, enableKeyboardShortcuts = true, toggleShortcut = '/', showPoweredBy = true, promptVariant, mentionableAgents, poweredByProps, clickOutsideToClose = false, escapeToClose = true, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip = 'Chat with AI', brandColor, buttonGlow = true, offset = 20, animationDuration = 200, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick = true, hideMessagesAfterToolUI = false, defaultViewMode = 'floating', onViewModeChange, sidebarMountPoint = null, showPanelBackdrop = false, availableModels, showModelSelector = false, showToolsMenu = false, showSkillsMenu = false, showTokenUsage = true, showContextRing = false, themeVariant, themeOverrides, colorMode, runtimeId, historyEndpoint, authToken, historyAuthToken, pendingPrompt, showInformation = false, onInformationClick, onToolCallStart, onToolCallComplete, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, panelProps, launching = false, launchingMessage, assistantCharacter = DEFAULT_ASSISTANT_CHARACTER, balloonDisplay: balloonDisplayGiven = DEFAULT_BALLOON_DISPLAY, expandTarget, conversation, decisions, voice, inspector, onBalloonDisplayChange, onChangeCharacter, about, sandbox, contextMenu, }) {
74
76
  // The chat's own send, once it can: what a suggestion in the balloon sends.
75
77
  const chatControls = useRef(null);
76
78
  const [suggestionPrompt, setSuggestionPrompt] = useState();
@@ -150,6 +152,8 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
150
152
  const [ownTool, setOwnTool] = useState();
151
153
  const [messageCount, setMessageCount] = useState(0);
152
154
  // The conversation's messages, listed in the closed `history` balloon.
155
+ // The chat's own items — its messages and tool calls — as it holds them:
156
+ // the balloon draws them with the chat's components.
153
157
  const [ownHistory, setOwnHistory] = useState([]);
154
158
  /*
155
159
  * Its voice (VOICE.md V1): the answers said by the speech service, as
@@ -273,7 +277,16 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
273
277
  // The tool line, while its call runs or its turn goes on (T-23).
274
278
  const toolSaid = toolLine && (toolLine.phase === 'running' || atWork) ? toolLine : undefined;
275
279
  // Current: what is said now — thinking until the answer's words arrive.
276
- const currentWords = atWork && !answering ? 'Thinking…' : saying?.text || undefined;
280
+ // The words as written (markdown, drawn by the chat's markdown), or cut
281
+ // to fit with the whole kept for *more*.
282
+ const currentWords = atWork && !answering
283
+ ? 'Thinking…'
284
+ : (saying?.more ? saying.text : saying?.markdown) || undefined;
285
+ const currentWhole = atWork && !answering
286
+ ? undefined
287
+ : saying?.more
288
+ ? saying.markdown
289
+ : undefined;
277
290
  // History: the closed balloon lists the conversation, not its newest line.
278
291
  const listedHistory = !showsCurrent && !conversation && ownHistory.length > 0
279
292
  ? ownHistory
@@ -303,6 +316,7 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
303
316
  ? // Current: the words as they are written, whole.
304
317
  {
305
318
  text: currentWords ?? description,
319
+ fullText: currentWhole,
306
320
  more: saying?.more,
307
321
  speaking: answering && atWork,
308
322
  busy: atWork,
@@ -371,12 +385,7 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
371
385
  ? previous
372
386
  : line);
373
387
  setMessageCount(conversationCount(items));
374
- const listed = balloonHistoryOf(items);
375
- setOwnHistory(previous => previous.length === listed.length &&
376
- previous.every((message, index) => message.id === listed[index].id &&
377
- message.text === listed[index].text)
378
- ? previous
379
- : listed);
388
+ setOwnHistory(items);
380
389
  setVoiceItems(items);
381
390
  const said = latestSaying(items);
382
391
  setSaying(previous => previous?.id === said?.id && previous?.text === said?.text
@@ -540,6 +549,34 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
540
549
  showSkillsMenu,
541
550
  showTokenUsage,
542
551
  ]);
552
+ // What the assistant's menu says of the agent (*Agent Details…*): the
553
+ // host's words first, the chat's own agent and runtime under them.
554
+ const runtimeBase = endpoint?.match(/^(.*?)\/api\/v1\//)?.[1];
555
+ const agentAbout = useMemo(() => about || protocol?.agentId
556
+ ? {
557
+ name: title,
558
+ protocol: protocol?.type,
559
+ url: protocol?.endpoint,
560
+ agentId: protocol?.agentId,
561
+ apiBase: runtimeBase,
562
+ ...about,
563
+ }
564
+ : undefined, [about, protocol, title, runtimeBase]);
565
+ // Its sandbox (*Code Sandbox Details…*): the host's, or what its runtime
566
+ // reports.
567
+ const codemodeStatus = useAgentRuntimeCodemodeStatus();
568
+ const agentSandbox = useMemo(() => sandbox ??
569
+ assistantSandboxOf(codemodeStatus
570
+ ?.sandbox, { agentId: protocol?.agentId, serverUrl: runtimeBase }) ??
571
+ // An agent on a runtime can always have one: offered before it runs.
572
+ (protocol?.agentId && runtimeBase
573
+ ? {
574
+ kind: 'runtime',
575
+ status: 'not running',
576
+ agentId: protocol.agentId,
577
+ serverUrl: runtimeBase,
578
+ }
579
+ : undefined), [sandbox, codemodeStatus, protocol?.agentId, runtimeBase]);
543
580
  // Clear messages when endpoint/protocol changes (e.g., switching examples)
544
581
  useEffect(() => {
545
582
  clearStoreMessages();
@@ -1058,7 +1095,7 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
1058
1095
  showAvatars: true,
1059
1096
  }, placeholder: "Type a message...", backgroundColor: "canvas.subtle", frontendTools: frontendTools, showModelSelector: showModelSelector, availableModels: availableModels, showToolsMenu: showToolsMenu, showSkillsMenu: showSkillsMenu, showTokenUsage: showTokenUsage, showContextRing: showContextRing, runtimeId: runtimeId, historyEndpoint: historyEndpoint, historyAuthToken: historyAuthToken, pendingPrompt: pendingPrompt ?? suggestionPrompt, inspector: inspector, showInformation: showInformation, onInformationClick: onInformationClick, onToolCallStart: onToolCallStart, onToolCallComplete: onToolCallComplete, showToolApprovalBanner: showToolApprovalBanner, pendingApprovals: pendingApprovals, onApproveApproval: onApproveApproval, onRejectApproval: onRejectApproval, voice: voice, voiceSpeaking: speakerState.speaking, onStopSpeaking: speaker ? stopSpeaking : undefined, ...panelProps, ...assistantChat, onLoadingChange: handleLoadingChange, onDisplayItemsChange: handleDisplayItemsChange, onSendReady: handleSendReady, children: conversationBalloon && currentOpen ? (
1060
1097
  // Current: the one thing said or done now, over the composer.
1061
- _jsx(Box, { sx: { px: 3, pt: 3, pb: 2, overflow: 'hidden' }, children: _jsx(CurrentBalloonBody, { text: toolSaid ? undefined : (currentWords ?? description), tool: toolSaid, busy: atWork, speaking: answering && atWork, waiting: atWork && !answering }) })) : (children) }))] }));
1098
+ _jsx(Box, { sx: { px: 3, pt: 3, pb: 2, overflow: 'hidden' }, children: _jsx(CurrentBalloonBody, { text: toolSaid ? undefined : (currentWords ?? description), fullText: toolSaid ? undefined : currentWhole, tool: toolSaid, busy: atWork, speaking: answering && atWork, waiting: atWork && !answering }) })) : (children) }))] }));
1062
1099
  /*
1063
1100
  * The floating popup's button. Words not yet heard make it blink for the
1064
1101
  * person's attention, until the chat is opened; hovered, they show in a
@@ -1118,7 +1155,7 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
1118
1155
  setSpeechMuted(!speechMuted);
1119
1156
  },
1120
1157
  }
1121
- : undefined, onResetPosition: stageDrag.position ? stageDrag.reset : undefined, about: about, contextMenu: contextMenu })), showButton && !isOpen && !assistantShown && (_jsx(Box, { sx: {
1158
+ : undefined, onResetPosition: stageDrag.position ? stageDrag.reset : undefined, about: agentAbout, sandbox: agentSandbox, contextMenu: contextMenu })), showButton && !isOpen && !assistantShown && (_jsx(Box, { sx: {
1122
1159
  ...getPositionStyles(),
1123
1160
  }, children: _jsxs(Box, { sx: {
1124
1161
  position: 'relative',
@@ -0,0 +1,21 @@
1
+ /**
2
+ * *Agent Details…*, from the assistant's menu: the agent's `AgentDetails`
3
+ * in a dialog over the page. On an agent-runtimes server it reads what that
4
+ * server says of the agent (its spec, MCP servers, codemode, context); an
5
+ * agent in the page, or a peer known by its A2A card, is described by what
6
+ * its host knows: its Appspec, model and where it runs.
7
+ *
8
+ * Loaded when it is first opened, never with the character.
9
+ *
10
+ * @module chat/assistant/AgentDetailsDialog
11
+ */
12
+ import type { JSX } from 'react';
13
+ import type { AssistantAbout } from './AssistantStage';
14
+ export type AgentDetailsDialogProps = {
15
+ about: AssistantAbout;
16
+ /** The character's name, when the agent has none of its own. */
17
+ name: string;
18
+ onClose: () => void;
19
+ };
20
+ export declare function AgentDetailsDialog({ about, name, onClose, }: AgentDetailsDialogProps): JSX.Element;
21
+ export default AgentDetailsDialog;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import { Dialog } from '@primer/react';
4
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
5
+ import { AgentDetails } from '../../agents/AgentDetails';
6
+ export function AgentDetailsDialog({ about, name, onClose, }) {
7
+ // AgentDetails reads the runtime through react-query; a page that shows
8
+ // only a character has no client of its own.
9
+ const queries = useMemo(() => new QueryClient(), []);
10
+ const onRuntime = Boolean(about.agentId && about.apiBase);
11
+ return (_jsx(Dialog, { title: `${about.name ?? name} · Agent Details`, onClose: onClose, width: "xlarge", height: "large", children: _jsx("div", { "data-assistant-agent-details": "", children: _jsx(QueryClientProvider, { client: queries, children: _jsx(AgentDetails, { name: about.name ?? name, protocol: about.protocol ?? (onRuntime ? 'agent-runtimes' : 'browser'), url: about.url ?? '', messageCount: 0, agentId: about.agentId, apiBase: about.apiBase, onBack: onClose, showBackHeader: false, showUsage: onRuntime, padded: false, runtime: onRuntime, summary: {
12
+ spec: about.spec,
13
+ model: about.model,
14
+ where: about.where,
15
+ description: about.description,
16
+ skills: about.skills,
17
+ } }) }) }) }));
18
+ }
19
+ export default AgentDetailsDialog;
@@ -30,11 +30,13 @@ import { type AssistantCharacter } from './characters';
30
30
  import { type BalloonSuggestion } from './SpeechBalloon';
31
31
  import { type AssistantMenuItem } from './AssistantContextMenu';
32
32
  import type { AgentInspectorSink } from '../../components/inspector/agentInspector';
33
+ import type { AssistantSandbox } from './assistantDetails';
33
34
  import { type BalloonExpandTarget, type BalloonVisual } from './BalloonVisual';
34
35
  import type { AssistantCharacterData } from './formats/types';
35
36
  import type { DecisionAsker } from './decisions';
36
- import type { BalloonDisplay, BalloonToolLine } from './toolLine';
37
- import { type AssistantAway, type AssistantState, type BalloonApproval, type BalloonHistoryMessage } from './state';
37
+ import { type BalloonDisplay, type BalloonToolLine } from './toolLine';
38
+ import type { DisplayItem } from '../../types/chat';
39
+ import { type AssistantAway, type AssistantState, type BalloonApproval } from './state';
38
40
  /** What the assistant's *About* says. */
39
41
  export type AssistantAbout = {
40
42
  /** The agent's name, or its application's. */
@@ -45,6 +47,19 @@ export type AssistantAbout = {
45
47
  model?: string;
46
48
  /** Where it runs: `in your browser`, `on a runtime`. */
47
49
  where?: string;
50
+ /** What it does, in a sentence: its card's or its spec's description. */
51
+ description?: string;
52
+ /** What it can do: its card's skills. */
53
+ skills?: string[];
54
+ /**
55
+ * The agent on an agent-runtimes server, and that server: *Agent
56
+ * Details…* then reads its spec, MCP servers and codemode there.
57
+ */
58
+ agentId?: string;
59
+ apiBase?: string;
60
+ /** How it is reached (`a2a`, `ag-ui`, …) and where. */
61
+ protocol?: string;
62
+ url?: string;
48
63
  };
49
64
  /**
50
65
  * The entries of the assistant's menu, composed from what the host passes:
@@ -58,6 +73,10 @@ export declare function assistantMenuItems(options: {
58
73
  /** The conversation entry's label; `false` leaves it out. */
59
74
  conversationLabel?: string | false;
60
75
  inspect?: () => void;
76
+ /** Opens *Agent Details…*: offered where the host describes the agent. */
77
+ agentDetails?: () => void;
78
+ /** Opens *Code Sandbox Details…*: offered where the agent has a sandbox. */
79
+ sandboxDetails?: () => void;
61
80
  balloonDisplay?: BalloonDisplay;
62
81
  onBalloonDisplayChange?: (display: BalloonDisplay) => void;
63
82
  suggestions?: readonly BalloonSuggestion[];
@@ -123,6 +142,17 @@ export interface AssistantStageProps {
123
142
  open: boolean;
124
143
  /** Open or close the conversation. */
125
144
  onToggle: () => void;
145
+ /**
146
+ * What a click on the character does, when it is not `onToggle`: a team's
147
+ * member shows and hides its balloon, and its menu's conversation entry
148
+ * (*Ask Sales*) still does `onToggle`.
149
+ */
150
+ onCharacterClick?: () => void;
151
+ /**
152
+ * A key pressed on the focused character, after its own (the menu's):
153
+ * a team's member moves with the arrow keys.
154
+ */
155
+ onCharacterKeyDown?: (event: React.KeyboardEvent<HTMLElement>) => void;
126
156
  /**
127
157
  * The peek while the conversation is closed: one short line — the agent's
128
158
  * newest words, as the Office Assistant said them (T-23), or a welcome —
@@ -149,7 +179,7 @@ export interface AssistantStageProps {
149
179
  * The conversation's messages (`history`): the balloon lists them all,
150
180
  * counted and scrolled, rather than the newest line alone.
151
181
  */
152
- history?: readonly BalloonHistoryMessage[];
182
+ history?: readonly DisplayItem[];
153
183
  /**
154
184
  * The large visual `attachment` is the compact form of (a notebook):
155
185
  * the balloon offers *Expand*, and draws it large — into
@@ -211,8 +241,13 @@ export interface AssistantStageProps {
211
241
  };
212
242
  /** Puts it back where it started, after a drag: offered in its menu. */
213
243
  onResetPosition?: () => void;
214
- /** What its menu's *About* says. */
244
+ /** What its menu's *About* and *Agent Details…* say. */
215
245
  about?: AssistantAbout;
246
+ /**
247
+ * The agent's code sandbox, when it has one: its menu offers *Code
248
+ * Sandbox Details…* — where it runs, and its variables.
249
+ */
250
+ sandbox?: AssistantSandbox;
216
251
  /** The host's or a plugin's own entries of its menu. */
217
252
  contextMenu?: readonly AssistantMenuItem[];
218
253
  /** Send it away (T-27): for the page, for the session, or for good. */
@@ -239,6 +274,17 @@ export interface AssistantStageProps {
239
274
  * and its neighbours, not a page somebody is working on.
240
275
  */
241
276
  stayPut?: boolean;
277
+ /**
278
+ * The agent's own name, used in place of the character's by its menu and
279
+ * its *Send … away*: `Sales`, where the character is a paper clip.
280
+ */
281
+ agentName?: string;
282
+ /**
283
+ * The figure's accessible name, in place of *Talk to <character>*:
284
+ * `Sales (in your browser)`. Given this or `agentName`, the character's
285
+ * name describes the figure instead (`aria-describedby`).
286
+ */
287
+ label?: string;
242
288
  }
243
289
  /** The openings of the mouth, by level: shut, a little, half, wide. */
244
290
  export declare function mouthOpening(level: number): 0 | 1 | 2 | 3;
@@ -247,5 +293,5 @@ export declare function mouthOpening(level: number): 0 | 1 | 2 | 3;
247
293
  * `data-assistant-mouth`, each frame, without drawing the character again.
248
294
  */
249
295
  export declare function useMouth(stageRef: RefObject<HTMLElement | null>, mouthLevel: (() => number) | undefined, speaking: boolean): void;
250
- export declare function AssistantStage({ character, state, size, place, stageRef, onDragStart, open, onToggle, balloon, insist, onDismiss, ownRef, decide, mouthLevel, stayPut, balloonDisplay, expandTarget, expandOnArrival, suggestions, onSuggestion, inspector, inspectAgent, conversationLabel, onBalloonDisplayChange, onStop, onNewChat, onClear, onChangeCharacter, speech, onResetPosition, about, contextMenu, }: AssistantStageProps): JSX.Element;
296
+ export declare function AssistantStage({ character, state, size, place, stageRef, onDragStart, open, onToggle, onCharacterClick, onCharacterKeyDown, balloon, insist, onDismiss, ownRef, decide, mouthLevel, stayPut, balloonDisplay, expandTarget, expandOnArrival, suggestions, onSuggestion, inspector, inspectAgent, conversationLabel, onBalloonDisplayChange, onStop, onNewChat, onClear, onChangeCharacter, speech, onResetPosition, about, sandbox, contextMenu, agentName, label, }: AssistantStageProps): JSX.Element;
251
297
  export default AssistantStage;
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Suspense, lazy, useCallback, useEffect, useRef, useState, } from 'react';
2
+ import { Suspense, lazy, useCallback, useEffect, useId, useRef, useState, } from 'react';
3
3
  import { ActionList, ActionMenu, IconButton, useTheme } from '@primer/react';
4
4
  import { Box } from '@datalayer/primer-addons';
5
- import { CommentDiscussionIcon, InfoIcon, MuteIcon, PencilIcon, PlusIcon, PulseIcon, ScreenNormalIcon, SquareFillIcon, TrashIcon, UnmuteIcon, XIcon, } from '@primer/octicons-react';
5
+ import { CodeIcon, CommentDiscussionIcon, DependabotIcon, InfoIcon, MuteIcon, PencilIcon, PlusIcon, PulseIcon, ScreenNormalIcon, SquareFillIcon, TrashIcon, UnmuteIcon, XIcon, } from '@primer/octicons-react';
6
6
  import { Dialog, Text } from '@primer/react';
7
7
  import { assistantCharacter } from './characters';
8
8
  import { BalloonHistoryLarge, SpeechBalloon, } from './SpeechBalloon';
@@ -10,6 +10,7 @@ import { conversationHeaderText } from './BalloonParts';
10
10
  import { AssistantContextMenu, LONG_PRESS_MS, opensContextMenu, } from './AssistantContextMenu';
11
11
  import { BalloonExpandContext, ExpandedVisual, focusExpanded, } from './BalloonVisual';
12
12
  import { SpriteCharacter } from './SpriteCharacter';
13
+ import { conversationCount, } from './toolLine';
13
14
  import { ASSISTANT_OBSTACLES, POINTER_CALM_MS, boxesMeet, pointerNear, } from './state';
14
15
  /** The motions, by the state the stage is in. */
15
16
  const MOTIONS = {
@@ -63,6 +64,10 @@ const AWAY_CHOICES = [
63
64
  ];
64
65
  /** The Agent Inspector's dialog: loaded when it is first asked for. */
65
66
  const AgentInspectorDialog = lazy(() => import('../../components/inspector/AgentInspectorDialog'));
67
+ /** *Agent Details…*: loaded when it is first asked for. */
68
+ const AgentDetailsDialog = lazy(() => import('./AgentDetailsDialog'));
69
+ /** *Code Sandbox Details…*: loaded when it is first asked for. */
70
+ const SandboxDetailsDialog = lazy(() => import('./SandboxDetailsDialog'));
66
71
  /**
67
72
  * The entries of the assistant's menu, composed from what the host passes:
68
73
  * each shows when what it does is there to do.
@@ -77,6 +82,22 @@ export function assistantMenuItems(options) {
77
82
  onSelect: options.inspect,
78
83
  });
79
84
  }
85
+ if (options.agentDetails) {
86
+ items.push({
87
+ id: 'agent-details',
88
+ label: 'Agent Details…',
89
+ icon: DependabotIcon,
90
+ onSelect: options.agentDetails,
91
+ });
92
+ }
93
+ if (options.sandboxDetails) {
94
+ items.push({
95
+ id: 'sandbox-details',
96
+ label: 'Code Sandbox Details…',
97
+ icon: CodeIcon,
98
+ onSelect: options.sandboxDetails,
99
+ });
100
+ }
80
101
  if (options.conversationLabel !== false) {
81
102
  items.push({
82
103
  id: 'conversation',
@@ -335,7 +356,7 @@ export function useMouth(stageRef, mouthLevel, speaking) {
335
356
  };
336
357
  }, [stageRef, mouthLevel, speaking]);
337
358
  }
338
- export function AssistantStage({ character, state, size = 88, place, stageRef, onDragStart, open, onToggle, balloon, insist = false, onDismiss, ownRef, decide, mouthLevel, stayPut = false, balloonDisplay = 'history', expandTarget, expandOnArrival = false, suggestions, onSuggestion, inspector, inspectAgent, conversationLabel, onBalloonDisplayChange, onStop, onNewChat, onClear, onChangeCharacter, speech, onResetPosition, about, contextMenu, }) {
359
+ export function AssistantStage({ character, state, size = 88, place, stageRef, onDragStart, open, onToggle, onCharacterClick, onCharacterKeyDown, balloon, insist = false, onDismiss, ownRef, decide, mouthLevel, stayPut = false, balloonDisplay = 'history', expandTarget, expandOnArrival = false, suggestions, onSuggestion, inspector, inspectAgent, conversationLabel, onBalloonDisplayChange, onStop, onNewChat, onClear, onChangeCharacter, speech, onResetPosition, about, sandbox, contextMenu, agentName, label, }) {
339
360
  // A shipped one by id, a drawing contributed by a plugin (T-24), or a
340
361
  // character read from a file (T-26).
341
362
  const shipped = typeof character === 'string'
@@ -343,9 +364,14 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
343
364
  : 'Drawing' in character
344
365
  ? character
345
366
  : undefined;
346
- const name = shipped
367
+ const characterName = shipped
347
368
  ? shipped.name
348
369
  : character.name;
370
+ // The agent's name where the host gives it, else the character's.
371
+ const name = agentName ?? characterName;
372
+ // The character, as the figure's description, when it is not its name.
373
+ const describedBy = useId();
374
+ const described = Boolean(agentName || label);
349
375
  // Drawn for the chat's colour mode: the dark drawing on a dark page (T-25).
350
376
  const { colorScheme } = useTheme();
351
377
  const colorMode = colorScheme?.startsWith('dark') ? 'dark' : 'light';
@@ -355,13 +381,19 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
355
381
  const [menuAt, setMenuAt] = useState(null);
356
382
  const [inspecting, setInspecting] = useState(false);
357
383
  const [telling, setTelling] = useState(false);
384
+ const [detailing, setDetailing] = useState(null);
358
385
  const characterRef = useRef(null);
359
386
  const longPress = useRef(undefined);
360
387
  const closeMenu = useCallback(() => setMenuAt(null), []);
361
388
  useEffect(() => () => clearTimeout(longPress.current), []);
362
389
  // Where the press began: a press that moves is a drag, not a click.
363
390
  const pressedAt = useRef(null);
364
- const aside = useKeepClear(stageRef, ownRef, menuOpen || menuAt !== null || inspecting || telling || stayPut);
391
+ const aside = useKeepClear(stageRef, ownRef, menuOpen ||
392
+ menuAt !== null ||
393
+ inspecting ||
394
+ telling ||
395
+ detailing !== null ||
396
+ stayPut);
365
397
  useMouth(stageRef, mouthLevel, state === 'speaking');
366
398
  // A decision being asked, or its answer, keeps the balloon up.
367
399
  const [deciding, setDeciding] = useState(false);
@@ -379,6 +411,8 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
379
411
  onDismiss,
380
412
  conversationLabel,
381
413
  inspect: inspector ? () => setInspecting(true) : undefined,
414
+ agentDetails: about ? () => setDetailing('agent') : undefined,
415
+ sandboxDetails: sandbox ? () => setDetailing('sandbox') : undefined,
382
416
  balloonDisplay,
383
417
  onBalloonDisplayChange,
384
418
  suggestions,
@@ -410,7 +444,7 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
410
444
  const historyVisual = balloonDisplay !== 'current' && history && history.length > 0
411
445
  ? {
412
446
  id: 'balloon-history',
413
- title: conversationHeaderText(history.length),
447
+ title: conversationHeaderText(conversationCount(history)),
414
448
  shrink: true,
415
449
  render: () => (_jsx(BalloonHistoryLarge, { history: history, tool: balloon?.tool, attachment: balloon?.attachment })),
416
450
  }
@@ -530,7 +564,8 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
530
564
  : undefined, suggestions: waitsForQuestion ? suggestions : undefined, fullText: balloon.fullText, waiting: (state === 'thinking' ||
531
565
  state === 'working' ||
532
566
  state === 'waiting') &&
533
- !balloon.speaking, onSuggestion: onSuggestion, decide: decide, onDecisionActive: setDeciding, wide: deciding, onOpen: onToggle, above: size + 8, side: balloonSide(place).side, align: balloonSide(place).align, tailAt: size / 2 }) })), _jsx(Box, { as: "button", type: "button", "aria-label": open ? `Close the conversation with ${name}` : `Talk to ${name}`, "aria-expanded": open, "aria-haspopup": "menu", ref: characterRef, "data-assistant-figure": "", onContextMenu: (event) => {
567
+ !balloon.speaking, onSuggestion: onSuggestion, decide: decide, onDecisionActive: setDeciding, wide: deciding, onOpen: onToggle, above: size + 8, side: balloonSide(place).side, align: balloonSide(place).align, tailAt: size / 2 }) })), _jsxs(Box, { as: "button", type: "button", "aria-label": label ??
568
+ (open ? `Close the conversation with ${name}` : `Talk to ${name}`), "aria-describedby": described ? describedBy : undefined, "aria-expanded": open, "aria-haspopup": "menu", ref: characterRef, "data-assistant-figure": "", onContextMenu: (event) => {
534
569
  event.preventDefault();
535
570
  clearTimeout(longPress.current);
536
571
  setMenuAt({ x: event.clientX, y: event.clientY });
@@ -539,7 +574,9 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
539
574
  event.preventDefault();
540
575
  const box = event.currentTarget.getBoundingClientRect();
541
576
  setMenuAt({ x: box.left + box.width / 2, y: box.bottom });
577
+ return;
542
578
  }
579
+ onCharacterKeyDown?.(event);
543
580
  }, onPointerUp: () => clearTimeout(longPress.current), onPointerCancel: () => clearTimeout(longPress.current), onPointerMove: (event) => {
544
581
  const from = pressedAt.current;
545
582
  if (from &&
@@ -565,7 +602,7 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
565
602
  Math.hypot(event.clientX - from.x, event.clientY - from.y) > 4) {
566
603
  return;
567
604
  }
568
- onToggle();
605
+ (onCharacterClick ?? onToggle)();
569
606
  }, sx: {
570
607
  display: 'block',
571
608
  width: size,
@@ -583,13 +620,26 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
583
620
  outlineOffset: 2,
584
621
  borderRadius: '50%',
585
622
  },
586
- }, children: shipped ? (_jsx(shipped.Drawing, { size: size, mode: colorMode })) : (_jsx(SpriteCharacter, { character: character, state: state, size: size })) }), (hovered || menuOpen) && !aside && state !== 'goodbye' && (_jsx(Box, { sx: { position: 'absolute', top: '-6px', right: '-6px' }, children: _jsxs(ActionMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [_jsx(ActionMenu.Anchor, { children: _jsx(IconButton, { icon: XIcon, "aria-label": `Send ${name} away`, size: "small", variant: "invisible", "data-assistant-dismiss": "", sx: {
623
+ }, children: [described && (_jsx(Box, { as: "span", id: describedBy, sx: {
624
+ position: 'absolute',
625
+ width: 1,
626
+ height: 1,
627
+ overflow: 'hidden',
628
+ clip: 'rect(0 0 0 0)',
629
+ whiteSpace: 'nowrap',
630
+ }, children: `Its character: ${characterName}` })), shipped ? (_jsx(shipped.Drawing, { size: size, mode: colorMode })) : (_jsx(SpriteCharacter, { character: character, state: state, size: size }))] }), (hovered || menuOpen) && !aside && state !== 'goodbye' && (_jsx(Box, { sx: { position: 'absolute', top: '-6px', right: '-6px' }, children: _jsxs(ActionMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [_jsx(ActionMenu.Anchor, { children: _jsx(IconButton, { icon: XIcon, "aria-label": `Send ${name} away`, size: "small", variant: "invisible", "data-assistant-dismiss": "", sx: {
587
631
  bg: 'canvas.default',
588
632
  borderRadius: '50%',
589
633
  boxShadow: 'shadow.small',
590
634
  } }) }), _jsx(ActionMenu.Overlay, { width: "auto", children: _jsx(ActionList, { children: AWAY_CHOICES.map(choice => (_jsx(ActionList.Item, { "data-assistant-away": choice.away, onSelect: () => onDismiss(choice.away), children: choice.label }, choice.away))) }) })] }) })), _jsx(AssistantContextMenu, { at: menuAt, items: menuItems, onClose: closeMenu, returnFocusRef: characterRef, label: `${name}\u2019s menu` }), inspecting && (_jsx(Suspense, { fallback: null, children: _jsx(AgentInspectorDialog, { sink: inspector ?? null, agent: inspectAgent, title: `${about?.name ?? name} \u00b7 Agent Inspector`, onClose: () => {
591
635
  setInspecting(false);
592
636
  characterRef.current?.focus();
637
+ } }) })), detailing === 'agent' && about && (_jsx(Suspense, { fallback: null, children: _jsx(AgentDetailsDialog, { about: about, name: name, onClose: () => {
638
+ setDetailing(null);
639
+ characterRef.current?.focus();
640
+ } }) })), detailing === 'sandbox' && sandbox && (_jsx(Suspense, { fallback: null, children: _jsx(SandboxDetailsDialog, { sandbox: sandbox, name: about?.name ?? name, onClose: () => {
641
+ setDetailing(null);
642
+ characterRef.current?.focus();
593
643
  } }) })), telling && about && (_jsx(Dialog, { title: `About ${about.name ?? name}`, onClose: () => {
594
644
  setTelling(false);
595
645
  characterRef.current?.focus();
@@ -598,7 +648,7 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
598
648
  ['Spec', about.spec],
599
649
  ['Model', about.model],
600
650
  ['Runs', about.where],
601
- ['Character', name],
651
+ ['Character', characterName],
602
652
  ]
603
653
  .filter(([, value]) => value)
604
654
  .map(([key, value]) => (_jsxs(Text, { as: "p", sx: { m: 0, mb: 1 }, children: [_jsxs(Text, { sx: { color: 'fg.muted' }, children: [key, ": "] }), value] }, key))) }))] }));
@@ -7,15 +7,29 @@
7
7
  * @module chat/assistant/BalloonParts
8
8
  */
9
9
  import type { JSX, ReactNode } from 'react';
10
+ import { type ChatDensity } from '../messages/ChatMarkdown';
11
+ import type { DisplayItem } from '../../types/chat';
10
12
  import { type BalloonToolLine } from './toolLine';
11
13
  /**
12
- * A tool call in the balloon, in plain words: its mark when the catalogue
13
- * gives one (an MCP server's, a skill's, a tool set's), else a tool; "Using
14
- * **list_invoices**…", "Done: **list_invoices**", "**list_invoices** failed".
14
+ * The conversation's items in the balloon, drawn by the chat's own
15
+ * components (`ChatMessageList`): markdown, code blocks, tool calls and
16
+ * their approvals, notes, the three dots — in the compact density, or the
17
+ * chat's own when drawn large.
18
+ */
19
+ export declare function BalloonChatItems({ items, density, waiting, }: {
20
+ items: readonly DisplayItem[];
21
+ density?: ChatDensity;
22
+ /** At work with nothing written yet: the chat's dots, last. */
23
+ waiting?: boolean;
24
+ }): JSX.Element;
25
+ /**
26
+ * The tool being called, in the balloon: the chat's tool call card, compact,
27
+ * with its runtime's own words (`Asking Accounting…`) as its summary.
15
28
  * Seen, not read out: {@link ToolLineAnnouncer} says it once per change.
16
29
  */
17
- export declare function BalloonToolLineView({ line, }: {
30
+ export declare function BalloonToolCall({ line, waiting, }: {
18
31
  line: BalloonToolLine;
32
+ waiting?: boolean;
19
33
  }): JSX.Element;
20
34
  /**
21
35
  * What a screen reader hears of the tool lines, politely: once when a call