@datalayer/agent-runtimes 1.3.74 → 1.3.78

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 (143) hide show
  1. package/lib/agents/AgentDetails.d.ts +16 -2
  2. package/lib/agents/AgentDetails.js +381 -272
  3. package/lib/chat/ChatFloating.d.ts +27 -1
  4. package/lib/chat/ChatFloating.js +97 -13
  5. package/lib/chat/assistant/AgentDetailsDialog.d.ts +21 -0
  6. package/lib/chat/assistant/AgentDetailsDialog.js +19 -0
  7. package/lib/chat/assistant/AssistantContextMenu.d.ts +67 -0
  8. package/lib/chat/assistant/AssistantContextMenu.js +68 -0
  9. package/lib/chat/assistant/AssistantStage.d.ts +144 -4
  10. package/lib/chat/assistant/AssistantStage.js +280 -10
  11. package/lib/chat/assistant/BalloonParts.d.ts +33 -5
  12. package/lib/chat/assistant/BalloonParts.js +66 -44
  13. package/lib/chat/assistant/BalloonVisual.d.ts +10 -2
  14. package/lib/chat/assistant/BalloonVisual.js +4 -3
  15. package/lib/chat/assistant/SandboxDetailsDialog.d.ts +44 -0
  16. package/lib/chat/assistant/SandboxDetailsDialog.js +214 -0
  17. package/lib/chat/assistant/SpeechBalloon.d.ts +54 -6
  18. package/lib/chat/assistant/SpeechBalloon.js +73 -22
  19. package/lib/chat/assistant/assistantDetails.d.ts +84 -0
  20. package/lib/chat/assistant/assistantDetails.js +140 -0
  21. package/lib/chat/assistant/formats/files.d.ts +23 -0
  22. package/lib/chat/assistant/formats/files.js +48 -0
  23. package/lib/chat/assistant/formats/index.d.ts +2 -0
  24. package/lib/chat/assistant/formats/index.js +1 -0
  25. package/lib/chat/assistant/state.d.ts +7 -14
  26. package/lib/chat/assistant/state.js +21 -20
  27. package/lib/chat/assistant/toolLine.d.ts +16 -0
  28. package/lib/chat/assistant/toolLine.js +46 -0
  29. package/lib/chat/base/ChatBase.js +71 -1
  30. package/lib/chat/base/loopMessage.d.ts +37 -0
  31. package/lib/chat/base/loopMessage.js +37 -0
  32. package/lib/chat/indicators/TypingDots.d.ts +13 -0
  33. package/lib/chat/indicators/TypingDots.js +21 -0
  34. package/lib/chat/messages/ChatMarkdown.d.ts +16 -0
  35. package/lib/chat/messages/ChatMarkdown.js +18 -0
  36. package/lib/chat/messages/ChatMessageList.d.ts +8 -1
  37. package/lib/chat/messages/ChatMessageList.js +25 -33
  38. package/lib/chat/styles/streamdownStyles.js +3 -1
  39. package/lib/chat/tools/ToolCallDisplay.d.ts +8 -1
  40. package/lib/chat/tools/ToolCallDisplay.js +8 -7
  41. package/lib/components/code-sandboxes/CodeSandboxCellVariablesDialog.js +5 -11
  42. package/lib/components/code-sandboxes/CodeSandboxVariables.d.ts +8 -0
  43. package/lib/components/code-sandboxes/CodeSandboxVariables.js +17 -11
  44. package/lib/components/inspector/AgentInspector.d.ts +59 -0
  45. package/lib/components/inspector/AgentInspector.js +220 -0
  46. package/lib/components/inspector/AgentInspectorDialog.d.ts +19 -0
  47. package/lib/components/inspector/AgentInspectorDialog.js +9 -0
  48. package/lib/components/inspector/JsonTree.d.ts +24 -0
  49. package/lib/components/inspector/JsonTree.js +89 -0
  50. package/lib/components/inspector/a2aInspect.d.ts +56 -0
  51. package/lib/components/inspector/a2aInspect.js +478 -0
  52. package/lib/components/inspector/agentInspector.d.ts +179 -0
  53. package/lib/components/inspector/agentInspector.js +267 -0
  54. package/lib/components/inspector/chatInspect.d.ts +38 -0
  55. package/lib/components/inspector/chatInspect.js +65 -0
  56. package/lib/components/inspector/classify.d.ts +19 -0
  57. package/lib/components/inspector/classify.js +42 -0
  58. package/lib/components/inspector/index.d.ts +14 -0
  59. package/lib/components/inspector/index.js +18 -0
  60. package/lib/components/teams/A2ATeamGraph.d.ts +69 -1
  61. package/lib/components/teams/A2ATeamGraph.js +277 -37
  62. package/lib/components/teams/NotebookPreviewView.js +9 -1
  63. package/lib/components/teams/TeamNotebook.d.ts +3 -1
  64. package/lib/components/teams/TeamNotebook.js +3 -3
  65. package/lib/components/teams/TeamNotebookView.js +15 -0
  66. package/lib/components/teams/jupyterThemeVariables.d.ts +9 -0
  67. package/lib/components/teams/jupyterThemeVariables.js +441 -0
  68. package/lib/components/teams/teamConnections.d.ts +9 -1
  69. package/lib/components/teams/teamConnections.js +20 -0
  70. package/lib/components/teams/teamNotebookKernel.d.ts +3 -0
  71. package/lib/components/teams/teamNotebookKernel.js +17 -0
  72. package/lib/components/teams/useA2ATeam.d.ts +20 -3
  73. package/lib/components/teams/useA2ATeam.js +108 -23
  74. package/lib/examples/AgentA2ATeamExample.d.ts +13 -0
  75. package/lib/examples/AgentA2ATeamExample.js +67 -13
  76. package/lib/examples/AssistantExample.js +65 -26
  77. package/lib/examples/AssistantGalleryExample.js +2 -1
  78. package/lib/examples/exampleGroups.d.ts +1 -1
  79. package/lib/examples/exampleGroups.js +1 -1
  80. package/lib/examples/utils/assistantGallery.d.ts +7 -6
  81. package/lib/examples/utils/assistantGallery.js +23 -8
  82. package/lib/jupyter/exec/Python.d.ts +0 -1
  83. package/lib/jupyter/exec/Python.js +0 -32
  84. package/lib/jupyter/exec/Snippets.d.ts +4 -12
  85. package/lib/jupyter/exec/Snippets.js +0 -8
  86. package/lib/loop/apps/AppFeedback.js +3 -1
  87. package/lib/loop/apps/AppKept.d.ts +22 -0
  88. package/lib/loop/apps/AppKept.js +36 -0
  89. package/lib/loop/apps/AppRenderer.d.ts +11 -1
  90. package/lib/loop/apps/AppRenderer.js +22 -4
  91. package/lib/loop/apps/checks.d.ts +7 -0
  92. package/lib/loop/apps/checks.js +39 -0
  93. package/lib/loop/apps/index.d.ts +3 -0
  94. package/lib/loop/apps/index.js +3 -0
  95. package/lib/loop/apps/kept.d.ts +30 -0
  96. package/lib/loop/apps/kept.js +52 -0
  97. package/lib/loop/apps/records.d.ts +12 -4
  98. package/lib/loop/apps/records.js +13 -5
  99. package/lib/loop/apps/saved.d.ts +30 -0
  100. package/lib/loop/apps/saved.js +40 -0
  101. package/lib/loop/core/index.d.ts +17 -0
  102. package/lib/loop/core/index.js +1 -0
  103. package/lib/loop/embed/AppEmbed.d.ts +8 -1
  104. package/lib/loop/embed/AppEmbed.js +4 -4
  105. package/lib/loop/embed/LoopEmbed.d.ts +6 -1
  106. package/lib/loop/embed/LoopEmbed.js +4 -2
  107. package/lib/loop/embed/element.js +1 -1
  108. package/lib/loop/plugins/agents/DatalayerAgentBridge.js +12 -6
  109. package/lib/loop/plugins/agents/browserService.d.ts +7 -1
  110. package/lib/loop/plugins/agents/browserService.js +4 -0
  111. package/lib/loop/plugins/agents/plugin.d.ts +16 -0
  112. package/lib/loop/plugins/agents/switchable.d.ts +3 -0
  113. package/lib/loop/plugins/agents/switchable.js +1 -0
  114. package/lib/loop/plugins/app-activity/index.js +3 -0
  115. package/lib/loop/plugins/app-computer/index.js +3 -0
  116. package/lib/loop/plugins/app-rules/AppRulesCard.d.ts +5 -0
  117. package/lib/loop/plugins/app-rules/AppRulesCard.js +25 -6
  118. package/lib/loop/plugins/app-rules/index.js +3 -0
  119. package/lib/loop/plugins/assistant/index.d.ts +7 -2
  120. package/lib/loop/plugins/assistant/index.js +58 -4
  121. package/lib/loop/plugins/assistant-characters/index.d.ts +7 -0
  122. package/lib/loop/plugins/assistant-characters/index.js +17 -0
  123. package/lib/loop/plugins/chat/ChatView.js +4 -1
  124. package/lib/loop/plugins/page-layout/SplitLayout.d.ts +2 -1
  125. package/lib/loop/plugins/page-layout/SplitLayout.js +4 -0
  126. package/lib/loop/presets.d.ts +4 -0
  127. package/lib/loop/presets.js +3 -1
  128. package/lib/loop/shell/LoopWorkspace.d.ts +7 -0
  129. package/lib/loop/shell/LoopWorkspace.js +5 -4
  130. package/lib/loop/shell/SidebarRail.d.ts +53 -0
  131. package/lib/loop/shell/SidebarRail.js +74 -0
  132. package/lib/loop/shell/index.d.ts +2 -0
  133. package/lib/loop/shell/index.js +2 -0
  134. package/lib/loop/shell/paneMotion.d.ts +21 -0
  135. package/lib/loop/shell/paneMotion.js +37 -0
  136. package/lib/runtimes/browser/a2aPeer.d.ts +4 -1
  137. package/lib/specs/apps.js +8 -5
  138. package/lib/specs/uiPlugins.js +529 -0
  139. package/lib/types/agentspecs.d.ts +5 -3
  140. package/lib/types/chat.d.ts +12 -0
  141. package/package.json +2 -2
  142. package/scripts/codegen/generate_jupyter_theme_variables.mjs +57 -0
  143. package/scripts/codegen/generate_ui_plugins.py +112 -2
