@datalayer/agent-runtimes 1.3.83 → 1.3.85

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 (168) hide show
  1. package/lib/chat/ChatFloating.d.ts +5 -4
  2. package/lib/chat/ChatFloating.js +8 -6
  3. package/lib/chat/ChatLanguage.d.ts +17 -0
  4. package/lib/chat/ChatLanguage.js +29 -0
  5. package/lib/chat/assistant/AssistantStage.d.ts +4 -4
  6. package/lib/chat/assistant/AssistantStage.js +4 -2
  7. package/lib/chat/assistant/BalloonParts.d.ts +2 -1
  8. package/lib/chat/assistant/BalloonParts.js +12 -5
  9. package/lib/chat/assistant/BalloonVisual.js +3 -1
  10. package/lib/chat/assistant/ConversationBalloon.d.ts +1 -1
  11. package/lib/chat/assistant/ConversationBalloon.js +3 -2
  12. package/lib/chat/assistant/SpeechBalloon.d.ts +1 -1
  13. package/lib/chat/assistant/SpeechBalloon.js +10 -7
  14. package/lib/chat/assistant/toolLine.d.ts +8 -4
  15. package/lib/chat/assistant/toolLine.js +13 -9
  16. package/lib/chat/base/ChatBase.js +30 -11
  17. package/lib/chat/base/loopElement.d.ts +53 -0
  18. package/lib/chat/base/loopElement.js +78 -0
  19. package/lib/chat/base/loopWindow.d.ts +31 -0
  20. package/lib/chat/base/loopWindow.js +74 -0
  21. package/lib/chat/display/EmptyState.js +3 -1
  22. package/lib/chat/index.d.ts +2 -0
  23. package/lib/chat/index.js +3 -0
  24. package/lib/chat/messages/ChatMessages.js +3 -1
  25. package/lib/chat/messages/TurnFooter.js +3 -1
  26. package/lib/chat/prompt/InputPrompt.js +3 -1
  27. package/lib/chat/prompt/InputPromptLexical.js +3 -1
  28. package/lib/chat/prompt/footer/InPromptFooter.js +3 -1
  29. package/lib/chat/tools/ToolApprovalBanner.js +5 -3
  30. package/lib/chat/tools/ToolApprovalDialog.js +5 -3
  31. package/lib/chat/tools/ToolCallDisplay.js +29 -25
  32. package/lib/chat/words.d.ts +102 -0
  33. package/lib/chat/words.js +460 -0
  34. package/lib/components/a2ui/custom/index.d.ts +39 -0
  35. package/lib/components/a2ui/custom/index.js +95 -0
  36. package/lib/components/a2ui/custom/sandbox.d.ts +73 -0
  37. package/lib/components/a2ui/custom/sandbox.js +188 -0
  38. package/lib/components/a2ui/datalayer/FileUpload.d.ts +10 -2
  39. package/lib/components/a2ui/datalayer/FileUpload.js +10 -7
  40. package/lib/components/a2ui/datalayer/Form.d.ts +2 -0
  41. package/lib/components/a2ui/datalayer/Form.js +9 -2
  42. package/lib/components/a2ui/datalayer/formWidgets.d.ts +19 -0
  43. package/lib/components/a2ui/datalayer/formWidgets.js +51 -0
  44. package/lib/components/a2ui/datalayer/index.d.ts +1 -1
  45. package/lib/components/a2ui/datalayer/index.js +1 -1
  46. package/lib/components/a2ui/datalayer/schema.d.ts +10 -0
  47. package/lib/components/a2ui/datalayer/schema.js +12 -1
  48. package/lib/components/a2ui/index.d.ts +1 -0
  49. package/lib/components/a2ui/index.js +1 -0
  50. package/lib/components/a2ui/visibleWhen.d.ts +12 -1
  51. package/lib/components/a2ui/visibleWhen.js +24 -3
  52. package/lib/components/inspector/AgentInspector.d.ts +25 -44
  53. package/lib/components/inspector/AgentInspector.js +27 -215
  54. package/lib/components/inspector/AgentInspectorDialog.d.ts +6 -6
  55. package/lib/components/inspector/AgentInspectorDialog.js +2 -2
  56. package/lib/components/inspector/a2aSpans.d.ts +51 -0
  57. package/lib/components/inspector/a2aSpans.js +373 -0
  58. package/lib/components/inspector/agentSpans.d.ts +120 -0
  59. package/lib/components/inspector/agentSpans.js +253 -0
  60. package/lib/components/inspector/chatSpans.d.ts +36 -0
  61. package/lib/components/inspector/chatSpans.js +50 -0
  62. package/lib/components/inspector/classify.d.ts +11 -8
  63. package/lib/components/inspector/classify.js +23 -24
  64. package/lib/components/inspector/index.d.ts +7 -7
  65. package/lib/components/inspector/index.js +7 -7
  66. package/lib/components/teams/A2ATeamGraph.d.ts +4 -4
  67. package/lib/components/teams/SceneTranscript.d.ts +29 -0
  68. package/lib/components/teams/SceneTranscript.js +54 -0
  69. package/lib/components/teams/SceneView.d.ts +41 -0
  70. package/lib/components/teams/SceneView.js +28 -0
  71. package/lib/components/teams/index.d.ts +3 -0
  72. package/lib/components/teams/index.js +3 -0
  73. package/lib/components/teams/sceneTranscript.d.ts +74 -0
  74. package/lib/components/teams/sceneTranscript.js +294 -0
  75. package/lib/components/teams/teamConnections.d.ts +2 -2
  76. package/lib/components/teams/teamConnections.js +3 -3
  77. package/lib/components/teams/useA2ATeam.d.ts +4 -4
  78. package/lib/components/teams/useA2ATeam.js +50 -46
  79. package/lib/examples/AgentA2ATeamExample.d.ts +10 -9
  80. package/lib/examples/AgentA2ATeamExample.js +70 -60
  81. package/lib/examples/AssistantExample.js +2 -2
  82. package/lib/loop/apps/AppComposer.d.ts +40 -4
  83. package/lib/loop/apps/AppComposer.js +194 -19
  84. package/lib/loop/apps/AppRenderer.d.ts +21 -3
  85. package/lib/loop/apps/AppRenderer.js +88 -48
  86. package/lib/loop/apps/appspec.d.ts +13 -1
  87. package/lib/loop/apps/appspec.js +305 -12
  88. package/lib/loop/apps/checks.d.ts +14 -0
  89. package/lib/loop/apps/checks.js +276 -5
  90. package/lib/loop/apps/composer.d.ts +21 -10
  91. package/lib/loop/apps/composer.js +41 -8
  92. package/lib/loop/apps/customComponents.d.ts +41 -0
  93. package/lib/loop/apps/customComponents.js +260 -0
  94. package/lib/loop/apps/hostTools.d.ts +8 -1
  95. package/lib/loop/apps/hostTools.js +9 -0
  96. package/lib/loop/apps/index.d.ts +1 -0
  97. package/lib/loop/apps/index.js +1 -0
  98. package/lib/loop/apps/language.d.ts +68 -0
  99. package/lib/loop/apps/language.js +275 -0
  100. package/lib/loop/apps/settingsInputs.d.ts +29 -0
  101. package/lib/loop/apps/settingsInputs.js +147 -0
  102. package/lib/loop/apps/uploads.d.ts +43 -0
  103. package/lib/loop/apps/uploads.js +66 -0
  104. package/lib/loop/core/a2uiComponents.d.ts +10 -0
  105. package/lib/loop/core/a2uiComponents.js +15 -0
  106. package/lib/loop/core/index.d.ts +15 -1
  107. package/lib/loop/core/index.js +3 -0
  108. package/lib/loop/embed/AppEmbed.d.ts +25 -3
  109. package/lib/loop/embed/AppEmbed.js +106 -18
  110. package/lib/loop/embed/element.d.ts +5 -0
  111. package/lib/loop/embed/element.js +84 -5
  112. package/lib/loop/embed/embedConfig.d.ts +8 -0
  113. package/lib/loop/embed/embedConfig.js +18 -0
  114. package/lib/loop/embed/embedSession.d.ts +14 -0
  115. package/lib/loop/embed/embedSession.js +34 -0
  116. package/lib/loop/embed/hostBridge.d.ts +50 -3
  117. package/lib/loop/embed/hostBridge.js +22 -2
  118. package/lib/loop/index.d.ts +4 -3
  119. package/lib/loop/index.js +4 -3
  120. package/lib/loop/plugins/a2ui-surface/InlineSurface.d.ts +7 -1
  121. package/lib/loop/plugins/a2ui-surface/InlineSurface.js +7 -2
  122. package/lib/loop/plugins/a2ui-surface/SurfaceToolResult.js +4 -1
  123. package/lib/loop/plugins/a2ui-surface/ownComponents.d.ts +6 -0
  124. package/lib/loop/plugins/a2ui-surface/ownComponents.js +30 -0
  125. package/lib/loop/plugins/app-components/index.d.ts +26 -0
  126. package/lib/loop/plugins/app-components/index.js +56 -0
  127. package/lib/loop/plugins/app-elements/AppElements.d.ts +27 -0
  128. package/lib/loop/plugins/app-elements/AppElements.js +79 -0
  129. package/lib/loop/plugins/app-elements/index.d.ts +20 -0
  130. package/lib/loop/plugins/app-elements/index.js +43 -0
  131. package/lib/loop/plugins/app-page/AppPage.d.ts +9 -0
  132. package/lib/loop/plugins/app-page/AppPage.js +106 -8
  133. package/lib/loop/plugins/app-page/appPageModel.d.ts +17 -1
  134. package/lib/loop/plugins/app-page/appPageModel.js +122 -4
  135. package/lib/loop/plugins/app-page/index.d.ts +1 -0
  136. package/lib/loop/plugins/app-page/index.js +1 -0
  137. package/lib/loop/plugins/app-page/pageRun.d.ts +46 -0
  138. package/lib/loop/plugins/app-page/pageRun.js +111 -0
  139. package/lib/loop/plugins/assistant/index.js +8 -6
  140. package/lib/loop/plugins/chat/ChatView.js +16 -6
  141. package/lib/loop/plugins/chat/index.d.ts +1 -1
  142. package/lib/loop/plugins/chat/index.js +2 -1
  143. package/lib/models/PageTag.d.ts +1 -1
  144. package/lib/protocols/BrowserAgentAdapter.d.ts +8 -6
  145. package/lib/protocols/BrowserAgentAdapter.js +13 -10
  146. package/lib/runtimes/browser/a2aPeer.d.ts +2 -1
  147. package/lib/runtimes/browser/protocol.d.ts +1 -1
  148. package/lib/specs/actions.js +78 -1
  149. package/lib/specs/apps.d.ts +5 -0
  150. package/lib/specs/apps.js +1518 -216
  151. package/lib/specs/appspecSchema.js +630 -3
  152. package/lib/specs/teams/teams.d.ts +3 -0
  153. package/lib/specs/teams/teams.js +249 -0
  154. package/lib/specs/uiPlugins.js +6 -1
  155. package/lib/types/agentspecs.d.ts +200 -1
  156. package/lib/types/chat.d.ts +6 -5
  157. package/lib/types/teams.d.ts +13 -2
  158. package/package.json +2 -2
  159. package/scripts/codegen/generate_apps.py +20 -2
  160. package/scripts/codegen/generate_teams.py +15 -2
  161. package/lib/components/inspector/JsonTree.d.ts +0 -24
  162. package/lib/components/inspector/JsonTree.js +0 -89
  163. package/lib/components/inspector/a2aInspect.d.ts +0 -56
  164. package/lib/components/inspector/a2aInspect.js +0 -478
  165. package/lib/components/inspector/agentInspector.d.ts +0 -179
  166. package/lib/components/inspector/agentInspector.js +0 -267
  167. package/lib/components/inspector/chatInspect.d.ts +0 -38
  168. package/lib/components/inspector/chatInspect.js +0 -65
