@datalayer/agent-runtimes 1.3.89 → 1.3.90

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 (257) hide show
  1. package/lib/Agent.js +2 -18
  2. package/lib/AgentDocument.js +5 -55
  3. package/lib/AgentNode.js +31 -208
  4. package/lib/AgentNotebook.js +5 -59
  5. package/lib/agent-node/AgentNodeGallery.js +23 -111
  6. package/lib/agents/AgentDetails.js +36 -274
  7. package/lib/agents/AgentRuntimeChat.js +1 -8
  8. package/lib/chat/Chat.js +7 -46
  9. package/lib/chat/ChatFloating.js +15 -100
  10. package/lib/chat/ChatInline.js +5 -47
  11. package/lib/chat/ChatPopupStandalone.js +5 -53
  12. package/lib/chat/ChatSidebar.js +4 -51
  13. package/lib/chat/ChatStandalone.js +4 -45
  14. package/lib/chat/EphemeralSurfaceControl.js +5 -25
  15. package/lib/chat/assistant/AssistantContextMenu.d.ts +8 -0
  16. package/lib/chat/assistant/AssistantContextMenu.js +17 -1
  17. package/lib/chat/assistant/AssistantStage.js +6 -25
  18. package/lib/chat/assistant/BalloonParts.js +8 -40
  19. package/lib/chat/assistant/BalloonVisual.js +2 -2
  20. package/lib/chat/assistant/ConversationBalloon.js +2 -11
  21. package/lib/chat/assistant/DecisionAsk.js +3 -3
  22. package/lib/chat/assistant/SandboxDetailsDialog.js +3 -17
  23. package/lib/chat/assistant/SpeechBalloon.js +14 -78
  24. package/lib/chat/base/ChatBase.js +37 -172
  25. package/lib/chat/display/EmptyState.js +7 -35
  26. package/lib/chat/display/FloatingBrandButton.js +4 -34
  27. package/lib/chat/display/PoweredByTag.js +3 -14
  28. package/lib/chat/document/EphemeralDocument.js +3 -18
  29. package/lib/chat/header/ChatHeader.js +1 -17
  30. package/lib/chat/header/ChatHeaderBase.js +2 -24
  31. package/lib/chat/header/ChatViewModeToggle.js +7 -29
  32. package/lib/chat/indicators/McpStatusIndicator.js +3 -12
  33. package/lib/chat/indicators/SandboxStatusIndicator.js +6 -34
  34. package/lib/chat/indicators/SkillsStatusIndicator.js +3 -12
  35. package/lib/chat/indicators/TypingDots.js +1 -11
  36. package/lib/chat/messages/ChatMessageList.js +58 -185
  37. package/lib/chat/messages/ChatMessages.js +15 -79
  38. package/lib/chat/messages/FormSubmissionMessage.js +2 -33
  39. package/lib/chat/messages/NotebookToolSurfaces.js +12 -41
  40. package/lib/chat/messages/TurnFooter.js +4 -10
  41. package/lib/chat/notebook/EphemeralNotebook.js +2 -10
  42. package/lib/chat/parts/ReasoningPart.js +2 -16
  43. package/lib/chat/parts/TextPart.js +2 -12
  44. package/lib/chat/parts/ToolPart.js +16 -90
  45. package/lib/chat/presence/Presence.js +5 -33
  46. package/lib/chat/prompt/FloatingCard.js +1 -13
  47. package/lib/chat/prompt/InputPrompt.js +1 -6
  48. package/lib/chat/prompt/InputPromptBase.js +4 -17
  49. package/lib/chat/prompt/InputPromptLexical.js +44 -45
  50. package/lib/chat/prompt/InputPromptText.js +1 -1
  51. package/lib/chat/prompt/footer/InPromptFooter.js +1 -8
  52. package/lib/chat/prompt/menus/AgentsMenu.js +1 -1
  53. package/lib/chat/prompt/menus/InlineAgentsMenu.js +1 -1
  54. package/lib/chat/prompt/menus/ModelSelector.js +1 -5
  55. package/lib/chat/prompt/menus/SkillsMenu.js +3 -30
  56. package/lib/chat/prompt/menus/SuggestionsMenu.js +1 -1
  57. package/lib/chat/prompt/menus/ToolsMenu.js +4 -48
  58. package/lib/chat/prompt/plugins/AgentMentionPlugin.js +2 -9
  59. package/lib/chat/prompt/plugins/CommandPlugin.js +2 -9
  60. package/lib/chat/prompt/plugins/MentionChip.js +1 -15
  61. package/lib/chat/prompt/stack.js +1 -19
  62. package/lib/chat/tools/A2AAgentDialog.js +9 -42
  63. package/lib/chat/tools/SubagentActivity.js +5 -22
  64. package/lib/chat/tools/ToolApprovalBanner.js +4 -34
  65. package/lib/chat/tools/ToolApprovalDialog.js +4 -19
  66. package/lib/chat/tools/ToolCallDisplay.js +12 -97
  67. package/lib/chat/usage/ContextPie.js +4 -45
  68. package/lib/components/a2ui/datalayer/Chart.js +4 -10
  69. package/lib/components/a2ui/datalayer/Chat.js +2 -10
  70. package/lib/components/a2ui/datalayer/Download.js +1 -1
  71. package/lib/components/a2ui/datalayer/Evidence.js +1 -15
  72. package/lib/components/a2ui/datalayer/FileUpload.js +1 -12
  73. package/lib/components/a2ui/datalayer/Table.js +9 -17
  74. package/lib/components/a2ui/datalayer/formWidgets.js +3 -2
  75. package/lib/components/a2ui/datalayer/parts.js +1 -16
  76. package/lib/components/agents/AgentSummary.js +1 -51
  77. package/lib/components/cards/NotificationEventCard.js +6 -72
  78. package/lib/components/cards/OutputCard.js +4 -48
  79. package/lib/components/cards/ToolApprovalCard.js +2 -35
  80. package/lib/components/code-sandboxes/CodeSandboxCellVariables.js +1 -1
  81. package/lib/components/code-sandboxes/CodeSandboxEnvironmentSelect.js +4 -14
  82. package/lib/components/code-sandboxes/CodeSandboxPicker.js +16 -21
  83. package/lib/components/code-sandboxes/CodeSandboxVariables.js +2 -2
  84. package/lib/components/scheduler/ScheduleMenu.js +5 -10
  85. package/lib/components/specs/SpecPayloadPreview.js +1 -26
  86. package/lib/components/teams/A2ATeamGraph.d.ts +4 -3
  87. package/lib/components/teams/A2ATeamGraph.js +25 -71
  88. package/lib/components/teams/AnswerSurfacesView.js +2 -2
  89. package/lib/components/teams/NotebookPreview.js +1 -10
  90. package/lib/components/teams/NotebookPreviewView.js +2 -3
  91. package/lib/components/teams/SceneTranscript.js +3 -17
  92. package/lib/components/teams/SceneView.js +1 -8
  93. package/lib/components/teams/TeamNotebook.js +5 -13
  94. package/lib/components/teams/TeamNotebookView.js +2 -12
  95. package/lib/components/teams/index.d.ts +1 -0
  96. package/lib/components/teams/index.js +1 -0
  97. package/lib/components/teams/useBalloonRoom.d.ts +39 -0
  98. package/lib/components/teams/useBalloonRoom.js +89 -0
  99. package/lib/config/AgentConfiguration.js +22 -225
  100. package/lib/context/ContextDistribution.js +7 -41
  101. package/lib/context/ContextInspector.js +9 -107
  102. package/lib/context/ContextPanel.js +11 -86
  103. package/lib/context/ContextUsage.js +6 -34
  104. package/lib/context/CostTracker.js +7 -42
  105. package/lib/context/MessageHistory.js +3 -37
  106. package/lib/context/TurnGraphChart.js +9 -41
  107. package/lib/examples/A2UiAgentExample.js +6 -108
  108. package/lib/examples/A2UiComponentsGalleryExample.js +1 -1
  109. package/lib/examples/A2UiContactCardExample.js +1 -1
  110. package/lib/examples/A2UiJupyterOutputExample.js +25 -125
  111. package/lib/examples/A2UiRestaurantExample.js +1 -1
  112. package/lib/examples/A2UiViewerExample.js +1 -1
  113. package/lib/examples/AgUiAgenticExample.js +3 -35
  114. package/lib/examples/AgUiBackendToolRenderingExample.js +2 -25
  115. package/lib/examples/AgUiHaikuGenUiExample.js +2 -32
  116. package/lib/examples/AgUiHumanInTheLoopExample.js +5 -59
  117. package/lib/examples/AgUiSharedStateExample.js +6 -56
  118. package/lib/examples/AgUiToolsBasedGenUiExample.js +25 -120
  119. package/lib/examples/AgentA2AExample.js +1 -15
  120. package/lib/examples/AgentA2ATeamExample.js +6 -30
  121. package/lib/examples/AgentCheckpointsExample.js +11 -145
  122. package/lib/examples/AgentCodeSandboxExample.js +5 -108
  123. package/lib/examples/AgentCodeSandboxesExample.js +3 -30
  124. package/lib/examples/AgentCodemodeExample.js +9 -85
  125. package/lib/examples/AgentCompactionExample.js +3 -64
  126. package/lib/examples/AgentDecideExample.js +1 -13
  127. package/lib/examples/AgentEvalsExample.js +5 -60
  128. package/lib/examples/AgentGuardrailsExample.js +4 -28
  129. package/lib/examples/AgentHooksExample.js +1 -1
  130. package/lib/examples/AgentInferenceProviderExample.js +5 -96
  131. package/lib/examples/AgentMCPExample.js +7 -105
  132. package/lib/examples/AgentMemoryExample.js +5 -74
  133. package/lib/examples/AgentMonitoringExample.js +7 -53
  134. package/lib/examples/AgentNotificationsExample.js +3 -61
  135. package/lib/examples/AgentOtelExample.js +3 -72
  136. package/lib/examples/AgentOutputsExample.js +6 -81
  137. package/lib/examples/AgentParametersExample.js +2 -37
  138. package/lib/examples/AgentSkillsExample.js +3 -45
  139. package/lib/examples/AgentSubagentsExample.js +6 -56
  140. package/lib/examples/AgentToolApprovalsExample.js +1 -11
  141. package/lib/examples/AgentTriggersExample.js +29 -239
  142. package/lib/examples/AgentspecsExample.js +6 -60
  143. package/lib/examples/AssistantExample.js +5 -5
  144. package/lib/examples/AssistantGalleryExample.js +8 -65
  145. package/lib/examples/CellExample.js +1 -6
  146. package/lib/examples/ChatCustomExample.js +2 -31
  147. package/lib/examples/ChatExample.js +1 -9
  148. package/lib/examples/ChatStandaloneExample.js +3 -37
  149. package/lib/examples/CopilotKitLexicalExample.js +1 -24
  150. package/lib/examples/DecksAgent.js +1 -1
  151. package/lib/examples/DocumentPageAgent.js +1 -1
  152. package/lib/examples/HomeExample.js +14 -62
  153. package/lib/examples/Lexical2Example.js +3 -32
  154. package/lib/examples/LexicalAgentExample.js +2 -34
  155. package/lib/examples/LexicalAgentSidebarExample.js +3 -34
  156. package/lib/examples/LoopAppComputerExample.js +1 -1
  157. package/lib/examples/LoopShellExample.js +2 -2
  158. package/lib/examples/LoopStrategyExample.js +15 -87
  159. package/lib/examples/LoopWorkspaceEmbed.js +2 -18
  160. package/lib/examples/LoopWorkspaceExample.js +2 -2
  161. package/lib/examples/NotebookAgentExample.js +2 -33
  162. package/lib/examples/NotebookAgentSidebarExample.js +3 -46
  163. package/lib/examples/NotebookCollaborationExample.js +1 -31
  164. package/lib/examples/NotebookExample.js +1 -18
  165. package/lib/examples/NotebookPageAgent.js +1 -1
  166. package/lib/examples/ScenesExample.js +5 -24
  167. package/lib/examples/VoiceChatExample.js +1 -1
  168. package/lib/examples/components/AuthRequiredView.js +1 -7
  169. package/lib/examples/components/ErrorView.js +1 -8
  170. package/lib/examples/components/ExampleErrorBoundary.js +1 -14
  171. package/lib/examples/components/FooterMetrics.js +1 -7
  172. package/lib/examples/components/Header.js +12 -51
  173. package/lib/examples/components/HeaderControls.js +1 -9
  174. package/lib/examples/components/LexicalEditor.js +1 -8
  175. package/lib/examples/components/MainContent.js +1 -13
  176. package/lib/examples/components/MockFileBrowser.js +4 -40
  177. package/lib/examples/components/SessionTabs.js +1 -1
  178. package/lib/examples/components/TimeTravel.js +1 -13
  179. package/lib/examples/main.js +13 -81
  180. package/lib/examples/scenes/A2UiComponentsGalleryScene.js +3 -34
  181. package/lib/examples/scenes/A2UiContactCardScene.js +3 -35
  182. package/lib/examples/scenes/A2UiRestaurantScene.js +3 -53
  183. package/lib/examples/scenes/A2UiViewerScene.js +3 -34
  184. package/lib/examples/utils/AssistantGalleryGrid.js +6 -35
  185. package/lib/examples2/DatalayerNotebookExample.js +3 -33
  186. package/lib/examples2/NativeNavigationExample.js +4 -10
  187. package/lib/examples2/NotebookMutationsKernel.js +2 -1
  188. package/lib/examples2/NotebookMutationsServiceManager.js +2 -1
  189. package/lib/examples2/ReactRouterExample.js +14 -42
  190. package/lib/hooks/useToolApprovals.d.ts +2 -34
  191. package/lib/hooks/useToolApprovals.js +1 -64
  192. package/lib/identity/AgentIdentity.js +17 -62
  193. package/lib/identity/IdentityConnect.js +13 -59
  194. package/lib/identity/OAuthCallback.js +6 -44
  195. package/lib/lexical/ChatInlinePlugin.js +6 -14
  196. package/lib/loop/apps/AppRenderer.d.ts +4 -3
  197. package/lib/loop/apps/AppRenderer.js +11 -12
  198. package/lib/loop/apps/appspec.js +6 -3
  199. package/lib/loop/embed/AppEmbed.d.ts +1 -1
  200. package/lib/loop/embed/AppEmbed.js +2 -1
  201. package/lib/loop/embed/LoopEmbed.js +1 -7
  202. package/lib/loop/embed/embedConfig.d.ts +3 -3
  203. package/lib/loop/embed/embedConfig.js +2 -3
  204. package/lib/loop/embed/embedTheme.d.ts +4 -4
  205. package/lib/loop/embed/embedTheme.js +11 -7
  206. package/lib/loop/plugins/a2a-sidebar/A2ASidebar.js +7 -34
  207. package/lib/loop/plugins/a2ui/A2uiView.js +4 -12
  208. package/lib/loop/plugins/a2ui-surface/InlineSurface.js +1 -16
  209. package/lib/loop/plugins/a2ui-surface/SurfaceToolResult.js +2 -12
  210. package/lib/loop/plugins/agents/AnonymousKeyBadge.js +3 -2
  211. package/lib/loop/plugins/agents/SandboxSelector.js +3 -7
  212. package/lib/loop/plugins/agents/SandboxView.js +4 -27
  213. package/lib/loop/plugins/agents/TeamMemberPicker.js +2 -2
  214. package/lib/loop/plugins/agentspecs/AgentspecPicker.js +3 -2
  215. package/lib/loop/plugins/app-activity/AppActivity.js +1 -1
  216. package/lib/loop/plugins/app-computer/AppComputer.js +5 -21
  217. package/lib/loop/plugins/app-elements/AppElements.js +2 -31
  218. package/lib/loop/plugins/app-page/AppPage.js +1 -1
  219. package/lib/loop/plugins/app-rules/AppRulesCard.js +4 -20
  220. package/lib/loop/plugins/assistant/index.js +1 -13
  221. package/lib/loop/plugins/chat/ChatView.js +40 -106
  222. package/lib/loop/plugins/checkpoints-sidebar/CheckpointsSidebar.js +2 -13
  223. package/lib/loop/plugins/decks/DeckSurface.js +2 -2
  224. package/lib/loop/plugins/document/DocumentView.js +4 -12
  225. package/lib/loop/plugins/document-toolbar/SandboxStatusItem.js +3 -8
  226. package/lib/loop/plugins/graph/GraphView.js +2 -2
  227. package/lib/loop/plugins/input-prompt/ComposerView.js +1 -1
  228. package/lib/loop/plugins/notebook/NotebookView.js +3 -11
  229. package/lib/loop/plugins/page-layout/SplitLayout.js +11 -34
  230. package/lib/loop/plugins/page-layout/TurnPanel.js +9 -35
  231. package/lib/loop/plugins/shell/useEditorPreviews.js +3 -2
  232. package/lib/loop/plugins/subagent-activity/SubagentPulse.js +1 -13
  233. package/lib/loop/plugins/window-frame/WindowFrame.js +10 -44
  234. package/lib/loop/plugins/window-frame/index.js +1 -1
  235. package/lib/loop/shell/LoopWorkspace.js +34 -77
  236. package/lib/loop/shell/PluginToggles.js +4 -15
  237. package/lib/loop/shell/SidebarRail.js +8 -40
  238. package/lib/loop/shell/ViewSwitcher.js +4 -24
  239. package/lib/loop-main.js +2 -3
  240. package/lib/mcp/McpServerManager.js +6 -37
  241. package/lib/portable/index.d.ts +11 -0
  242. package/lib/portable/index.js +20 -0
  243. package/lib/protocols/AGUIAdapter.js +2 -2
  244. package/lib/protocols/BaseProtocolAdapter.d.ts +2 -0
  245. package/lib/protocols/BaseProtocolAdapter.js +4 -0
  246. package/lib/specs/apps.js +6 -0
  247. package/lib/specs/appspecSchema.js +11 -4
  248. package/lib/stories/loop/ReferenceScreens.js +17 -91
  249. package/lib/stories/loop/pictures-main.js +1 -1
  250. package/lib/types/agentspecs.d.ts +5 -2
  251. package/lib/types/protocol.d.ts +2 -0
  252. package/lib/utils/approvals.d.ts +59 -0
  253. package/lib/utils/approvals.js +101 -0
  254. package/lib/voice/VoiceInput.js +3 -39
  255. package/package.json +2 -2
  256. package/lib/shims/primerAddonsBox.d.ts +0 -1
  257. package/lib/shims/primerAddonsBox.js +0 -7