@@ -0,0 +1,16 @@
1
+ /**
2
+ * An agent's words, as markdown: what the chat's messages draw them with
3
+ * (`ChatMessageList`), and what the floating assistant's balloon draws its
4
+ * current line with — one renderer, so a code block, a table or a list
5
+ * looks the same wherever the words are read.
6
+ *
7
+ * @module chat/messages/ChatMarkdown
8
+ */
9
+ import type { JSX } from 'react';
10
+ /** How dense the chat's components draw: the chat's own, or the balloon's. */
11
+ export type ChatDensity = 'comfortable' | 'compact';
12
+ export declare function ChatMarkdown({ text, density, }: {
13
+ text: string;
14
+ density?: ChatDensity;
15
+ }): JSX.Element;
16
+ export default ChatMarkdown;
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box } from '@datalayer/primer-addons';
3
+ import { Streamdown } from 'streamdown';
4
+ import { streamdownMarkdownStyles } from '../styles/streamdownStyles';
5
+ import { normalizeAssistantMarkdown } from './assistantMarkdown';
6
+ export function ChatMarkdown({ text, density = 'comfortable', }) {
7
+ return (_jsx(Box, { "data-chat-markdown": "", sx: {
8
+ ...streamdownMarkdownStyles,
9
+ ...(density === 'compact'
10
+ ? {
11
+ lineHeight: 1.4,
12
+ '& p': { marginTop: 0, marginBottom: '0.4em' },
13
+ '& p:last-child': { marginBottom: 0 },
14
+ }
15
+ : {}),
16
+ }, children: _jsx(Streamdown, { children: normalizeAssistantMarkdown(text) }) }));
17
+ }
18
+ export default ChatMarkdown;
@@ -1,4 +1,5 @@
1
1
  import { type ReactNode, type RefObject } from 'react';
