@theoremjs/studio 0.3.4-next.474.gdb1d5d7 → 0.3.4-next.482.g7e608f2

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 (50) hide show
  1. package/README.md +1 -1
  2. package/draft.js +1 -1
  3. package/package.json +4 -4
  4. package/page/assets/{Banner-TdHtbVjU.js → Banner-CrUhb26_.js} +2 -2
  5. package/page/assets/{ConsoleFrame-DgjR7mxh.js → ConsoleFrame-6cEEvO4i.js} +1 -1
  6. package/page/assets/{ContextMenu-D-6K0Fs2.js → ContextMenu-WnsgC14_.js} +2 -2
  7. package/page/assets/{ToolResultCharts-0ddlwgFH.js → ToolResultCharts-BEhuo0Z4.js} +1 -1
  8. package/page/assets/{TraceInspector-egLHbVIj.js → TraceInspector-k1w1q0XO.js} +1 -1
  9. package/page/assets/{TraceOverview-CRTN7VoT.js → TraceOverview-Crxd-sTS.js} +1 -1
  10. package/page/assets/{_virtual_studio-type-sources-DdSjKnMh.js → _virtual_studio-type-sources-DAabvYbE.js} +16 -6
  11. package/page/assets/{browser-engine-tXDx3yU4.js → browser-engine-C78edv3x.js} +7 -7
  12. package/page/assets/{browser-transport-ffGDz5MD.js → browser-transport-mGxdvtBL.js} +4 -4
  13. package/page/assets/{crypto-C5mfRMPv.js → crypto-iT_LZ8Et.js} +1 -1
  14. package/page/assets/encode-files-8AFMw7Er.js +1 -0
  15. package/page/assets/{export-agent-Y58EdieU.js → export-agent-BedkRp13.js} +1 -1
  16. package/page/assets/{guardrail-tester-CDawxhDM.js → guardrail-tester-XwnZWNsg.js} +1 -1
  17. package/page/assets/{index-DtLCmecg.js → index-BVHT-9mR.js} +9 -9
  18. package/page/assets/{live-messages-CcUq850L.js → live-messages-B65rUlNM.js} +1 -1
  19. package/page/assets/{reader-DkhgU7-Z.js → reader-XebgyCzF.js} +4 -4
  20. package/page/assets/{shaped-data-Hq2l-bCM.js → shaped-data-Bc6u4pow.js} +2 -2
  21. package/page/assets/{stub-9noS56tk.js → stub-DG5wxM-A.js} +1 -1
  22. package/page/assets/{studio-code-pane-CTGeGFc3.js → studio-code-pane-p4fjtQhL.js} +3 -3
  23. package/page/assets/{studio-console-bsXe3dk3.js → studio-console-BtZY4aUM.js} +1 -1
  24. package/page/assets/{studio-decision-CEcqOCMb.js → studio-decision-BovTBIwV.js} +1 -1
  25. package/page/assets/{studio-embedding-C1KeE3S4.js → studio-embedding-BY6UQk0k.js} +1 -1
  26. package/page/assets/{studio-host-console-mg-gOPJs.js → studio-host-console-D9NFWXxV.js} +2 -2
  27. package/page/assets/{studio-labels-DyUKoK3A.js → studio-labels-C3yQoEd0.js} +1 -1
  28. package/page/assets/{studio-live-D4qKxLHi.js → studio-live-B_cVDiqs.js} +1 -1
  29. package/page/assets/{studio-map-CsQoRSdx.js → studio-map-iN6-MOzK.js} +1 -1
  30. package/page/assets/studio-trace-replay-B3k21TSg.js +2 -0
  31. package/page/assets/{studio-type-checker-Ch0YO2TO.js → studio-type-checker-Bljo3amv.js} +1 -1
  32. package/page/assets/{tool-schema-DUAd6AXZ.js → tool-schema-BmScISma.js} +8 -8
  33. package/page/assets/{trace-record-Dfx7WS9n.js → trace-record-D4xAUHLZ.js} +1 -1
  34. package/page/assets/{tree-q4zfZBm3.js → tree-BiZScKs7.js} +2 -2
  35. package/page/assets/{turn-client-BHueOGtF.js → turn-client-CBWNoFgo.js} +2 -2
  36. package/page/assets/types-zRlFhC9U.js +1 -0
  37. package/page/assets/{use-one-call-BF7eEAPL.js → use-one-call-rh-5EjBB.js} +1 -1
  38. package/page/assets/{workspace-D8wB8WWL.js → workspace-kAEf4Zn4.js} +1 -1
  39. package/page/index.html +15 -15
  40. package/policy.js +2 -2
  41. package/replay.js +2 -3
  42. package/server/draft-decide.d.ts +4 -1
  43. package/server/draft-decide.js +1 -1
  44. package/ui/lib/tree-map-layout.d.ts +38 -14
  45. package/ui/lib/tree-map-layout.js +210 -142
  46. package/ui/tree-map.d.ts +10 -9
  47. package/ui/tree-map.js +60 -40
  48. package/page/assets/encode-files-CZXrfYAp.js +0 -1
  49. package/page/assets/studio-trace-replay-aP7TzJuO.js +0 -2
  50. package/page/assets/types-CbxtWiCN.js +0 -1
