@datalayer/agent-runtimes 1.3.74 → 1.3.75

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 (55) hide show
  1. package/lib/chat/ChatFloating.d.ts +17 -1
  2. package/lib/chat/ChatFloating.js +52 -5
  3. package/lib/chat/assistant/AssistantContextMenu.d.ts +67 -0
  4. package/lib/chat/assistant/AssistantContextMenu.js +68 -0
  5. package/lib/chat/assistant/AssistantStage.d.ts +95 -1
  6. package/lib/chat/assistant/AssistantStage.js +227 -7
  7. package/lib/chat/assistant/BalloonParts.d.ts +15 -1
  8. package/lib/chat/assistant/BalloonParts.js +26 -9
  9. package/lib/chat/assistant/BalloonVisual.d.ts +10 -2
  10. package/lib/chat/assistant/BalloonVisual.js +3 -3
  11. package/lib/chat/assistant/SpeechBalloon.d.ts +47 -1
  12. package/lib/chat/assistant/SpeechBalloon.js +60 -8
  13. package/lib/chat/base/ChatBase.js +51 -1
  14. package/lib/chat/indicators/TypingDots.d.ts +13 -0
  15. package/lib/chat/indicators/TypingDots.js +21 -0
  16. package/lib/chat/messages/ChatMessageList.js +1 -15
  17. package/lib/components/inspector/AgentInspector.d.ts +59 -0
  18. package/lib/components/inspector/AgentInspector.js +220 -0
  19. package/lib/components/inspector/AgentInspectorDialog.d.ts +19 -0
  20. package/lib/components/inspector/AgentInspectorDialog.js +9 -0
  21. package/lib/components/inspector/JsonTree.d.ts +24 -0
  22. package/lib/components/inspector/JsonTree.js +89 -0
  23. package/lib/components/inspector/a2aInspect.d.ts +56 -0
  24. package/lib/components/inspector/a2aInspect.js +478 -0
  25. package/lib/components/inspector/agentInspector.d.ts +179 -0
  26. package/lib/components/inspector/agentInspector.js +267 -0
  27. package/lib/components/inspector/chatInspect.d.ts +38 -0
  28. package/lib/components/inspector/chatInspect.js +65 -0
  29. package/lib/components/inspector/classify.d.ts +19 -0
  30. package/lib/components/inspector/classify.js +42 -0
  31. package/lib/components/inspector/index.d.ts +14 -0
  32. package/lib/components/inspector/index.js +18 -0
  33. package/lib/components/teams/A2ATeamGraph.d.ts +42 -1
  34. package/lib/components/teams/A2ATeamGraph.js +24 -7
  35. package/lib/components/teams/NotebookPreviewView.js +9 -1
  36. package/lib/components/teams/TeamNotebook.d.ts +3 -1
  37. package/lib/components/teams/TeamNotebook.js +3 -3
  38. package/lib/components/teams/jupyterThemeVariables.d.ts +9 -0
  39. package/lib/components/teams/jupyterThemeVariables.js +441 -0
  40. package/lib/components/teams/teamConnections.d.ts +9 -1
  41. package/lib/components/teams/teamConnections.js +20 -0
  42. package/lib/components/teams/useA2ATeam.d.ts +17 -4
  43. package/lib/components/teams/useA2ATeam.js +87 -23
  44. package/lib/examples/AgentA2ATeamExample.d.ts +13 -0
  45. package/lib/examples/AgentA2ATeamExample.js +61 -13
  46. package/lib/examples/AssistantExample.js +62 -2
  47. package/lib/loop/apps/AppRenderer.js +1 -1
  48. package/lib/loop/core/index.d.ts +17 -0
  49. package/lib/loop/core/index.js +1 -0
  50. package/lib/loop/plugins/assistant/index.d.ts +1 -1
  51. package/lib/loop/plugins/assistant/index.js +8 -3
  52. package/lib/runtimes/browser/a2aPeer.d.ts +4 -1
  53. package/lib/types/chat.d.ts +7 -0
  54. package/package.json +1 -1
  55. package/scripts/codegen/generate_jupyter_theme_variables.mjs +57 -0
@@ -25,6 +25,11 @@
25
25
  import type { JSX } from 'react';