2
+ import { type ChatDensity } from './ChatMarkdown';
2
3
  import { type MarkedMcpServer } from '../marks';
3
4
  import type { DisplayItem, AvatarConfig, RenderToolResult } from '../../types/chat';
4
5
  import type { ChatMessage } from '../../types/messages';
@@ -67,6 +68,12 @@ export interface ChatMessageListProps {
67
68
  * and runtime tools are found in the catalogues.
68
69
  */
69
70
  mcpServers?: readonly MarkedMcpServer[];
71
+ /**
72
+ * How dense it draws: the chat's own (`comfortable`), or the floating
73
+ * assistant's balloon (`compact`: no avatars, smaller bubbles and tool
74
+ * rows, no turn footers). The same components either way.
75
+ */
76
+ density?: ChatDensity;
70
77
  }
71
78
  type SubagentAvatarConfig = Required<Pick<AvatarConfig, 'userAvatar' | 'assistantAvatar' | 'showAvatars' | 'avatarSize' | 'userAvatarBg' | 'assistantAvatarBg'>>;
72
79
  export interface SubagentChatPanelProps {
@@ -86,5 +93,5 @@ export interface SubagentChatPanelProps {
86
93
  * approval decisions are sent over the shared monitoring socket.
87
94
  */
88
95
  export declare function SubagentChatPanel({ toolCallId, subagentName: subagentNameHint, height, avatarConfig, }: SubagentChatPanelProps): React.ReactElement | null;
89
- export declare function ChatMessageList({ displayItems, isLoading, isStreaming, showLoadingIndicator, hideMessagesAfterToolUI, avatarConfig, padding, renderToolResult, emptyContent, messagesEndRef, onRespond, approvalConfig, showTurnFooters, agentUsage, onRemoveItems, renderMessageFooter, mcpServers, }: ChatMessageListProps): import("react").JSX.Element;
96
+ export declare function ChatMessageList({ displayItems, isLoading, isStreaming, showLoadingIndicator, hideMessagesAfterToolUI, avatarConfig, padding, renderToolResult, emptyContent, messagesEndRef, onRespond, approvalConfig, showTurnFooters, agentUsage, onRemoveItems, renderMessageFooter, mcpServers, density, }: ChatMessageListProps): import("react").JSX.Element;
90
97
  export {};
@@ -14,12 +14,12 @@ import { Fragment, useState, useCallback, useEffect, useMemo, useRef, } from 're
14
14
  import { Text, Spinner, Link, Label, RelativeTime } from '@primer/react';
15
15
  import { ArrowRightIcon, BroadcastIcon, ClockIcon, DependabotIcon, PersonIcon, SkipIcon, ToolsIcon, XCircleFillIcon, } from '@primer/octicons-react';
16
16
  import { Box } from '@datalayer/primer-addons';
17
- import { Streamdown } from 'streamdown';
18
- import { streamdownMarkdownStyles, streamdownCodeBlockStyles, } from '../styles/streamdownStyles';
17
+ import { streamdownCodeBlockStyles } from '../styles/streamdownStyles';
18
+ import { ChatMarkdown } from './ChatMarkdown';
19
19
  import { ToolCallDisplay } from '../tools/ToolCallDisplay';
20
20
  import { marksOfToolCall, skillIdOfCall } from '../marks';
21
+ import { TypingDots } from '../indicators/TypingDots';
21
22
  import { TurnFooter } from './TurnFooter';
22
- import { normalizeAssistantMarkdown } from './assistantMarkdown';
23
23
  import { parseFormSubmission } from './formSubmission';
24
24
  import { FormSubmissionMessage } from './FormSubmissionMessage';
25
25
  import { isToolCallMessage, getMessageText } from '../../utils';
@@ -62,21 +62,6 @@ function toneColorsOf(tone) {
62
62
  fg: `${tone}.fg`,
63
63
  };
64
64
  }
65
- /** Three pulsing dots: a speaker is still writing and has not settled yet. */
66
- function TypingDots({ size = 8 }) {
67
- return (_jsx(Box, { sx: { display: 'flex', alignItems: 'center', gap: '4px' }, children: [0, 0.2, 0.4].map((delay, index) => (_jsx(Box, { sx: {
68
- width: size,
69
- height: size,
70
- borderRadius: '50%',
71
- bg: 'fg.muted',
72
- animation: 'typingPulse 1.4s ease-in-out infinite',
73
- animationDelay: `${delay}s`,
74
- '@keyframes typingPulse': {
75
- '0%, 60%, 100%': { transform: 'scale(0.6)', opacity: 0.4 },
76
- '30%': { transform: 'scale(1)', opacity: 1 },
77
- },
78
- } }, index))) }));
79
- }
80
65
  const SUBAGENT_AVATAR_CONFIG = {
81
66
  userAvatar: _jsx(PersonIcon, { size: 14 }),
82
67
  assistantAvatar: _jsx(DependabotIcon, { size: 14 }),
@@ -277,7 +262,7 @@ export function SubagentChatPanel({ toolCallId, subagentName: subagentNameHint,
277
262
  // DefaultToolCallRenderer — reads approvals from the Zustand store,
278
263
  // sends decisions over the shared WebSocket (no REST polling).
279
264
  // ---------------------------------------------------------------------------
280
- function DefaultToolCallRenderer({ item, onRespond, mcpServers, }) {
265
+ function DefaultToolCallRenderer({ item, onRespond, mcpServers, density, }) {
281
266
  const resultObject = item.result && typeof item.result === 'object'
282
267
  ? item.result
283
268
  : undefined;
@@ -393,12 +378,18 @@ function DefaultToolCallRenderer({ item, onRespond, mcpServers, }) {
393
378
  ? () => makeDecision('approve')
394
379
  : undefined, onDeny: effectiveApprovalId && !decision && !externalDecision
395
380
  ? () => makeDecision('reject')
396
- : undefined, approvalLoading: false, marks: marks }), isSubagentDelegation && (_jsx(SubagentChatPanel, { toolCallId: item.toolCallId, subagentName: delegatedSubagentName }))] }));
381
+ : undefined, approvalLoading: false, marks: marks, summary: item.summary, density: density }), isSubagentDelegation && (_jsx(SubagentChatPanel, { toolCallId: item.toolCallId, subagentName: delegatedSubagentName }))] }));
397
382
  }
