@datalayer/agent-runtimes 1.3.89 → 1.3.91

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 (265) 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/chat/words.d.ts +7 -0
  69. package/lib/chat/words.js +12 -0
  70. package/lib/components/a2ui/datalayer/Chart.js +4 -10
  71. package/lib/components/a2ui/datalayer/Chat.js +2 -10
  72. package/lib/components/a2ui/datalayer/Download.js +1 -1
  73. package/lib/components/a2ui/datalayer/Evidence.js +1 -15
  74. package/lib/components/a2ui/datalayer/FileUpload.js +1 -12
  75. package/lib/components/a2ui/datalayer/Table.js +9 -17
  76. package/lib/components/a2ui/datalayer/formWidgets.js +3 -2
  77. package/lib/components/a2ui/datalayer/parts.js +1 -16
  78. package/lib/components/a2ui/styles.js +16 -5
  79. package/lib/components/agents/AgentSummary.js +1 -51
  80. package/lib/components/cards/NotificationEventCard.js +6 -72
  81. package/lib/components/cards/OutputCard.js +4 -48
  82. package/lib/components/cards/ToolApprovalCard.js +2 -35
  83. package/lib/components/code-sandboxes/CodeSandboxCellVariables.js +1 -1
  84. package/lib/components/code-sandboxes/CodeSandboxEnvironmentSelect.js +4 -14
  85. package/lib/components/code-sandboxes/CodeSandboxPicker.js +16 -21
  86. package/lib/components/code-sandboxes/CodeSandboxVariables.js +2 -2
  87. package/lib/components/scheduler/ScheduleMenu.js +5 -10
  88. package/lib/components/specs/SpecPayloadPreview.js +1 -26
  89. package/lib/components/teams/A2ATeamGraph.d.ts +4 -3
  90. package/lib/components/teams/A2ATeamGraph.js +25 -71
  91. package/lib/components/teams/AnswerSurfacesView.js +2 -2
  92. package/lib/components/teams/NotebookPreview.js +1 -10
  93. package/lib/components/teams/NotebookPreviewView.js +2 -3
  94. package/lib/components/teams/SceneTranscript.js +3 -17
  95. package/lib/components/teams/SceneView.js +1 -8
  96. package/lib/components/teams/TeamNotebook.js +5 -13
  97. package/lib/components/teams/TeamNotebookView.js +2 -12
  98. package/lib/components/teams/index.d.ts +1 -0
  99. package/lib/components/teams/index.js +1 -0
  100. package/lib/components/teams/useBalloonRoom.d.ts +39 -0
  101. package/lib/components/teams/useBalloonRoom.js +89 -0
  102. package/lib/config/AgentConfiguration.js +22 -225
  103. package/lib/context/ContextDistribution.js +7 -41
  104. package/lib/context/ContextInspector.js +9 -107
  105. package/lib/context/ContextPanel.js +11 -86
  106. package/lib/context/ContextUsage.js +6 -34
  107. package/lib/context/CostTracker.js +7 -42
  108. package/lib/context/MessageHistory.js +3 -37
  109. package/lib/context/TurnGraphChart.js +9 -41
  110. package/lib/examples/A2UiAgentExample.js +6 -108
  111. package/lib/examples/A2UiComponentsGalleryExample.js +1 -1
  112. package/lib/examples/A2UiContactCardExample.js +1 -1
  113. package/lib/examples/A2UiJupyterOutputExample.js +25 -125
  114. package/lib/examples/A2UiRestaurantExample.js +1 -1
  115. package/lib/examples/A2UiViewerExample.js +1 -1
  116. package/lib/examples/AgUiAgenticExample.js +3 -35
  117. package/lib/examples/AgUiBackendToolRenderingExample.js +2 -25
  118. package/lib/examples/AgUiHaikuGenUiExample.js +2 -32
  119. package/lib/examples/AgUiHumanInTheLoopExample.js +5 -59
  120. package/lib/examples/AgUiSharedStateExample.js +6 -56
  121. package/lib/examples/AgUiToolsBasedGenUiExample.js +25 -120
  122. package/lib/examples/AgentA2AExample.js +1 -15
  123. package/lib/examples/AgentA2ATeamExample.js +6 -30
  124. package/lib/examples/AgentCheckpointsExample.js +11 -145
  125. package/lib/examples/AgentCodeSandboxExample.js +5 -108
  126. package/lib/examples/AgentCodeSandboxesExample.js +3 -30
  127. package/lib/examples/AgentCodemodeExample.js +9 -85
  128. package/lib/examples/AgentCompactionExample.js +3 -64
  129. package/lib/examples/AgentDecideExample.js +1 -13
  130. package/lib/examples/AgentEvalsExample.js +5 -60
  131. package/lib/examples/AgentGuardrailsExample.js +4 -28
  132. package/lib/examples/AgentHooksExample.js +1 -1
  133. package/lib/examples/AgentInferenceProviderExample.js +5 -96
  134. package/lib/examples/AgentMCPExample.js +7 -105
  135. package/lib/examples/AgentMemoryExample.js +5 -74
  136. package/lib/examples/AgentMonitoringExample.js +7 -53
  137. package/lib/examples/AgentNotificationsExample.js +3 -61
  138. package/lib/examples/AgentOtelExample.js +3 -72
  139. package/lib/examples/AgentOutputsExample.js +6 -81
  140. package/lib/examples/AgentParametersExample.js +2 -37
  141. package/lib/examples/AgentSkillsExample.js +3 -45
  142. package/lib/examples/AgentSubagentsExample.js +6 -56
  143. package/lib/examples/AgentToolApprovalsExample.js +1 -11
  144. package/lib/examples/AgentTriggersExample.js +29 -239
  145. package/lib/examples/AgentspecsExample.js +6 -60
  146. package/lib/examples/AssistantExample.js +5 -5
  147. package/lib/examples/AssistantGalleryExample.js +8 -65
  148. package/lib/examples/CellExample.js +1 -6
  149. package/lib/examples/ChatCustomExample.js +2 -31
  150. package/lib/examples/ChatExample.js +1 -9
  151. package/lib/examples/ChatStandaloneExample.js +3 -37
  152. package/lib/examples/CopilotKitLexicalExample.js +1 -24
  153. package/lib/examples/DecksAgent.js +1 -1
  154. package/lib/examples/DocumentPageAgent.js +1 -1
  155. package/lib/examples/HomeExample.js +14 -62
  156. package/lib/examples/Lexical2Example.js +3 -32
  157. package/lib/examples/LexicalAgentExample.js +2 -34
  158. package/lib/examples/LexicalAgentSidebarExample.js +3 -34
  159. package/lib/examples/LoopAppComputerExample.js +1 -1
  160. package/lib/examples/LoopShellExample.js +2 -2
  161. package/lib/examples/LoopStrategyExample.js +15 -87
  162. package/lib/examples/LoopWorkspaceEmbed.js +2 -18
  163. package/lib/examples/LoopWorkspaceExample.js +2 -2
  164. package/lib/examples/NotebookAgentExample.js +2 -33
  165. package/lib/examples/NotebookAgentSidebarExample.js +3 -46
  166. package/lib/examples/NotebookCollaborationExample.js +1 -31
  167. package/lib/examples/NotebookExample.js +1 -18
  168. package/lib/examples/NotebookPageAgent.js +1 -1
  169. package/lib/examples/ScenesExample.js +5 -24
  170. package/lib/examples/VoiceChatExample.js +1 -1
  171. package/lib/examples/components/AuthRequiredView.js +1 -7
  172. package/lib/examples/components/ErrorView.js +1 -8
  173. package/lib/examples/components/ExampleErrorBoundary.js +1 -14
  174. package/lib/examples/components/FooterMetrics.js +1 -7
  175. package/lib/examples/components/Header.js +12 -51
  176. package/lib/examples/components/HeaderControls.js +1 -9
  177. package/lib/examples/components/LexicalEditor.js +1 -8
  178. package/lib/examples/components/MainContent.js +1 -13
  179. package/lib/examples/components/MockFileBrowser.js +4 -40
  180. package/lib/examples/components/SessionTabs.js +1 -1
  181. package/lib/examples/components/TimeTravel.js +1 -13
  182. package/lib/examples/main.js +13 -81
  183. package/lib/examples/scenes/A2UiComponentsGalleryScene.js +3 -34
  184. package/lib/examples/scenes/A2UiContactCardScene.js +3 -35
  185. package/lib/examples/scenes/A2UiRestaurantScene.js +3 -53
  186. package/lib/examples/scenes/A2UiViewerScene.js +3 -34
  187. package/lib/examples/utils/AssistantGalleryGrid.js +6 -35
  188. package/lib/examples2/DatalayerNotebookExample.js +3 -33
  189. package/lib/examples2/NativeNavigationExample.js +4 -10
  190. package/lib/examples2/NotebookMutationsKernel.js +2 -1
  191. package/lib/examples2/NotebookMutationsServiceManager.js +2 -1
  192. package/lib/examples2/ReactRouterExample.js +14 -42
  193. package/lib/hooks/useToolApprovals.d.ts +2 -34
  194. package/lib/hooks/useToolApprovals.js +1 -64
  195. package/lib/identity/AgentIdentity.js +17 -62
  196. package/lib/identity/IdentityConnect.js +13 -59
  197. package/lib/identity/OAuthCallback.js +6 -44
  198. package/lib/lexical/ChatInlinePlugin.js +6 -14
  199. package/lib/loop/apps/AppFeedback.js +12 -3
  200. package/lib/loop/apps/AppRenderer.d.ts +4 -3
  201. package/lib/loop/apps/AppRenderer.js +11 -12
  202. package/lib/loop/apps/appspec.js +6 -3
  203. package/lib/loop/apps/feedback.d.ts +3 -2
  204. package/lib/loop/apps/feedback.js +4 -2
  205. package/lib/loop/core/index.d.ts +19 -0
  206. package/lib/loop/core/index.js +27 -0
  207. package/lib/loop/embed/AppEmbed.d.ts +1 -1
  208. package/lib/loop/embed/AppEmbed.js +2 -1
  209. package/lib/loop/embed/LoopEmbed.js +1 -7
  210. package/lib/loop/embed/embedConfig.d.ts +3 -3
  211. package/lib/loop/embed/embedConfig.js +2 -3
  212. package/lib/loop/embed/embedTheme.d.ts +4 -4
  213. package/lib/loop/embed/embedTheme.js +11 -7
  214. package/lib/loop/plugins/a2a-sidebar/A2ASidebar.js +7 -34
  215. package/lib/loop/plugins/a2ui/A2uiView.js +4 -12
  216. package/lib/loop/plugins/a2ui-surface/InlineSurface.js +1 -16
  217. package/lib/loop/plugins/a2ui-surface/SurfaceToolResult.js +2 -12
  218. package/lib/loop/plugins/agents/AnonymousKeyBadge.js +3 -2
  219. package/lib/loop/plugins/agents/SandboxSelector.js +3 -7
  220. package/lib/loop/plugins/agents/SandboxView.js +4 -27
  221. package/lib/loop/plugins/agents/TeamMemberPicker.js +2 -2
  222. package/lib/loop/plugins/agentspecs/AgentspecPicker.js +3 -2
  223. package/lib/loop/plugins/app-activity/AppActivity.js +1 -1
  224. package/lib/loop/plugins/app-computer/AppComputer.js +32 -27
  225. package/lib/loop/plugins/app-elements/AppElements.js +2 -31
  226. package/lib/loop/plugins/app-page/AppPage.js +26 -8
  227. package/lib/loop/plugins/app-rules/AppRulesCard.js +4 -20
  228. package/lib/loop/plugins/assistant/index.js +1 -13
  229. package/lib/loop/plugins/chat/ChatView.js +89 -130
  230. package/lib/loop/plugins/checkpoints-sidebar/CheckpointsSidebar.js +2 -13
  231. package/lib/loop/plugins/decks/DeckSurface.js +2 -2
  232. package/lib/loop/plugins/document/DocumentView.js +4 -12
  233. package/lib/loop/plugins/document-toolbar/SandboxStatusItem.js +3 -8
  234. package/lib/loop/plugins/graph/GraphView.js +2 -2
  235. package/lib/loop/plugins/input-prompt/ComposerView.js +1 -1
  236. package/lib/loop/plugins/notebook/NotebookView.js +3 -11
  237. package/lib/loop/plugins/page-layout/SplitLayout.js +11 -34
  238. package/lib/loop/plugins/page-layout/TurnPanel.js +9 -35
  239. package/lib/loop/plugins/shell/useEditorPreviews.js +3 -2
  240. package/lib/loop/plugins/subagent-activity/SubagentPulse.js +1 -13
  241. package/lib/loop/plugins/window-frame/WindowFrame.js +10 -44
  242. package/lib/loop/plugins/window-frame/index.js +1 -1
  243. package/lib/loop/shell/LoopWorkspace.js +34 -77
  244. package/lib/loop/shell/PluginToggles.js +4 -15
  245. package/lib/loop/shell/SidebarRail.js +8 -40
  246. package/lib/loop/shell/ViewSwitcher.js +4 -24
  247. package/lib/loop-main.js +2 -3
  248. package/lib/mcp/McpServerManager.js +6 -37
  249. package/lib/portable/index.d.ts +11 -0
  250. package/lib/portable/index.js +20 -0
  251. package/lib/protocols/AGUIAdapter.js +2 -2
  252. package/lib/protocols/BaseProtocolAdapter.d.ts +2 -0
  253. package/lib/protocols/BaseProtocolAdapter.js +4 -0
  254. package/lib/specs/apps.js +6 -0
  255. package/lib/specs/appspecSchema.js +11 -4
  256. package/lib/stories/loop/ReferenceScreens.js +17 -91
  257. package/lib/stories/loop/pictures-main.js +1 -1
  258. package/lib/types/agentspecs.d.ts +5 -2
  259. package/lib/types/protocol.d.ts +2 -0
  260. package/lib/utils/approvals.d.ts +59 -0
  261. package/lib/utils/approvals.js +101 -0
  262. package/lib/voice/VoiceInput.js +3 -39
  263. package/package.json +2 -2
  264. package/lib/shims/primerAddonsBox.d.ts +0 -1
  265. package/lib/shims/primerAddonsBox.js +0 -7
