@datalayer/agent-runtimes 1.3.94 → 1.3.96
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.
- package/dist-embed/chunks/AgentInspector-DaMCROPs.js +1 -0
- package/dist-embed/chunks/{AgentInspectorDialog-LBbHMnDa.js → AgentInspectorDialog-zGMiFR5z.js} +1 -1
- package/dist-embed/chunks/ChatView-DE-jo1oJ.js +288 -0
- package/dist-embed/datalayer-app-main.js +110 -110
- package/dist-embed/datalayer-app.js +1 -1
- package/lib/apps/__tests__/fixtures/sceneCheckCases.json +352 -0
- package/lib/apps/apps/computer.d.ts +25 -1
- package/lib/apps/apps/computer.js +45 -2
- package/lib/apps/apps/sceneChecks.d.ts +92 -0
- package/lib/apps/apps/sceneChecks.js +649 -0
- package/lib/apps/apps/sceneShape.d.ts +8 -0
- package/lib/apps/apps/sceneShape.js +191 -0
- package/lib/apps/apps/sceneYaml.d.ts +64 -0
- package/lib/apps/apps/sceneYaml.js +253 -0
- package/lib/apps/core/canvasParts.d.ts +28 -0
- package/lib/apps/core/canvasParts.js +14 -0
- package/lib/apps/core/index.d.ts +1 -0
- package/lib/apps/core/index.js +2 -0
- package/lib/apps/embed/loader.js +10 -0
- package/lib/apps/plugins/agents/SandboxSelector.js +13 -2
- package/lib/apps/plugins/agents/host.d.ts +2 -0
- package/lib/apps/plugins/agents/host.js +16 -0
- package/lib/apps/plugins/agents/plugin.js +10 -2
- package/lib/apps/plugins/agents/switchable.d.ts +12 -0
- package/lib/apps/plugins/agents/switchable.js +23 -0
- package/lib/apps/plugins/app-computer/AppComputer.js +18 -2
- package/lib/apps/plugins/canvas-parts/index.d.ts +44 -0
- package/lib/apps/plugins/canvas-parts/index.js +209 -0
- package/lib/components/teams/useA2ATeam.js +1 -1
- package/lib/examples/HomeExample.js +1 -1
- package/lib/examples/ScenesExample.d.ts +1 -1
- package/lib/examples/example-selector.js +1 -1
- package/lib/hooks/useAgUi.js +4 -1
- package/lib/protocols/AGUIAdapter.js +5 -1
- package/lib/protocols/agUiRefusal.d.ts +47 -0
- package/lib/protocols/agUiRefusal.js +87 -0
- package/lib/specs/apps.js +32 -24
- package/lib/specs/scenes.js +147 -142
- package/lib/specs/teams/teams.js +13 -13
- package/package.json +3 -1
- package/scripts/dist-embed.mjs +116 -0
- package/scripts/record-scene-checks.py +600 -0
- package/dist-embed/chunks/AgentInspector-DfPciQ79.js +0 -1
- package/dist-embed/chunks/ChatView-BzFbN_mp.js +0 -288
|
@@ -0,0 +1,600 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
# Distributed under the terms of the Modified BSD License.
|
|
4
|
+
|
|
5
|
+
"""Record what ``loop`` refuses of a scene, for every editor of a scene to be held to it.
|
|
6
|
+
|
|
7
|
+
plans/STUDIO.md S-10: one validation over the three — what the spec editor
|
|
8
|
+
refuses, the stage refuses and ``loop`` refuses, in the same words. The
|
|
9
|
+
browser's half is ``src/apps/apps/sceneChecks.ts``; this script
|
|
10
|
+
writes down what agentspecs itself says of the same scenes, and
|
|
11
|
+
``src/apps/__tests__/scene-checks.test.ts`` holds it to it sentence by
|
|
12
|
+
sentence. Two copies of a rule drift unless something compares them.
|
|
13
|
+
|
|
14
|
+
Each case is a scene as a person writes it, in agentspecs' own spelling, so
|
|
15
|
+
the table also exercises the editor's reader (``sceneOfYaml``).
|
|
16
|
+
|
|
17
|
+
Usage:
|
|
18
|
+
python3 scripts/record-scene-checks.py \
|
|
19
|
+
--agentspecs agentspecs \
|
|
20
|
+
--output src/apps/__tests__/fixtures/sceneCheckCases.json
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import argparse
|
|
26
|
+
import json
|
|
27
|
+
import sys
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from typing import Any, Dict, List
|
|
30
|
+
|
|
31
|
+
#: A cast, a setting and a script that parse, as pieces the cases lay over.
|
|
32
|
+
HEAD = """schema: loop.scene/v1
|
|
33
|
+
id: probe
|
|
34
|
+
version: 0.0.1
|
|
35
|
+
name: Probe
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
SALES = """ - member: sales
|
|
39
|
+
app: sales
|
|
40
|
+
role: initiator
|
|
41
|
+
runs_in: runtime
|
|
42
|
+
persona:
|
|
43
|
+
name: Sales
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
BOOKS = """ - member: books
|
|
47
|
+
app: accounting
|
|
48
|
+
role: contributor
|
|
49
|
+
runs_in: runtime
|
|
50
|
+
persona:
|
|
51
|
+
name: Accounting
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
ODOO = """ - member: odoo
|
|
55
|
+
server: odoo-accounting
|
|
56
|
+
persona:
|
|
57
|
+
name: Odoo
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
#: One member reaching one system of the setting, for the tool cases.
|
|
61
|
+
TOOL_SCENE = (
|
|
62
|
+
HEAD
|
|
63
|
+
+ "entry: {member}\ncast:\n - member: {member}\n app: {app}\n role: contributor\n"
|
|
64
|
+
+ " runs_in: runtime\n persona:\n name: {persona}\n"
|
|
65
|
+
+ "setting:\n systems:\n - server: {server}\n as: Odoo\n"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
#: Each case: its name, and the scene as it is written.
|
|
69
|
+
CASES: List[Dict[str, str]] = [
|
|
70
|
+
{
|
|
71
|
+
"name": "a scene with nobody on stage",
|
|
72
|
+
"yaml": HEAD,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "the entry is not in the cast",
|
|
76
|
+
"yaml": HEAD + "entry: nobody\ncast:\n" + SALES,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "the entry is a system",
|
|
80
|
+
"yaml": HEAD + "entry: odoo\ncast:\n" + ODOO,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "a system asks",
|
|
84
|
+
"yaml": HEAD
|
|
85
|
+
+ "entry: sales\ncast:\n"
|
|
86
|
+
+ SALES
|
|
87
|
+
+ ODOO
|
|
88
|
+
+ " talks_to:\n - member: sales\n over: a2a\n",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"name": "a member talks to itself",
|
|
92
|
+
"yaml": HEAD
|
|
93
|
+
+ "entry: sales\ncast:\n"
|
|
94
|
+
+ SALES
|
|
95
|
+
+ " talks_to:\n - member: sales\n over: a2a\n",
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"name": "a member talks to nobody of the cast",
|
|
99
|
+
"yaml": HEAD
|
|
100
|
+
+ "entry: sales\ncast:\n"
|
|
101
|
+
+ SALES
|
|
102
|
+
+ " talks_to:\n - member: ghost\n over: a2a\n",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "a system asked over a2a",
|
|
106
|
+
"yaml": HEAD
|
|
107
|
+
+ "entry: sales\ncast:\n"
|
|
108
|
+
+ SALES
|
|
109
|
+
+ " talks_to:\n - member: odoo\n over: a2a\n"
|
|
110
|
+
+ ODOO,
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"name": "an agent asked over mcp",
|
|
114
|
+
"yaml": HEAD
|
|
115
|
+
+ "entry: sales\ncast:\n"
|
|
116
|
+
+ SALES
|
|
117
|
+
+ " talks_to:\n - member: books\n over: mcp\n"
|
|
118
|
+
+ BOOKS,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"name": "a member named twice",
|
|
122
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES + SALES,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"name": "two beats with one name",
|
|
126
|
+
"yaml": HEAD
|
|
127
|
+
+ "entry: sales\ncast:\n"
|
|
128
|
+
+ SALES
|
|
129
|
+
+ """script:
|
|
130
|
+
- id: open
|
|
131
|
+
cue:
|
|
132
|
+
say: Show the books
|
|
133
|
+
expect: The books are read
|
|
134
|
+
moves:
|
|
135
|
+
- who: sales
|
|
136
|
+
answers: words
|
|
137
|
+
- id: open
|
|
138
|
+
cue:
|
|
139
|
+
say: Show them again
|
|
140
|
+
expect: The books are read again
|
|
141
|
+
moves:
|
|
142
|
+
- who: sales
|
|
143
|
+
answers: words
|
|
144
|
+
""",
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"name": "a member placed outside the box",
|
|
148
|
+
"yaml": HEAD
|
|
149
|
+
+ "entry: sales\ncast:\n"
|
|
150
|
+
+ SALES
|
|
151
|
+
+ "stage:\n positions:\n sales:\n x: 40\n y: 0.5\n",
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"name": "a member that is nothing at all",
|
|
155
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES + " - member: ghost\n",
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"name": "the scene wears a member's face",
|
|
159
|
+
"yaml": HEAD
|
|
160
|
+
+ "emoji: \U0001f9ee\nentry: sales\ncast:\n"
|
|
161
|
+
+ SALES
|
|
162
|
+
+ " face: \U0001f9ee\n",
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"name": "a system of the setting that is no server",
|
|
166
|
+
"yaml": HEAD
|
|
167
|
+
+ "entry: sales\ncast:\n"
|
|
168
|
+
+ SALES
|
|
169
|
+
+ "setting:\n systems:\n - server: nosuch\n as: Nope\n",
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"name": "a system nobody reaches",
|
|
173
|
+
"yaml": HEAD
|
|
174
|
+
+ "entry: sales\ncast:\n"
|
|
175
|
+
+ SALES
|
|
176
|
+
+ "setting:\n systems:\n - server: odoo-accounting\n as: Odoo\n",
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"name": "a system reached through a connection",
|
|
180
|
+
"yaml": HEAD
|
|
181
|
+
+ "entry: books\ncast:\n"
|
|
182
|
+
+ BOOKS
|
|
183
|
+
+ "setting:\n systems:\n - server: odoo-accounting\n as: Odoo\n",
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"name": "a Frame the catalogue has not",
|
|
187
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES + "setting:\n frames:\n - nosuch\n",
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"name": "the stage places someone not in the cast",
|
|
191
|
+
"yaml": HEAD
|
|
192
|
+
+ "entry: sales\ncast:\n"
|
|
193
|
+
+ SALES
|
|
194
|
+
+ "stage:\n positions:\n ghost:\n x: 0.2\n y: 0.4\n",
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"name": "a balloon opens first for someone not in the cast",
|
|
198
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES + "stage:\n opens_first: ghost\n",
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"name": "an address for someone not in the cast",
|
|
202
|
+
"yaml": HEAD
|
|
203
|
+
+ "entry: sales\ncast:\n"
|
|
204
|
+
+ SALES
|
|
205
|
+
+ "deployment:\n addresses:\n ghost: GHOST_URL\n",
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"name": "an address for a member in the browser",
|
|
209
|
+
"yaml": HEAD
|
|
210
|
+
+ "entry: sales\ncast:\n"
|
|
211
|
+
+ SALES.replace("runs_in: runtime", "runs_in: browser")
|
|
212
|
+
+ "deployment:\n addresses:\n sales: SALES_URL\n",
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"name": "visitors may watch and a member has no address",
|
|
216
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES + "audience:\n who: visitors\n",
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"name": "a beat its entry does not answer",
|
|
220
|
+
"yaml": HEAD
|
|
221
|
+
+ "entry: sales\ncast:\n"
|
|
222
|
+
+ SALES
|
|
223
|
+
+ BOOKS
|
|
224
|
+
+ """script:
|
|
225
|
+
- id: open
|
|
226
|
+
cue:
|
|
227
|
+
say: Show the books
|
|
228
|
+
expect: The books are read
|
|
229
|
+
moves:
|
|
230
|
+
- who: books
|
|
231
|
+
answers: table
|
|
232
|
+
""",
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"name": "a beat moved by someone not in the cast",
|
|
236
|
+
"yaml": HEAD
|
|
237
|
+
+ "entry: sales\ncast:\n"
|
|
238
|
+
+ SALES
|
|
239
|
+
+ """script:
|
|
240
|
+
- id: open
|
|
241
|
+
cue:
|
|
242
|
+
say: Show the books
|
|
243
|
+
expect: The books are read
|
|
244
|
+
moves:
|
|
245
|
+
- who: sales
|
|
246
|
+
answers: words
|
|
247
|
+
- who: ghost
|
|
248
|
+
answers: words
|
|
249
|
+
""",
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"name": "a beat moved by a system",
|
|
253
|
+
"yaml": HEAD
|
|
254
|
+
+ "entry: sales\ncast:\n"
|
|
255
|
+
+ SALES
|
|
256
|
+
+ ODOO
|
|
257
|
+
+ """script:
|
|
258
|
+
- id: open
|
|
259
|
+
cue:
|
|
260
|
+
say: Show the books
|
|
261
|
+
expect: The books are read
|
|
262
|
+
moves:
|
|
263
|
+
- who: sales
|
|
264
|
+
answers: words
|
|
265
|
+
- who: odoo
|
|
266
|
+
answers: words
|
|
267
|
+
""",
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"name": "a move that asks someone not in the cast",
|
|
271
|
+
"yaml": HEAD
|
|
272
|
+
+ "entry: sales\ncast:\n"
|
|
273
|
+
+ SALES
|
|
274
|
+
+ """script:
|
|
275
|
+
- id: open
|
|
276
|
+
cue:
|
|
277
|
+
say: Show the books
|
|
278
|
+
expect: The books are read
|
|
279
|
+
moves:
|
|
280
|
+
- who: sales
|
|
281
|
+
asks: ghost
|
|
282
|
+
over: a2a
|
|
283
|
+
what: the books
|
|
284
|
+
""",
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
"name": "a move over mcp that asks no system",
|
|
288
|
+
"yaml": HEAD
|
|
289
|
+
+ "entry: sales\ncast:\n"
|
|
290
|
+
+ SALES
|
|
291
|
+
+ BOOKS
|
|
292
|
+
+ """script:
|
|
293
|
+
- id: open
|
|
294
|
+
cue:
|
|
295
|
+
say: Show the books
|
|
296
|
+
expect: The books are read
|
|
297
|
+
moves:
|
|
298
|
+
- who: sales
|
|
299
|
+
asks: books
|
|
300
|
+
over: mcp
|
|
301
|
+
what: the books
|
|
302
|
+
""",
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"name": "a move over a2a that asks a system",
|
|
306
|
+
"yaml": HEAD
|
|
307
|
+
+ "entry: sales\ncast:\n"
|
|
308
|
+
+ SALES
|
|
309
|
+
+ ODOO
|
|
310
|
+
+ """script:
|
|
311
|
+
- id: open
|
|
312
|
+
cue:
|
|
313
|
+
say: Show the books
|
|
314
|
+
expect: The books are read
|
|
315
|
+
moves:
|
|
316
|
+
- who: sales
|
|
317
|
+
asks: odoo
|
|
318
|
+
over: a2a
|
|
319
|
+
what: the books
|
|
320
|
+
""",
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"name": "a move that asks a member it does not talk to",
|
|
324
|
+
"yaml": HEAD
|
|
325
|
+
+ "entry: sales\ncast:\n"
|
|
326
|
+
+ SALES
|
|
327
|
+
+ BOOKS
|
|
328
|
+
+ """script:
|
|
329
|
+
- id: open
|
|
330
|
+
cue:
|
|
331
|
+
say: Show the books
|
|
332
|
+
expect: The books are read
|
|
333
|
+
moves:
|
|
334
|
+
- who: sales
|
|
335
|
+
asks: books
|
|
336
|
+
over: a2a
|
|
337
|
+
what: the books
|
|
338
|
+
""",
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
"name": "a branch that goes on to no beat",
|
|
342
|
+
"yaml": HEAD
|
|
343
|
+
+ "entry: sales\ncast:\n"
|
|
344
|
+
+ SALES
|
|
345
|
+
+ """script:
|
|
346
|
+
- id: open
|
|
347
|
+
cue:
|
|
348
|
+
say: Show the books
|
|
349
|
+
expect: The books are read
|
|
350
|
+
moves:
|
|
351
|
+
- who: sales
|
|
352
|
+
answers: words
|
|
353
|
+
branch:
|
|
354
|
+
- decision: there is nothing to read
|
|
355
|
+
expect: it says so
|
|
356
|
+
then: nowhere
|
|
357
|
+
""",
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
"name": "a rehearsal of a beat that is not in the script",
|
|
361
|
+
"yaml": HEAD
|
|
362
|
+
+ "entry: sales\ncast:\n"
|
|
363
|
+
+ SALES
|
|
364
|
+
+ """rehearsal:
|
|
365
|
+
beats:
|
|
366
|
+
- beat: nowhere
|
|
367
|
+
lines:
|
|
368
|
+
- 'You → Sales'
|
|
369
|
+
""",
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
"name": "a rehearsal that names a beat twice",
|
|
373
|
+
"yaml": HEAD
|
|
374
|
+
+ "entry: sales\ncast:\n"
|
|
375
|
+
+ SALES
|
|
376
|
+
+ """script:
|
|
377
|
+
- id: open
|
|
378
|
+
cue:
|
|
379
|
+
say: Show the books
|
|
380
|
+
expect: The books are read
|
|
381
|
+
moves:
|
|
382
|
+
- who: sales
|
|
383
|
+
answers: words
|
|
384
|
+
rehearsal:
|
|
385
|
+
beats:
|
|
386
|
+
- beat: open
|
|
387
|
+
lines:
|
|
388
|
+
- 'You → Sales'
|
|
389
|
+
- beat: open
|
|
390
|
+
lines:
|
|
391
|
+
- 'Sales: a table'
|
|
392
|
+
""",
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
"name": "a rehearsal that names someone not on stage",
|
|
396
|
+
"yaml": HEAD
|
|
397
|
+
+ "entry: sales\ncast:\n"
|
|
398
|
+
+ SALES
|
|
399
|
+
+ """script:
|
|
400
|
+
- id: open
|
|
401
|
+
cue:
|
|
402
|
+
say: Show the books
|
|
403
|
+
expect: The books are read
|
|
404
|
+
moves:
|
|
405
|
+
- who: sales
|
|
406
|
+
answers: words
|
|
407
|
+
rehearsal:
|
|
408
|
+
beats:
|
|
409
|
+
- beat: open
|
|
410
|
+
lines:
|
|
411
|
+
- 'You → Stranger'
|
|
412
|
+
""",
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
"name": "a scene that plays",
|
|
416
|
+
"yaml": HEAD
|
|
417
|
+
+ "entry: sales\ncast:\n"
|
|
418
|
+
+ SALES
|
|
419
|
+
+ " talks_to:\n - member: books\n over: a2a\n"
|
|
420
|
+
+ BOOKS
|
|
421
|
+
+ """setting:
|
|
422
|
+
systems:
|
|
423
|
+
- server: odoo-accounting
|
|
424
|
+
as: Odoo
|
|
425
|
+
holds: Datalayer's books
|
|
426
|
+
stage:
|
|
427
|
+
positions:
|
|
428
|
+
sales:
|
|
429
|
+
x: 0
|
|
430
|
+
y: 0
|
|
431
|
+
books:
|
|
432
|
+
x: 0.5
|
|
433
|
+
y: 0
|
|
434
|
+
opens_first: sales
|
|
435
|
+
script:
|
|
436
|
+
- id: open
|
|
437
|
+
cue:
|
|
438
|
+
say: Show the books
|
|
439
|
+
expect: The books are read
|
|
440
|
+
moves:
|
|
441
|
+
- who: sales
|
|
442
|
+
asks: books
|
|
443
|
+
over: a2a
|
|
444
|
+
what: the open invoices
|
|
445
|
+
- who: sales
|
|
446
|
+
answers: table
|
|
447
|
+
rehearsal:
|
|
448
|
+
beats:
|
|
449
|
+
- beat: open
|
|
450
|
+
lines:
|
|
451
|
+
- 'You → Sales'
|
|
452
|
+
- 'Sales → Accounting'
|
|
453
|
+
- 'Sales: a table'
|
|
454
|
+
""",
|
|
455
|
+
},
|
|
456
|
+
# --- a cast under a team of the catalogue: personas and briefs only ---
|
|
457
|
+
# The team says who its members are; a scene that names it says how each
|
|
458
|
+
# is played, and nothing of what each is (`scene_problems`).
|
|
459
|
+
{
|
|
460
|
+
"name": "a scene of a team that plays",
|
|
461
|
+
"yaml": HEAD + "team: sales-and-accounting\ncast:\n - member: sales\n persona:\n name: Sales\n brief: Ask for the open invoices.\n",
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
"name": "a cast under a team names someone not in it",
|
|
465
|
+
"yaml": HEAD + "team: sales-and-accounting\ncast:\n - member: ghost\n persona:\n name: Ghost\n",
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
"name": "a cast under a team says what a member is",
|
|
469
|
+
"yaml": HEAD + "team: sales-and-accounting\ncast:\n - member: sales\n app: sales\n persona:\n name: Sales\n",
|
|
470
|
+
},
|
|
471
|
+
# --- a tool a system is asked for: offered, offered for this, reached ---
|
|
472
|
+
# What agentspecs reads of the catalogue's servers and connections
|
|
473
|
+
# (`_tool_problem`): on a move of the script, and on a rehearsal's line.
|
|
474
|
+
{
|
|
475
|
+
"name": "a move asks a system for a tool it does not offer",
|
|
476
|
+
"yaml": TOOL_SCENE.format(member="books", app="accounting", persona="Accounting", server="odoo-accounting")
|
|
477
|
+
+ "script:\n - id: open\n cue:\n say: Show the books\n expect: It is answered\n moves:\n"
|
|
478
|
+
+ " - who: books\n asks: odoo-accounting\n over: mcp\n tool: odoo_accounting_burn_the_books\n",
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
"name": "a move asks for a tool to do what it does not",
|
|
482
|
+
"yaml": TOOL_SCENE.format(member="crop", app="crop-monitoring", persona="Crop", server="earthdata")
|
|
483
|
+
+ "script:\n - id: look\n cue:\n say: What is there\n expect: It is answered\n moves:\n"
|
|
484
|
+
+ " - who: crop\n asks: earthdata\n over: mcp\n tool: download_earth_data_granules\n does: read\n",
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
"name": "a move asks for a tool no connection of the member offers",
|
|
488
|
+
"yaml": TOOL_SCENE.format(member="inbox", app="inbox-triage", persona="Inbox", server="google-workspace")
|
|
489
|
+
+ "script:\n - id: mail\n cue:\n say: What came in\n expect: It is answered\n moves:\n"
|
|
490
|
+
+ " - who: inbox\n asks: google-workspace\n over: mcp\n tool: list_calendar_events\n",
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
"name": "a rehearsal expects a tool a system does not offer",
|
|
494
|
+
"yaml": TOOL_SCENE.format(member="books", app="accounting", persona="Accounting", server="odoo-accounting")
|
|
495
|
+
+ "script:\n - id: open\n cue:\n say: Show the books\n expect: It is answered\n moves:\n"
|
|
496
|
+
+ " - who: books\n answers: table\n"
|
|
497
|
+
+ "rehearsal:\n beats:\n - beat: open\n lines:\n"
|
|
498
|
+
+ " - 'Accounting → Odoo: odoo_accounting_burn_the_books'\n"
|
|
499
|
+
+ " - 'Accounting: a table'\n",
|
|
500
|
+
},
|
|
501
|
+
# --- the shape of a scene: what pydantic refuses before any rule is read ---
|
|
502
|
+
# Each mistyped once, as a person typing a scene by hand does. agentspecs
|
|
503
|
+
# reports every issue pydantic finds, joined by "; ", and its after
|
|
504
|
+
# validators never run on a scene of the wrong shape.
|
|
505
|
+
{
|
|
506
|
+
"name": "a cast that is a word",
|
|
507
|
+
"yaml": HEAD + "entry: sales\ncast: sales\n",
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
"name": "a name that is a number",
|
|
511
|
+
"yaml": HEAD.replace("name: Probe", "name: 123") + "entry: sales\ncast:\n" + SALES,
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
"name": "a scene with no name",
|
|
515
|
+
"yaml": HEAD.replace("name: Probe\n", "") + "entry: sales\ncast:\n" + SALES,
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
"name": "a field the spec does not have",
|
|
519
|
+
"yaml": HEAD + "colour: red\nentry: sales\ncast:\n" + SALES,
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
"name": "a member with a field it does not have",
|
|
523
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES + " mood: happy\n",
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
"name": "a member running nowhere",
|
|
527
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES.replace("runs_in: runtime", "runs_in: nowhere"),
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
"name": "a member's role nobody plays",
|
|
531
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES.replace("role: initiator", "role: boss"),
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
"name": "an audience that is a word",
|
|
535
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES + "audience: everyone\n",
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
"name": "an audience nobody can be",
|
|
539
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES + "audience:\n who: nobody-at-all\n",
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
"name": "a ceiling below nothing",
|
|
543
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES + "audience:\n ceiling_per_ask: -1\n",
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
"name": "a ceiling that is no number",
|
|
547
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES + "audience:\n ceiling_per_ask: lots\n",
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
"name": "a rehearsal bound that is no duration",
|
|
551
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES + "rehearsal:\n within: soon\n",
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
"name": "a stage that is a list",
|
|
555
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES + "stage: []\n",
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
"name": "places that are a word",
|
|
559
|
+
"yaml": HEAD + "entry: sales\ncast:\n" + SALES + "stage:\n positions: everywhere\n",
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
"name": "two things wrong at once",
|
|
563
|
+
"yaml": HEAD + "entry: sales\ncast: sales\nrehearsal:\n within: soon\n",
|
|
564
|
+
},
|
|
565
|
+
]
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
def main() -> int:
|
|
569
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
570
|
+
parser.add_argument("--agentspecs", type=Path, required=True, help="The agentspecs clone to read the checks from")
|
|
571
|
+
parser.add_argument("--output", type=Path, required=True, help="The JSON table the browser's checks are held to")
|
|
572
|
+
args = parser.parse_args()
|
|
573
|
+
|
|
574
|
+
sys.path.insert(0, str(args.agentspecs.resolve()))
|
|
575
|
+
import yaml # noqa: PLC0415
|
|
576
|
+
from agentspecs.scenes import SceneError, parse_scene, scene_problems # noqa: PLC0415
|
|
577
|
+
|
|
578
|
+
recorded: List[Dict[str, Any]] = []
|
|
579
|
+
for case in CASES:
|
|
580
|
+
data = yaml.safe_load(case["yaml"])
|
|
581
|
+
try:
|
|
582
|
+
scene = parse_scene(data)
|
|
583
|
+
except SceneError as error:
|
|
584
|
+
says = [str(error)]
|
|
585
|
+
else:
|
|
586
|
+
says = scene_problems(scene)
|
|
587
|
+
recorded.append({"name": case["name"], "yaml": case["yaml"], "says": says})
|
|
588
|
+
|
|
589
|
+
table = {
|
|
590
|
+
"says": "What `loop` refuses of a scene, recorded from agentspecs (plans/STUDIO.md S-10).",
|
|
591
|
+
"recordedWith": "scripts/record-scene-checks.py",
|
|
592
|
+
"cases": recorded,
|
|
593
|
+
}
|
|
594
|
+
args.output.write_text(json.dumps(table, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
|
|
595
|
+
print(f"{len(recorded)} cases written to {args.output}")
|
|
596
|
+
return 0
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
if __name__ == "__main__":
|
|
600
|
+
raise SystemExit(main())
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as f,j as e,bp as l,cP as re,eI as ie,T as c,bm as W,cO as F,L as D,I as oe,eJ as le,eK as V,c as U,P as ae,eL as de,k as ce,eM as ue,dw as H,bd as M,eN as xe,eO as fe,eP as K,eQ as pe,eR as he}from"../datalayer-app-main.js";import{B as $,U as B}from"./index-Begrz6qi.js";function E(t){const n=Number(t);return!isNaN(n)&&n>1e15?n/1e6:!isNaN(n)&&n>1e12?n/1e3:isNaN(n)?new Date(String(t)).getTime():n}function J(t){return t==null?"—":t<.001?"<1µs":t<1?`${(t*1e3).toFixed(0)}µs`:t<1e3?`${t.toFixed(1)}ms`:t<6e4?`${(t/1e3).toFixed(2)}s`:`${(t/6e4).toFixed(1)}m`}function me(t){if(t==null||t==="")return"—";try{const n=E(t),s=new Date(n);return isNaN(s.getTime())?String(t):s.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",second:"2-digit",fractionalSecondDigits:3})}catch{return String(t)}}const X=["#0969da","#1a7f37","#cf222e","#8250df","#bf8700","#0550ae","#116329","#a40e26","#6639ba","#953800","#0e8a16","#e36209"];function ge(t){let n=0;for(let s=0;s<t.length;s++)n=n*31+t.charCodeAt(s)|0;return X[Math.abs(n)%X.length]}function Q(t){const n=new Map,s=t.map(o=>({...o,children:[],depth:0}));for(const o of s)n.set(o.span_id,o);const r=[];for(const o of s)if(o.parent_span_id&&n.has(o.parent_span_id)){const x=n.get(o.parent_span_id);x.children=x.children??[],x.children.push(o)}else r.push(o);function a(o,x){o.depth=x;for(const p of o.children??[])a(p,x+1)}for(const o of r)a(o,0);return r}const be="peer.service";function je(t,n){return t.service_name===n||t.attributes?.[be]===n}function Se(t,n){return n?t.filter(s=>je(s,n)):[...t]}const Y=[],_e=()=>()=>{};function we(t){return f.useSyncExternalStore(t?t.subscribe:_e,()=>t?t.spans():Y,()=>t?t.spans():Y)}const ye="140px 1fr 160px 90px",ve="96px minmax(0, 1fr) 96px 64px";function ke(t){const n=t.attributes;if(!n)return null;const s=n["gen_ai.usage.input_tokens"]!=null?Number(n["gen_ai.usage.input_tokens"]):void 0,r=n["gen_ai.usage.output_tokens"]!=null?Number(n["gen_ai.usage.output_tokens"]):void 0;return s==null&&r==null?null:{input:s,output:r}}const Ce=({spans:t,loading:n,selectedSpanId:s,onSelectSpan:r,emptyText:a,compact:o=!1,defaultExpanded:x=!1,renderSpanMark:p,describeSpan:u})=>{const[h,d]=f.useState(new Set),m=f.useMemo(()=>({has:i=>x?!h.has(i):h.has(i)}),[h,x]),j=o?ve:ye,S=f.useMemo(()=>Q(t),[t]),g=f.useMemo(()=>{const i=[];function y(b,A){const v=b.children??[];if(i.push({span:b,depth:A,hasChildren:v.length>0}),m.has(b.span_id))for(const T of v)y(T,A+1)}for(const b of S)y(b,0);return i},[S,m]),O=f.useCallback(i=>{d(y=>{const b=new Set(y);return b.has(i)?b.delete(i):b.add(i),b})},[]);return n?e.jsx(l,{sx:{display:"flex",justifyContent:"center",p:5},children:e.jsx(re,{size:"medium"})}):t.length===0?e.jsxs($,{children:[e.jsx($.Visual,{children:e.jsx(ie,{size:24})}),e.jsx($.Heading,{children:"No traces found"}),e.jsx($.Description,{children:a??"Send some telemetry data first."})]}):e.jsxs(l,{sx:{width:"100%",flex:1,minHeight:0,overflow:"auto"},children:[e.jsx(l,{sx:{display:"grid",gridTemplateColumns:j,gap:2,px:3,position:"sticky",top:0,bg:"canvas.subtle",zIndex:1,borderBottom:"2px solid",borderColor:"border.default"},children:["Time","Message","Scope","Duration"].map(i=>e.jsx(c,{sx:{fontWeight:"bold",fontSize:0,color:"fg.muted",textTransform:"uppercase",letterSpacing:"0.05em",py:2,...i==="Duration"?{textAlign:"right"}:{}},children:i},i))}),g.map(({span:i,depth:y,hasChildren:b},A)=>{const v=s===i.span_id,T=m.has(i.span_id),C=y*(o?12:20),k=u?.(i);return e.jsxs(l,{"data-otel-span":i.span_id,"data-otel-span-name":i.span_name,onClick:()=>{b&&O(i.span_id),r?.(i)},sx:{display:"grid",gridTemplateColumns:j,gap:2,px:3,py:"5px",cursor:"pointer",bg:v?"accent.subtle":y>0?"canvas.inset":"canvas.default",borderBottom:"1px solid",borderColor:"border.muted",":hover":{bg:v?"accent.subtle":"canvas.subtle"}},children:[e.jsx(c,{sx:{fontSize:o?0:1,fontFamily:"mono",color:"fg.muted",whiteSpace:"nowrap",lineHeight:"22px"},children:me(i.start_time)}),e.jsxs(l,{sx:{display:"flex",alignItems:"center",gap:1,overflow:"hidden",lineHeight:"22px",pl:`${C}px`},children:[b?e.jsx(l,{sx:{flexShrink:0,color:"fg.muted",display:"flex",alignItems:"center"},children:T?e.jsx(W,{size:14}):e.jsx(F,{size:14})}):y>0?e.jsx(l,{sx:{flexShrink:0,width:"14px",display:"flex",alignItems:"center",justifyContent:"center",color:"fg.subtle",fontSize:0},children:"─"}):null,p?.(i),e.jsx(c,{sx:{fontSize:1,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",flexShrink:k?0:1,maxWidth:k?"60%":void 0},title:i.span_name,children:i.span_name}),i.in_progress&&e.jsx(D,{variant:"attention",size:"small",children:"running"}),i.status_code==="ERROR"&&e.jsx(D,{variant:"danger",size:"small",children:"ERROR"}),(()=>{const I=ke(i);return I?e.jsxs(l,{sx:{display:"inline-flex",alignItems:"center",gap:"2px",border:"1px solid",borderColor:"border.default",borderRadius:2,px:1,fontSize:"10px",fontFamily:"mono",color:"fg.muted",flexShrink:0,lineHeight:"16px"},children:[I.input!=null&&e.jsxs(l,{sx:{display:"inline-flex",alignItems:"center",gap:"1px"},children:[e.jsx(c,{sx:{fontSize:"9px",color:"fg.subtle"},children:"↗"}),e.jsx(c,{children:I.input})]}),I.output!=null&&e.jsxs(l,{sx:{display:"inline-flex",alignItems:"center",gap:"1px"},children:[e.jsx(c,{sx:{fontSize:"9px",color:"fg.subtle"},children:"↙"}),e.jsx(c,{children:I.output})]})]}):null})(),k&&e.jsx(c,{sx:{fontSize:1,color:"fg.muted",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",minWidth:0},title:k,"data-otel-span-description":"",children:k}),i.otel_scope_name&&!o&&e.jsx(D,{size:"small",variant:"secondary",sx:{flexShrink:0,fontSize:"10px"},children:i.otel_scope_name})]}),e.jsx(c,{sx:{fontSize:1,color:"fg.muted",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",lineHeight:"22px"},title:`${i.service_name} / ${i.otel_scope_name??""}`,children:i.service_name}),e.jsx(c,{sx:{fontSize:1,fontFamily:"mono",textAlign:"right",lineHeight:"22px",color:i.duration_ms!=null&&i.duration_ms>1e3?"danger.fg":"fg.default"},children:i.in_progress?"…":J(i.duration_ms)})]},`${i.trace_id}-${i.span_id}-${A}`)})]})},ze=20,Z=({span:t,depth:n,selectedSpanId:s,onSelectSpan:r,expandedIds:a,toggleExpanded:o,traceMinTime:x,traceDuration:p})=>{const u=(t.children?.length??0)>0,h=a.has(t.span_id),d=s===t.span_id,m=ge(t.service_name),j=(E(t.start_time)-x)/p*100,S=Math.max((t.duration_ms||0)/p*100,.5);return e.jsxs(e.Fragment,{children:[e.jsxs(l,{sx:{display:"flex",alignItems:"center",height:28,pl:`${n*ze}px`,pr:2,cursor:"pointer",bg:d?"accent.subtle":"canvas.default",borderBottom:"1px solid",borderColor:"border.muted",":hover":{bg:d?"accent.subtle":"canvas.subtle"}},onClick:()=>r?.(t),children:[e.jsx(l,{sx:{width:20,textAlign:"center",color:"fg.muted",userSelect:"none",flexShrink:0,cursor:u?"pointer":"default"},onClick:g=>{g.stopPropagation(),u&&o(t.span_id)},children:u?h?e.jsx(W,{size:12}):e.jsx(F,{size:12}):e.jsx(c,{sx:{color:"fg.subtle",fontSize:0},children:"·"})}),e.jsx(l,{sx:{width:8,height:8,borderRadius:"50%",bg:m,flexShrink:0,mr:1}}),e.jsx(c,{sx:{flex:"0 0 200px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",fontSize:1,fontWeight:d?"bold":"normal"},title:`${t.service_name} / ${t.span_name}`,children:t.span_name}),e.jsx(l,{sx:{flex:1,position:"relative",height:12,bg:"canvas.subtle",borderRadius:1,mx:2,overflow:"hidden"},children:e.jsx(l,{sx:{position:"absolute",left:`${j}%`,width:`${S}%`,height:"100%",bg:m,borderRadius:1,opacity:d?1:.7}})}),e.jsx(c,{sx:{minWidth:60,textAlign:"right",fontSize:0,fontFamily:"mono",color:"fg.muted",flexShrink:0},children:J(t.duration_ms)})]}),u&&h&&t.children.map(g=>e.jsx(Z,{span:g,depth:n+1,selectedSpanId:s,onSelectSpan:r,expandedIds:a,toggleExpanded:o,traceMinTime:x,traceDuration:p},g.span_id))]})},Ie=({spans:t,selectedSpanId:n,onSelectSpan:s,defaultExpandDepth:r=2})=>{const a=f.useMemo(()=>{const d=new Set;function m(j,S){for(const g of j)S<r&&d.add(g.span_id),g.children&&m(g.children,S+1)}return m(t,0),d},[t,r]),[o,x]=f.useState(a),p=f.useCallback(d=>{x(m=>{const j=new Set(m);return j.has(d)?j.delete(d):j.add(d),j})},[]),{traceMinTime:u,traceDuration:h}=f.useMemo(()=>{let d=1/0,m=-1/0;function j(S){for(const g of S){const O=E(g.start_time),i=E(g.end_time);O<d&&(d=O),i>m&&(m=i),g.children&&j(g.children)}}return j(t),d===1/0?{traceMinTime:0,traceDuration:1}:{traceMinTime:d,traceDuration:m-d||1}},[t]);return t.length===0?e.jsx(l,{sx:{p:3,color:"fg.muted",textAlign:"center"},children:e.jsx(c,{children:"No span tree to display."})}):e.jsxs(l,{sx:{width:"100%",overflow:"auto"},children:[e.jsxs(l,{sx:{display:"flex",alignItems:"center",height:28,px:2,borderBottom:"2px solid",borderColor:"border.default",bg:"canvas.subtle"},children:[e.jsx(l,{sx:{width:20}}),e.jsx(l,{sx:{width:8,mr:1}}),e.jsx(c,{sx:{flex:"0 0 200px",fontSize:0,fontWeight:"bold",color:"fg.muted",textTransform:"uppercase",letterSpacing:"0.05em"},children:"Span"}),e.jsx(c,{sx:{flex:1,mx:2,fontSize:0,fontWeight:"bold",color:"fg.muted",textTransform:"uppercase",letterSpacing:"0.05em"},children:"Timeline"}),e.jsx(c,{sx:{minWidth:60,textAlign:"right",fontSize:0,fontWeight:"bold",color:"fg.muted",textTransform:"uppercase",letterSpacing:"0.05em"},children:"Duration"})]}),t.map(d=>e.jsx(Z,{span:d,depth:0,selectedSpanId:n,onSelectSpan:s,expandedIds:o,toggleExpanded:p,traceMinTime:u,traceDuration:h},d.span_id))]})},w=({label:t,value:n,mono:s=!1})=>n==null||n===""?null:e.jsxs(l,{sx:{display:"flex",py:1,borderBottom:"1px solid",borderColor:"border.muted",gap:2},children:[e.jsx(c,{sx:{width:140,minWidth:140,color:"fg.muted",fontSize:1,fontWeight:"bold"},children:t}),e.jsx(c,{sx:{fontSize:1,fontFamily:s?"mono":"normal",wordBreak:"break-all"},children:String(n)})]}),q=({title:t,data:n,defaultOpen:s=!1})=>{const[r,a]=f.useState(s);return!n||Object.keys(n).length===0?null:e.jsxs(l,{sx:{mt:3},children:[e.jsxs(l,{sx:{display:"flex",alignItems:"center",gap:1,cursor:"pointer",py:1,userSelect:"none"},onClick:()=>a(!r),children:[r?e.jsx(W,{size:16}):e.jsx(F,{size:16}),e.jsx(c,{sx:{fontSize:1,fontWeight:"bold"},children:t}),e.jsx(V,{children:Object.keys(n).length})]}),r&&e.jsx(l,{sx:{bg:"canvas.subtle",borderRadius:2,border:"1px solid",borderColor:"border.default",p:2,mt:1,overflowX:"auto"},children:Object.entries(n).map(([o,x])=>e.jsx(L,{attrKey:o,value:x,depth:0},o))})]})};function Te(t){if(typeof t!="string")return t;const n=t.trim();if(!/^[[{]/.test(n))return t;try{const s=JSON.parse(n);return typeof s=="object"&&s!==null?s:t}catch{return t}}const L=({attrKey:t,value:n,depth:s})=>{const r=f.useMemo(()=>Te(n),[n]),[a,o]=f.useState(s<1),x=typeof r=="object"&&r!==null&&!Array.isArray(r),p=Array.isArray(r),u=x||p;return e.jsxs(l,{sx:{borderBottom:s===0?"1px solid":"none",borderColor:"border.muted",pb:s===0?1:0,mb:s===0?1:0},children:[e.jsxs(l,{sx:{display:"flex",gap:2,py:1,pl:s*16+"px",alignItems:"flex-start"},children:[u?e.jsx(l,{sx:{cursor:"pointer",color:"fg.muted",userSelect:"none",width:16,flexShrink:0},onClick:()=>o(!a),children:a?e.jsx(W,{size:12}):e.jsx(F,{size:12})}):e.jsx(l,{sx:{width:16,flexShrink:0}}),e.jsx(c,{sx:{color:"accent.fg",fontSize:1,fontFamily:"mono",minWidth:180,wordBreak:"break-all",flexShrink:0},children:t}),!u&&e.jsx(c,{sx:{fontSize:1,fontFamily:"mono",whiteSpace:"pre-wrap",wordBreak:"break-word",color:typeof r=="string"?"accent.emphasis":"attention.fg"},children:typeof r=="string"?r:JSON.stringify(r)}),u&&!a&&e.jsx(c,{sx:{fontSize:0,color:"fg.muted",fontFamily:"mono"},children:p?`[${r.length} items]`:`{${Object.keys(r).length} keys}`})]}),u&&a&&e.jsx(l,{children:p?r.map((h,d)=>e.jsx(L,{attrKey:`[${d}]`,value:h,depth:s+1},d)):Object.entries(r).map(([h,d])=>e.jsx(L,{attrKey:h,value:d,depth:s+1},h))})]})},Oe=({span:t,traceSpans:n,onClose:s})=>{const[r,a]=f.useState("details");if(!t)return e.jsx(l,{sx:{p:5,color:"fg.muted",textAlign:"center"},children:e.jsx(c,{children:"Select a span to view details."})});const o={},x={};if(t.attributes)for(const[u,h]of Object.entries(t.attributes))u.startsWith("gen_ai.")||u.startsWith("model_request")?o[u]=h:x[u]=h;const p=n&&n.length>0?Q(n):void 0;return e.jsxs(l,{sx:{height:"100%",overflow:"auto",borderLeft:"1px solid",borderColor:"border.default",bg:"canvas.default",display:"flex",flexDirection:"column"},children:[e.jsxs(l,{sx:{px:3,py:2,borderBottom:"1px solid",borderColor:"border.default",display:"flex",justifyContent:"space-between",alignItems:"center",bg:"canvas.subtle",flexShrink:0},children:[e.jsx(c,{sx:{fontSize:2,fontWeight:"bold"},children:t.span_name}),s&&e.jsx(oe,{icon:le,"aria-label":"Close detail panel",variant:"invisible",size:"small",onClick:s})]}),e.jsxs(B,{"aria-label":"Span detail tabs",children:[e.jsx(B.Item,{"aria-current":r==="details"?"page":void 0,onClick:()=>a("details"),children:"Details"}),p&&e.jsx(B.Item,{"aria-current":r==="tree"?"page":void 0,onClick:()=>a("tree"),children:"Trace Tree"}),e.jsx(B.Item,{"aria-current":r==="raw"?"page":void 0,onClick:()=>a("raw"),children:"Raw Data"})]}),e.jsxs(l,{sx:{flex:1,overflow:"auto"},children:[r==="details"&&e.jsxs(l,{sx:{p:3},children:[e.jsx(w,{label:"span_name",value:t.span_name}),e.jsx(w,{label:"service_name",value:t.service_name}),e.jsx(w,{label:"otel_scope_name",value:t.otel_scope_name}),e.jsx(w,{label:"kind",value:t.kind}),e.jsx(w,{label:"trace_id",value:t.trace_id,mono:!0}),e.jsx(w,{label:"span_id",value:t.span_id,mono:!0}),e.jsx(w,{label:"parent_span_id",value:t.parent_span_id,mono:!0}),e.jsx(w,{label:"duration",value:J(t.duration_ms)}),e.jsx(w,{label:"start_time",value:t.start_time,mono:!0}),e.jsx(w,{label:"end_time",value:t.end_time,mono:!0}),e.jsx(w,{label:"status_code",value:t.status_code}),e.jsx(w,{label:"status_message",value:t.status_message}),e.jsx(q,{title:"Arguments",data:o,defaultOpen:Object.keys(o).length>0}),e.jsx(q,{title:"Attributes",data:x}),t.events&&t.events.length>0&&e.jsxs(l,{sx:{mt:3},children:[e.jsxs(l,{sx:{display:"flex",alignItems:"center",gap:1},children:[e.jsx(c,{sx:{fontWeight:"bold",fontSize:1},children:"Events"}),e.jsx(V,{children:t.events.length})]}),t.events.map((u,h)=>e.jsxs(l,{sx:{bg:"canvas.subtle",borderRadius:2,border:"1px solid",borderColor:"border.default",p:2,mt:2},children:[e.jsxs(l,{sx:{display:"flex",gap:2},children:[e.jsx(D,{children:u.name}),e.jsx(c,{sx:{fontSize:0,color:"fg.muted",fontFamily:"mono"},children:u.timestamp})]}),u.attributes&&Object.keys(u.attributes).length>0&&e.jsx(l,{sx:{mt:1},children:Object.entries(u.attributes).map(([d,m])=>e.jsx(L,{attrKey:d,value:m,depth:0},d))})]},h))]}),t.links&&t.links.length>0&&e.jsxs(l,{sx:{mt:3},children:[e.jsxs(l,{sx:{display:"flex",alignItems:"center",gap:1},children:[e.jsx(c,{sx:{fontWeight:"bold",fontSize:1},children:"Links"}),e.jsx(V,{children:t.links.length})]}),t.links.map((u,h)=>e.jsxs(c,{sx:{display:"block",fontSize:1,fontFamily:"mono",py:1,borderBottom:"1px solid",borderColor:"border.muted"},children:["trace: ",u.trace_id," → span: ",u.span_id]},h))]})]}),r==="tree"&&p&&e.jsx(Ie,{spans:p,selectedSpanId:t.span_id,defaultExpandDepth:4}),r==="raw"&&e.jsx(l,{as:"pre",sx:{p:3,fontSize:0,fontFamily:"mono",whiteSpace:"pre-wrap",wordBreak:"break-word",m:0,bg:"canvas.subtle"},children:JSON.stringify(t,null,2)})]})]})},Ae=[{label:"Service",value:t=>t.service_name},{label:"Kind",value:t=>t.kind}];function Ne(t,n,s){return t.filter(r=>n.every((a,o)=>{const x=s[o];if(!x?.size)return!0;const p=a.value(r);return p!==void 0&&x.has(p)}))}function Re(t,n){const s=new Set(t);return s.has(n)?s.delete(n):s.add(n),s}function Ee({facet:t,options:n,selected:s,onChange:r}){const a=t.name??(o=>o);return e.jsxs(H,{children:[e.jsxs(H.Button,{size:"small","data-otel-facet":t.label.toLowerCase(),children:[t.label,s.size?` · ${s.size}`:""]}),e.jsx(H.Overlay,{width:"auto",children:e.jsxs(M,{selectionVariant:"multiple","aria-label":t.label,children:[e.jsx(M.Item,{selected:!s.size,onSelect:()=>r(new Set),children:"All"}),e.jsx(M.Divider,{}),n.map(o=>e.jsx(M.Item,{selected:s.has(o),onSelect:()=>r(Re(s,o)),children:a(o)},o))]})})]})}function Me(t,n){const s=new Blob([JSON.stringify(n,null,2)],{type:"application/json"}),r=URL.createObjectURL(s),a=document.createElement("a");a.href=r,a.download=`${t}.json`,a.click(),setTimeout(()=>URL.revokeObjectURL(r),1e3)}const $e=({tracer:t,spans:n,service:s,facets:r=Ae,compact:a=!1,maxHeight:o=420,detailPlacement:x="below",emptyText:p="Nothing recorded yet.",exportName:u="otel-spans",label:h="Spans",renderSpanMark:d,describeSpan:m})=>{const j=we(n?null:t),S=n??j,[g,O]=f.useState(0),[i,y]=f.useState(null),[b,A]=f.useState(()=>r.map(()=>new Set)),[v,T]=f.useState(null),C=f.useMemo(()=>{const _=Se(S,s);return g?_.filter(z=>E(z.start_time)>=g):_},[S,s,g]),k=i??C,I=i?C.length-i.length:0,ee=f.useMemo(()=>r.map(_=>[...new Set(C.map(z=>_.value(z)).filter(z=>z!==void 0))].sort()),[r,C]),N=f.useMemo(()=>Ne(k,r,b),[k,r,b]),R=f.useMemo(()=>v?S.find(_=>_.span_id===v)??null:null,[S,v]),te=f.useMemo(()=>R?S.filter(_=>_.trace_id===R.trace_id):[],[S,R]),P=x==="side"&&!a;return e.jsxs(l,{"data-otel-live-spans":"",sx:{border:"1px solid",borderColor:"border.default",borderRadius:2,bg:"canvas.default",color:"fg.default",minWidth:0},children:[e.jsxs(l,{role:"toolbar","aria-label":h,sx:{display:"flex",flexWrap:"wrap",gap:2,alignItems:"center",p:2,borderBottom:"1px solid",borderColor:"border.default"},children:[r.map((_,z)=>e.jsx(Ee,{facet:_,options:ee[z]??[],selected:b[z]??new Set,onChange:ne=>A(se=>r.map((Le,G)=>G===z?ne:se[G]??new Set))},_.label)),e.jsx(l,{sx:{flex:1}}),e.jsxs(c,{sx:{fontSize:0,color:"fg.muted"},"data-otel-span-count":"",children:[N.length===k.length?`${N.length} ${N.length===1?"span":"spans"}`:`${N.length} of ${k.length}`,I>0?` · ${I} new`:""]}),e.jsx(U,{size:"small",leadingVisual:i?ae:de,"aria-pressed":i!==null,onClick:()=>y(i?null:C),"data-otel-pause":"",children:i?"Resume":"Pause"}),e.jsx(U,{size:"small",leadingVisual:ce,onClick:()=>{y(null),T(null),t&&!n&&!s?t.clear():O(Date.now())},"data-otel-clear":"",children:"Clear"}),e.jsx(U,{size:"small",leadingVisual:ue,disabled:!C.length,onClick:()=>Me(u,{exportedAt:new Date().toISOString(),spans:[...C]}),"data-otel-export":"",children:"Export"})]}),e.jsxs(l,{sx:{display:P?"grid":"block",gridTemplateColumns:P?"minmax(0, 3fr) minmax(0, 2fr)":void 0},children:[e.jsx(l,{sx:{maxHeight:o,overflowY:"auto",minWidth:0},children:e.jsx(Ce,{spans:N,selectedSpanId:v,onSelectSpan:_=>T(_.span_id),emptyText:p,compact:a,defaultExpanded:!0,renderSpanMark:d,describeSpan:m})}),R&&e.jsx(l,{"data-otel-live-detail":"",sx:{maxHeight:o,overflowY:"auto",minWidth:0,borderTop:P?"none":"1px solid",borderColor:"border.default"},children:e.jsx(Oe,{span:R,traceSpans:te,onClose:()=>T(null)})})]})]})},Be=[{label:"Source",value:fe,name:t=>xe[t]??t},{label:"Operation",value:t=>{const n=t.attributes??{},s=n[K.operation]??n["rpc.method"];return s===void 0?void 0:String(s)}},{label:"Agent",value:t=>t.service_name}];function De(t){const n=t.attributes?.[K.markIcon],s=t.attributes?.[K.markEmoji];return n||s?e.jsx(he,{icon:typeof n=="string"?n:void 0,emoji:typeof s=="string"?s:void 0,size:14}):null}function Pe({tracer:t,spans:n,agent:s,maxHeight:r=420,compact:a=!1,emptyText:o="Nothing recorded yet.",exportName:x="agent-inspector"}){return e.jsx("div",{"data-agent-inspector":s??"",children:e.jsx($e,{tracer:t,spans:n,service:s,facets:Be,compact:a,maxHeight:r,detailPlacement:"side",emptyText:o,exportName:x,label:s?`${s}'s Agent Inspector`:"Agent Inspector",renderSpanMark:De,describeSpan:pe})})}export{Be as AGENT_INSPECTOR_FACETS,Pe as AgentInspector,Pe as default};
|