package/ui/tree-map.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { IconAdjustments, IconArrowsMinimize, IconChecks, IconCloud, IconEngine, IconFlag, IconKey, IconRepeat, IconSettingsAutomation, IconShieldCheck, IconTimeline, IconTool, } from '@tabler/icons-react';
2
+ import { IconAdjustments, IconArrowsMinimize, IconChecks, IconCloud, IconEngine, IconKey, IconLock, IconPlugConnected, IconRepeat, IconSettingsAutomation, IconShieldCheck, IconStack2, IconTimeline, IconWorldCheck, } from '@tabler/icons-react';
3
3
  import { useMemo, useRef, useState } from 'react';
4
4
  import { mapCurve } from "../map-line.js";
5
5
  import { createBlankDraft, libraryDraft } from "../mod.js";
6
6
  import { drawnAt, HALF, INDENT, PAD, placeAt, rowId, treeMapLayout, } from "./lib/tree-map-layout.js";
7
- import { toolTypeIcon } from "./lib/type-icons.js";
7
+ import { AGENT_ICON, profileTypeIcon, toolTypeIcon } from "./lib/type-icons.js";
8
8
  import { MapToken, useTokenWidths } from "./map-token.js";
9
9
  import { nodeIcon } from "./node-icon.js";
10
10
  import { drags, follow } from "./pan.js";
@@ -15,7 +15,7 @@ const TRUNK = 13;
15
15
  const TURN = 8;
16
16
  /** Between a token's side and its line. */
17
17
  const LINE_GAP = 4;
18
- /** How far right of the widest feed a line coming round them runs. */
18
+ /** How far right of what it passes a line coming round a column runs. */
19
19
  const RAIL = 20;
20
20
  /** A token's width until it is measured. */
21
21
  const GUESS = 120;
@@ -23,28 +23,37 @@ const STEP_ICONS = {
23
23
  resolve: IconAdjustments,
24
24
  sanitize: IconShieldCheck,
25
25
  compaction: IconArrowsMinimize,
26
- canary: IconKey,
27
- pre_turn: IconFlag,
28
26
  stream: IconCloud,
29
27
  tools: IconRepeat,
30
- before_end: IconFlag,
31
28
  validation: IconChecks,
32
29
  egress: IconShieldCheck,
33
30
  trace: IconTimeline,
34
- post_turn: IconFlag,
31
+ };
32
+ const CHECK_ICONS = {
33
+ permission: IconLock,
34
+ 'sign-in': IconKey,
35
+ network: IconWorldCheck,
36
+ result: IconShieldCheck,
35
37
  };
36
38
  function feedIcon(feed) {
39
+ const of = feed.of ?? '';
37
40
  if (feed.kind === 'runner')
38
41
  return IconEngine;
42
+ if (feed.kind === 'step')
43
+ return STEP_ICONS[of] ?? IconRepeat;
39
44
  if (feed.kind === 'provider')
40
45
  return IconCloud;
46
+ if (feed.kind === 'protocol')
47
+ return IconPlugConnected;
41
48
  if (feed.kind === 'tool')
42
- return toolTypeIcon(feed.of ?? '');
49
+ return toolTypeIcon(of);
50
+ if (feed.kind === 'branch')
51
+ return IconStack2;
52
+ if (feed.kind === 'subagent')
53
+ return profileTypeIcon(of) ?? AGENT_ICON;
43
54
  if (feed.kind === 'tool-runner')
44
55
  return IconSettingsAutomation;
45
- if (feed.kind === 'step')
46
- return STEP_ICONS[feed.of ?? ''] ?? IconFlag;
47
- return IconTool;
56
+ return CHECK_ICONS[of] ?? IconShieldCheck;
48
57
  }
49
58
  /** Right from `from` to `rail`, up or down it, and back left to `to`, its corners turned. */