@@ -20,8 +20,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
20
20
  * @module stories/loop/ReferenceScreens
21
21
  */
22
22
  import { useEffect, useRef, useState } from 'react';
23
- import { Box, Button, Heading, Text } from '@primer/react';
24
- import { DatalayerThemeProvider, loopAccentStyles, setupPrimerPortals, themeConfigs, } from '@datalayer/primer-addons';
23
+ import { Button, Heading, Text } from '@primer/react';
24
+ import { Box, DatalayerThemeProvider, setupPrimerPortals, themeAccentVars, themeConfigs, } from '@datalayer/primer-addons';
25
25
  import { ChatBaseHeader } from '../../chat/header/ChatHeaderBase';
26
26
  import { ChatMessageList } from '../../chat/messages/ChatMessageList';
27
27
  import { InputPrompt } from '../../chat/prompt/InputPrompt';
@@ -84,29 +84,12 @@ export function ReferenceTheme({ theme, mode, children, }) {
84
84
  document.documentElement.setAttribute('data-reference-mode', mode);
85
85
  }, [theme, mode]);
86
86
  return (_jsx(DatalayerThemeProvider, { colorMode: mode, theme: config.primerTheme, themeStyles: config.themeStyles, baseStyles: theme === 'loop'
87
- ? loopAccentStyles('green', mode)
88
- : undefined, children: _jsx(Box, { "data-reference-stage": "", sx: {
89
- position: 'fixed',
90
- inset: 0,
91
- p: 4,
92
- bg: 'var(--loop-stage, var(--bgColor-muted))',
93
- color: 'fg.default',
94
- display: 'flex',
95
- }, children: children }) }));
87
+ ? themeAccentVars('green', mode)
88
+ : undefined, children: _jsx(Box, { "data-reference-stage": "", position: "fixed", inset: 0, p: 4, bg: theme === 'loop' ? 'var(--theme-stage)' : 'var(--bgColor-muted)', color: "fg.default", display: "flex", children: children }) }));
96
89
  }