26
26
  import { type Edge, type EdgeProps, type Viewport } from '@xyflow/react';
27
27
  import '@xyflow/react/dist/base.css';
28
+ import { type AssistantAbout } from '../../chat/assistant/AssistantStage';
29
+ import type { BalloonSuggestion } from '../../chat/assistant/SpeechBalloon';
30
+ import type { BalloonHistoryMessage } from '../../chat/assistant/state';
31
+ import type { AssistantMenuItem } from '../../chat/assistant/AssistantContextMenu';
32
+ import type { AgentInspectorSink } from '../inspector/agentInspector';
28
33
  import { type A2ATeamCall, type A2ATeamConnection, type A2ATeamFlow } from './a2aTeamFlow';
29
34
  import type { A2ATeamPersona } from './useA2ATeam';
30
35
  import type { BalloonExpandTarget } from '../../chat/assistant/BalloonVisual';
@@ -65,6 +70,36 @@ export type A2ATeamGraphMember = {
65
70
  expandTarget?: BalloonExpandTarget;
66
71
  /** What its notebook is called: `Accounting's notebook`. */
67
72
  notebookTitle?: string;
73
+ /**
74
+ * What the person may ask it: chips in its balloon while it waits for a
75
+ * question, and a group of its menu; one chosen is sent (`onSuggestion`).
76
+ */
77
+ suggestions?: readonly BalloonSuggestion[];
78
+ onSuggestion?: (suggestion: BalloonSuggestion) => void;
79
+ /**
80
+ * The team's Agent Inspector: its menu offers *Inspect the agent…*, its
81
+ * own record (what it did, and the A2A messages it sent or received).
82
+ */
83
+ inspector?: AgentInspectorSink | null;
84
+ /** Stops its turn, from its menu, while it works. */
85
+ onStop?: () => void;
86
+ /** What its menu's *About* says. */
87
+ about?: AssistantAbout;
88
+ /** The host's own entries of its menu. */
89
+ contextMenu?: readonly AssistantMenuItem[];
90
+ /**
91
+ * What its menu calls a click on it (`onToggle`): `Ask Sales` where it
92
+ * takes the person to the composer. Without `onToggle`, its menu has no
93
+ * such entry.
94
+ */
95
+ conversationLabel?: string;
96
+ /**
97
+ * What it said and did, as its `history` balloon lists it (`useA2ATeam`'s
98
+ * `entryHistory`, `peerHistory`): shown when its menu chooses *History*.
99
+ */
100
+ history?: readonly BalloonHistoryMessage[];
101
+ /** Its balloon's display was chosen in its menu: the page may keep it. */
102
+ onBalloonDisplayChange?: (display: BalloonDisplay) => void;
68
103
  };