398
383
  // ---------------------------------------------------------------------------
399
384
  // Component
400
385
  // ---------------------------------------------------------------------------
401
- export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoadingIndicator, hideMessagesAfterToolUI, avatarConfig, padding, renderToolResult, emptyContent, messagesEndRef, onRespond, approvalConfig, showTurnFooters = false, agentUsage, onRemoveItems, renderMessageFooter, mcpServers, }) {
386
+ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoadingIndicator, hideMessagesAfterToolUI, avatarConfig, padding, renderToolResult, emptyContent, messagesEndRef, onRespond, approvalConfig, showTurnFooters = false, agentUsage, onRemoveItems, renderMessageFooter, mcpServers, density = 'comfortable', }) {
387
+ const compact = density === 'compact';
388
+ if (compact) {
389
+ // The balloon's: no avatars, no turn footers.
390
+ avatarConfig = { ...avatarConfig, showAvatars: false };
391
+ showTurnFooters = false;
392
+ }
402
393
  if (displayItems.length === 0) {
403
394
  return _jsx(_Fragment, { children: emptyContent });
404
395
  }
@@ -500,7 +491,7 @@ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoad
500
491
  not care about hid those tools entirely. Offering the default as a
501
492
  node lets it compose instead of choosing.
502
493
  */
503
- const defaultUI = (_jsx(DefaultToolCallRenderer, { item: item, approvalConfig: approvalConfig, onRespond: createRespondCallback(item.toolCallId), mcpServers: mcpServers }));
494
+ const defaultUI = (_jsx(DefaultToolCallRenderer, { item: item, approvalConfig: approvalConfig, onRespond: createRespondCallback(item.toolCallId), mcpServers: mcpServers, density: density }));
504
495
  const toolUI = renderToolResult
505
496
  ? renderToolResult({
506
497
  toolCallId: item.toolCallId,
@@ -516,7 +507,7 @@ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoad
516
507
  : defaultUI;
517
508
  if (toolUI === null || toolUI === undefined)
518
509
  return null;
519
- return (_jsx(Box, { sx: {
510
+ return (_jsx(Box, { "data-chat-tool-row": item.toolName, sx: {
520
511
  display: 'flex',
521
512
  flexDirection: 'column',
522
513
  alignItems: 'flex-start',
@@ -531,7 +522,7 @@ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoad
531
522
  */
532
523
  width: '100%',
533
524
  px: padding,
534
- py: 1,
525
+ py: compact ? '2px' : 1,
535
526
  }, children: toolUI }, item.id));
536
527
  }
537
528
  // ---- Chat message item ----
@@ -600,12 +591,12 @@ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoad
600
591
  }
601
592
  }
602
593
  }
603
- return (_jsx(Box, { sx: {
594
+ return (_jsx(Box, { "data-chat-message": message.role, sx: {
604
595
  display: 'flex',
605
596
  flexDirection: 'column',
606
597
  alignItems: isUser ? 'flex-end' : 'flex-start',
607
598
  px: padding,
608
- py: 1,
599
+ py: compact ? '2px' : 1,
609
600
  }, children: _jsxs(Box, { sx: {
610
601
  display: 'flex',
611
602
  gap: 2,
@@ -649,7 +640,7 @@ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoad
649
640
  ? speaker.initials || '?'
650
641
  : isUser
651
642
  ? avatarConfig.userAvatar
652
- : avatarConfig.assistantAvatar })), _jsxs(Box, { sx: { maxWidth: '85%', minWidth: 0 }, children: [speaker ? (_jsxs(Box, { sx: {
643
+ : avatarConfig.assistantAvatar })), _jsxs(Box, { sx: { maxWidth: compact ? '92%' : '85%', minWidth: 0 }, children: [speaker ? (_jsxs(Box, { sx: {
653
644
  display: 'flex',
654
645
  gap: 2,
655
646
  alignItems: 'baseline',
@@ -671,7 +662,8 @@ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoad
671
662
  fontSize: 1,
672
663
  color: toneColorsOf(message.directedTo.tone).fg,
673
664
  }, children: message.directedTo.name })] })) : speaker.role ? (_jsx(Label, { size: "small", children: speaker.role })) : null, message.createdAt ? (_jsx(RelativeTime, { datetime: message.createdAt.toISOString(), sx: { fontSize: 0, color: 'fg.muted' } })) : null] })) : null, _jsxs(Box, { sx: {
674
- p: 2,
665
+ p: compact ? 1 : 2,
666
+ px: compact ? 2 : 2,
675
667
  overflowX: 'auto',
676
668
  // The theme's bubble (LOOP T-03, T-06): today's 6px elsewhere.
677
669
  borderRadius: 'var(--theme-radius-bubble, 6px)',
@@ -710,7 +702,7 @@ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoad
710
702
  const text = getMessageText(message);
711
703
  const submission = parseFormSubmission(text);
712
704
  return submission ? (_jsx(FormSubmissionMessage, { submission: submission })) : (_jsxs(Text, { sx: {
713
- fontSize: 1,
705
+ fontSize: compact ? 0 : 1,
714
706
  whiteSpace: 'pre-wrap',
715
707
  wordBreak: 'break-word',
716
708
  }, children: [message.metadata?.input === 'voice' ? (_jsx(Box, { as: "span", "data-spoken": "", title: "Said aloud", "aria-label": "Said aloud:", sx: {
@@ -719,7 +711,7 @@ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoad
719
711
  mr: 1,
720
712
  opacity: 0.85,
721
713
  }, children: _jsx(MicrophoneIcon, { size: 14, "aria-hidden": "true" }) })) : null, text] }));
722
- })()) : message.live && !getMessageText(message) ? (_jsx(TypingDots, { size: 6 })) : (_jsx(Box, { sx: streamdownMarkdownStyles, children: _jsx(Streamdown, { children: normalizeAssistantMarkdown(getMessageText(message) || (isStreaming ? '...' : '')) }) }))] }), renderMessageFooter ? (_jsx(Box, { sx: {
714
+ })()) : message.live && !getMessageText(message) ? (_jsx(TypingDots, { size: 6 })) : (_jsx(ChatMarkdown, { density: density, text: getMessageText(message) || (isStreaming ? '...' : '') }))] }), renderMessageFooter ? (_jsx(Box, { sx: {
723
715
  display: 'flex',
724
716
  gap: 2,
725
717
  alignItems: 'center',
@@ -735,7 +727,7 @@ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoad
735
727
  return null;
736
728
  }
737
729
  return (_jsxs(Fragment, { children: [itemUI, footer] }, item.id));
738
- }), showLoadingIndicator && (isLoading || isStreaming) && (_jsx(Box, { sx: {
730
+ }), showLoadingIndicator && (isLoading || isStreaming) && (_jsx(Box, { "data-chat-typing": "", sx: {
739
731
  display: 'flex',
740
732
  alignItems: 'flex-start',
741
733
  px: padding,
@@ -757,9 +749,9 @@ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoad
757
749
  }, children: avatarConfig.assistantAvatar })), _jsx(Box, { sx: {
758
750
  display: 'flex',
759
751
  alignItems: 'center',
760
- p: 2,
752
+ p: compact ? 1 : 2,
761
753
  borderRadius: 'var(--theme-radius-bubble, 6px)',
762
754
  bg: 'canvas.subtle',
763
- minHeight: '32px',
755
+ minHeight: compact ? '20px' : '32px',
764
756
  }, children: _jsx(TypingDots, {}) })] }) })), _jsx("div", { ref: messagesEndRef })] }));