97
90
  /** One rounded surface on the stage: the theme's frame. */
98
91
  function Frame({ children }) {
99
- return (_jsx(Box, { sx: {
100
- flex: 1,
101
- minWidth: 0,
102
- display: 'flex',
103
- overflow: 'hidden',
104
- bg: 'canvas.default',
105
- borderRadius: 'var(--theme-radius-frame, 12px)',
106
- border: 'var(--theme-hairline, 1px) solid',
107
- borderColor: 'border.muted',
108
- boxShadow: 'var(--theme-shadow, none)',
109
- }, children: children }));
92
+ return (_jsx(Box, { flex: 1, minWidth: 0, display: "flex", overflow: "hidden", bg: "canvas.default", borderRadius: "var(--theme-radius-frame, 12px)", border: "var(--theme-hairline, 1px) solid", borderColor: "border.muted", boxShadow: "var(--theme-shadow, none)", children: children }));
110
93
  }
111
94
  // ---------------------------------------------------------------------------
112
95
  // Fixed data
@@ -188,47 +171,30 @@ const AVATARS = {
188
171
  function Conversation({ name, face, presence, items, composer = true, mcpServers, }) {
189
172
  const endRef = useRef(null);
190
173
  const [input, setInput] = useState('');
191
- return (_jsxs(Box, { sx: {
192
- flex: 1,
193
- minWidth: 0,
194
- display: 'flex',
195
- flexDirection: 'column',
196
- height: '100%',
197
- }, children: [_jsx(ChatBaseHeader, { title: name, brandIcon: _jsx(PresenceFace, { face: face, size: 20, state: presence }), headerContent: _jsx(PresenceLine, { state: presence }), padding: 3, messageCount: items.length, onNewChat: () => undefined, onClear: () => undefined }), _jsx(Box, { sx: { flex: 1, minHeight: 0, overflow: 'hidden' }, children: _jsx(ChatMessageList, { displayItems: items, isLoading: false, isStreaming: false, showLoadingIndicator: false, hideMessagesAfterToolUI: false, avatarConfig: AVATARS, padding: 3, emptyContent: null, messagesEndRef: endRef, onRespond: async () => undefined, mcpServers: mcpServers }) }), composer && (_jsx(InputPrompt, { input: input, setInput: setInput, isLoading: false, connectionConfirmed: true, placeholder: "Send a message", autoFocus: false, padding: 3, onSend: () => undefined, onStop: () => undefined, showTokenUsage: false, showModelSelector: false, showToolsMenu: false, showSkillsMenu: false, codemodeEnabled: false, hasConfigData: false, hasSkillsData: false, isA2AProtocol: false }))] }));
174
+ return (_jsxs(Box, { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", height: "100%", children: [_jsx(ChatBaseHeader, { title: name, brandIcon: _jsx(PresenceFace, { face: face, size: 20, state: presence }), headerContent: _jsx(PresenceLine, { state: presence }), padding: 3, messageCount: items.length, onNewChat: () => undefined, onClear: () => undefined }), _jsx(Box, { flex: 1, minHeight: 0, overflow: "hidden", children: _jsx(ChatMessageList, { displayItems: items, isLoading: false, isStreaming: false, showLoadingIndicator: false, hideMessagesAfterToolUI: false, avatarConfig: AVATARS, padding: 3, emptyContent: null, messagesEndRef: endRef, onRespond: async () => undefined, mcpServers: mcpServers }) }), composer && (_jsx(InputPrompt, { input: input, setInput: setInput, isLoading: false, connectionConfirmed: true, placeholder: "Send a message", autoFocus: false, padding: 3, onSend: () => undefined, onStop: () => undefined, showTokenUsage: false, showModelSelector: false, showToolsMenu: false, showSkillsMenu: false, codemodeEnabled: false, hasConfigData: false, hasSkillsData: false, isA2AProtocol: false }))] }));
198
175
  }
199
176
  // ---------------------------------------------------------------------------
200
177
  // The four screens
201
178
  // ---------------------------------------------------------------------------
202
179
  /** A conversation. */
203
180
  export function ConversationScreen() {
204
- return (_jsx(Frame, { children: _jsx(Box, { sx: { flex: 1, display: 'flex', justifyContent: 'center' }, children: _jsx(Box, { sx: { width: '100%', maxWidth: 640, display: 'flex' }, children: _jsx(Conversation, { name: "Support desk", face: "\uD83E\uDD8A", presence: "idle", items: CONVERSATION }) }) }) }));
181
+ return (_jsx(Frame, { children: _jsx(Box, { flex: 1, display: "flex", justifyContent: "center", children: _jsx(Box, { width: "100%", maxWidth: 640, display: "flex", children: _jsx(Conversation, { name: "Support desk", face: "\uD83E\uDD8A", presence: "idle", items: CONVERSATION }) }) }) }));
205
182
  }
206
183
  /** A conversation beside its work: the split, one hairline between them. */
207
184
  export function BesideWorkScreen() {
208
- return (_jsxs(Frame, { children: [_jsx(Box, { sx: { width: 400, flexShrink: 0, display: 'flex' }, children: _jsx(Conversation, { name: "Support desk", face: "\uD83E\uDD8A", presence: "idle", items: BESIDE_WORK }) }), _jsx(Box, { sx: {
209
- width: 'var(--theme-hairline, 1px)',
210
- bg: 'border.muted',
211
- flexShrink: 0,
212
- } }), _jsxs(Box, { "data-reference-work": "", sx: {
213
- flex: 1,
214
- minWidth: 0,
215
- p: 4,
216
- display: 'flex',
217
- flexDirection: 'column',
218
- gap: 3,
219
- }, children: [_jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: "Draft \u00B7 reply" }), _jsx(Heading, { as: "h2", sx: { fontSize: 3, fontWeight: 600 }, children: "Your order 1042" }), _jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: "To ada@example.com" }), _jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx(Text, { as: "p", sx: { m: 0 }, children: "Dear Ada," }), _jsx(Text, { as: "p", sx: { m: 0 }, children: "We are sorry your order arrived four days late. It left our warehouse on Monday and is with you by Thursday, 8 October." }), _jsx(Text, { as: "p", sx: { m: 0 }, children: "Your next order ships free, with no code to enter." }), _jsx(Text, { as: "p", sx: { m: 0 }, children: "The support desk" })] }), _jsxs(Box, { sx: { display: 'flex', gap: 2, mt: 'auto' }, children: [_jsx(Button, { variant: "primary", children: "Send" }), _jsx(Button, { children: "Edit" })] })] })] }));
185
+ return (_jsxs(Frame, { children: [_jsx(Box, { width: 400, flexShrink: 0, display: "flex", children: _jsx(Conversation, { name: "Support desk", face: "\uD83E\uDD8A", presence: "idle", items: BESIDE_WORK }) }), _jsx(Box, { width: "var(--theme-hairline, 1px)", bg: "border.muted", flexShrink: 0 }), _jsxs(Box, { "data-reference-work": "", flex: 1, minWidth: 0, p: 4, display: "flex", flexDirection: "column", gap: 3, children: [_jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: "Draft \u00B7 reply" }), _jsx(Heading, { as: "h2", sx: { fontSize: 3, fontWeight: 600 }, children: "Your order 1042" }), _jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: "To ada@example.com" }), _jsxs(Box, { display: "flex", flexDirection: "column", gap: 2, children: [_jsx(Text, { as: "p", sx: { m: 0 }, children: "Dear Ada," }), _jsx(Text, { as: "p", sx: { m: 0 }, children: "We are sorry your order arrived four days late. It left our warehouse on Monday and is with you by Thursday, 8 October." }), _jsx(Text, { as: "p", sx: { m: 0 }, children: "Your next order ships free, with no code to enter." }), _jsx(Text, { as: "p", sx: { m: 0 }, children: "The support desk" })] }), _jsxs(Box, { display: "flex", gap: 2, mt: "auto", children: [_jsx(Button, { variant: "primary", children: "Send" }), _jsx(Button, { children: "Edit" })] })] })] }));
220
186
  }