50
59
  function sidePath(from, to, rail) {
@@ -77,7 +86,8 @@ export function StudioTreeMap({ workspace, agents, grow = 0, fit, draggable = fa
77
86
  const [dragging, setDragging] = useState(false);
78
87
  // why: Every token is drawn from the start, the undrawn ones unseen, so each is measured before it shows.
79
88
  const widths = useTokenWidths(root, workspace);
80
- const layout = useMemo(() => treeMapLayout(workspace, agents, (id) => widths[id] ?? GUESS), [workspace, agents, widths]);
89
+ const { width: fitWidth, height: fitHeight } = fit ?? { width: 0, height: 0 };
90
+ const layout = useMemo(() => treeMapLayout(workspace, agents, (id) => widths[id] ?? GUESS, fitWidth > 0 && fitHeight > 0 ? { width: fitWidth, height: fitHeight } : undefined), [workspace, agents, widths, fitWidth, fitHeight]);
81
91
  const width = (id) => widths[id] ?? GUESS;
82
92
  const drafts = new Map(workspace.agents.map((agent) => [
83
93
  agent.key,
@@ -91,46 +101,65 @@ export function StudioTreeMap({ workspace, agents, grow = 0, fit, draggable = fa
91
101
  };
92
102
  const drawn = (id) => drawnAt(layout, id, grow);
93
103
  const feedById = new Map(feeds.map((feed) => [feed.id, feed]));
94
- const lineDrawn = (id) => {
95
- const part = drawn(id);
96
- return part === undefined
97
- ? {}
98
- : { pathLength: 1, style: { strokeDasharray: 1, strokeDashoffset: 1 - clamp(part * 2) } };
104
+ /** A line draws in its first half of the later of its two ends drawing, its token in the second. */
105
+ const lineDrawn = (...ids) => {
106
+ const parts = ids.flatMap((id) => drawn(id) ?? []);
107
+ if (parts.length === 0)
108
+ return {};
109
+ const part = Math.min(...parts);
110
+ return { pathLength: 1, style: { strokeDasharray: 1, strokeDashoffset: 1 - clamp(part * 2) } };
99
111
  };
100
112
  const shown = feeds.filter((feed) => (drawn(feed.id) ?? 1) > 0);
101
113
  const right = (id) => at(id).x + width(id);
102
- /** Right of every feed from `above` down to `feed`, where each stands now. */
103
- const railFor = (feed, above) => {
104
- const [top, bottom] = [at(above.id).y, at(feed.id).y].sort((a, b) => a - b);
114
+ /** Right of every feed in its column from `to` to `feed`, where each stands now. */
115
+ const railFor = (feed, to) => {
116
+ const [top, bottom] = [at(to.id).y, at(feed.id).y].sort((a, b) => a - b);
105
117
  const lying = shown.filter((each) => {
106
118
  const { y } = at(each.id);
107
- return y >= (top ?? 0) && y <= (bottom ?? 0) && each.id !== feed.id;
119
+ return each.column === feed.column && y >= (top ?? 0) && y <= (bottom ?? 0);
108
120
  });
109
- return Math.max(right(feed.id), ...lying.map((each) => right(each.id))) + RAIL;
121
+ return Math.max(...lying.map((each) => right(each.id))) + RAIL;
110
122
  };
111
- const places = [...rows.map(rowId), ...shown.map((feed) => feed.id)];
112
- const rails = shown.flatMap((feed) => {
113
- const above = feed.under === undefined ? undefined : feedById.get(feed.under);
114
- return above && feed.depth <= above.depth ? [railFor(feed, above)] : [];
123
+ const joins = shown.flatMap((feed) => {
124
+ const to = feed.joins === undefined ? undefined : feedById.get(feed.joins);
125
+ return to && (drawn(to.id) ?? 1) > 0 ? [{ feed, to }] : [];
115
126
  });
127
+ /** A join to a feed further right runs across to it; to one in its own column, round their right. */
128
+ const joinPath = (feed, to) => {
129
+ const from = { x: right(feed.id) + LINE_GAP, y: at(feed.id).y };
130
+ if (to.column > feed.column) {
131
+ return mapCurve(from, { x: at(to.id).x - LINE_GAP, y: at(to.id).y }).d;
132
+ }
133
+ return sidePath(from, { x: right(to.id) + LINE_GAP, y: at(to.id).y }, railFor(feed, to));
134
+ };
135
+ const places = [...rows.map(rowId), ...shown.map((feed) => feed.id)];
136
+ const rails = joins.flatMap(({ feed, to }) => to.column === feed.column ? [railFor(feed, to)] : []);
116
137
  const mapWidth = Math.max(GUESS, ...places.map(right), ...rails) + PAD;
117
138
  const height = Math.max(...places.map((id) => at(id).y)) + HALF + PAD;
118
139
  const grown = useMemo(() => {
119
140
  const ids = [...layout.rows.map(rowId), ...layout.feeds.map((feed) => feed.id)];
120
141
  const ends = ids.map((id) => ({ id, ...placeAt(layout, id, 1) }));
121
142
  return {
122
- width: Math.max(...ends.map((end) => end.x + (widths[end.id] ?? GUESS))) + RAIL + PAD,
143
+ width: Math.max(...ends.map((end) => end.x + (widths[end.id] ?? GUESS))) + PAD,
123
144
  height: Math.max(...ends.map((end) => end.y)) + HALF + PAD,
124
145
  };
125
146
  }, [layout, widths]);
126
147
  const fits = fit ? Math.min(1, fit.width / grown.width, fit.height / grown.height) : 1;
127
148
  const scale = 1 + (fits - 1) * clamp(grow);
149
+ // why: Grown, the map stands in the middle of the box it fills; closed, at its top left.
150
+ const centre = fit
151
+ ? {
152
+ x: (Math.max(0, fit.width - grown.width * fits) / 2) * clamp(grow),
153
+ y: (Math.max(0, fit.height - grown.height * fits) / 2) * clamp(grow),
154
+ }
155
+ : NONE;
128
156
  // why: The pointer moves in the page's pixels; the map is scaled, so a move is divided back into its own.
129
157
  const drag = (event) => {
130
158
  if (!draggable || !drags(event))
131
159
  return;
132
160
  event.preventDefault();
133
- const token = event.target.closest('[data-map-token]')?.dataset['mapToken'];
161
+ const token = event.target.closest('[data-map-token]')?.dataset
162
+ .mapToken;
134
163
  const from = token === undefined ? field : (moved[token] ?? NONE);
135
164
  const put = (to) => {
136
165
  if (token === undefined)
@@ -147,7 +176,8 @@ export function StudioTreeMap({ workspace, agents, grow = 0, fit, draggable = fa
147
176
  setDragging(false);
148
177
  });
149
178
  };
150
- const translate = field.x || field.y ? { translate: `${field.x}px ${field.y}px` } : {};
179
+ const shift = { x: field.x + centre.x, y: field.y + centre.y };
180
+ const translate = shift.x || shift.y ? { translate: `${shift.x}px ${shift.y}px` } : {};
151
181
  return (_jsxs("div", { ref: root, className: "studio-tree-map", style: {
152
182
  width: mapWidth,
153
183
  height,
@@ -157,17 +187,7 @@ export function StudioTreeMap({ workspace, agents, grow = 0, fit, draggable = fa
157
187
  const from = at(feed.id);
158
188
  const { d } = mapCurve({ x: from.x - LINE_GAP, y: from.y }, { x: right(id) + LINE_GAP, y: at(id).y });
159
189
  return _jsx("path", { className: "map-line", d: d }, `${feed.id}>${id}`);
160
- })), shown.map((feed) => {
161
- const above = feed.under === undefined ? undefined : feedById.get(feed.under);
162
- if (above === undefined)
163
- return null;
164
- // One of its own comes down from it, as a tree row does; one level with it comes round
165
- // the right of what lies between, so it reads as joining the feed, not as one of its own.
166
- const d = feed.depth > above.depth
167
- ? underPath(at(above.id), at(feed.id))
168
- : sidePath({ x: right(feed.id) + LINE_GAP, y: at(feed.id).y }, { x: right(above.id) + LINE_GAP, y: at(above.id).y }, railFor(feed, above));
169
- return _jsx("path", { className: "map-line", d: d, ...lineDrawn(feed.id) }, `${feed.id}^`);
170
- })] }), rows.map((row) => {
190
+ })), shown.map((feed) => feed.under !== undefined && (_jsx("path", { className: "map-line", d: underPath(at(feed.under), at(feed.id)), ...lineDrawn(feed.id) }, `${feed.id}^`))), joins.map(({ feed, to }) => (_jsx("path", { className: "map-line", d: joinPath(feed, to), ...lineDrawn(feed.id, to.id) }, `${feed.id}~${to.id}`)))] }), rows.map((row) => {
171
191
  const draft = drafts.get(row.agent) ?? createBlankDraft();
172
192
  const { x, y } = at(rowId(row));
173
193
  return (_jsx(MapToken, { id: rowId(row), label: row.node.label, icon: nodeIcon(draft, row.node.ref), x: x, y: y }, rowId(row)));
@@ -1 +0,0 @@
1
- import{fn as e,pn as t}from"./shaped-data-Hq2l-bCM.js";function n(e){return e.map(e=>({name:e.name,mimeType:e.type||`application/octet-stream`,sizeBytes:e.size}))}function r(t){let n=[];for(let r of t){if(typeof r.data!=`string`||r.data.length===0)continue;let t=e(r.data),i=t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength);n.push(new File([i],r.name,{type:r.mimeType||`application/octet-stream`}))}return n}async function i(e){let n=[];for(let r of e)n.push({name:r.name,mimeType:r.type||`application/octet-stream`,data:t(new Uint8Array(await r.arrayBuffer()))});return n}function a(e,t,n){let r=0,i=0;return e.map(e=>{if(e.kind===`user-attachment`){let n=t?.[r]?.data;return r+=1,n===void 0?e:{...e,data:n}}if(e.kind===`user-voice`){let t=n?.[i]?.data;return i+=1,t===void 0?e:{...e,data:t}}return e})}export{r as i,i as n,n as r,a as t};
@@ -1,2 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{c as t,u as n}from"./themeProps-3IqahpCr.js";import{n as r,t as i}from"./SegmentedControlItem-BLuJOusN.js";import{t as a}from"./VStack-CkVMcNiK.js";import{A as o,_ as s,a as c,o as l,s as u,v as d}from"./browser-transport-ffGDz5MD.js";import{r as f}from"./IconButton-CG5klqF1.js";import{t as p}from"./Text-BsiAsowd.js";import{n as m,t as h}from"./labels-provider-BSiD6Lrb.js";import{a as g,t as _}from"./Banner-TdHtbVjU.js";import{t as v,v as ee}from"./studio-labels-DyUKoK3A.js";import{c as y}from"./host-patterns-C9RMP16Q.js";import{n as b}from"./trace-record-Dfx7WS9n.js";import{n as x}from"./trace-schema-9CdEyG6Q.js";import{_ as S}from"./turn-client-BHueOGtF.js";import{a as C,i as w,o as T,t as E}from"./ConsoleFrame-DgjR7mxh.js";import{C as D,a as O,b as k,g as te,x as ne}from"./index-DtLCmecg.js";var A=e=>typeof e==`object`&&!!e&&!Array.isArray(e),j=(e,t)=>e.attributes[t],M=(e,t)=>{let n=j(e,t);return typeof n==`string`?n:void 0};function N(e,t,n){let r=j(t,n);return r===void 0?void 0:b(e,r)}function P(e,t,n){let r=N(e,t,n);return r===void 0?``:typeof r==`string`?r:JSON.stringify(r)}function F(e,t,n){let r=N(e,t,n);return Array.isArray(r)?r.filter(A):[]}var I=e=>Array.isArray(e.parts)?e.parts.filter(A):[],L=e=>BigInt(String(e.startTimeUnixNano)),R=(e,t)=>{let n=L(e)-L(t);return n===0n?0:n<0n?-1:1},re=e=>`content_sha256`in e||`json_sha256`in e;function z(e){let t=e.arguments;if(A(t))return t;if(typeof t!=`string`)return{};try{let e=JSON.parse(t);return A(e)?e:{}}catch{return{}}}function B(e){if(typeof e.content==`string`){if(e.type===`reasoning`)return{type:`thought`,text:e.content};if(e.type===`text`)return{type:`text`,text:e.content}}}function ie(e){let t=[],n=[],r=!1;for(let i of e){let e=I(i),a=e.some(e=>e.type===`text`);for(let i of e){let e=B(i);re(i)?r=!0:e?t.push(e):i.type===`structured`&&!a?t.push({type:`text`,text:JSON.stringify(i.content)}):i.type===`tool_call`&&typeof i.name==`string`?(n.push(i.name),t.push({type:`tool`,tool:{name:i.name,callId:typeof i.id==`string`?i.id:`replay-${String(n.length)}`,arguments:z(i)}})):(i.type===`blob`||i.type===`uri`)&&(r=!0)}}return{events:t,calls:n,missing:r}}function ae(e,t){for(let n=e;n;n=t.get(n.parentSpanId??``)){let e=M(n,`gen_ai.agent.name`);if(M(n,`gen_ai.operation.name`)===`invoke_agent`&&e)return e}return``}var V=e=>M(e,`gen_ai.operation.name`);function oe(e){let t=new Map(e.spans.map(e=>[e.spanId,e]));return e.spans.filter(e=>V(e)===`chat`).toSorted(R).map(n=>{let r=ie(F(e,n,`gen_ai.output.messages`)),i=M(n,`theorem.stop.kind`)??`completed`;return{agent:ae(n,t),...r,events:[...r.events,{type:`done`,stop:{kind:i}}]}})}function se(e){return e.spans.filter(e=>V(e)===`execute_tool`).toSorted(R).map(t=>({name:M(t,`gen_ai.tool.name`)??``,result:P(e,t,`gen_ai.tool.call.result`),failed:M(t,`theorem.tool.outcome`)===`error`}))}function ce(e,t){let n=F(e,t,`gen_ai.input.messages`).findLast(e=>e.role===`user`),r=n?I(n):[];return{text:r.flatMap(e=>e.type===`text`&&typeof e.content==`string`?[e.content]:[]).join(`
2
- `),attachments:r.filter(e=>e.type===`blob`||e.type===`uri`).length}}function le(e,t){let n=e.spans.filter(e=>V(e)===`execute_tool`).toSorted(R),r=new Set,i=(e,t)=>{let i=n.find(t=>M(t,`gen_ai.tool.call.id`)===e)??n.find(e=>!r.has(e)&&M(e,`gen_ai.tool.name`)===t);return i&&r.add(i),i},a=[];for(let n of F(e,t,`gen_ai.output.messages`))for(let t of I(n)){let n=B(t);if(n)a.push(n);else if(t.type===`tool_call`&&typeof t.name==`string`){let n=typeof t.id==`string`?t.id:`call-${String(a.length)}`;a.push(...ue(e,t.name,n,z(t),i))}}let o=P(e,t,`theorem.error.public`);t.status.code===`ERROR`&&a.push({type:`error`,errorKind:`internal`,error:o||t.status.message});let s=M(t,`theorem.stop.kind`)??`completed`;return a.push({type:`done`,stop:{kind:s}}),a}function ue(e,t,n,r,i){let a=i(n,t),o={type:`tool`,tool:{name:t,callId:n,arguments:r}};if(!a)return[o];let s=Number(L(a)/1000000n),c=P(e,a,`gen_ai.tool.call.result`);return[o,{type:`tool`,tool:{name:t,callId:n,at:s,...M(a,`theorem.tool.outcome`)===`error`?{phase:`error`,failure:{code:M(a,`theorem.tool.failure.code`)??`failed`,kind:`internal`,message:c}}:{phase:`complete`,output:H(c)}}}]}function H(e){try{return JSON.parse(e)}catch{return e}}var de=e=>e.spans.find(e=>!e.parentSpanId);function fe(e){let t=``,n,r=[];return e.forEach((e,i)=>{let a=de(e);if(!a||V(a)!==`invoke_agent`)return;let o=M(a,`gen_ai.agent.name`)??``;t||=o;let s=oe(e),c=se(e),l=r.at(-1);if(o!==t&&l){l.calls.push(...s),l.results.push(...c);return}n??=Number(L(a)/1000000n);let u=ce(e,a);r.push({...u,calls:s,results:c,blocks:S({text:u.text},le(e,a),{idPrefix:`recorded-${String(i)}`})})}),{agent:t,turns:r,...n===void 0?{}:{recordedAt:n}}}function pe(e){if(e.failed)throw Error(e.result);let t=H(e.result);return A(t)?t:{result:t}}var me=e=>{let t=e%100,n=t>=11&&t<=13?`th`:{1:`st`,2:`nd`,3:`rd`}[e%10]??`th`;return`${String(e)}${n}`};function he(e,t,n){if(!e)return`The profile asked the model a ${me(t+1)} time this turn; the recording answered ${String(t)}.`;if(e.missing)return`The recording does not hold all of this reply.`;let r=new Set((n.wireTools??[]).map(e=>e.name)),i=e.calls.find(e=>!r.has(e));return i&&`The recording calls ${i}, which the profile no longer offers.`}function ge(e,t,n){let r=0,i=new Map,a=new Map,o=t=>{let n=a.get(t);if(!n){n=new Map;for(let r of e.turns[t]?.results??[])n.set(r.name,[...n.get(r.name)??[],r]);a.set(t,n)}return n},s=t=>({async*complete(a){let o=e.turns[r]?.calls.filter(e=>e.agent===t)??[],s=`${String(r)} ${t}`,c=i.get(s)??0;i.set(s,c+1);let l=he(o[c],o.length,a);if(l)throw n({turn:r,call:c+1,reason:l}),new y(`request`,`Replay stopped: ${l}`);yield*o[c]?.events??[]}}),c=e=>()=>{let t=o(r).get(e)?.shift();if(!t)throw Error(`The recording has no further result for ${e}.`);return pe(t)},l=new Set(e.turns.flatMap(e=>e.results.map(e=>e.name)));return{provider:n=>s(n.id===t?e.agent:n.id),toolHandlers:Object.fromEntries([...l].map(e=>[e,c(e)])),startTurn:e=>{r=e}}}function U(e){return e.map(e=>{if(e.type===`agent`)return e;let{name:t,description:n,category:r,access:i,permission:a,loadTier:o,paths:s}=e;return{type:`function`,name:t,description:n,category:r,access:i,permission:a,loadTier:o,paths:s,inputSchema:e.inputSchema,outputSchema:e.outputSchema,...e.labels?{labels:e.labels}:{}}})}function _e(e){return{...e,customTools:U(e.customTools),...e.dependencies?{dependencies:e.dependencies.map(e=>({...e,customTools:U(e.customTools)}))}:{}}}function W(e){return e.turns.flatMap(e=>e.blocks)}function ve(e){let t;try{t=JSON.parse(e)}catch{throw new y(`request`,`This file is not JSON.`)}let n=Array.isArray(t)?t:[t];return n.map((e,t)=>{let r=x.safeParse(e);if(r.success)return r.data;let i=n.length>1?` (record ${String(t+1)})`:``;throw new y(`request`,`This file is not a Theorem trace${i}.`)})}var G=e(n(),1),K=t();function ye(e,t,n){return t?l(e,t,{conversationKey:O(),blocks:n}):s(e,n)}var q=e=>`turn ${String(e+1)}`;function J({iface:e,feed:t,trace:n,card:r,conversation:i}){let a=g(e,t,n);return(0,K.jsxs)(E,{inspector:a,maxWidth:`960px`,requestLabel:`Trace`,children:[r,i]})}function Y({iface:e,blocks:t,banner:n,chat:r}){let i=m();return(0,K.jsxs)(C,{label:`Conversation`,children:[n,(0,K.jsx)(D,{blocks:t,handle:i(`@theorem.agent.handle`,{handle:e.identity.handle}),labels:e.labels,streaming:r?.streaming,delivery:r?.delivery,answering:r?.answering,onToolDecision:r&&((e,t)=>{r.handleToolDecision(e,t)}),onAuthenticated:r&&((e,t)=>{r.handleAuthenticated(e,t)})})]})}function be({onImport:e}){let[t,n]=(0,G.useState)(),[r,i]=(0,G.useState)(!1);return(0,K.jsxs)(a,{gap:2,children:[(0,K.jsx)(ne,{label:`Trace file`,isLabelHidden:!0,mode:`dropzone`,accept:`application/json,.json`,isLoading:r,placeholder:`Drop a trace (.json) or choose a file`,value:null,changeAction:async t=>{let r=Array.isArray(t)?t[0]:t;if(r){i(!0);try{e({name:r.name,records:ve(await r.text())}),n(void 0)}catch(e){n(e instanceof Error?e.message:String(e))}finally{i(!1)}}},onChange:()=>void 0}),t?(0,K.jsx)(_,{status:`error`,title:t}):null]})}var xe=e=>e.recordedAt===void 0?void 0:new Intl.DateTimeFormat(void 0,{dateStyle:`medium`,timeStyle:`short`}).format(e.recordedAt);function Se({shown:e,onShown:t}){return(0,K.jsxs)(r,{label:`Show`,size:`sm`,value:e,onChange:e=>{t(e===`replayed`?`replayed`:`recorded`)},children:[(0,K.jsx)(i,{value:`recorded`,label:`Recorded`}),(0,K.jsx)(i,{value:`replayed`,label:`Replayed`})]})}function X({controls:e}){let{script:t,payload:n}=e,r=t.turns.length,i=[t.agent||`No agent`,`${String(r)} ${r===1?`turn`:`turns`}`,xe(t)];return(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(a,{gap:0,children:[(0,K.jsx)(p,{type:`label`,maxLines:1,children:e.opened.name}),(0,K.jsx)(p,{type:`supporting`,color:`secondary`,maxLines:1,children:i.filter(Boolean).join(` · `)})]}),t.agent&&t.agent!==n.profile.id?(0,K.jsx)(_,{status:`info`,title:`Recorded with ${t.agent}; a replay runs through ${n.profile.id}.`}):null,r===0?(0,K.jsx)(_,{status:`info`,title:`This trace holds no conversation to replay.`}):null,(0,K.jsx)(k,{label:`Live tools`,description:`Run the profile's tools instead of answering them from the recording.`,value:e.liveTools,onChange:e.onLiveTools})]})}var Z=()=>void 0;function Q({onImport:e,controls:t}){let n=t?.onReplay??Z;return(0,K.jsxs)(w,{title:`Trace`,onRun:n,actions:t?.shown?(0,K.jsx)(Se,{shown:t.shown,onShown:t.onShown}):null,children:[(0,K.jsx)(be,{onImport:e}),t?(0,K.jsx)(X,{controls:t}):null,(0,K.jsx)(T,{note:t?`Answers each model call from the recording, so it needs no keys.`:null,isReady:(t?.script.turns.length??0)>0,isRunning:t?.isRunning??!1,runLabel:t?.shown?`Replay again`:`Replay`,runningLabel:`Replaying`,stopLabel:`Stop`,onRun:n,onStop:t?.onStop??Z})]})}function Ce({status:e,turns:t,onContinue:n,onLive:r}){let[i,o]=(0,G.useState)(!1),[s,c]=(0,G.useState)(),l=e=>(0,K.jsx)(f,{label:`Continue live`,variant:`secondary`,size:`sm`,isLoading:i,onClick:async()=>{o(!0),c(void 0);try{await r(e)}catch(e){c(e instanceof Error?e.message:String(e)),o(!1)}}}),u=(()=>{switch(e.kind){case`running`:return(0,K.jsx)(_,{status:`info`,title:`Replaying ${q(e.turn)} of ${String(t)}`});case`waiting`:return(0,K.jsx)(_,{status:`info`,title:`${q(e.turn-1)} waits on you`,description:`Answer it in the conversation, then continue the replay.`,endContent:(0,K.jsx)(f,{label:`Continue replay`,variant:`secondary`,size:`sm`,onClick:()=>{n(e.turn)}})});case`missing`:return(0,K.jsx)(_,{status:`warning`,title:`Replay stopped before ${q(e.turn)}`,description:`It was sent with files, and a trace never holds a file's bytes. Continue live to send it again with yours.`,endContent:l(e.turn)});case`diverged`:{let{turn:t,call:n,reason:r}=e.divergence;return(0,K.jsx)(_,{status:`warning`,title:`Replay stopped at ${q(t)}, model call ${String(n)}`,description:r,endContent:l(t)})}case`failed`:return(0,K.jsx)(_,{status:`error`,title:`Replay stopped at ${q(e.turn)}`,description:e.message,endContent:l(e.turn)});case`done`:return(0,K.jsx)(_,{status:`success`,title:`Replayed ${String(t)} ${t===1?`turn`:`turns`}`,description:`Every model call this profile made was one the recording answered.`})}})();return(0,K.jsxs)(a,{gap:1,children:[u,s?(0,K.jsx)(_,{status:`error`,title:s}):null]})}function $(e){let t=o();for(let n of e)t.push(n);return t}function we({payload:e,iface:t,trace:n,card:r,opened:i,script:a,shown:s,liveTools:l,runtime:u,onLive:d}){let f=(0,G.useRef)(void 0),[p,m]=(0,G.useState)({kind:`running`,turn:0}),[h]=(0,G.useState)(o),g=(0,G.useMemo)(()=>$(i.records),[i.records]),_=(0,G.useMemo)(()=>ge(a,e.profile.id,e=>{f.current??=e}),[a,e.profile.id]),v=(0,G.useMemo)(()=>c(l?e:_e(e),{mode:`byok`,provider:_.provider,...l?{}:{toolHandlers:_.toolHandlers}},{conversationKey:O(),traces:h}),[e,_,l,h]),y=(0,G.useMemo)(()=>l?ee(e):void 0,[l,e]),b=te({transport:v,iface:t,pageTools:y}),{sendText:x,handleStop:S}=b,C=(0,G.useRef)(b.phase);C.current=b.phase;let[w,T]=(0,G.useState)(0);(0,G.useEffect)(()=>{let e=!1,t=async()=>{for(;!e&&C.current===`streaming`;)await new Promise(e=>requestAnimationFrame(e))};return(async()=>{for(let n=w;n<a.turns.length;n+=1){if(await t(),e)return;if(C.current===`gated`)return _.startTurn(n-1),m({kind:`waiting`,turn:n});let{text:r,attachments:i}=a.turns[n];if(i>0)return m({kind:`missing`,turn:n});_.startTurn(n),m({kind:`running`,turn:n});try{let t=await x(r);if(e)return;if(f.current)return m({kind:`diverged`,divergence:f.current});t||--n}catch(e){let t=e instanceof Error?e.message:String(e);return m({kind:`failed`,turn:n,message:t})}}m({kind:`done`})})(),()=>{e=!0,S()}},[w,_,a,x,S]);let E=async t=>{d({...await ye(e,u,a.turns.slice(0,t).flatMap(e=>e.blocks)),text:a.turns[t]?.text??``})},D=s===`replayed`;return(0,K.jsx)(J,{iface:t,feed:D?h:g,trace:n,card:r({isRunning:p.kind===`running`,onStop:()=>{S(),m({kind:`done`})}}),conversation:(0,K.jsx)(Y,{iface:t,blocks:D?[...b.blocks,...b.streamBlocks]:W(a),chat:D?b:void 0,banner:D?(0,K.jsx)(Ce,{status:p,turns:a.turns.length,onContinue:T,onLive:E}):void 0})})}function Te(e){return(0,K.jsx)(u,{children:(0,K.jsx)(h,{labels:v,children:(0,K.jsx)(Ee,{...e})})})}function Ee({payload:e,trace:t,runtime:n,onLive:r}){let i=(0,G.useMemo)(()=>d(e),[e]),[a,o]=(0,G.useState)(),s=(0,G.useMemo)(()=>a&&fe(a.records),[a]),c=(0,G.useMemo)(()=>$(a?.records??[]),[a]),[l,u]=(0,G.useState)(0),[f,p]=(0,G.useState)(`recorded`),[m,h]=(0,G.useState)(!1),g=e=>{o(e),u(0),p(`recorded`)},_=()=>{u(e=>e+1),p(`replayed`)};if(i.type===`live`)return null;if(!a||!s)return(0,K.jsx)(J,{iface:i,feed:c,trace:t,card:(0,K.jsx)(Q,{onImport:g}),conversation:null});let v=({isRunning:t,onStop:n})=>(0,K.jsx)(Q,{onImport:g,controls:{opened:a,script:s,payload:e,shown:l>0?f:null,onShown:p,liveTools:m,onLiveTools:e=>{h(e),l>0&&_()},isRunning:t,onReplay:_,onStop:n}});return l===0?(0,K.jsx)(J,{iface:i,feed:c,trace:t,card:v({isRunning:!1,onStop:()=>void 0}),conversation:(0,K.jsx)(Y,{iface:i,blocks:W(s)})}):(0,K.jsx)(we,{payload:e,iface:i,trace:t,card:v,opened:a,script:s,shown:f,liveTools:m,runtime:n,onLive:r},l)}export{Te as TraceReplay};
@@ -1 +0,0 @@
1
- import{ur as e}from"./tool-schema-DUAd6AXZ.js";var t=e.filter(e=>e!==`builtin`),n=`Tool type must be ${t.join(`, `).replace(/, ([^,]+)$/,`, or $1`)}.`;export{n,t};