69
104
  export type A2ATeamGraphProps = {
70
105
  /** The member that asks: drawn on the left. */
@@ -81,6 +116,12 @@ export type A2ATeamGraphProps = {
81
116
  size?: number;
82
117
  /** The tool calls running now, to the members' connections (`useA2ATeam`). */
83
118
  calls?: A2ATeamCall[];
119
+ /**
120
+ * The room above the members for their balloons, in pixels at full scale:
121
+ * a page that shows suggestions, *more* and a notebook in them gives more.
122
+ * A notebook in a balloon gets at least its own.
123
+ */
124
+ balloonRoom?: number;
84
125
  };
85
126
  /** The words on the edge for a flow. */
86
127
  export declare function flowWords(flow: A2ATeamFlow, entry: string, peer: string): string;
@@ -95,5 +136,5 @@ export declare function callWords(member: string, connection: A2ATeamConnection,
95
136
  /** The viewport that shows the graph's width whole in a box `width` wide, never larger than drawn. */
96
137
  export declare function teamViewport(width: number): Viewport;
97
138
  /** Draw a team of two over A2A, the link moving with what travels on it. */
98
- export declare function A2ATeamGraph({ entry, peer, flow, connected, label, size, calls, }: A2ATeamGraphProps): JSX.Element;
139
+ export declare function A2ATeamGraph({ entry, peer, flow, connected, label, size, calls, balloonRoom, }: A2ATeamGraphProps): JSX.Element;
99
140
  export default A2ATeamGraph;
@@ -4,7 +4,7 @@ import { BaseEdge, EdgeLabelRenderer, Handle, Position, ReactFlow, } from '@xyfl
4
4
  import '@xyflow/react/dist/base.css';
5
5
  import { Button, Label, Text } from '@primer/react';
6
6
  import { Box } from '@datalayer/primer-addons';
7
- import { AssistantStage } from '../../chat/assistant/AssistantStage';
7
+ import { AssistantStage, } from '../../chat/assistant/AssistantStage';
8
8
  import { SpecMark } from '../../chat/marks/SpecMark';
9
9
  import { toolWords, } from './a2aTeamFlow';
10
10
  import { NotebookPreview } from './NotebookPreview';
@@ -14,7 +14,7 @@ import { toolLineText } from '../../chat/assistant/toolLine';
14
14
  const NODE_WIDTH = 200;
15
15
  const BALLOON_ROOM = 144;
16
16
  /** The room a balloon that holds a notebook needs above its member. */
17
- const NOTEBOOK_BALLOON_ROOM = 340;
17
+ const NOTEBOOK_BALLOON_ROOM = 480;
18
18
  /** How tall the notebook in a balloon grows before it scrolls. */
19
19
  const NOTEBOOK_PREVIEW_HEIGHT = 180;
20
20
  const GAP = 220;
@@ -50,10 +50,17 @@ const MemberNode = memo(function MemberNode({ data, }) {
50
50
  const { id, side, size } = data;
51
51
  const member = useContext(Members)[id];
52
52
  const stageRef = useRef(null);
53
+ // Its balloon's display, as its menu changes it.
54
+ const [display, setDisplay] = useState();
53
55
  if (!member) {
54
56
  return null;
55
57
  }
56
58
  const { persona } = member;
59
+ const shownDisplay = display ?? member.balloonDisplay ?? 'current';
60
+ // History: what it said and did, listed.
61
+ const listed = shownDisplay === 'history' && member.history?.length
62
+ ? { history: member.history }
63
+ : {};
57
64
  // A notebook it was given: read-only in its balloon, and its large visual
58
65
  // the one that runs, editable — under the graph, or in a dialog.
59
66
  const notebookTitle = member.notebookTitle ?? (persona.notebook?.name || 'The notebook');
@@ -86,24 +93,34 @@ const MemberNode = memo(function MemberNode({ data, }) {
86
93
  // middle of the graph: rightward from the left member.
87
94
  place: side === 'left'
88
95
  ? { position: 'absolute', left: 'auto' }
89
- : { position: 'absolute', right: 'auto' }, stageRef: stageRef, onDragStart: () => undefined, open: false, onToggle: member.onToggle ?? (() => undefined), balloonDisplay: member.balloonDisplay ?? 'current', balloon: persona.tool
96
+ : { position: 'absolute', right: 'auto' }, stageRef: stageRef, onDragStart: () => undefined, open: false, onToggle: member.onToggle ?? (() => undefined), balloonDisplay: shownDisplay, onBalloonDisplayChange: next => {
97
+ setDisplay(next);
98
+ member.onBalloonDisplayChange?.(next);
99
+ }, conversationLabel: member.onToggle ? (member.conversationLabel ?? undefined) : false, balloon: persona.tool
90
100
  ? {
91
101
  text: toolLineText(persona.tool),
92
102
  tool: persona.tool,
93
103
  busy: persona.state !== 'idle',
94
104
  ...given,
105
+ ...listed,
95
106
  }
96
107
  : persona.saying
97
108
  ? {
98
109
  text: persona.saying,
110
+ ...(persona.full ? { fullText: persona.full } : {}),
99
111
  more: persona.saying.endsWith('…'),
100
112
  speaking: persona.state === 'speaking',
101
113
  busy: persona.state === 'thinking' ||
102
114
  persona.state === 'working' ||
103
115
  persona.state === 'speaking',
104
116
  ...given,
117
+ ...listed,
105
118
  }
106
- : undefined, expandTarget: member.expandTarget, expandOnArrival: !!member.expandTarget, insist: persona.insist, onDismiss: away => member.onAway?.(away !== 'none'),
119
+ : 'history' in listed
120
+ ? { text: '', ...listed }
121
+ : undefined, expandTarget: member.expandTarget, expandOnArrival: !!member.expandTarget,
122
+ // History, chosen in its menu: shown until Current is.
123
+ insist: persona.insist || display === 'history', onDismiss: away => member.onAway?.(away !== 'none'), suggestions: member.suggestions, onSuggestion: member.onSuggestion, inspector: member.inspector, inspectAgent: member.name, onStop: member.onStop, about: member.about, contextMenu: member.contextMenu,
107
124
  // A member of the graph: what is clicked around it is the graph.
108
125
  stayPut: true })) }), _jsxs(Text, { sx: { fontWeight: 600, textAlign: 'center' }, children: [member.emoji ? `${member.emoji} ` : '', member.name] }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', textAlign: 'center' }, "data-member-where": "", children: member.where }), _jsx(Handle, { type: "source", position: Position.Right, style: HANDLE(size), isConnectable: false }), member.connections?.length ? (_jsx(Handle, { id: "connections", type: "source", position: Position.Bottom, style: { ...HANDLE(size), top: 'auto', bottom: 0 }, isConnectable: false })) : null] }));
109
126
  });