221
187
  /** The activity of a worker: what it did on its own, as it did it. */
222
188
  export function WorkerActivityScreen() {
223
- return (_jsx(Frame, { children: _jsx(Box, { sx: { flex: 1, display: 'flex', justifyContent: 'center' }, children: _jsx(Box, { sx: { width: '100%', maxWidth: 680, display: 'flex' }, children: _jsx(Conversation, { name: "Inbox triage", face: "\uD83D\uDCEC", presence: "working", items: WORKER_ACTIVITY, composer: false }) }) }) }));
189
+ return (_jsx(Frame, { children: _jsx(Box, { flex: 1, display: "flex", justifyContent: "center", children: _jsx(Box, { width: "100%", maxWidth: 680, display: "flex", children: _jsx(Conversation, { name: "Inbox triage", face: "\uD83D\uDCEC", presence: "working", items: WORKER_ACTIVITY, composer: false }) }) }) }));
224
190
  }
225
191
  /** An approval: the action, the rule that asks, and the one decision. */
226
192
  export function ApprovalScreen() {
227
- return (_jsx(Frame, { children: _jsx(Box, { sx: { flex: 1, display: 'flex', justifyContent: 'center' }, children: _jsx(Box, { sx: { width: '100%', maxWidth: 640, display: 'flex' }, children: _jsx(Conversation, { name: "Support desk", face: "\uD83E\uDD8A", presence: "waiting", items: APPROVAL }) }) }) }));
193
+ return (_jsx(Frame, { children: _jsx(Box, { flex: 1, display: "flex", justifyContent: "center", children: _jsx(Box, { width: "100%", maxWidth: 640, display: "flex", children: _jsx(Conversation, { name: "Support desk", face: "\uD83E\uDD8A", presence: "waiting", items: APPROVAL }) }) }) }));
228
194
  }