@@ -1,220 +1,32 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import { useMemo, useState } from 'react';
3
- import { ActionList, ActionMenu, Button, Label, Text } from '@primer/react';
4
- import { Box } from '@datalayer/primer-addons';
5
- import { DownloadIcon, PlayIcon, TrashIcon, PauseIcon, } from '@primer/octicons-react';
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { OtelLiveSpans, } from '@datalayer/core/lib/otel/views/OtelLiveSpans';
6
3
  import { SpecMark } from '../../chat/marks';
7
- import { AGENT_INSPECTOR_SOURCES, AGENT_INSPECTOR_SOURCE_LABELS, formatBytes, useAgentInspectorEntries, } from './agentInspector';
8
- import { JsonTree } from './JsonTree';
9
- /** Whether an entry is one agent's: done by it, or sent to or by it. */
10
- export function isAgentsEntry(entry, agent) {
11
- return (entry.actor === agent ||
12
- entry.direction?.from === agent ||
13
- entry.direction?.to === agent);
14
- }
15
- /** Which way an entry went, from one agent's side: `→ Accounting`, `← Accounting`. */
16
- export function directionFrom(entry, agent) {
17
- const direction = entry.direction;
18
- if (!direction) {
19
- return entry.actor;
20
- }
21
- if (agent === direction.from) {
22
- return `sent → ${direction.to}`;
23
- }
24
- if (agent === direction.to) {
25
- return `received ← ${direction.from}`;
26
- }
27
- return `${direction.from} → ${direction.to}`;
28
- }
29
- /** A kind, as its label is coloured. */
30
- const KIND_VARIANTS = {
31
- request: 'accent',
32
- 'status-update': 'attention',
33
- 'artifact-update': 'success',
34
- task: 'secondary',
35
- message: 'done',
36
- 'agent-card': 'secondary',
37
- response: 'secondary',
38
- 'tool-call': 'sponsors',
39
- turn: 'primary',
40
- error: 'danger',
41
- approval: 'severe',
42
- };
43
- const pad = (value, length = 2) => String(value).padStart(length, '0');
44
- /** A time of day, to the millisecond: `15:44:31.299`. */
45
- export function clockTime(at) {
46
- const date = new Date(at);
47
- return `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}.${pad(date.getMilliseconds(), 3)}`;
48
- }
49
- /** Time since the first entry: `+1.204s`. */
50
- export function sinceFirst(at, first) {
51
- return `+${((at - first) / 1000).toFixed(3)}s`;
52
- }
53
- /** How long a call took: `412 ms`, `3.4 s`. */
54
- export function durationText(ms) {
55
- return ms < 1000 ? `${Math.round(ms)} ms` : `${(ms / 1000).toFixed(1)} s`;
56
- }
57
- /** The entries a filter keeps: an empty set keeps every value. */
58
- export function filterEntries(entries, filter) {
59
- return entries.filter(entry => (!filter.sources.size || filter.sources.has(entry.source)) &&
60
- (!filter.kinds.size || filter.kinds.has(entry.kind)) &&
61
- (!filter.actors.size || filter.actors.has(entry.actor)));
62
- }
63
- /** A session, as JSON. */
64
- export function exportEntries(entries) {
65
- return { exportedAt: new Date().toISOString(), entries: [...entries] };
66
- }
67
- function toggle(set, value) {
68
- const next = new Set(set);
69
- if (next.has(value)) {
70
- next.delete(value);
71
- }
72
- else {
73
- next.add(value);
74
- }
75
- return next;
76
- }
77
- function FilterMenu({ label, options, selected, onToggle, onAll, name, }) {
78
- return (_jsxs(ActionMenu, { children: [_jsxs(ActionMenu.Button, { size: "small", "data-inspector-filter": label.toLowerCase(), children: [label, selected.size ? ` · ${selected.size}` : ''] }), _jsx(ActionMenu.Overlay, { width: "auto", children: _jsxs(ActionList, { selectionVariant: "multiple", "aria-label": label, children: [_jsx(ActionList.Item, { selected: !selected.size, onSelect: onAll, children: "All" }), _jsx(ActionList.Divider, {}), options.map(option => (_jsx(ActionList.Item, { selected: selected.has(option), onSelect: () => onToggle(option), children: name(option) }, option)))] }) })] }));
79
- }
80
- function Payload({ title, value, large, }) {
81
- const bytes = useMemo(() => {
82
- try {
83
- return new TextEncoder().encode(JSON.stringify(value) ?? '').length;
84
- }
85
- catch {
86
- return 0;
87
- }
88
- }, [value]);
89
- const [shown, setShown] = useState(bytes <= large);
90
- return (_jsxs(Box, { sx: { minWidth: 0 }, "data-inspector-payload": title, children: [_jsxs(Text, { sx: {
91
- fontSize: 0,
92
- color: 'fg.muted',
93
- fontWeight: 600,
94
- display: 'block',
95
- }, children: [title, " \u00B7 ", formatBytes(bytes)] }), shown ? (_jsx(JsonTree, { value: value, expandDepth: bytes > large ? 1 : 2 })) : (_jsxs(Button, { size: "small", onClick: () => setShown(true), "data-inspector-large": "", children: ["Show ", formatBytes(bytes)] }))] }));
96
- }
97
- function Row({ entry, first, open, onToggle, large, agent, }) {
98
- const ended = entry.endedAt !== undefined;
99
- return (_jsxs(Box, { as: "li", "data-inspector-entry": entry.id, "data-inspector-source": entry.source, "data-inspector-kind": entry.kind, "data-inspector-status": entry.status ?? '', sx: {
100
- borderBottom: '1px solid',
101
- borderColor: 'border.muted',
102
- listStyle: 'none',
103
- }, children: [_jsxs(Box, { as: "button", type: "button", "aria-expanded": open, onClick: onToggle, sx: {
104
- width: '100%',
105
- display: 'grid',
106
- gridTemplateColumns: ['auto 1fr', 'auto auto auto minmax(0, 1fr)'],
107
- columnGap: 2,
108
- rowGap: 1,
109
- alignItems: 'center',
110
- px: 2,
111
- py: 1,
112
- border: 0,
113
- bg: open ? 'canvas.subtle' : 'transparent',
114
- color: 'fg.default',
115
- font: 'inherit',
116
- fontSize: 0,
117
- textAlign: 'left',
118
- cursor: 'pointer',
119
- '&:hover': { bg: 'canvas.subtle' },
120
- }, children: [_jsxs(Box, { sx: { fontFamily: 'mono', color: 'fg.muted', whiteSpace: 'nowrap' }, children: [_jsx("span", { title: new Date(entry.at).toISOString(), children: clockTime(entry.at) }), ' ', _jsx(Text, { sx: { opacity: 0.7 }, children: sinceFirst(entry.at, first) })] }), _jsx(Text, { sx: { whiteSpace: 'nowrap', fontWeight: 600 }, "data-inspector-direction": "", children: directionFrom(entry, agent) }), _jsxs(Box, { sx: { display: 'flex', gap: 1, flexWrap: 'wrap' }, children: [_jsx(Label, { size: "small", variant: "secondary", children: AGENT_INSPECTOR_SOURCE_LABELS[entry.source] }), _jsx(Label, { size: "small", variant: KIND_VARIANTS[entry.kind] ?? 'secondary', children: entry.kind })] }), _jsxs(Box, { sx: { display: 'flex', gap: 1, alignItems: 'center', minWidth: 0 }, children: [(entry.icon || entry.emoji) && (_jsx(SpecMark, { icon: entry.icon, emoji: entry.emoji, size: 14 })), entry.name && entry.kind !== 'request' && (_jsx(Text, { sx: { fontFamily: 'mono', fontWeight: 600, whiteSpace: 'nowrap' }, children: entry.name })), entry.status && (_jsxs(Label, { size: "small", variant: entry.status === 'failed'
121
- ? 'danger'
122
- : entry.status === 'running'
123
- ? 'attention'
124
- : 'success', children: [entry.status, ended && entry.endedAt !== undefined
125
- ? ` · ${durationText(entry.endedAt - entry.at)}`
126
- : ''] })), _jsx(Text, { sx: {
127
- color: 'fg.muted',
128
- overflow: 'hidden',
129
- textOverflow: 'ellipsis',
130
- whiteSpace: 'nowrap',
131
- minWidth: 0,
132
- }, title: entry.summary, children: entry.summary }), entry.bytes > large && (_jsx(Text, { sx: { color: 'fg.muted', whiteSpace: 'nowrap' }, children: formatBytes(entry.bytes) }))] })] }), open && (_jsxs(Box, { "data-inspector-details": "", sx: {
133
- px: 3,
134
- py: 2,
135
- display: 'flex',
136
- flexDirection: 'column',
137
- gap: 2,
138
- bg: 'canvas.subtle',
139
- }, children: [entry.a2a && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontFamily: 'mono' }, children: [
140
- entry.a2a.method && `method ${entry.a2a.method}`,
141
- entry.a2a.rpcId !== undefined && `id ${entry.a2a.rpcId}`,
142
- entry.a2a.taskId && `task ${entry.a2a.taskId}`,
143
- entry.a2a.contextId && `context ${entry.a2a.contextId}`,
144
- entry.a2a.state && entry.a2a.state,
145
- entry.a2a.chunks &&
146
- entry.a2a.chunks > 1 &&
147
- `${entry.a2a.chunks} chunks`,
148
- ]
149
- .filter(Boolean)
150
- .join(' · ') })), entry.error && (_jsx(Text, { sx: { color: 'danger.fg', fontSize: 0 }, children: entry.error })), entry.payload !== undefined && (_jsx(Payload, { title: entry.kind === 'tool-call' ? 'Arguments' : 'Payload', value: entry.payload, large: large })), entry.result !== undefined && (_jsx(Payload, { title: "Result", value: entry.result, large: large })), entry.events.length > 0 && (_jsx(Payload, { title: "Events", value: entry.events, large: large })), entry.links.length > 0 && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["Linked: ", entry.links.join(', ')] }))] }))] }));
151
- }
152
- /** Save a session as a JSON file. */
153
- function download(name, session) {
154
- const blob = new Blob([JSON.stringify(session, null, 2)], {
155
- type: 'application/json',
156
- });
157
- const url = URL.createObjectURL(blob);
158
- const link = document.createElement('a');
159
- link.href = url;
160
- link.download = `${name}.json`;
161
- link.click();
162
- setTimeout(() => URL.revokeObjectURL(url), 1000);
4
+ import { AGENT_SPAN_ATTRIBUTES, SPAN_SOURCE_LABELS, describeAgentSpan, sourceOfSpan, } from './agentSpans';
5
+ /** The Inspector's filters: where a span comes from, what it does, which agent. */
6
+ export const AGENT_INSPECTOR_FACETS = [
7
+ {
8
+ label: 'Source',
9
+ value: sourceOfSpan,
10
+ name: value => SPAN_SOURCE_LABELS[value] ?? value,
11
+ },
12
+ {
13
+ label: 'Operation',
14
+ value: span => {
15
+ const attributes = span.attributes ?? {};
16
+ const operation = attributes[AGENT_SPAN_ATTRIBUTES.operation] ?? attributes['rpc.method'];
17
+ return operation === undefined ? undefined : String(operation);
18
+ },
19
+ },
20
+ { label: 'Agent', value: span => span.service_name },
21
+ ];
22
+ /** A span's mark: its tool's, as the catalogue gives it. */
23
+ function spanMark(span) {
24
+ const icon = span.attributes?.[AGENT_SPAN_ATTRIBUTES.markIcon];
25
+ const emoji = span.attributes?.[AGENT_SPAN_ATTRIBUTES.markEmoji];
26
+ return icon || emoji ? (_jsx(SpecMark, { icon: typeof icon === 'string' ? icon : undefined, emoji: typeof emoji === 'string' ? emoji : undefined, size: 14 })) : null;
163
27
  }
164
28
  /** The Agent Inspector. */
165
- export function AgentInspector({ sink, entries: given, maxHeight = 420, largeBytes = 16_000, emptyText = 'Nothing recorded yet.', exportName = 'agent-inspector', agent, }) {
166
- const live = useAgentInspectorEntries(sink);
167
- const everything = given ?? live;
168
- const all = useMemo(() => agent
169
- ? everything.filter(entry => isAgentsEntry(entry, agent))
170
- : everything, [everything, agent]);
171
- const [held, setHeld] = useState(null);
172
- const [clearedAt, setClearedAt] = useState(0);
173
- const [sources, setSources] = useState(new Set());
174
- const [kinds, setKinds] = useState(new Set());
175
- const [actors, setActors] = useState(new Set());
176
- const [open, setOpen] = useState(new Set());
177
- const recorded = useMemo(() => (clearedAt ? all.filter(entry => entry.at >= clearedAt) : all), [all, clearedAt]);
178
- const shown = held ?? recorded;
179
- const waiting = held ? recorded.length - held.length : 0;
180
- const kindOptions = useMemo(() => [...new Set(recorded.map(entry => entry.kind))].sort(), [recorded]);
181
- const actorOptions = useMemo(() => [...new Set(recorded.map(entry => entry.actor))].sort(), [recorded]);
182
- const sourceOptions = useMemo(() => AGENT_INSPECTOR_SOURCES.filter(source => recorded.some(entry => entry.source === source)), [recorded]);
183
- const rows = useMemo(() => filterEntries(shown, { sources, kinds, actors }), [shown, sources, kinds, actors]);
184
- const first = shown[0]?.at ?? 0;
185
- return (_jsxs(Box, { "data-agent-inspector": "", sx: {
186
- border: '1px solid',
187
- borderColor: 'border.default',
188
- borderRadius: 2,
189
- bg: 'canvas.default',
190
- color: 'fg.default',
191
- minWidth: 0,
192
- }, children: [_jsxs(Box, { role: "toolbar", "aria-label": agent ? `${agent}'s Agent Inspector` : 'Agent Inspector', sx: {
193
- display: 'flex',
194
- flexWrap: 'wrap',
195
- gap: 2,
196
- alignItems: 'center',
197
- p: 2,
198
- borderBottom: '1px solid',
199
- borderColor: 'border.default',
200
- }, children: [_jsx(FilterMenu, { label: "Source", options: sourceOptions, selected: sources, onToggle: value => setSources(toggle(sources, value)), onAll: () => setSources(new Set()), name: value => AGENT_INSPECTOR_SOURCE_LABELS[value] }), _jsx(FilterMenu, { label: "Kind", options: kindOptions, selected: kinds, onToggle: value => setKinds(toggle(kinds, value)), onAll: () => setKinds(new Set()), name: value => value }), _jsx(FilterMenu, { label: "Actor", options: actorOptions, selected: actors, onToggle: value => setActors(toggle(actors, value)), onAll: () => setActors(new Set()), name: value => value }), _jsx(Box, { sx: { flex: 1 } }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, "data-inspector-count": "", children: [rows.length === shown.length
201
- ? `${rows.length} ${rows.length === 1 ? 'entry' : 'entries'}`
202
- : `${rows.length} of ${shown.length}`, waiting > 0 ? ` · ${waiting} new` : ''] }), _jsx(Button, { size: "small", leadingVisual: held ? PlayIcon : PauseIcon, "aria-pressed": held !== null, onClick: () => setHeld(held ? null : recorded), "data-inspector-pause": "", children: held ? 'Resume' : 'Pause' }), _jsx(Button, { size: "small", leadingVisual: TrashIcon, onClick: () => {
203
- setOpen(new Set());
204
- setHeld(null);
205
- // One agent's view of a shared record clears only itself.
206
- if (sink && !given && !agent) {
207
- sink.clear();
208
- }
209
- else {
210
- setClearedAt(Date.now());
211
- }
212
- }, "data-inspector-clear": "", children: "Clear" }), _jsx(Button, { size: "small", leadingVisual: DownloadIcon, disabled: !recorded.length, onClick: () => download(exportName, exportEntries(recorded)), "data-inspector-export": "", children: "Export" })] }), _jsx(Box, { as: "ol", "aria-label": "Recorded", sx: { m: 0, p: 0, maxHeight, overflowY: 'auto' }, children: rows.length === 0 ? (_jsx(Text, { as: "li", sx: {
213
- display: 'block',
214
- p: 3,
215
- color: 'fg.muted',
216
- fontSize: 1,
217
- listStyle: 'none',
218
- }, children: emptyText })) : (rows.map(entry => (_jsx(Row, { entry: entry, first: first, large: largeBytes, agent: agent, open: open.has(entry.id), onToggle: () => setOpen(toggle(open, entry.id)) }, entry.id)))) })] }));
29
+ export function AgentInspector({ tracer, spans, agent, maxHeight = 420, compact = false, emptyText = 'Nothing recorded yet.', exportName = 'agent-inspector', }) {
30
+ return (_jsx("div", { "data-agent-inspector": agent ?? '', children: _jsx(OtelLiveSpans, { tracer: tracer, spans: spans, service: agent, facets: AGENT_INSPECTOR_FACETS, compact: compact, maxHeight: maxHeight, detailPlacement: "side", emptyText: emptyText, exportName: exportName, label: agent ? `${agent}'s Agent Inspector` : 'Agent Inspector', renderSpanMark: spanMark, describeSpan: describeAgentSpan }) }));
219
31
  }
220
32
  export default AgentInspector;
@@ -1,19 +1,19 @@
1
1
  /**
2
2
  * The Agent Inspector over the page: a large dialog, the inspector loaded
3
- * only when it opens, fed by the sink the agent's chat or team feeds. Esc
4
- * closes it.
3
+ * only when it opens, drawing the spans the agent's chat or team records
4
+ * into its tracer. Esc closes it.
5
5
  *
6
6
  * @module components/inspector/AgentInspectorDialog
7
7
  */
8
8
  import type { JSX } from 'react';
9
- import type { AgentInspectorSink } from './agentInspector';
9
+ import type { OtelLiveTracer } from '@datalayer/core/lib/otel/live';
10
10
  export type AgentInspectorDialogProps = {
11
- sink: AgentInspectorSink | null;
11
+ tracer: OtelLiveTracer | null;
12
12
  /** The dialog's title. */
13
13
  title?: string;
14
- /** One agent's own record (`AgentInspector`'s `agent`); all of it without. */
14
+ /** One agent's own spans (`AgentInspector`'s `agent`); all of them without. */
15
15
  agent?: string;
16
16
  onClose: () => void;
17
17
  };
18
- export declare function AgentInspectorDialog({ sink, title, agent, onClose, }: AgentInspectorDialogProps): JSX.Element;
18
+ export declare function AgentInspectorDialog({ tracer, title, agent, onClose, }: AgentInspectorDialogProps): JSX.Element;
19
19
  export default AgentInspectorDialog;
@@ -3,7 +3,7 @@ import { Suspense, lazy } from 'react';
3
3
  import { Dialog } from '@primer/react';
4
4
  import { Text } from '@primer/react';
5
5
  const AgentInspector = lazy(() => import('./AgentInspector'));
6
- export function AgentInspectorDialog({ sink, title = 'Agent Inspector', agent, onClose, }) {
7
- return (_jsx(Dialog, { title: title, onClose: onClose, width: "xlarge", height: "large", "data-agent-inspector-dialog": "", children: _jsx(Suspense, { fallback: _jsx(Text, { sx: { color: 'fg.muted' }, children: "Loading the Agent Inspector\u2026" }), children: _jsx(AgentInspector, { sink: sink, agent: agent, maxHeight: "calc(80vh - 140px)", emptyText: "Nothing recorded yet: what the agent does shows here as it does it." }) }) }));
6
+ export function AgentInspectorDialog({ tracer, title = 'Agent Inspector', agent, onClose, }) {
7
+ return (_jsx(Dialog, { title: title, onClose: onClose, width: "xlarge", height: "large", "data-agent-inspector-dialog": "", children: _jsx(Suspense, { fallback: _jsx(Text, { sx: { color: 'fg.muted' }, children: "Loading the Agent Inspector\u2026" }), children: _jsx(AgentInspector, { tracer: tracer, agent: agent, maxHeight: "calc(80vh - 140px)", emptyText: "Nothing recorded yet: what the agent does shows here as it does it." }) }) }));
8
8
  }
9
9
  export default AgentInspectorDialog;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The A2A traffic between two agents, as OpenTelemetry spans: a fetch that
3
+ * hands every request on and records each JSON-RPC request as a client span
4
+ * of the asker's — `a2a <method>`, with the RPC conventions (`rpc.system`
5
+ * `jsonrpc`, `rpc.service` `a2a`, `rpc.method`, `rpc.jsonrpc.request_id`),
6
+ * the agent asked as `peer.service`, the request whole (`a2a.request`) and
7
+ * its words (`a2a.message.text`) — and what came back as its events: a
8
+ * JSON-RPC response, or each server-sent event of a stream (`a2a.task`,
9
+ * `a2a.status_update`, `a2a.artifact_update`, `a2a.message`, `a2a.error`),
10
+ * each with its task, context and state, and the event whole (`a2a.event`).
11
+ * The text chunks of one artifact are one event, their count kept.
12
+ *
13
+ * Any other request (the agent card) is a client span too: `a2a agent card`
14
+ * when it brings one back, its name and skills with it.
15
+ *
16
+ * A peer served by agent-runtimes tells each tool call of its agent on a
17
+ * `working` status (`{tool_call}`, then `{tool_result}`): each is recorded as
18
+ * an `execute_tool` span of the peer's under the request's span, from its
19
+ * start to its end, an MCP call, a skill, codemode's or a tool its runtime
20
+ * runs, by who claims its name (`datalayer.span.origin` `a2a.status`: the
21
+ * page knows of it from the peer's own words).
22
+ *
23
+ * It sits under the A2A SDK (`ClientFactory`'s `JsonRpcTransportFactory`
24
+ * takes a `fetchImpl`): the SDK reads the response it is handed, and this
25
+ * reads a copy of its body. Nothing it records changes what the SDK sees,
26
+ * and a key sent as a header is never recorded.
27
+ *
28
+ * @module components/inspector/a2aSpans
29
+ */
30
+ import type { OtelLiveTracer } from '@datalayer/core/lib/otel/live';
31
+ import { type ToolClass } from './agentSpans';
32
+ export type A2ASpansOptions = {
33
+ tracer: OtelLiveTracer;
34
+ /** The agent that asks: `Sales`. */
35
+ asker: string;
36
+ /** The agent asked: `Accounting`. */
37
+ peer: string;
38
+ /**
39
+ * Where a peer's tool call comes from — an MCP server's, a skill, … — and
40
+ * its marks (`classifyToolCall`, or a team's `teamToolClassifier`).
41
+ * Without it, a tool the peer's runtime runs.
42
+ */
43
+ classifyTool?: (name: string, args?: Record<string, unknown>) => ToolClass;
44
+ };
45
+ /** The text of an A2A 1.0 message's or artifact's parts, as JSON carries them. */
46
+ export declare function partsText(parts: unknown): string;
47
+ /**
48
+ * A fetch that records the A2A traffic it carries as spans into
49
+ * `options.tracer`, and hands the SDK what the network gave.
50
+ */
51
+ export declare function traceA2AFetch(base: typeof globalThis.fetch, options: A2ASpansOptions): typeof globalThis.fetch;