@@ -201,7 +218,7 @@ export function teamViewport(width) {
201
218
  return { zoom, x: (width - WIDTH * zoom) / 2, y: 0 };
202
219
  }
203
220
  /** Draw a team of two over A2A, the link moving with what travels on it. */
204
- export function A2ATeamGraph({ entry, peer, flow, connected, label = 'A2A', size = 96, calls = [], }) {
221
+ export function A2ATeamGraph({ entry, peer, flow, connected, label = 'A2A', size = 96, calls = [], balloonRoom = BALLOON_ROOM, }) {
205
222
  const box = useRef(null);
206
223
  const [width, setWidth] = useState(0);
207
224
  useEffect(() => {
@@ -234,8 +251,8 @@ export function A2ATeamGraph({ entry, peer, flow, connected, label = 'A2A', size
234
251
  const hasConnections = placed.some(({ connections }) => connections.length);
235
252
  // A notebook in a balloon: more room above the members.
236
253
  const room = [entry, peer].some(member => member.persona.notebook)
237
- ? NOTEBOOK_BALLOON_ROOM
238
- : BALLOON_ROOM;
254
+ ? Math.max(NOTEBOOK_BALLOON_ROOM, balloonRoom)
255
+ : balloonRoom;
239
256
  const height = Math.ceil((room +
240
257
  memberHeight +
241
258
  (hasConnections ? CONNECTION_GAP + connectionHeight : 0)) *
@@ -3,6 +3,7 @@ import { useMemo } from 'react';
3
3
  import { useTheme } from '@primer/react';
4
4
  import { Box } from '@datalayer/primer-addons';
5
5
  import { JupyterReactTheme, Notebook, ServiceManagerLess, } from '@datalayer/jupyter-react';
6
+ import { JUPYTER_DARK_VARIABLES, JUPYTER_LIGHT_VARIABLES, } from './jupyterThemeVariables';
6
7
  /** Each preview has its own id in jupyter-react's store. */
7
8
  let drawn = 0;
8
9
  export function NotebookPreviewView({ nbformat, height, }) {
@@ -16,7 +17,14 @@ export function NotebookPreviewView({ nbformat, height, }) {
16
17
  }, [nbformat]);
17
18
  const content = useMemo(() => JSON.parse(JSON.stringify(nbformat)), [nbformat]);
18
19
  const { colorScheme } = useTheme();
19
- return (_jsxs(Box, { "data-notebook-preview-theme": "", sx: { height }, children: [_jsx("span", { "data-jupyter-react-theme-root": "notebook-preview", hidden: true }), _jsx(JupyterReactTheme, { colormode: colorScheme?.startsWith('dark') ? 'dark' : 'light', children: _jsx(Box, { "data-notebook-preview-view": id, sx: {
20
+ const mode = colorScheme?.startsWith('dark') ? 'dark' : 'light';
21
+ return (_jsxs(Box, { "data-notebook-preview-theme": mode, sx: { height },
22
+ // JupyterLab writes its theme for the whole page, so two previews in
23
+ // two modes would share the last one written: each carries its own
24
+ // mode's variables on its own subtree.
25
+ style: (mode === 'dark'
26
+ ? JUPYTER_DARK_VARIABLES
27
+ : JUPYTER_LIGHT_VARIABLES), children: [_jsx("span", { "data-jupyter-react-theme-root": "notebook-preview", hidden: true }), _jsx(JupyterReactTheme, { colormode: mode, children: _jsx(Box, { "data-notebook-preview-view": id, sx: {
20
28
  height,
21
29
  // No toolbar: no room kept for one.
22
30
  '& .datalayer-NotebookPanel-header': {
@@ -25,11 +25,13 @@ export type TeamNotebookProps = {
25
25
  title: string;
26
26
  /** How tall the notebook is, in pixels. */
27
27
  height?: number;
28
+ /** Leave the heading out: the dialog it is drawn in shows the title. */
29
+ hideTitle?: boolean;
28
30
  };
29
31
  /** The file a notebook is saved as: the peer's name for it, else its name. */
30
32
  export declare function notebookFileName(notebook: A2APeerArtifact): string;
31
33
  /** A notebook a member of the team gave, under its title, to run in the page. */
32
- export declare function TeamNotebook({ notebook, title, height, }: TeamNotebookProps): JSX.Element;
34
+ export declare function TeamNotebook({ notebook, title, height, hideTitle, }: TeamNotebookProps): JSX.Element;
33
35
  /**
34
36
  * A notebook as a balloon's large visual: read-only in the balloon, and,
35
37
  * expanded, this notebook — editable, run on the browser sandbox, loaded
@@ -16,7 +16,7 @@ export function notebookFileName(notebook) {
16
16
  return `${stem}.ipynb`;
17
17
  }
18
18
  /** A notebook a member of the team gave, under its title, to run in the page. */
19
- export function TeamNotebook({ notebook, title, height = 560, }) {
19
+ export function TeamNotebook({ notebook, title, height = 560, hideTitle = false, }) {
20
20
  return (_jsxs(Box, { as: "section", "aria-label": title, "data-team-notebook": "",
21
21
  // Focused when the notebook in a balloon is clicked (`focusExpanded`).
22
22
  tabIndex: -1, sx: {
@@ -32,7 +32,7 @@ export function TeamNotebook({ notebook, title, height = 560, }) {
32
32
  outlineOffset: 4,
33
33
  borderRadius: 2,
34
34
  },
35
- }, children: [_jsx(Heading, { as: "h3", sx: { fontSize: 2, m: 0 }, children: title }), _jsx(Suspense, { fallback: _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "Opening the notebook\u2026" }), children: _jsx(TeamNotebookView, { notebook: notebook, fileName: notebookFileName(notebook), height: height }) })] }));
35
+ }, children: [!hideTitle && (_jsx(Heading, { as: "h3", sx: { fontSize: 2, m: 0 }, children: title })), _jsx(Suspense, { fallback: _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "Opening the notebook\u2026" }), children: _jsx(TeamNotebookView, { notebook: notebook, fileName: notebookFileName(notebook), height: height }) })] }));
36
36
  }
37
37
  /**
38
38
  * A notebook as a balloon's large visual: read-only in the balloon, and,
@@ -43,7 +43,7 @@ export function notebookBalloonVisual(notebook, title, height) {
43
43
  return {
44
44
  id: `notebook:${notebook.filename ?? notebook.name}`,
45
45
  title,
46
- render: () => (_jsx(TeamNotebook, { notebook: notebook, title: title, height: height })),
46
+ render: place => (_jsx(TeamNotebook, { notebook: notebook, title: title, height: height, hideTitle: place === 'overlay' })),
47
47
  };
48
48
  }
49
49
  export default TeamNotebook;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * JupyterLab's theme variables, light and dark, as its theme extensions state
3
+ * them. Generated by scripts/codegen/generate_jupyter_theme_variables.mjs: do
4
+ * not edit.
5
+ *
6
+ * @module components/teams/jupyterThemeVariables
7
+ */
8
+ export declare const JUPYTER_LIGHT_VARIABLES: Readonly<Record<string, string>>;
9
+ export declare const JUPYTER_DARK_VARIABLES: Readonly<Record<string, string>>;