229
195
  /** Tool calls, each led by the mark of whoever the tool belongs to. */
230
196
  export function ToolMarksScreen() {
231
- return (_jsx(Frame, { children: _jsx(Box, { sx: { flex: 1, display: 'flex', justifyContent: 'center' }, children: _jsx(Box, { sx: { width: '100%', maxWidth: 680, display: 'flex' }, children: _jsx(Conversation, { name: "Bookkeeper", face: "\uD83E\uDDEE", presence: "idle", items: TOOL_MARKS, composer: false, mcpServers: TOOL_MARKS_SERVERS }) }) }) }));
197
+ return (_jsx(Frame, { children: _jsx(Box, { flex: 1, display: "flex", justifyContent: "center", children: _jsx(Box, { width: "100%", maxWidth: 680, display: "flex", children: _jsx(Conversation, { name: "Bookkeeper", face: "\uD83E\uDDEE", presence: "idle", items: TOOL_MARKS, composer: false, mcpServers: TOOL_MARKS_SERVERS }) }) }) }));
232
198
  }
233
199
  export const REFERENCE_SCREEN_COMPONENTS = {
234
200
  conversation: ConversationScreen,
@@ -284,20 +250,7 @@ export function AssistantScreen({ picture, }) {
284
250
  ? 'working'
285
251
  : picture;
286
252
  const balloon = BALLOONS[picture];
287
- return (_jsxs(Box, { sx: { flex: 1, position: 'relative' }, children: [picture === 'open' && _jsx(OpenConversation, {}), picture === 'aside' && (_jsxs(Box, { role: "dialog", "aria-label": "A dialog over the assistant", sx: {
288
- position: 'fixed',
289
- right: 24,
290
- bottom: 24,
291
- width: 280,
292
- height: 160,
293
- p: 3,
294
- zIndex: 2000,
295
- bg: 'canvas.overlay',
296
- border: 'var(--theme-hairline, 1px) solid',
297
- borderColor: 'border.default',
298
- borderRadius: 'var(--theme-radius-card, 6px)',
299
- boxShadow: 'var(--theme-shadow, none)',
300
- }, children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "A dialog" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1 }, children: "The assistant steps aside while this is open." })] })), _jsx(AssistantStage, { character: "paperclip", state: state, place: { right: 48, bottom: 48 }, stageRef: stageRef, onDragStart: () => undefined, open: picture === 'open', onToggle: () => undefined, balloon: balloon, balloonDisplay: picture === 'current' ? 'current' : 'history', insist: !!balloon, onDismiss: () => undefined })] }));
253
+ return (_jsxs(Box, { flex: 1, position: "relative", children: [picture === 'open' && _jsx(OpenConversation, {}), picture === 'aside' && (_jsxs(Box, { role: "dialog", "aria-label": "A dialog over the assistant", position: "fixed", right: 24, bottom: 24, width: 280, height: 160, p: 3, zIndex: 2000, bg: "canvas.overlay", border: "var(--theme-hairline, 1px) solid", borderColor: "border.default", borderRadius: "var(--theme-radius-card, 6px)", boxShadow: "var(--theme-shadow, none)", children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "A dialog" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1 }, children: "The assistant steps aside while this is open." })] })), _jsx(AssistantStage, { character: "paperclip", state: state, place: { right: 48, bottom: 48 }, stageRef: stageRef, onDragStart: () => undefined, open: picture === 'open', onToggle: () => undefined, balloon: balloon, balloonDisplay: picture === 'current' ? 'current' : 'history', insist: !!balloon, onDismiss: () => undefined })] }));
301
254
  }
302
255
  /** What the open picture's conversation holds. */
