@theoremjs/studio 0.3.4-next.458.gbf7b487 → 0.3.4-next.460.g4444a29
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/package.json +4 -4
- package/page/assets/{Banner-C4MPbvft.js → Banner-BXLdz4y2.js} +2 -2
- package/page/assets/{ConsoleFrame-BkzieVRC.js → ConsoleFrame-DJ2vIGy8.js} +1 -1
- package/page/assets/{ContextMenu-BGP2gdee.js → ContextMenu-DnU_R5on.js} +2 -2
- package/page/assets/{ToolResultCharts-xDwNDd-T.js → ToolResultCharts-BFLDoF4L.js} +1 -1
- package/page/assets/{TraceInspector-CHpdhiVX.js → TraceInspector-CLL7OG3M.js} +1 -1
- package/page/assets/{TraceOverview-DCGew7UN.js → TraceOverview-BUqgljgU.js} +1 -1
- package/page/assets/{browser-engine-Ca2pvYX0.js → browser-engine-zievI8f-.js} +1 -1
- package/page/assets/{browser-transport-DYgEItHi.js → browser-transport-ArRkOmu8.js} +3 -3
- package/page/assets/{export-agent-5rXmF-g1.js → export-agent-Dz3Y7tO7.js} +1 -1
- package/page/assets/{guardrail-tester-B-ZfQFVu.js → guardrail-tester-D-hsX8gK.js} +1 -1
- package/page/assets/{index-Dajtrq_Z.js → index-DGzlieAM.js} +6 -6
- package/page/assets/{studio-code-pane-CKYRitdD.js → studio-code-pane-BNwB_may.js} +1 -1
- package/page/assets/{studio-console-DwhqnNyw.js → studio-console-gYuEwLzY.js} +1 -1
- package/page/assets/{studio-decision-Ckj4UNNt.js → studio-decision-BenlP-cQ.js} +1 -1
- package/page/assets/{studio-embedding-8qL_dVlz.js → studio-embedding-ChUIvwWb.js} +1 -1
- package/page/assets/{studio-host-console-BXwwloN4.js → studio-host-console-Dg6LezAO.js} +2 -2
- package/page/assets/{studio-labels-C1pvg0JC.js → studio-labels-YnrLEnjn.js} +1 -1
- package/page/assets/{studio-live-26srJ74m.js → studio-live-CaYSM1iE.js} +1 -1
- package/page/assets/{studio-map-C5zsJusF.js → studio-map-BYqiUV_l.js} +1 -1
- package/page/assets/{studio-trace-replay-B38TicvO.js → studio-trace-replay-DDcuo5Zv.js} +1 -1
- package/page/assets/{use-one-call-DjVkallj.js → use-one-call-DLdyrBVf.js} +1 -1
- package/page/index.html +5 -5
- package/ui/tree-map.css +66 -27
- package/ui/tree-map.d.ts +5 -5
- package/ui/tree-map.js +77 -24
package/ui/tree-map.css
CHANGED
|
@@ -15,44 +15,83 @@
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* goes back from
|
|
18
|
+
* Detail adds nodes. What is drawn moves to make room first, then each added node draws in after
|
|
19
|
+
* the one before, as the loader's map draws (read-map.css): its line, then its token. Without
|
|
20
|
+
* detail, the added ones leave in the reverse order, then the rest moves back.
|
|
21
|
+
* invariant: Transitions, not keyframes, so both ways ease, and a turn mid-way goes back from
|
|
22
|
+
* where it is. An added node only ever jumps to its place while it is not drawn.
|
|
22
23
|
*/
|
|
23
24
|
.studio-tree-map {
|
|
24
|
-
--
|
|
25
|
+
--added-step: 40ms;
|
|
26
|
+
--added-draw: var(--duration-medium, 240ms);
|
|
27
|
+
--map-move: var(--duration-slow, 400ms);
|
|
28
|
+
/* How long the added nodes take to leave, before the rest moves back. */
|
|
29
|
+
--map-leave: calc(var(--added-n) * var(--added-step) + 2 * var(--added-draw));
|
|
30
|
+
--map-ease: var(--ease-standard, ease-out);
|
|
25
31
|
}
|
|
26
32
|
|
|
27
|
-
.studio-tree-map
|
|
28
|
-
|
|
29
|
-
stroke-dashoffset: 0;
|
|
30
|
-
transition: stroke-dashoffset var(--duration-medium, 240ms) var(--ease-standard, ease-out)
|
|
31
|
-
calc(var(--feed-i) * var(--feed-step));
|
|
33
|
+
.studio-tree-map > [data-added] {
|
|
34
|
+
opacity: 0;
|
|
32
35
|
}
|
|
33
36
|
|
|
34
|
-
.studio-tree-map
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
.studio-tree-map-lines [data-added] {
|
|
38
|
+
stroke-dasharray: 1;
|
|
39
|
+
stroke-dashoffset: var(--added-from);
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
.studio-tree-map[data-
|
|
40
|
-
opacity:
|
|
41
|
-
transition-delay: calc((var(--feed-n) - var(--feed-i)) * var(--feed-step));
|
|
42
|
+
.studio-tree-map[data-detail] > [data-added] {
|
|
43
|
+
opacity: 1;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
.studio-tree-map[data-
|
|
45
|
-
stroke-dashoffset:
|
|
46
|
-
transition-delay: calc(
|
|
47
|
-
(var(--feed-n) - var(--feed-i)) *
|
|
48
|
-
var(--feed-step) +
|
|
49
|
-
var(--duration-medium, 240ms)
|
|
50
|
-
);
|
|
46
|
+
.studio-tree-map[data-detail] .studio-tree-map-lines [data-added] {
|
|
47
|
+
stroke-dashoffset: 0;
|
|
51
48
|
}
|
|
52
49
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
.studio-tree-map >
|
|
56
|
-
|
|
50
|
+
/* invariant: With reduced motion, nothing moves: each node is at once where it ends. */
|
|
51
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
52
|
+
.studio-tree-map > .map-token,
|
|
53
|
+
.studio-tree-map-lines .map-line {
|
|
54
|
+
transition:
|
|
55
|
+
top var(--map-move) var(--map-ease) var(--map-leave),
|
|
56
|
+
left var(--map-move) var(--map-ease) var(--map-leave),
|
|
57
|
+
d var(--map-move) var(--map-ease) var(--map-leave);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.studio-tree-map > [data-added] {
|
|
61
|
+
transition:
|
|
62
|
+
opacity var(--added-draw) var(--map-ease)
|
|
63
|
+
calc((var(--added-n) - var(--added-i)) * var(--added-step)),
|
|
64
|
+
top 0s var(--map-leave),
|
|
65
|
+
left 0s var(--map-leave);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.studio-tree-map-lines [data-added] {
|
|
69
|
+
transition:
|
|
70
|
+
stroke-dashoffset var(--added-draw) var(--map-ease)
|
|
71
|
+
calc((var(--added-n) - var(--added-i)) * var(--added-step) + var(--added-draw)),
|
|
72
|
+
d 0s var(--map-leave);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.studio-tree-map[data-detail] > .map-token {
|
|
76
|
+
transition-delay: 0s;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.studio-tree-map[data-detail] > [data-added] {
|
|
80
|
+
transition:
|
|
81
|
+
opacity var(--added-draw) var(--map-ease)
|
|
82
|
+
calc(var(--map-move) + var(--added-i) * var(--added-step) + var(--added-draw)),
|
|
83
|
+
top 0s,
|
|
84
|
+
left 0s;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.studio-tree-map[data-detail] .studio-tree-map-lines .map-line {
|
|
88
|
+
transition-delay: 0s;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.studio-tree-map[data-detail] .studio-tree-map-lines [data-added] {
|
|
92
|
+
transition:
|
|
93
|
+
stroke-dashoffset var(--added-draw) var(--map-ease)
|
|
94
|
+
calc(var(--map-move) + var(--added-i) * var(--added-step)),
|
|
95
|
+
d 0s;
|
|
57
96
|
}
|
|
58
97
|
}
|
package/ui/tree-map.d.ts
CHANGED
|
@@ -4,10 +4,10 @@ export interface StudioTreeMapProps {
|
|
|
4
4
|
/** The keys of the agents to draw, in the workspace's order; every agent when unset. */
|
|
5
5
|
agents?: readonly string[] | undefined;
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
* before, its line
|
|
9
|
-
* reverse order
|
|
7
|
+
* Every tool in the registry, not a few, and each turn runner opened into the steps of a turn. Turned on, what is drawn moves to make room, then each
|
|
8
|
+
* node it adds draws in after the one before, its line first, as the loader's map draws; turned
|
|
9
|
+
* off, they leave in the reverse order and the rest moves back.
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
detail?: boolean | undefined;
|
|
12
12
|
}
|
|
13
|
-
export declare function StudioTreeMap({ workspace, agents,
|
|
13
|
+
export declare function StudioTreeMap({ workspace, agents, detail }: StudioTreeMapProps): import("react").JSX.Element;
|
package/ui/tree-map.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { IconCloud, IconEngine, IconSettingsAutomation, IconTool } from '@tabler/icons-react';
|
|
2
|
+
import { IconAdjustments, IconArrowsMinimize, IconChecks, IconCloud, IconEngine, IconFlag, IconKey, IconRepeat, IconSettingsAutomation, IconShieldCheck, IconTimeline, IconTool, } from '@tabler/icons-react';
|
|
3
3
|
import { useRef } from 'react';
|
|
4
4
|
import { mapCurve } from "../map-line.js";
|
|
5
5
|
import { createBlankDraft, libraryDraft, workspaceTree, } from "../mod.js";
|
|
@@ -72,7 +72,26 @@ function runnerLabel(type) {
|
|
|
72
72
|
return 'Embedding runner';
|
|
73
73
|
return 'Turn runner';
|
|
74
74
|
}
|
|
75
|
-
|
|
75
|
+
/**
|
|
76
|
+
* What a turn runner does in one turn, in order.
|
|
77
|
+
* why: The kernel contract's turn lifecycle (docs/contracts/kernel.md, "Turn lifecycle"), step for
|
|
78
|
+
* step; a decision and a session have no such list there, so their runners open into nothing.
|
|
79
|
+
*/
|
|
80
|
+
const TURN_STEPS = [
|
|
81
|
+
{ id: 'resolve', label: 'Resolve', icon: IconAdjustments },
|
|
82
|
+
{ id: 'sanitize', label: 'Sanitize', icon: IconShieldCheck },
|
|
83
|
+
{ id: 'compaction', label: 'Compaction', icon: IconArrowsMinimize },
|
|
84
|
+
{ id: 'canary', label: 'Canary bind', icon: IconKey },
|
|
85
|
+
{ id: 'pre_turn', label: 'pre_turn', icon: IconFlag },
|
|
86
|
+
{ id: 'stream', label: 'Provider stream', icon: IconCloud },
|
|
87
|
+
{ id: 'tools', label: 'Tool loop', icon: IconRepeat },
|
|
88
|
+
{ id: 'before_end', label: 'before_end', icon: IconFlag },
|
|
89
|
+
{ id: 'validation', label: 'Validation', icon: IconChecks },
|
|
90
|
+
{ id: 'egress', label: 'Egress', icon: IconShieldCheck },
|
|
91
|
+
{ id: 'trace', label: 'Trace', icon: IconTimeline },
|
|
92
|
+
{ id: 'post_turn', label: 'post_turn', icon: IconFlag },
|
|
93
|
+
];
|
|
94
|
+
function feedsOf(workspace, rows, detail) {
|
|
76
95
|
const feeds = [];
|
|
77
96
|
const add = (id, label, icon, into, under, depth = 0) => {
|
|
78
97
|
const below = (feeds.at(-1)?.y ?? Number.NEGATIVE_INFINITY) + ROW;
|
|
@@ -93,8 +112,13 @@ function feedsOf(workspace, rows) {
|
|
|
93
112
|
if (!name)
|
|
94
113
|
continue;
|
|
95
114
|
const runner = runnerLabel(agent.identity.profileType);
|
|
96
|
-
if (runner)
|
|
97
|
-
|
|
115
|
+
if (runner) {
|
|
116
|
+
const id = `${agent.key}/runner`;
|
|
117
|
+
add(id, runner, IconEngine, [name]);
|
|
118
|
+
const steps = detail && runner === 'Turn runner' ? TURN_STEPS : [];
|
|
119
|
+
for (const step of steps)
|
|
120
|
+
add(`${id}/${step.id}`, step.label, step.icon, [], id, 1);
|
|
121
|
+
}
|
|
98
122
|
const providers = new Map();
|
|
99
123
|
for (const binding of agent.modelBindings) {
|
|
100
124
|
const row = mine.find((each) => each.node.ref.facet === 'modelBinding' && each.node.ref.key === binding.key);
|
|
@@ -113,7 +137,7 @@ function feedsOf(workspace, rows) {
|
|
|
113
137
|
else if (tools && workspace.toolSpecs.length > 0) {
|
|
114
138
|
const registry = REGISTRY;
|
|
115
139
|
add(registry, 'Tool registry', IconTool, [tools]);
|
|
116
|
-
for (const tool of
|
|
140
|
+
for (const tool of listedTools(workspace.toolSpecs, detail)) {
|
|
117
141
|
const icon = toolTypeIcon(tool.toolType);
|
|
118
142
|
add(`${registry}/${tool.key}`, tool.toolName, icon, [], registry, 1);
|
|
119
143
|
}
|
|
@@ -122,14 +146,18 @@ function feedsOf(workspace, rows) {
|
|
|
122
146
|
}
|
|
123
147
|
return feeds;
|
|
124
148
|
}
|
|
125
|
-
/**
|
|
126
|
-
|
|
149
|
+
/**
|
|
150
|
+
* The registry's tools: the first of each type, then the rest in the registry's order. A few of
|
|
151
|
+
* them, or with `detail` every one.
|
|
152
|
+
*/
|
|
153
|
+
function listedTools(tools, detail) {
|
|
127
154
|
const firsts = TOOL_TYPES.flatMap((type) => {
|
|
128
155
|
const tool = tools.find((each) => each.toolType === type);
|
|
129
156
|
return tool ? [tool] : [];
|
|
130
157
|
});
|
|
131
158
|
const rest = tools.filter((tool) => !firsts.includes(tool));
|
|
132
|
-
|
|
159
|
+
const listed = [...firsts, ...rest];
|
|
160
|
+
return detail ? listed : listed.slice(0, SHOWN_TOOLS);
|
|
133
161
|
}
|
|
134
162
|
/** Right from `from` to `rail`, up or down it, and back left to `to`, its corners turned. */
|
|
135
163
|
function sidePath(from, to, rail) {
|
|
@@ -142,12 +170,22 @@ function linePath(from, to) {
|
|
|
142
170
|
const x = from.x + TRUNK;
|
|
143
171
|
return `M ${x} ${from.y + HALF} V ${to.y - TURN} Q ${x} ${to.y} ${x + TURN} ${to.y} H ${to.x - LINE_GAP}`;
|
|
144
172
|
}
|
|
145
|
-
/** The order
|
|
146
|
-
const
|
|
147
|
-
|
|
173
|
+
/** The order an added node draws in, and which end its line starts from: 1 the path's start, -1 its end. */
|
|
174
|
+
const addedStyle = (index, from = 1) => ({ '--added-i': index, '--added-from': from });
|
|
175
|
+
/**
|
|
176
|
+
* A line's path as a style too, so a line that moves eases to its new shape where the browser
|
|
177
|
+
* eases `d`; the attribute draws it where it does not.
|
|
178
|
+
*/
|
|
179
|
+
const pathStyle = (d, style) => ({ ...style, d: `path("${d}")` });
|
|
180
|
+
export function StudioTreeMap({ workspace, agents, detail = false }) {
|
|
148
181
|
const root = useRef(null);
|
|
149
182
|
const rows = rowsOf(workspace, agents);
|
|
150
|
-
const
|
|
183
|
+
const few = feedsOf(workspace, rows, false);
|
|
184
|
+
const full = feedsOf(workspace, rows, true);
|
|
185
|
+
const fewIds = new Set(few.map((feed) => feed.id));
|
|
186
|
+
const addedIndex = new Map(full.filter((feed) => !fewIds.has(feed.id)).map((feed, index) => [feed.id, index]));
|
|
187
|
+
/** The feeds laid out; without detail, an added one waits on the feed it comes under. */
|
|
188
|
+
const feeds = detail ? full : few;
|
|
151
189
|
const widths = useTokenWidths(root, workspace);
|
|
152
190
|
const drafts = new Map(workspace.agents.map((agent) => [
|
|
153
191
|
agent.key,
|
|
@@ -157,6 +195,7 @@ export function StudioTreeMap({ workspace, agents, feeds: shown = 'shown' }) {
|
|
|
157
195
|
const feedX = Math.max(0, ...rows.map(right)) + GAP;
|
|
158
196
|
const byId = new Map(rows.map((row) => [rowId(row), row]));
|
|
159
197
|
const feedById = new Map(feeds.map((feed) => [feed.id, feed]));
|
|
198
|
+
const placed = (feed) => feedById.get(feed.id) ?? { ...feed, y: feedById.get(feed.under ?? '')?.y ?? feed.y };
|
|
160
199
|
const height = PAD * 2 + Math.max(rows.length * ROW, ...feeds.map((feed) => feed.y + HALF - PAD));
|
|
161
200
|
const feedLeft = (feed) => feedX + feed.depth * INDENT;
|
|
162
201
|
const feedRight = (feed) => feedLeft(feed) + (widths[feed.id] ?? GUESS);
|
|
@@ -168,28 +207,42 @@ export function StudioTreeMap({ workspace, agents, feeds: shown = 'shown' }) {
|
|
|
168
207
|
return above && feed.depth <= above.depth ? [railFor(feed, above)] : [];
|
|
169
208
|
});
|
|
170
209
|
const width = Math.max(GUESS, ...feeds.map(feedRight), ...rails) + PAD;
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return
|
|
179
|
-
|
|
210
|
+
/** What marks a node or line detail adds: its turn to draw, and the end its line draws from. */
|
|
211
|
+
const addedProps = (id, from = 1) => {
|
|
212
|
+
const index = addedIndex.get(id);
|
|
213
|
+
return index === undefined ? {} : { 'data-added': '', style: addedStyle(index, from) };
|
|
214
|
+
};
|
|
215
|
+
return (_jsxs("div", { ref: root, className: "studio-tree-map", "data-detail": detail ? '' : undefined, style: { width, height, '--added-n': addedIndex.size }, children: [_jsxs("svg", { className: "studio-tree-map-lines", width: width, height: height, "aria-hidden": "true", children: [rows.map((row) => row.parent && (_jsx("path", { className: "map-line", d: linePath(row.parent, row), style: pathStyle(linePath(row.parent, row)) }, rowId(row)))), full.flatMap((each) => {
|
|
216
|
+
const feed = placed(each);
|
|
217
|
+
return feed.into.map((id) => {
|
|
218
|
+
const row = byId.get(id);
|
|
219
|
+
if (!row)
|
|
220
|
+
return null;
|
|
221
|
+
const { d } = mapCurve({ x: feedX - LINE_GAP, y: feed.y }, { x: right(row) + LINE_GAP, y: row.y });
|
|
222
|
+
// The line runs from the feed to the row; it draws from the row.
|
|
223
|
+
const { style, ...added } = addedProps(feed.id, -1);
|
|
224
|
+
return (_jsx("path", { className: "map-line", d: d, pathLength: 1, style: pathStyle(d, style), ...added }, `${feed.id}>${id}`));
|
|
225
|
+
});
|
|
226
|
+
}), full.map((each) => {
|
|
227
|
+
const feed = placed(each);
|
|
180
228
|
const above = feed.under === undefined ? undefined : feedById.get(feed.under);
|
|
181
229
|
if (above === undefined)
|
|
182
230
|
return null;
|
|
183
231
|
const from = { x: feedLeft(above), y: above.y };
|
|
184
232
|
// One of its own turns in from the trunk, as a tree row does; one level with it comes round
|
|
185
233
|
// the right of what lies between, so it reads as joining the feed, not as one of its own.
|
|
186
|
-
const
|
|
234
|
+
const isOwn = feed.depth > above.depth;
|
|
235
|
+
const d = isOwn
|
|
187
236
|
? linePath(from, { x: feedLeft(feed), y: feed.y })
|
|
188
237
|
: sidePath({ x: feedRight(feed) + LINE_GAP, y: feed.y }, { x: feedRight(above) + LINE_GAP, y: above.y }, railFor(feed, above));
|
|
189
238
|
// A turn in runs from the feed above; a line round the side runs from this one.
|
|
190
|
-
|
|
239
|
+
const { style, ...added } = addedProps(feed.id, isOwn ? 1 : -1);
|
|
240
|
+
return (_jsx("path", { className: "map-line", d: d, pathLength: 1, style: pathStyle(d, style), ...added }, `${feed.id}^`));
|
|
191
241
|
})] }), rows.map((row) => {
|
|
192
242
|
const draft = drafts.get(row.agent) ?? createBlankDraft();
|
|
193
243
|
return (_jsx(MapToken, { id: rowId(row), label: row.node.label, icon: nodeIcon(draft, row.node.ref), x: row.x, y: row.y }, rowId(row)));
|
|
194
|
-
}),
|
|
244
|
+
}), full.map((each) => {
|
|
245
|
+
const feed = placed(each);
|
|
246
|
+
return (_jsx(MapToken, { id: feed.id, label: feed.label, icon: feed.icon, x: feedLeft(feed), y: feed.y, ...addedProps(feed.id) }, feed.id));
|
|
247
|
+
})] }));
|
|
195
248
|
}
|