765
757
  }
@@ -215,8 +215,10 @@ export const streamdownMarkdownStyles = {
215
215
  marginRight: 0,
216
216
  color: 'fg.muted',
217
217
  },
218
+ // A link reads as its theme says (LOOP T-06): in the accent, or plain —
219
+ // the colour of the words around it — and underlined in every theme.
218
220
  '& a': {
219
- color: 'accent.fg',
221
+ color: 'var(--theme-message-link, var(--fgColor-accent, #0969da))',
220
222
  textDecoration: 'underline',
221
223
  },
222
224
  '& table': {
@@ -50,6 +50,13 @@ export interface ToolCallDisplayProps {
50
50
  * icon, else the emoji, else nothing.
51
51
  */
52
52
  marks?: Marks | null;
53
+ /** What it does in its runtime's words: shown in place of the arguments. */
54
+ summary?: string;
55
+ /**
56
+ * How dense: the chat's (`comfortable`), or the floating assistant's
57
+ * balloon (`compact`: a smaller header, the same card).
58
+ */
59
+ density?: 'comfortable' | 'compact';
53
60
  }
54
61
  /**
55
62
  * ToolCallDisplay component - Default display for tool calls in chat
@@ -61,5 +68,5 @@ export interface ToolCallDisplayProps {
61
68
  * - Color-coded status indicators
62
69
  * - Rich error display distinguishing execution errors from code errors
63
70
  */
64
- export declare function ToolCallDisplay({ toolCallId, toolName, args, result, status, error, executionResult, codeError, exitCode, executionError, approvalRequired, approvalState, approvalDecisionSource, onApprove, onDeny, approvalLoading, marks, }: ToolCallDisplayProps): React.JSX.Element;
71
+ export declare function ToolCallDisplay({ toolCallId, toolName, args, result, status, error, executionResult, codeError, exitCode, executionError, approvalRequired, approvalState, approvalDecisionSource, onApprove, onDeny, approvalLoading, marks, summary, density, }: ToolCallDisplayProps): React.JSX.Element;
65
72
  export default ToolCallDisplay;
@@ -125,7 +125,8 @@ function getArgsSummary(args) {
125
125
  * - Color-coded status indicators
126
126
  * - Rich error display distinguishing execution errors from code errors
127
127
  */
128
- export function ToolCallDisplay({ toolCallId, toolName, args, result, status, error, executionResult, codeError, exitCode, executionError, approvalRequired = false, approvalState, approvalDecisionSource, onApprove, onDeny, approvalLoading = false, marks, }) {
128
+ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, error, executionResult, codeError, exitCode, executionError, approvalRequired = false, approvalState, approvalDecisionSource, onApprove, onDeny, approvalLoading = false, marks, summary, density = 'comfortable', }) {
129
+ const compact = density === 'compact';
129
130
  const [isExpanded, setIsExpanded] = useState(false);
130
131
  // Determine effective exit code from props or execution result
131
132
  const effectiveExitCode = exitCode ?? executionResult?.exit_code;
@@ -143,7 +144,7 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
143
144
  : undefined;
144
145
  const statusDisplay = getStatusDisplay(status, errorType);
145
146
  const displayName = formatToolName(toolName);
146
- const argsSummary = getArgsSummary(args);
147
+ const argsSummary = summary || getArgsSummary(args);
147
148
  const resultObject = result && typeof result === 'object'
148
149
  ? result
149
150
  : undefined;
@@ -168,19 +169,19 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
168
169
  result.stderr ??
169
170
  undefined)
170
171
  : undefined);