303
256
  const OPEN_CONVERSATION = [
@@ -316,37 +269,10 @@ function OpenConversation() {
316
269
  const [input, setInput] = useState('');
317
270
  const height = conversationBalloonHeight(window.innerHeight);
318
271
  const left = window.innerWidth - 48 - CONVERSATION_BALLOON_WIDTH;
319
- return (_jsxs(Box, { "data-conversation-balloon": "", sx: {
320
- position: 'fixed',
321
- right: '48px',
322
- bottom: `${48 + 88 + 16}px`,
323
- width: `${CONVERSATION_BALLOON_WIDTH}px`,
324
- height: `${height}px`,
325
- zIndex: 1001,
326
- display: 'flex',
327
- flexDirection: 'column',
328
- bg: 'canvas.default',
329
- border: '1px solid',
330
- borderColor: 'border.default',
331
- boxShadow: 'shadow.extra-large',
332
- ...conversationBalloonSx({
333
- edge: 'bottom',
334
- at: balloonTailAt(window.innerWidth - 48 - 44, left),
335
- }, 'canvas.subtle'),
336
- }, children: [_jsx(ConversationBalloonClose, { onClose: () => undefined }), _jsx(ConversationBalloonHeader, { count: OPEN_CONVERSATION.length - 1 }), _jsxs(Box, { sx: {
337
- flex: 1,
338
- minHeight: 0,
339
- display: 'flex',
340
- flexDirection: 'column',
341
- borderRadius: 'var(--theme-radius-bubble, 16px)',
342
- overflow: 'hidden',
343
- }, children: [_jsx(Box, { sx: { flex: 1, minHeight: 0, overflow: 'auto' }, children: _jsx(ChatMessageList, { displayItems: OPEN_CONVERSATION, isLoading: false, isStreaming: false, showLoadingIndicator: false, hideMessagesAfterToolUI: false, avatarConfig: { ...AVATARS, showAvatars: true }, padding: 2, emptyContent: null, messagesEndRef: endRef, onRespond: async () => undefined }) }), _jsx(Box, { sx: {
344
- px: 3,
345
- pb: 1,
346
- display: 'flex',
347
- justifyContent: 'flex-end',
348
- fontSize: 0,
349
- }, children: _jsx(DecisionAsk, { ask: async () => ({}) }) }), _jsx(InputPrompt, { input: input, setInput: setInput, isLoading: false, connectionConfirmed: true, placeholder: "Type a message...", autoFocus: false, padding: 2, promptVariant: "lexical", onSend: () => undefined, onStop: () => undefined, showTokenUsage: false, showModelSelector: false, showToolsMenu: false, showSkillsMenu: false, showAgentsMenu: false, codemodeEnabled: false, hasConfigData: false, hasSkillsData: false, isA2AProtocol: false })] })] }));
272
+ return (_jsxs(Box, { "data-conversation-balloon": "", position: "fixed", right: "48px", bottom: `${48 + 88 + 16}px`, width: `${CONVERSATION_BALLOON_WIDTH}px`, height: `${height}px`, zIndex: 1001, display: "flex", flexDirection: "column", bg: "canvas.default", border: "1px solid", borderColor: "border.default", boxShadow: "shadow.extra-large", sx: conversationBalloonSx({
273
+ edge: 'bottom',
274
+ at: balloonTailAt(window.innerWidth - 48 - 44, left),
275
+ }, 'canvas.subtle'), children: [_jsx(ConversationBalloonClose, { onClose: () => undefined }), _jsx(ConversationBalloonHeader, { count: OPEN_CONVERSATION.length - 1 }), _jsxs(Box, { flex: 1, minHeight: 0, display: "flex", flexDirection: "column", borderRadius: "var(--theme-radius-bubble, 16px)", overflow: "hidden", children: [_jsx(Box, { flex: 1, minHeight: 0, overflow: "auto", children: _jsx(ChatMessageList, { displayItems: OPEN_CONVERSATION, isLoading: false, isStreaming: false, showLoadingIndicator: false, hideMessagesAfterToolUI: false, avatarConfig: { ...AVATARS, showAvatars: true }, padding: 2, emptyContent: null, messagesEndRef: endRef, onRespond: async () => undefined }) }), _jsx(Box, { px: 3, pb: 1, display: "flex", justifyContent: "flex-end", fontSize: 0, children: _jsx(DecisionAsk, { ask: async () => ({}) }) }), _jsx(InputPrompt, { input: input, setInput: setInput, isLoading: false, connectionConfirmed: true, placeholder: "Type a message...", autoFocus: false, padding: 2, promptVariant: "lexical", onSend: () => undefined, onStop: () => undefined, showTokenUsage: false, showModelSelector: false, showToolsMenu: false, showSkillsMenu: false, showAgentsMenu: false, codemodeEnabled: false, hasConfigData: false, hasSkillsData: false, isA2AProtocol: false })] })] }));
350
276
  }
351
277
  // ---------------------------------------------------------------------------
352
278
  // The characters (T-25, T-24)
@@ -364,5 +290,5 @@ characterReactor.start();
364
290
  export function CharacterScreen({ character, ready, }) {
365
291
  const stageRef = useRef(null);
366
292
  const drawn = assistantCharacterNamed(characterReactor, character);
367
- return (_jsxs(Box, { sx: { flex: 1, position: 'relative' }, children: [_jsx(AssistantStage, { character: drawn, state: "idle", place: { right: 48, bottom: 48 }, stageRef: stageRef, onDragStart: () => undefined, open: false, onToggle: () => undefined, onDismiss: () => undefined }), ready] }));
293
+ return (_jsxs(Box, { flex: 1, position: "relative", children: [_jsx(AssistantStage, { character: drawn, state: "idle", place: { right: 48, bottom: 48 }, stageRef: stageRef, onDragStart: () => undefined, open: false, onToggle: () => undefined, onDismiss: () => undefined }), ready] }));
368
294
  }
@@ -68,7 +68,7 @@ function Ready() {
68
68
  */
69
69
  function GalleryScreen() {
70
70
  const { characters, ready } = useGalleryCharacters();
71
- return (_jsxs(Box, { sx: { flex: 1, bg: 'canvas.default', p: 2, overflow: 'hidden' }, children: [_jsx(AssistantGalleryGrid, { characters: characters }), ready && _jsx(Ready, {})] }));
71
+ return (_jsxs(Box, { flex: 1, bg: "canvas.default", p: 2, overflow: "hidden", children: [_jsx(AssistantGalleryGrid, { characters: characters }), ready && _jsx(Ready, {})] }));
72
72
  }
73
73
  function Page() {
74
74
  if (gallery) {
@@ -670,8 +670,11 @@ export interface AppUploadsSpec {
670
670
  /** What the user of an application sees. */
671
671
  export interface AppInterfaceSpec {
672
672
  layout: AppLayout;
673
- /** Its one colour, over the `loop` theme only. */
674
- accent: AppAccent;
673
+ /**
674
+ * Its one colour, over whichever theme it runs in; unsaid, it wears the
675
+ * theme's own colours (decided 2026-10-07).
676
+ */
677
+ accent?: AppAccent;
675
678
  /** The theme it runs in by default; the person's own when unsaid (T-30). */
676
679
  theme?: AppThemeSpec;
677
680
  welcome: string;
@@ -67,6 +67,8 @@ export interface ProtocolAdapterConfig {
67
67
  maxReconnectAttempts?: number;
68
68
  /** Request timeout in milliseconds */
69
69
  timeout?: number;
70
+ /** The fetch to use; a phone passes one whose response body streams (e.g. `expo/fetch`). Default: the global `fetch`. */
71
+ fetch?: typeof fetch;
70
72
  /** Additional protocol-specific options */
71
73
  options?: Record<string, unknown>;
72
74
  }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Normalised approval record. Both snake_case (server-native) and
3
+ * camelCase (TypeScript-idiomatic) keys are present so existing UI
4
+ * consumers keep working regardless of which naming they read.
5
+ */
6
+ export type ApprovalRecord = {
7
+ id: string;
8
+ agent_id: string;
9
+ agentId: string;
10
+ runtime_name: string;
11
+ runtimeName: string;
12
+ tool_name: string;
13
+ toolName: string;
14
+ tool_call_id?: string;
15
+ toolCallId?: string;
16
+ tool_args: Record<string, unknown>;
17
+ toolArgs: Record<string, unknown>;
18
+ status: string;
19
+ note?: string | null;
20
+ requester_uid?: string;
21
+ requesterUid?: string;
22
+ requested_by?: string;
23
+ requestedBy?: string;
24
+ resolved_by?: string;
25
+ resolvedBy?: string;
26
+ resolved_at?: string;
27
+ resolvedAt?: string;
28
+ created_at: string;
29
+ createdAt: string;
30
+ updated_at?: string;
31
+ updatedAt?: string;
32
+ read?: boolean;
33
+ };
34
+ /** An approval as the server or the `/ws` stream sends it; null without an id. */
35
+ export declare function normalizeApproval(raw: unknown): ApprovalRecord | null;
36
+ /** An approval's arguments, under either key: the web reads `tool_args`, mobile `toolArgs`. */
37
+ export type ApprovalArgs = {
38
+ tool_args?: Record<string, unknown>;
39
+ toolArgs?: Record<string, unknown>;
40
+ };
41
+ /** A message it asks to send, as the approval carries it, whole (LOOP W-05). */
42
+ export type MessageAsked = {
43
+ to: string;
44
+ cc: string;
45
+ bcc: string;
46
+ subject: string;
47
+ body: string;
48
+ /** It forwards a message received, named by its id. */
49
+ forwards: boolean;
50
+ /** A reply, in the conversation it names. */
51
+ replies: boolean;
52
+ };
53
+ /**
54
+ * The message a send asks for, to show whole before *Approve* (LOOP W-05):
55
+ * an approval whose arguments say to whom and what. `null` for anything else.
56
+ */
57
+ export declare function messageOfApproval(approval: ApprovalArgs): MessageAsked | null;
58
+ /** Why it was asked: the rule (`_rule`) or the check (`_check`). */
59
+ export declare const whyAsked: (approval: ApprovalArgs) => string;
@@ -0,0 +1,101 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ function str(value) {
6
+ return typeof value === 'string' ? value : value == null ? '' : String(value);
7
+ }
8
+ /** An approval as the server or the `/ws` stream sends it; null without an id. */
9
+ export function normalizeApproval(raw) {
10
+ if (!raw || typeof raw !== 'object')
11
+ return null;
12
+ const rec = raw;
13
+ const idSource = rec.id ?? rec.approval_id ?? rec.approvalId;
14
+ const id = typeof idSource === 'string' ? idSource : undefined;
15
+ if (!id)
16
+ return null;
17
+ const agent = str(rec.agent_id ?? rec.agentId);
18
+ const pod = str(rec.runtime_name ?? rec.runtimeName);
19
+ const tool = str(rec.tool_name ?? rec.toolName ?? 'unknown');
20
+ const toolCall = rec.tool_call_id ?? rec.toolCallId;
21
+ const args = rec.tool_args ??
22
+ rec.toolArgs ??
23
+ {};
24
+ const created = str(rec.created_at ?? rec.createdAt);
25
+ const updated = str(rec.updated_at ?? rec.updatedAt);
26
+ const resolvedBy = str(rec.resolved_by ?? rec.resolvedBy);
27
+ const requesterUid = str(rec.requester_uid ?? rec.requesterUid);
28
+ const requestedBy = str(rec.requested_by ?? rec.requestedBy);
29
+ const resolvedAtRaw = str(rec.resolved_at ?? rec.resolvedAt);
30
+ const status = str(rec.status ?? 'pending');
31
+ // Keep reviewer metadata from WS payloads. If this is dropped during
32
+ // normalization, downstream pages receive status=approved/rejected but no
33
+ // reviewer/timestamp context and can incorrectly render "review pending".
34
+ // Some producers only set updated_at on decision; for non-pending statuses,
35
+ // fall back to updated_at so UI can still show a decision time.
36
+ const resolvedAt = resolvedAtRaw || (status !== 'pending' ? updated || undefined : undefined);
37
+ return {
38
+ id,
39
+ agent_id: agent,
40
+ agentId: agent,
41
+ runtime_name: pod,
42
+ runtimeName: pod,
43
+ tool_name: tool,
44
+ toolName: tool,
45
+ tool_call_id: typeof toolCall === 'string' ? toolCall : undefined,
46
+ toolCallId: typeof toolCall === 'string' ? toolCall : undefined,
47
+ tool_args: args,
48
+ toolArgs: args,
49
+ status,
50
+ note: typeof rec.note === 'string'
51
+ ? rec.note
52
+ : rec.note === null
53
+ ? null
54
+ : undefined,
55
+ requester_uid: requesterUid || undefined,
56
+ requesterUid: requesterUid || undefined,
57
+ requested_by: requestedBy || undefined,
58
+ requestedBy: requestedBy || undefined,
59
+ resolved_by: resolvedBy || undefined,
60
+ resolvedBy: resolvedBy || undefined,
61
+ resolved_at: resolvedAt,
62
+ resolvedAt: resolvedAt,
63
+ created_at: created,
64
+ createdAt: created,
65
+ updated_at: updated || undefined,
66
+ updatedAt: updated || undefined,
67
+ read: typeof rec.read === 'boolean' ? rec.read : undefined,
68
+ };
69
+ }
70
+ const argsOf = (approval) => approval.tool_args ?? approval.toolArgs ?? {};
71
+ const said = (approval, key) => {
72
+ const value = argsOf(approval)[key];
73
+ return typeof value === 'string' ? value : '';
74
+ };
75
+ const addressed = (value) => Array.isArray(value)
76
+ ? value.filter(item => typeof item === 'string').join(', ')
77
+ : typeof value === 'string'
78
+ ? value
79
+ : '';
80
+ /**
81
+ * The message a send asks for, to show whole before *Approve* (LOOP W-05):
82
+ * an approval whose arguments say to whom and what. `null` for anything else.
83
+ */
84
+ export function messageOfApproval(approval) {
85
+ const args = argsOf(approval);
86
+ const to = addressed(args.to);
87
+ if (!to || typeof args.body !== 'string') {
88
+ return null;
89
+ }
90
+ return {
91
+ to,
92
+ cc: addressed(args.cc),
93
+ bcc: addressed(args.bcc),
94
+ subject: said(approval, 'subject'),
95
+ body: args.body,
96
+ forwards: Boolean(said(approval, 'forward_message_id')),
97
+ replies: Boolean(said(approval, 'thread_id') || said(approval, 'in_reply_to')),
98
+ };
99
+ }
100
+ /** Why it was asked: the rule (`_rule`) or the check (`_check`). */
101
+ export const whyAsked = (approval) => said(approval, '_rule') || said(approval, '_check');
@@ -158,24 +158,7 @@ export function VoiceInput({ hearing, language, onTranscript, onListen, consentK
158
158
  const label = listening
159
159
  ? 'Listening — let go to stop'
160
160
  : 'Hold to talk (Ctrl+Space)';
161
- return (_jsxs(Box, { "data-voice-input": state, sx: {
162
- display: 'inline-flex',
163
- alignItems: 'center',
164
- gap: 1,
165
- position: 'relative',
166
- }, children: [speaking && onStopSpeaking && (_jsx(Tooltip, { text: "Stop speaking (Esc)", direction: "n", children: _jsx(IconButton, { icon: MuteIcon, "aria-label": "Stop speaking", size: "small", variant: "invisible", "data-voice-stop": "", onClick: onStopSpeaking }) })), listening && (_jsx(Box, { "aria-hidden": "true", sx: {
167
- width: 40,
168
- height: 4,
169
- borderRadius: 2,
170
- bg: 'neutral.muted',
171
- overflow: 'hidden',
172
- }, children: _jsx(Box, { ref: meter, sx: {
173
- width: '100%',
174
- height: '100%',
175
- bg: 'danger.emphasis',
176
- transformOrigin: 'left',
177
- transform: prefersStill() ? 'scaleX(1)' : 'scaleX(0.04)',
178
- } }) })), (state === 'loading' || state === 'hearing') && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, "data-voice-progress": "", children: state === 'loading' && progress !== undefined ? `${progress}%` : '…' })), _jsx(Tooltip, { text: label, direction: "n", children: _jsx(IconButton, { icon: () => _jsx(MicrophoneIcon, { size: 16 }), "aria-label": label, "aria-pressed": listening, size: "small", variant: listening ? 'danger' : 'invisible', disabled: disabled || state === 'hearing', "data-voice-mic": "", onPointerDown: event => {
161
+ return (_jsxs(Box, { "data-voice-input": state, display: "inline-flex", alignItems: "center", gap: 1, position: "relative", children: [speaking && onStopSpeaking && (_jsx(Tooltip, { text: "Stop speaking (Esc)", direction: "n", children: _jsx(IconButton, { icon: MuteIcon, "aria-label": "Stop speaking", size: "small", variant: "invisible", "data-voice-stop": "", onClick: onStopSpeaking }) })), listening && (_jsx(Box, { "aria-hidden": "true", width: 40, height: 4, borderRadius: 2, bg: "neutral.muted", overflow: "hidden", children: _jsx(Box, { ref: meter, width: "100%", height: "100%", bg: "danger.emphasis", transformOrigin: "left", transform: prefersStill() ? 'scaleX(1)' : 'scaleX(0.04)' }) })), (state === 'loading' || state === 'hearing') && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, "data-voice-progress": "", children: state === 'loading' && progress !== undefined ? `${progress}%` : '…' })), _jsx(Tooltip, { text: label, direction: "n", children: _jsx(IconButton, { icon: () => _jsx(MicrophoneIcon, { size: 16 }), "aria-label": label, "aria-pressed": listening, size: "small", variant: listening ? 'danger' : 'invisible', disabled: disabled || state === 'hearing', "data-voice-mic": "", onPointerDown: event => {
179
162
  if (event.button !== 0) {
180
163
  return;
181
164
  }
@@ -203,31 +186,12 @@ export function VoiceInput({ hearing, language, onTranscript, onListen, consentK
203
186
  void start();
204
187
  }
205
188
  }
206
- } }) }), state === 'asking' && (_jsxs(Box, { role: "dialog", "aria-label": "Talk instead of typing", "data-voice-consent": "", sx: {
207
- position: 'absolute',
208
- bottom: '100%',
209
- right: 0,
210
- mb: 2,
211
- width: 280,
212
- p: 3,
213
- bg: 'canvas.overlay',
214
- border: '1px solid',
215
- borderColor: 'border.default',
216
- borderRadius: 2,
217
- boxShadow: 'shadow.large',
218
- zIndex: 10,
219
- }, children: [_jsx(Text, { as: "p", sx: { fontSize: 1, mb: 2 }, children: CONSENT_SENTENCE }), _jsxs(Box, { sx: { display: 'flex', gap: 2, justifyContent: 'flex-end' }, children: [_jsx(Button, { size: "small", onClick: () => setState('idle'), children: "Not now" }), _jsx(Button, { size: "small", variant: "primary", "data-voice-consent-yes": "", onClick: () => {
189
+ } }) }), state === 'asking' && (_jsxs(Box, { role: "dialog", "aria-label": "Talk instead of typing", "data-voice-consent": "", position: "absolute", bottom: "100%", right: 0, mb: 2, width: 280, p: 3, bg: "canvas.overlay", border: "1px solid", borderColor: "border.default", borderRadius: 2, boxShadow: "shadow.large", zIndex: 10, children: [_jsx(Text, { as: "p", sx: { fontSize: 1, mb: 2 }, children: CONSENT_SENTENCE }), _jsxs(Box, { display: "flex", gap: 2, justifyContent: "flex-end", children: [_jsx(Button, { size: "small", onClick: () => setState('idle'), children: "Not now" }), _jsx(Button, { size: "small", variant: "primary", "data-voice-consent-yes": "", onClick: () => {
220
190
  consent(consentKey);
221
191
  // Asked, and said yes: listen now, without another press.
222
192
  stateRef.current = 'idle';
223
193
  setState('idle');
224
194
  void start();
225
- }, children: "Use the microphone" })] })] })), _jsx(Box, { as: "span", role: "status", "aria-live": "polite", sx: {
226
- position: 'absolute',
227
- width: 1,
228
- height: 1,
229
- overflow: 'hidden',
230
- clip: 'rect(0 0 0 0)',
231
- }, children: WORDS[state] || said }), problem && (_jsx(Text, { role: "alert", sx: { fontSize: 0, color: 'danger.fg', maxWidth: 220 }, "data-voice-problem": "", children: problem }))] }));
195
+ }, children: "Use the microphone" })] })] })), _jsx(Box, { as: "span", role: "status", "aria-live": "polite", position: "absolute", width: 1, height: 1, overflow: "hidden", clip: "rect(0 0 0 0)", children: WORDS[state] || said }), problem && (_jsx(Text, { role: "alert", sx: { fontSize: 0, color: 'danger.fg', maxWidth: 220 }, "data-voice-problem": "", children: problem }))] }));
232
196
  }
233
197
  export default VoiceInput;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datalayer/agent-runtimes",
3
- "version": "1.3.89",
3
+ "version": "1.3.90",
4
4
  "type": "module",
5
5
  "workspaces": [
6
6
  ".",
@@ -154,7 +154,7 @@
154
154
  "@datalayer/jupyter-react": "^2.0.20",
155
155
  "@datalayer/jupyter-server-nbmodel": "^0.2.8",
156
156
  "@datalayer/lexical-loro": "^1.0.6",
157
- "@datalayer/primer-addons": "^1.0.23",
157
+ "@datalayer/primer-addons": "^1.0.39",
158
158
  "@datalayer/primer-rjsf": "^1.0.3",
159
159
  "@datalayer/reactor": "^1.0.4",
160
160
  "@datalayer/reactor-commands": "^1.0.4",
@@ -1 +0,0 @@
1
- export { Box as default, Box } from '@primer/react';
@@ -1,7 +0,0 @@
1
- /*
2
- * Copyright (c) 2025-2026 Datalayer, Inc.
3
- * Distributed under the terms of the Modified BSD License.
4
- */
5
- // Runtime shim: force the primer-addons Box export to use Primer's Box.
6
- // This prevents `sx` from being forwarded to raw DOM nodes as an attribute.
7
- export { Box as default, Box } from '@primer/react';