@@ -68,39 +68,16 @@ export function SplitLayout({ editors, hasEditor, transcript, prompt, chips, pic
68
68
  }
69
69
  };
70
70
  const percent = Math.round(share * 100);
71
- return (_jsxs(Box, { "data-testid": "loop-split-layout", sx: {
72
- flex: '1 1 auto',
73
- minHeight: 0,
74
- display: 'flex',
75
- flexDirection: 'column',
76
- }, children: [picker, _jsxs(Box, { ref: row, sx: {
77
- flex: '1 1 auto',
78
- minHeight: 0,
79
- display: 'flex',
80
- // The hidden editors position themselves against this row.
81
- position: 'relative',
82
- overflow: 'hidden',
83
- }, children: [_jsxs(Box, { "data-testid": "loop-split-conversation", sx: {
84
- flex: hasEditor ? `0 0 ${percent}%` : '1 1 auto',
85
- minWidth: 0,
86
- minHeight: 0,
87
- display: 'flex',
88
- flexDirection: 'column',
89
- // The transcript draws a rule on its left when an editor is on
90
- // screen, for the split it sits on the right of. Here it is on
91
- // the left, and the hairline is the separator: the rule is
92
- // pushed out of the row, which clips it.
93
- ml: hasEditor ? '-1px' : 0,
94
- }, children: [transcript, chips, prompt] }), hasEditor ? (_jsx(Box, { role: "separator", "aria-orientation": "vertical", "aria-label": "Resize the conversation and the page", "aria-valuemin": Math.round(SPLIT_MIN_SHARE * 100), "aria-valuemax": Math.round(SPLIT_MAX_SHARE * 100), "aria-valuenow": percent, tabIndex: 0, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, onKeyDown: onKeyDown, sx: {
95
- // A hairline to the eye, a few pixels to the pointer.
96
- flex: '0 0 7px',
97
- mx: '-3px',
98
- zIndex: 1,
99
- cursor: 'col-resize',
100
- touchAction: 'none',
101
- display: 'flex',
102
- justifyContent: 'center',
103
- outline: 'none',
71
+ return (_jsxs(Box, { "data-testid": "loop-split-layout", flex: "1 1 auto", minHeight: 0, display: "flex", flexDirection: "column", children: [picker, _jsxs(Box, { ref: row, flex: "1 1 auto", minHeight: 0, display: "flex",
72
+ // The hidden editors position themselves against this row.
73
+ position: "relative", overflow: "hidden", children: [_jsxs(Box, { "data-testid": "loop-split-conversation", flex: hasEditor ? `0 0 ${percent}%` : '1 1 auto', minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column",
74
+ // The transcript draws a rule on its left when an editor is on
75
+ // screen, for the split it sits on the right of. Here it is on
76
+ // the left, and the hairline is the separator: the rule is
77
+ // pushed out of the row, which clips it.
78
+ ml: hasEditor ? '-1px' : 0, children: [transcript, chips, prompt] }), hasEditor ? (_jsx(Box, { role: "separator", "aria-orientation": "vertical", "aria-label": "Resize the conversation and the page", "aria-valuemin": Math.round(SPLIT_MIN_SHARE * 100), "aria-valuemax": Math.round(SPLIT_MAX_SHARE * 100), "aria-valuenow": percent, tabIndex: 0, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, onKeyDown: onKeyDown,
79
+ // A hairline to the eye, a few pixels to the pointer.
80
+ flex: "0 0 7px", mx: "-3px", zIndex: 1, cursor: "col-resize", display: "flex", justifyContent: "center", outline: "none", touchAction: "none", sx: {
104
81
  '&::before': {
105
82
  content: '""',
106
83
  width: '1px',
@@ -110,7 +87,7 @@ export function SplitLayout({ editors, hasEditor, transcript, prompt, chips, pic
110
87
  '&:hover::before, &:focus-visible::before': {
111
88
  width: '3px',
112
89
  bg: 'accent.emphasis',
113
- },
90
+ }
114
91
  } })) : null, _jsx(Box, { "data-testid": "loop-split-page", sx: hasEditor
115
92
  ? {
116
93
  flex: '1 1 0',
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useRef, useState } from 'react';
3
- import { Box, IconButton, Text } from '@primer/react';
3
+ import { Box } from '@datalayer/primer-addons';
4
+ import { IconButton, Text } from '@primer/react';
4
5
  import { CheckIcon, CommentDiscussionIcon, CopyIcon, XIcon, } from '@primer/octicons-react';
5
6
  import { useContributions, useSignalValue } from '@datalayer/reactor/react';
6
7
  import { signal } from '@datalayer/reactor';
@@ -16,10 +17,7 @@ const NO_TURN = signal({ id: 0, status: 'idle' });
16
17
  const MAX_HEIGHT = 168;
17
18
  /** The three dots, while the agent has said nothing yet. */
18
19
  function Thinking() {
19
- return (_jsxs(Box, { as: "span", "aria-label": "The agent is thinking", sx: {
20
- display: 'inline-flex',
21
- gap: '4px',
22
- alignItems: 'center',
20
+ return (_jsxs(Box, { as: "span", "aria-label": "The agent is thinking", display: "inline-flex", gap: "4px", alignItems: "center", sx: {
23
21
  height: '1.5em',
24
22
  '& > i': {
25
23
  width: 5,
@@ -75,17 +73,7 @@ export function TurnPanel({ footer = 'full', }) {
75
73
  return null;
76
74
  }
77
75
  const working = turn.status === 'thinking' || turn.status === 'streaming';
78
- return (_jsxs(Box, { "data-turn-panel": "", sx: {
79
- borderTop: '1px solid',
80
- borderColor: 'border.muted',
81
- px: 3,
82
- pt: 2,
83
- pb: footer === 'none' ? 2 : 1,
84
- display: 'flex',
85
- flexDirection: 'column',
86
- gap: 2,
87
- bg: 'canvas.default',
88
- }, children: [_jsx(Box, { sx: { display: 'flex', justifyContent: 'flex-end' }, children: _jsx(Text, { sx: {
76
+ return (_jsxs(Box, { "data-turn-panel": "", borderTop: "1px solid", borderColor: "border.muted", px: 3, pt: 2, pb: footer === 'none' ? 2 : 1, display: "flex", flexDirection: "column", gap: 2, bg: "canvas.default", children: [_jsx(Box, { display: "flex", justifyContent: "flex-end", children: _jsx(Text, { sx: {
89
77
  fontSize: 0,
90
78
  lineHeight: 1.45,
91
79
  px: 2,
@@ -98,29 +86,15 @@ export function TurnPanel({ footer = 'full', }) {
98
86
  display: '-webkit-box',
99
87
  WebkitLineClamp: 2,
100
88
  WebkitBoxOrient: 'vertical',
101
- }, children: turn.user }) }), _jsxs(Box, { sx: { display: 'flex', gap: 2, alignItems: 'flex-start' }, children: [_jsx(Box, { ref: replyRef, sx: {
102
- flex: '1 1 auto',
103
- minWidth: 0,
104
- maxHeight: MAX_HEIGHT,
105
- overflowY: 'auto',
106
- fontSize: 0,
107
- lineHeight: 1.5,
108
- color: turn.assistant ? 'fg.default' : 'fg.muted',
109
- // Rendered markdown brings its own flow; the plain fallbacks
110
- // below keep their line breaks.
111
- whiteSpace: turn.assistant ? 'normal' : 'pre-wrap',
112
- overflowWrap: 'anywhere',
113
- }, children: turn.assistant ? (_jsx(Box, { sx: { ...streamdownMarkdownStyles, fontSize: 0 }, children: _jsx(Streamdown, { children: normalizeAssistantMarkdown(turn.assistant) }) })) : turn.activity ? (_jsx(Text, { sx: { color: 'fg.muted', fontStyle: 'italic' }, children: turn.activity })) : working ? (_jsx(Thinking, {})) : turn.status === 'error' ? ('The agent could not answer.') : ('Done — the result is in the page.') }), _jsx(IconButton, { icon: CommentDiscussionIcon, size: "small", variant: "invisible", "aria-label": "Open the conversation", onClick: openPagePanel, sx: { color: 'fg.muted', flexShrink: 0 } })] }), turn.assistant && turn.activity ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontStyle: 'italic' }, children: turn.activity })) : null, footer === 'full' ? (
89
+ }, children: turn.user }) }), _jsxs(Box, { display: "flex", gap: 2, alignItems: "flex-start", children: [_jsx(Box, { ref: replyRef, flex: "1 1 auto", minWidth: 0, maxHeight: MAX_HEIGHT, overflowY: "auto", fontSize: 0, lineHeight: 1.5, color: turn.assistant ? 'fg.default' : 'fg.muted',
90
+ // Rendered markdown brings its own flow; the plain fallbacks
91
+ // below keep their line breaks.
92
+ whiteSpace: turn.assistant ? 'normal' : 'pre-wrap', overflowWrap: "anywhere", children: turn.assistant ? (_jsx(Box, { sx: { ...streamdownMarkdownStyles, fontSize: 0 }, children: _jsx(Streamdown, { children: normalizeAssistantMarkdown(turn.assistant) }) })) : turn.activity ? (_jsx(Text, { sx: { color: 'fg.muted', fontStyle: 'italic' }, children: turn.activity })) : working ? (_jsx(Thinking, {})) : turn.status === 'error' ? ('The agent could not answer.') : ('Done — the result is in the page.') }), _jsx(IconButton, { icon: CommentDiscussionIcon, size: "small", variant: "invisible", "aria-label": "Open the conversation", onClick: openPagePanel, sx: { color: 'fg.muted', flexShrink: 0 } })] }), turn.assistant && turn.activity ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontStyle: 'italic' }, children: turn.activity })) : null, footer === 'full' ? (
114
93
  // The same footer the transcript draws under a turn: the window's
115
94
  // fill, this turn's tokens in and out, copy, and dismiss.
116
95
  _jsx(TurnFooter, { usage: turn.usage, live: working, latest: true, padding: 0, onCopy: copyTurn, onRemove: () => setDismissedId(turn.id) })) : footer === 'actions' ? (
117
96
  // The actions without the counters, for a host whose readers are not
118
97
  // asking about tokens.
119
- _jsxs(Box, { sx: {
120
- display: 'flex',
121
- justifyContent: 'flex-end',
122
- gap: 1,
123
- mt: -1,
124
- }, children: [_jsx(IconButton, { icon: copied ? CheckIcon : CopyIcon, size: "small", variant: "invisible", "aria-label": copied ? 'Copied' : 'Copy this turn', onClick: () => void copyTurn(), sx: { color: 'fg.muted' } }), _jsx(IconButton, { icon: XIcon, size: "small", variant: "invisible", "aria-label": "Dismiss until the next turn", onClick: () => setDismissedId(turn.id), sx: { color: 'fg.muted' } })] })) : null] }));
98
+ _jsxs(Box, { display: "flex", justifyContent: "flex-end", gap: 1, mt: -1, children: [_jsx(IconButton, { icon: copied ? CheckIcon : CopyIcon, size: "small", variant: "invisible", "aria-label": copied ? 'Copied' : 'Copy this turn', onClick: () => void copyTurn(), sx: { color: 'fg.muted' } }), _jsx(IconButton, { icon: XIcon, size: "small", variant: "invisible", "aria-label": "Dismiss until the next turn", onClick: () => setDismissedId(turn.id), sx: { color: 'fg.muted' } })] })) : null] }));
125
99
  }
126
100
  export default TurnPanel;
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useMemo, useState, useSyncExternalStore } from 'react';
3
- import { Box, Text } from '@primer/react';
3
+ import { Box } from '@datalayer/primer-addons';
4
+ import { Text } from '@primer/react';
4
5
  import { getEditorChoice, subscribeEditorChoice } from './editorChoice';
5
6
  let jupyterReact = null;
6
7
  function loadJupyterReact() {
@@ -21,7 +22,7 @@ function stripped(source) {
21
22
  }
22
23
  /** The card's body: one row per cell or block. */
23
24
  function PreviewList({ title, rows, }) {
24
- return (_jsxs(Box, { children: [_jsx(Text, { sx: { fontWeight: 'semibold', display: 'block', mb: 1 }, children: title }), rows.length === 0 ? (_jsx(Text, { sx: { color: 'fg.muted' }, children: "Empty so far." })) : (rows.map((row, index) => (_jsxs(Box, { sx: { display: 'flex', gap: 2, py: '2px', alignItems: 'baseline' }, children: [_jsxs(Text, { sx: { color: 'fg.muted', flexShrink: 0, fontFamily: 'mono' }, children: [index, " \u00B7 ", row.kind] }), _jsx(Text, { sx: {
25
+ return (_jsxs(Box, { children: [_jsx(Text, { sx: { fontWeight: 'semibold', display: 'block', mb: 1 }, children: title }), rows.length === 0 ? (_jsx(Text, { sx: { color: 'fg.muted' }, children: "Empty so far." })) : (rows.map((row, index) => (_jsxs(Box, { display: "flex", gap: 2, py: "2px", alignItems: "baseline", children: [_jsxs(Text, { sx: { color: 'fg.muted', flexShrink: 0, fontFamily: 'mono' }, children: [index, " \u00B7 ", row.kind] }), _jsx(Text, { sx: {
25
26
  fontFamily: 'mono',
26
27
  whiteSpace: 'nowrap',
27
28
  overflow: 'hidden',
@@ -28,18 +28,6 @@ export function SubagentPulse() {
28
28
  const label = overA2A
29
29
  ? `${name} is working over A2A…`
30
30
  : `${name} is working…`;
31
- return (_jsxs(_Fragment, { children: [_jsx("style", { children: KEYFRAMES }), _jsx(Tooltip, { text: label, direction: "n", children: _jsx(Box, { as: "button", type: "button", "aria-label": label, "data-subagent-pulse": name, sx: {
32
- display: 'inline-flex',
33
- alignItems: 'center',
34
- justifyContent: 'center',
35
- width: 28,
36
- height: 28,
37
- p: 0,
38
- border: 0,
39
- bg: 'transparent',
40
- color: 'accent.fg',
41
- cursor: 'default',
42
- animation: `${PULSE_ANIMATION} 1.4s ease-in-out infinite`,
43
- }, children: _jsx(Icon, { size: 16 }) }) })] }));
31
+ return (_jsxs(_Fragment, { children: [_jsx("style", { children: KEYFRAMES }), _jsx(Tooltip, { text: label, direction: "n", children: _jsx(Box, { as: "button", type: "button", "aria-label": label, "data-subagent-pulse": name, display: "inline-flex", alignItems: "center", justifyContent: "center", width: 28, height: 28, p: 0, border: 0, bg: "transparent", color: "accent.fg", cursor: "default", animation: `${PULSE_ANIMATION} 1.4s ease-in-out infinite`, children: _jsx(Icon, { size: 16 }) }) })] }));
44
32
  }
45
33
  export default SubagentPulse;
@@ -13,50 +13,16 @@ export function WindowFrame({ children, title, height, slotProps = {}, }) {
13
13
  * actions and fills them in when the workspace registers one.
14
14
  */
15
15
  const actions = useOptionalSlotComponents(WINDOW_ACTIONS_SLOT);
16
- return (_jsxs(Box, { sx: {
17
- position: 'relative',
18
- // Filling is the default: with no height given the frame takes the
19
- // space it was handed and the body gets the remainder.
20
- ...(height === undefined
21
- ? { height: '100%', display: 'flex', flexDirection: 'column' }
22
- : null),
23
- borderRadius: '14px',
24
- overflow: 'hidden',
25
- border: '1px solid',
26
- borderColor: 'border.default',
27
- bg: 'canvas.default',
28
- // Lifted off the field, so the workspace reads as a thing sitting on
29
- // the page rather than a hole cut into it.
30
- boxShadow: '0 24px 60px -28px rgba(0, 0, 0, 0.55)',
31
- }, children: [_jsxs(Box, { sx: {
32
- display: 'flex',
33
- alignItems: 'center',
34
- gap: 2,
35
- px: 3,
36
- py: 2,
37
- borderBottom: '1px solid',
38
- borderColor: 'border.default',
39
- bg: 'canvas.subtle',
40
- // The bar may be the page's first line of type as well as its
41
- // chrome, so it takes a second row on a narrow screen rather than
42
- // shedding its actions off the edge.
43
- flexWrap: 'wrap',
44
- rowGap: 2,
45
- // Never squeezed by the body beside it.
46
- flex: '0 0 auto',
47
- }, children: [_jsx(Box, { sx: {
48
- display: 'flex',
49
- alignItems: 'center',
50
- gap: '6px',
51
- mr: 1,
52
- flexShrink: 0,
53
- }, children: _jsx(ReactorSlot, { slot: WINDOW_CONTROLS_SLOT, props: slotProps }) }), _jsx(Box, { sx: { minWidth: 0, flex: '1 1 auto' }, children: title }), actions.length > 0 ? (_jsx(Box, { sx: {
54
- display: 'flex',
55
- alignItems: 'center',
56
- gap: 2,
57
- flexShrink: 0,
58
- ml: 'auto',
59
- }, children: _jsx(ReactorSlot, { slot: WINDOW_ACTIONS_SLOT, props: slotProps }) })) : null] }), _jsx(Box, { sx: height === undefined
16
+ return (_jsxs(Box, { position: "relative", borderRadius: "14px", overflow: "hidden", border: "1px solid", borderColor: "border.default", bg: "canvas.default",
17
+ // Lifted off the field, so the workspace reads as a thing sitting on
18
+ // the page rather than a hole cut into it.
19
+ boxShadow: "0 24px 60px -28px rgba(0, 0, 0, 0.55)", height: height === undefined ? '100%' : undefined, display: height === undefined ? 'flex' : undefined, flexDirection: height === undefined ? 'column' : undefined, children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, px: 3, py: 2, borderBottom: "1px solid", borderColor: "border.default", bg: "canvas.subtle",
20
+ // The bar may be the page's first line of type as well as its
21
+ // chrome, so it takes a second row on a narrow screen rather than
22
+ // shedding its actions off the edge.
23
+ flexWrap: "wrap", rowGap: 2,
24
+ // Never squeezed by the body beside it.
25
+ flex: "0 0 auto", children: [_jsx(Box, { display: "flex", alignItems: "center", gap: "6px", mr: 1, flexShrink: 0, children: _jsx(ReactorSlot, { slot: WINDOW_CONTROLS_SLOT, props: slotProps }) }), _jsx(Box, { minWidth: 0, flex: "1 1 auto", children: title }), actions.length > 0 ? (_jsx(Box, { display: "flex", alignItems: "center", gap: 2, flexShrink: 0, ml: "auto", children: _jsx(ReactorSlot, { slot: WINDOW_ACTIONS_SLOT, props: slotProps }) })) : null] }), _jsx(Box, { sx: height === undefined
60
26
  ? { flex: '1 1 auto', minHeight: 0 }
61
27
  : { height, minHeight: 0 }, children: children })] }));
62
28
  }
@@ -48,7 +48,7 @@ export const WINDOW_FRAME_PLUGIN_NAME = '@datalayer/loop-plugin-window-frame';
48
48
  * controls can switch this plugin off and fill the slot itself.
49
49
  */
50
50
  function WindowControls() {
51
- return (_jsx(_Fragment, { children: ['danger.emphasis', 'attention.emphasis', 'success.emphasis'].map(token => (_jsx(Box, { sx: { width: 10, height: 10, borderRadius: '50%', bg: token } }, token))) }));
51
+ return (_jsx(_Fragment, { children: ['danger.emphasis', 'attention.emphasis', 'success.emphasis'].map(token => (_jsx(Box, { width: 10, height: 10, borderRadius: "50%", bg: token }, token))) }));
52
52
  }
53
53
  export const WindowFramePlugin = definePlugin({
54
54
  name: WINDOW_FRAME_PLUGIN_NAME,
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { createPortal } from 'react-dom';
4
- import { Box } from '@primer/react';
4
+ import { Box } from '@datalayer/primer-addons';
5
5
  import { buildReactorFromPlugins, onView, } from '@datalayer/reactor';
6
6
  import { ReactorSlot, ReactorViewHost, useContributions, useReactorEvent, useSlotComponents, useReactor, } from '@datalayer/reactor/react';
7
7
  import { LoopCommand, LoopSlots, LoopViewType, canOpenView, createPromptChannel, parseCommand, loopSurfaceId, } from '../core';
@@ -168,82 +168,39 @@ function WorkspaceBody({ serverUrl, agentId: initialAgentId, conversationId, mod
168
168
  through the context: the plugin needs a DOM node and nothing else, and
169
169
  the shell should not have to publish one to be found.
170
170
  */
171
- , { "data-loop-workspace": "", sx: {
172
- display: 'flex',
173
- flexDirection: 'column',
174
- height: '100%',
175
- minHeight: 0,
176
- // The containing block for anything in the root slot that positions
177
- // itself absolutely — the floating prompt does. Without this it would
178
- // resolve against whatever ancestor happens to be positioned, and
179
- // float over the host's page instead of over the workspace.
180
- position: 'relative',
181
- bg: 'canvas.default',
182
- color: 'fg.default',
183
- }, children: [showHeader && headerContainer
184
- ? createPortal(_jsx(Box, { sx: {
185
- display: 'flex',
186
- alignItems: 'center',
187
- flexWrap: 'wrap',
188
- gap: 2,
189
- }, children: headerControls }), headerContainer)
190
- : null, showHeader && headerContainer === undefined ? (_jsx(Box, { as: "header", sx: {
191
- display: 'flex',
192
- alignItems: 'center',
193
- // In a column there is no room for a row: the header wraps rather
194
- // than pushing the model chip off the edge.
195
- justifyContent: compact ? 'flex-start' : 'space-between',
196
- /*
197
- Allowed to wrap at any width.
198
-
199
- `nowrap` meant the row absorbed whatever a plugin put in it by
200
- squeezing everything else — a sandbox failure message, a long
201
- agent name — instead of taking a second line. The controls stayed
202
- on one row and got narrower, which is the wrong trade: a header
203
- two lines tall is legible, a compressed one is not.
204
- */
205
- flexWrap: 'wrap',
206
- gap: 2,
207
- px: compact ? 2 : 3,
208
- py: 2,
209
- borderBottom: '1px solid',
210
- borderColor: 'border.default',
211
- flex: '0 0 auto',
212
- }, children: headerControls })) : null, _jsxs(Box, { sx: { flex: '1 1 auto', minHeight: 0, display: 'flex' }, children: [_jsx(Box, { sx: {
213
- flex: '1 1 auto',
214
- minWidth: 0,
215
- minHeight: 0,
216
- position: 'relative',
217
- }, children: _jsx(ReactorViewHost, { point: LoopViewType, active: effectiveViewType, props: { viewType: effectiveViewType, workspace }, fallback: _jsx(Centered, { children: "Loading\u2026" }), empty: _jsx(Centered, { children: "No view is available yet." }), errorFallback: error => (_jsxs(Centered, { children: ["This view failed to load: ", error.message] })) }) }), sidebar.length > 0 && sidebarRail && !compact ? (_jsx(SidebarRail, { components: sidebar, props: { workspace }, width: SIDEBAR_WIDTH })) : sidebar.length > 0 ? (_jsx(Box, { as: "aside", sx: {
218
- flex: '0 0 auto',
219
- // Wide enough for a plugin's name, its description and a switch
220
- // on one line. The panel truncates to the same number, and takes
221
- // it from `SIDEBAR_WIDTH` so the two cannot drift.
222
- width: compact ? '100%' : `${SIDEBAR_WIDTH}px`,
223
- minWidth: 0,
224
- // On the trailing edge: the work is what a person reads first,
225
- // and the switches belong beside it rather than in front of it.
226
- borderLeft: compact ? 'none' : '1px solid',
227
- borderTop: compact ? '1px solid' : 'none',
228
- borderColor: 'border.default',
229
- bg: 'canvas.subtle',
230
- overflowY: 'auto',
231
- // The shell's chrome, not the plugins': a contributed panel
232
- // should not have to guess how far its host keeps things from
233
- // the edge, and two of them would guess differently.
234
- px: 3,
235
- py: 3,
236
- }, children: _jsx(ReactorSlot, { slot: LoopSlots.sidebar, props: { workspace } }) })) : null] }), _jsxs(Box, { sx: { flex: '0 0 auto' }, children: [_jsx(ReactorSlot, { slot: LoopSlots.footer, props: { workspace } }), _jsx(ReactorSlot, { slot: LoopSlots.status, props: { workspace } })] }), _jsx(ReactorSlot, { slot: LoopSlots.root, props: { workspace } })] }));
171
+ , { "data-loop-workspace": "", display: "flex", flexDirection: "column", height: "100%", minHeight: 0,
172
+ // The containing block for anything in the root slot that positions
173
+ // itself absolutely — the floating prompt does. Without this it would
174
+ // resolve against whatever ancestor happens to be positioned, and
175
+ // float over the host's page instead of over the workspace.
176
+ position: "relative", bg: "canvas.default", color: "fg.default", children: [showHeader && headerContainer
177
+ ? createPortal(_jsx(Box, { display: "flex", alignItems: "center", flexWrap: "wrap", gap: 2, children: headerControls }), headerContainer)
178
+ : null, showHeader && headerContainer === undefined ? (_jsx(Box, { as: "header", display: "flex", alignItems: "center",
179
+ // In a column there is no room for a row: the header wraps rather
180
+ // than pushing the model chip off the edge.
181
+ justifyContent: compact ? 'flex-start' : 'space-between',
182
+ /*
183
+ Allowed to wrap at any width.
184
+
185
+ `nowrap` meant the row absorbed whatever a plugin put in it by
186
+ squeezing everything else — a sandbox failure message, a long
187
+ agent name — instead of taking a second line. The controls stayed
188
+ on one row and got narrower, which is the wrong trade: a header
189
+ two lines tall is legible, a compressed one is not.
190
+ */
191
+ flexWrap: "wrap", gap: 2, px: compact ? 2 : 3, py: 2, borderBottom: "1px solid", borderColor: "border.default", flex: "0 0 auto", children: headerControls })) : null, _jsxs(Box, { flex: "1 1 auto", minHeight: 0, display: "flex", children: [_jsx(Box, { flex: "1 1 auto", minWidth: 0, minHeight: 0, position: "relative", children: _jsx(ReactorViewHost, { point: LoopViewType, active: effectiveViewType, props: { viewType: effectiveViewType, workspace }, fallback: _jsx(Centered, { children: "Loading\u2026" }), empty: _jsx(Centered, { children: "No view is available yet." }), errorFallback: error => (_jsxs(Centered, { children: ["This view failed to load: ", error.message] })) }) }), sidebar.length > 0 && sidebarRail && !compact ? (_jsx(SidebarRail, { components: sidebar, props: { workspace }, width: SIDEBAR_WIDTH })) : sidebar.length > 0 ? (_jsx(Box, { as: "aside", flex: "0 0 auto",
192
+ // Wide enough for a plugin's name, its description and a switch
193
+ // on one line. The panel truncates to the same number, and takes
194
+ // it from `SIDEBAR_WIDTH` so the two cannot drift.
195
+ width: compact ? '100%' : `${SIDEBAR_WIDTH}px`, minWidth: 0,
196
+ // On the trailing edge: the work is what a person reads first,
197
+ // and the switches belong beside it rather than in front of it.
198
+ borderLeft: compact ? 'none' : '1px solid', borderTop: compact ? '1px solid' : 'none', borderColor: "border.default", bg: "canvas.subtle", overflowY: "auto",
199
+ // The shell's chrome, not the plugins': a contributed panel
200
+ // should not have to guess how far its host keeps things from
201
+ // the edge, and two of them would guess differently.
202
+ px: 3, py: 3, children: _jsx(ReactorSlot, { slot: LoopSlots.sidebar, props: { workspace } }) })) : null] }), _jsxs(Box, { flex: "0 0 auto", children: [_jsx(ReactorSlot, { slot: LoopSlots.footer, props: { workspace } }), _jsx(ReactorSlot, { slot: LoopSlots.status, props: { workspace } })] }), _jsx(ReactorSlot, { slot: LoopSlots.root, props: { workspace } })] }));
237
203
  }
238
204
  function Centered({ children }) {
239
- return (_jsx(Box, { sx: {
240
- height: '100%',
241
- display: 'flex',
242
- alignItems: 'center',
243
- justifyContent: 'center',
244
- color: 'fg.muted',
245
- fontSize: 1,
246
- px: 3,
247
- textAlign: 'center',
248
- }, children: children }));
205
+ return (_jsx(Box, { height: "100%", display: "flex", alignItems: "center", justifyContent: "center", color: "fg.muted", fontSize: 1, px: 3, textAlign: "center", children: children }));
249
206
  }
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useSyncExternalStore } from 'react';
3
- import { Box, Text } from '@primer/react';
3
+ import { Box } from '@datalayer/primer-addons';
4
+ import { Text } from '@primer/react';
4
5
  import { useReactorPlatform } from '@datalayer/reactor/react';
5
6
  /** Trim the package scope so the list reads as names rather than paths. */
6
7
  function shortName(name) {
@@ -21,21 +22,9 @@ export function PluginToggles({ locked = [], title = 'Plugins', }) {
21
22
  reactor.disable(name);
22
23
  }
23
24
  }, [reactor]);
24
- return (_jsxs(Box, { sx: {
25
- p: 3,
26
- borderBottom: '1px solid',
27
- borderColor: 'border.default',
28
- bg: 'canvas.subtle',
29
- }, children: [_jsx(Text, { sx: { fontSize: 0, fontWeight: 'bold', color: 'fg.muted' }, children: title }), _jsx(Box, { sx: { display: 'flex', flexWrap: 'wrap', gap: 3, mt: 2 }, children: reactor.listPlugins().map(name => {
25
+ return (_jsxs(Box, { p: 3, borderBottom: "1px solid", borderColor: "border.default", bg: "canvas.subtle", children: [_jsx(Text, { sx: { fontSize: 0, fontWeight: 'bold', color: 'fg.muted' }, children: title }), _jsx(Box, { display: "flex", flexWrap: "wrap", gap: 3, mt: 2, children: reactor.listPlugins().map(name => {
30
26
  const isLocked = locked.includes(name);
31
- return (_jsxs(Box, { as: "label", sx: {
32
- display: 'inline-flex',
33
- alignItems: 'center',
34
- gap: 1,
35
- fontSize: 1,
36
- cursor: isLocked ? 'not-allowed' : 'pointer',
37
- opacity: isLocked ? 0.6 : 1,
38
- }, children: [_jsx("input", { type: "checkbox", checked: reactor.isEnabled(name), disabled: isLocked, onChange: event => toggle(name, event.target.checked) }), shortName(name)] }, name));
27
+ return (_jsxs(Box, { as: "label", display: "inline-flex", alignItems: "center", gap: 1, fontSize: 1, cursor: isLocked ? 'not-allowed' : 'pointer', opacity: isLocked ? 0.6 : 1, children: [_jsx("input", { type: "checkbox", checked: reactor.isEnabled(name), disabled: isLocked, onChange: event => toggle(name, event.target.checked) }), shortName(name)] }, name));
39
28
  }) })] }));
40
29
  }
41
30
  export default PluginToggles;
@@ -23,51 +23,19 @@ export function SidebarRail({ components, props, width, }) {
23
23
  const [chosen, setChosen] = useState(items[0]?.id ?? null);
24
24
  // A panel that left the slot is no longer chosen.
25
25
  const open = items.some(item => item.id === chosen) ? chosen : null;
26
- return (_jsxs(Box, { as: "aside", "data-loop-rail-sidebar": "", sx: { flex: '0 0 auto', display: 'flex', minHeight: 0 }, children: [_jsx(Box, { "data-loop-rail-panel": open ?? undefined, sx: {
27
- display: open ? 'block' : 'none',
28
- width: `${width}px`,
29
- minWidth: 0,
30
- borderLeft: 'var(--theme-hairline, 1px) solid',
31
- borderColor: 'border.default',
32
- overflowY: 'auto',
33
- px: 3,
34
- py: 3,
35
- }, children: components.map(component => {
26
+ return (_jsxs(Box, { as: "aside", "data-loop-rail-sidebar": "", flex: "0 0 auto", display: "flex", minHeight: 0, children: [_jsx(Box, { "data-loop-rail-panel": open ?? undefined, display: open ? 'block' : 'none', width: `${width}px`, minWidth: 0, borderLeft: "var(--theme-hairline, 1px) solid", borderColor: "border.default", overflowY: "auto", px: 3, py: 3, children: components.map(component => {
36
27
  const { Component } = component;
37
28
  const shown = component.id === open;
38
29
  return (_jsx(Box, { id: `loop-rail-panel-${component.id}`, role: "region", "aria-label": railItemsOf([component])[0].label, hidden: !shown, sx: shown ? paneOpening('right') : undefined, children: _jsx(Component, { ...props }) }, component.id));
39
- }) }), _jsx(Box, { as: "nav", "aria-label": "Panels", sx: {
40
- width: `${RAIL_WIDTH}px`,
41
- flex: `0 0 ${RAIL_WIDTH}px`,
42
- display: 'flex',
43
- flexDirection: 'column',
44
- alignItems: 'center',
45
- gap: 1,
46
- py: 2,
47
- borderLeft: 'var(--theme-hairline, 1px) solid',
48
- borderColor: 'border.default',
49
- }, children: items.map(item => {
30
+ }) }), _jsx(Box, { as: "nav", "aria-label": "Panels", width: `${RAIL_WIDTH}px`, flex: `0 0 ${RAIL_WIDTH}px`, display: "flex", flexDirection: "column", alignItems: "center", gap: 1, py: 2, borderLeft: "var(--theme-hairline, 1px) solid", borderColor: "border.default", children: items.map(item => {
50
31
  const Icon = item.icon;
51
32
  const active = item.id === open;
52
- return (_jsx(Box, { as: "button", type: "button", "data-loop-rail-item": item.id, "aria-label": item.label, title: item.label, "aria-pressed": active, "aria-controls": `loop-rail-panel-${item.id}`, onClick: () => setChosen(railChoiceAfter(open, item.id)), sx: {
53
- width: 32,
54
- height: 32,
55
- display: 'inline-flex',
56
- alignItems: 'center',
57
- justifyContent: 'center',
58
- p: 0,
59
- border: 'none',
60
- borderRadius: 2,
61
- cursor: 'pointer',
62
- // One weight, no colour: the ink, quieter when not chosen.
63
- color: active ? 'fg.default' : 'fg.muted',
64
- bg: active ? 'neutral.muted' : 'transparent',
65
- '&:hover': { color: 'fg.default', bg: 'neutral.subtle' },
66
- '&:focus-visible': {
67
- outline: '2px solid',
68
- outlineColor: 'var(--focus-outlineColor, #0969da)',
69
- outlineOffset: '1px',
70
- },
33
+ return (_jsx(Box, { as: "button", type: "button", "data-loop-rail-item": item.id, "aria-label": item.label, title: item.label, "aria-pressed": active, "aria-controls": `loop-rail-panel-${item.id}`, onClick: () => setChosen(railChoiceAfter(open, item.id)), width: 32, height: 32, display: "inline-flex", alignItems: "center", justifyContent: "center", p: 0, border: "none", borderRadius: 2, cursor: "pointer",
34
+ // One weight, no colour: the ink, quieter when not chosen.
35
+ color: active ? 'fg.default' : 'fg.muted', bg: active ? 'neutral.muted' : 'transparent', hover: { color: 'fg.default', bg: 'neutral.subtle' }, focusVisible: {
36
+ outline: '2px solid',
37
+ outlineColor: 'var(--focus-outlineColor, #0969da)',
38
+ outlineOffset: '1px',
71
39
  }, children: _jsx(Icon, { size: 16 }) }, item.id));
72
40
  }) })] }));
73
41
  }
@@ -1,19 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Tooltip } from '@primer/react';
2
+ import { Box } from '@datalayer/primer-addons';
3
+ import { Tooltip } from '@primer/react';
3
4
  import { canOpenView, } from '../core';
4
5
  export function ViewSwitcher({ views, workspace, compact = false, }) {
5
6
  // One choice is not a choice.
6
7
  if (views.length < 2) {
7
8
  return null;
8
9
  }
9
- return (_jsx(Box, { role: "tablist", "aria-label": "Workspace views", sx: {
10
- display: 'inline-flex',
11
- alignItems: 'center',
12
- bg: 'neutral.muted',
13
- borderRadius: '6px',
14
- p: '2px',
15
- gap: '1px',
16
- }, children: views.map(entry => {
10
+ return (_jsx(Box, { role: "tablist", "aria-label": "Workspace views", display: "inline-flex", alignItems: "center", bg: "neutral.muted", borderRadius: "6px", p: "2px", gap: "1px", children: views.map(entry => {
17
11
  const view = entry.value;
18
12
  const open = canOpenView(view, workspace);
19
13
  const active = workspace.activeViewType === view.viewType;
@@ -24,20 +18,6 @@ export function ViewSwitcher({ views, workspace, compact = false, }) {
24
18
  const label = open
25
19
  ? view.title
26
20
  : `${view.title} — ${view.unavailableReason?.(workspace) ?? 'unavailable'}`;
27
- return (_jsx(Tooltip, { text: label, direction: "n", children: _jsxs(Box, { as: "button", role: "tab", "aria-selected": active, "aria-disabled": !open, onClick: () => open && workspace.setActiveViewType(view.viewType), sx: {
28
- display: 'inline-flex',
29
- alignItems: 'center',
30
- gap: 1,
31
- border: 'none',
32
- borderRadius: '5px',
33
- px: 2,
34
- py: '4px',
35
- fontSize: 0,
36
- cursor: open ? 'pointer' : 'not-allowed',
37
- opacity: open ? 1 : 0.5,
38
- bg: active ? 'canvas.default' : 'transparent',
39
- color: active ? 'fg.default' : 'fg.muted',
40
- boxShadow: active ? 'shadow.small' : 'none',
41
- }, children: [Icon ? _jsx(Icon, { size: 14 }) : null, compact && Icon ? null : view.title] }) }, view.viewType));
21
+ return (_jsx(Tooltip, { text: label, direction: "n", children: _jsxs(Box, { as: "button", role: "tab", "aria-selected": active, "aria-disabled": !open, onClick: () => open && workspace.setActiveViewType(view.viewType), display: "inline-flex", alignItems: "center", gap: 1, border: "none", borderRadius: "5px", px: 2, py: "4px", fontSize: 0, cursor: open ? 'pointer' : 'not-allowed', opacity: open ? 1 : 0.5, bg: active ? 'canvas.default' : 'transparent', color: active ? 'fg.default' : 'fg.muted', boxShadow: active ? 'shadow.small' : 'none', children: [Icon ? _jsx(Icon, { size: 14 }) : null, compact && Icon ? null : view.title] }) }, view.viewType));
42
22
  }) }));
43
23
  }
package/lib/loop-main.js CHANGED
@@ -31,8 +31,7 @@ if (globals['__webpack_public_path__'] === undefined) {
31
31
  import { StrictMode, useEffect, useState } from 'react';
32
32
  import { createRoot } from 'react-dom/client';
33
33
  import { QueryClientProvider } from '@tanstack/react-query';
34
- import { Box } from '@primer/react';
35
- import { DatalayerThemeProvider, setupPrimerPortals, themeConfigs, useSystemColorMode, useThemeStore, } from '@datalayer/primer-addons';
34
+ import { Box, DatalayerThemeProvider, setupPrimerPortals, themeConfigs, useSystemColorMode, useThemeStore, } from '@datalayer/primer-addons';
36
35
  import { configurePlugin } from '@datalayer/reactor';
37
36
  import { LoopWorkspace } from './loop/shell/LoopWorkspace';
38
37
  import { ChatPlugin } from './loop/plugins/chat';
@@ -113,7 +112,7 @@ function LoopPage() {
113
112
  const serverUrl = window.location.origin;
114
113
  void resolveSession(serverUrl).then(setSession);
115
114
  }, []);
116
- return (_jsx(DatalayerThemeProvider, { colorMode: resolvedMode, theme: themeConfig.primerTheme, themeStyles: themeConfig.themeStyles, children: _jsx(QueryClientProvider, { client: internalQueryClient, children: _jsx(Box, { sx: { height: '100vh', overflow: 'hidden' }, children: session ? (_jsx(LoopWorkspace, { serverUrl: session.serverUrl, agentId: session.agentId, conversationId: session.conversationId, model: session.model, sandbox: session.sandbox, initialViewType: session.view,
115
+ return (_jsx(DatalayerThemeProvider, { colorMode: resolvedMode, theme: themeConfig.primerTheme, themeStyles: themeConfig.themeStyles, children: _jsx(QueryClientProvider, { client: internalQueryClient, children: _jsx(Box, { height: "100vh", overflow: "hidden", children: session ? (_jsx(LoopWorkspace, { serverUrl: session.serverUrl, agentId: session.agentId, conversationId: session.conversationId, model: session.model, sandbox: session.sandbox, initialViewType: session.view,
117
116
  // The notebook and document plugins depend on the sandbox, so
118
117
  // the reactor pulls it in; it is named here only to be told which
119
118
  // server it talks to.