171
- return (_jsxs(Box, { sx: {
172
+ return (_jsxs(Box, { "data-tool-call": toolName, "data-tool-call-status": status, sx: {
172
173
  width: '100%',
173
174
  border: '1px solid',
174
175
  borderColor: 'border.default',
175
- borderRadius: '12px',
176
+ borderRadius: compact ? '8px' : '12px',
176
177
  overflow: 'hidden',
177
178
  backgroundColor: 'canvas.default',
178
179
  }, children: [_jsxs(Box, { as: "button", onClick: () => setIsExpanded(!isExpanded), sx: {
179
180
  width: '100%',
180
181
  display: 'flex',
181
182
  alignItems: 'center',
182
- gap: 2,
183
- padding: 2,
183
+ gap: compact ? 1 : 2,
184
+ padding: compact ? 1 : 2,
184
185
  backgroundColor: 'canvas.subtle',
185
186
  border: 'none',
186
187
  borderBottom: isExpanded ? '1px solid' : 'none',
@@ -192,7 +193,7 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
192
193
  },
193
194
  }, children: [_jsx(Box, { sx: { color: 'fg.muted', flexShrink: 0 }, children: isExpanded ? (_jsx(ChevronDownIcon, { size: 16 })) : (_jsx(ChevronRightIcon, { size: 16 })) }), hasMark(marks) && (_jsx(Box, { sx: { color: 'fg.muted', flexShrink: 0, display: 'flex' }, children: _jsx(SpecMark, { icon: marks?.icon, emoji: marks?.emoji, size: 16 }) })), _jsx(Text, { sx: {
194
195
  fontWeight: 'semibold',
195
- fontSize: 1,
196
+ fontSize: compact ? 0 : 1,
196
197
  color: 'fg.default',
197
198
  flexShrink: 0,
198
199
  }, children: displayName }), _jsxs(Box, { sx: {
@@ -3,8 +3,9 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
3
3
  import { Dialog } from '@primer/react/experimental';
4
4
  import { nullTranslator } from '@jupyterlab/translation';
5
5
  import { JSONExt } from '@lumino/coreutils';
6
- import { KernelExecutor } from '@datalayer/jupyter-react';
6
+ import { kernelConnectionExecutor, listKernelVariables, } from '@datalayer/jupyter-react';
7
7
  import { RuntimeSnippetsFacade } from '../../jupyter';
8
+ import { transferableVariables } from './CodeSandboxVariables';
8
9
  import { CodeSandboxCellVariables } from './CodeSandboxCellVariables';
9
10
  /**
10
11
  * Dialog to define the runtime cell variables to transfer
@@ -53,16 +54,9 @@ export function CodeSandboxCellVariablesDialog(props) {
53
54
  }
54
55
  const connection = sessionContext.session.kernel;
55
56
  const spec = sessionContext.specsManager.specs.kernelspecs[connection.model.name];
56
- const snippets = new RuntimeSnippetsFacade(spec.language);
57
- const outputs = await new KernelExecutor({ connection }).execute(snippets.listVariables());
58
- const content = outputs.get(0).data['text/plain'];
59
- if (content) {
60
- const runtimeVariables = JSON.parse(
61
- // We need to remove the quotes prior to parsing
62
- content.slice(1, content.length - 1));
63
- return Object.keys(runtimeVariables ?? {});
64
- }
65
- return [];
57
+ return Object.keys(transferableVariables(await listKernelVariables(kernelConnectionExecutor(connection), {
58
+ language: spec.language,
59
+ })));
66
60
  }, [preference, sessionContext]);
67
61
  const getOutputCandidates = useCallback(async () => {
68
62
  // TODO this is only valid for python - using cell mimetype?
@@ -1,7 +1,15 @@
1
1
  import { ReactElement } from 'react';
2
2
  import { ISessionContext } from '@jupyterlab/apputils';
3
3
  import { ITranslator } from '@jupyterlab/translation';
4
+ import { type KernelVariable } from '@datalayer/jupyter-react';
4
5
  import type { IRuntimeDesc } from '../../models';
6
+ /**
7
+ * The variables that can be carried to another sandbox, by name and type:
8
+ * values, not the modules, functions and classes code defines again.
9
+ */
10
+ export declare function transferableVariables(variables: readonly KernelVariable[]): {
11
+ [name: string]: string;
12
+ };
5
13
  /** What {@link useCodeSandboxVariablesTransfer} answers. */
6
14
  export interface ICodeSandboxVariablesTransfer {
7
15
  /**
@@ -10,8 +10,19 @@ import { Blankslate, DataTable, Table } from '@primer/react/experimental';
10
10
  import { nullTranslator } from '@jupyterlab/translation';
11
11
  import { checkIcon } from '@jupyterlab/ui-components';
12
12
  import { JSONExt } from '@lumino/coreutils';
13
- import { KernelExecutor } from '@datalayer/jupyter-react';
13
+ import { kernelConnectionExecutor, listKernelVariables, } from '@datalayer/jupyter-react';
14
14
  import { RuntimeSnippetsFacade } from '../../jupyter';
15
+ /**
16
+ * The variables that can be carried to another sandbox, by name and type:
17
+ * values, not the modules, functions and classes code defines again.
18
+ */
19
+ export function transferableVariables(variables) {
20
+ return Object.fromEntries(variables
21
+ .filter(variable => variable.kind !== 'module' &&
22
+ variable.kind !== 'function' &&
23
+ variable.kind !== 'class')
24
+ .map(variable => [variable.name, variable.type]));
25
+ }
15
26
  /**
16
27
  * The variables of the current sandbox, and which of them to carry over.
17
28
  *
@@ -45,18 +56,13 @@ export function useCodeSandboxVariablesTransfer(sessionContext, target, enabled
45
56
  setVariables({});
46
57
  return;
47
58
  }
48
- const snippets = new RuntimeSnippetsFacade(spec.language);
49
- const outputs = await new KernelExecutor({ connection }).execute(snippets.listVariables());
50
- const content = outputs.get(0).data['text/plain'];
51
- if (!content) {
52
- setVariables({});
53
- return;
54
- }
55
- // The payload comes quoted, as the representation of a string.
56
- const listedVariables = JSON.parse(content.slice(1, content.length - 1));
59
+ // jupyter-react's snippet, run silently: the variables, typed.
60
+ const listedVariables = transferableVariables(await listKernelVariables(kernelConnectionExecutor(connection), {
61
+ language: spec.language,
62
+ }));
57
63
  setVariables(listedVariables);
58
64
  // Everything is carried over unless the user says otherwise.
59
- setSelectedState(Object.keys(listedVariables ?? {}));
65
+ setSelectedState(Object.keys(listedVariables));
60
66
  }, [listed, sessionContext]);
61
67
  const setSelected = useCallback((names) => {
62
68
  setSelectedState(current => JSONExt.deepEqual(current, names) ? current : names);
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The Agent Inspector: what agents do, one row a thing, newest last — the
3
+ * time (to the millisecond, and since the first), who did it and toward
4
+ * whom, its source and kind, its name with its mark, its status and
5
+ * duration, and a line that says it. A row unfolds to its payload as a JSON
6
+ * tree (a call's arguments and its result), and to what was made of it.
7
+ *
8
+ * Filters by source, kind and actor; *Pause* holds the rows still while the
9
+ * record goes on, *Clear* empties it, *Export* saves the session as JSON. A
10
+ * large payload (a notebook) says its size and stays folded until asked.
11
+ *
12
+ * Fed by a sink (`useAgentInspector`) or given its entries.
13
+ *
14
+ * @module components/inspector/AgentInspector
15
+ */
16
+ import type { JSX } from 'react';
17
+ import { type AgentInspectorEntry, type AgentInspectorExport, type AgentInspectorSink, type AgentInspectorSource } from './agentInspector';
18
+ export type AgentInspectorProps = {
19
+ /** The record to show, kept current. */
20
+ sink?: AgentInspectorSink | null;
21
+ /** Or its entries, as given. */
22
+ entries?: readonly AgentInspectorEntry[];
23
+ /** How tall the rows grow before they scroll. */
24
+ maxHeight?: number | string;
25
+ /** Payloads larger than this, in bytes, stay folded until asked. */
26
+ largeBytes?: number;
27
+ /** What is said while nothing is recorded. */
28
+ emptyText?: string;
29
+ /** The file name the session is exported as, without `.json`. */
30
+ exportName?: string;
31
+ /**
32
+ * One agent's own record: what it did (`actor`), and the A2A messages it
33
+ * sent or received — one message shows in the sender's and in the
34
+ * receiver's, the same entry, as sent in one and received in the other.
35
+ */
36
+ agent?: string;
37
+ };
38
+ /** Whether an entry is one agent's: done by it, or sent to or by it. */
39
+ export declare function isAgentsEntry(entry: AgentInspectorEntry, agent: string): boolean;
40
+ /** Which way an entry went, from one agent's side: `→ Accounting`, `← Accounting`. */
41
+ export declare function directionFrom(entry: AgentInspectorEntry, agent: string | undefined): string;
42
+ /** A time of day, to the millisecond: `15:44:31.299`. */
43
+ export declare function clockTime(at: number): string;
44
+ /** Time since the first entry: `+1.204s`. */
45
+ export declare function sinceFirst(at: number, first: number): string;
46
+ /** How long a call took: `412 ms`, `3.4 s`. */
47
+ export declare function durationText(ms: number): string;
48
+ export type AgentInspectorFilter = {
49
+ sources: ReadonlySet<AgentInspectorSource>;
50
+ kinds: ReadonlySet<string>;
51
+ actors: ReadonlySet<string>;
52
+ };
53
+ /** The entries a filter keeps: an empty set keeps every value. */
54
+ export declare function filterEntries(entries: readonly AgentInspectorEntry[], filter: AgentInspectorFilter): AgentInspectorEntry[];
55
+ /** A session, as JSON. */
56
+ export declare function exportEntries(entries: readonly AgentInspectorEntry[]): AgentInspectorExport;
57
+ /** The Agent Inspector. */
58
+ export declare function AgentInspector({ sink, entries: given, maxHeight, largeBytes, emptyText, exportName, agent, }: AgentInspectorProps): JSX.Element;
59
+ export default AgentInspector;