@tangle-network/sandbox-ui 0.138.1 → 0.139.0

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.
@@ -0,0 +1,25 @@
1
+ // src/lib/reveal-in-scroller.ts
2
+ /**
3
+ * Scrolls an element into view inside its nearest scrolling ancestor only. Element.scrollIntoView moves every scrolling
4
+ * ancestor, the window included, so a pane that reveals its selection on load would jump the whole page.
5
+ */
6
+ function revealInScroller(element, block = "nearest") {
7
+ let scroller = parentOf(element);
8
+ while (scroller && !scrolls(scroller)) scroller = parentOf(scroller);
9
+ if (!scroller || scroller === document.scrollingElement || scroller === document.body) return;
10
+ const box = scroller.getBoundingClientRect();
11
+ const target = element.getBoundingClientRect();
12
+ const above = target.top - box.top;
13
+ const below = target.bottom - box.top - scroller.clientHeight;
14
+ if (block === "center") scroller.scrollTop += above - (scroller.clientHeight - target.height) / 2;
15
+ else if (above < 0) scroller.scrollTop += above;
16
+ else if (below > 0) scroller.scrollTop += Math.min(below, above);
17
+ }
18
+ function parentOf(node) {
19
+ return node.parentElement ?? node.getRootNode().host ?? null;
20
+ }
21
+ function scrolls(node) {
22
+ const { overflowY } = getComputedStyle(node);
23
+ return (overflowY === "auto" || overflowY === "scroll") && node.scrollHeight > node.clientHeight;
24
+ }
25
+ export { revealInScroller as t };
@@ -1,6 +1,7 @@
1
1
  import { t as cn } from "./utils-BER_bdgE.js";
2
2
  import { i as modelBrandFor, t as ModelBrandStack } from "./model-brand-bTcMjQtB.js";
3
3
  import { t as ProviderIcon } from "./provider-logo-CPKRPHcS.js";
4
+ import { t as AgentGraph } from "./AgentGraph-Beld8p6x.js";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
5
6
  import { useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
6
7
  import { X } from "lucide-react";
@@ -219,6 +220,36 @@ function useAgentStream(url) {
219
220
  function agentOf(span, byId) {
220
221
  for (let cursor = span; cursor; cursor = cursor.parentId ? byId.get(cursor.parentId) : void 0) if (cursor.kind === "pipeline") return cursor;
221
222
  }
223
+ /** The trace's agents as a spawn tree at the cursor: an agent not started by then is left out, one that ends after it is
224
+ * still running, so the Graph and the Timeline always show the same moment. */
225
+ function agentGraphAt(spans, byId, at, epoch, cards) {
226
+ const nodes = [];
227
+ const edges = [];
228
+ for (const span of spans) {
229
+ if (span.kind !== "pipeline" || !span.id || at !== null && span.startMs > at) continue;
230
+ const running = at === null ? span.status === "running" : span.endMs > at || span.status === "running";
231
+ nodes.push({
232
+ id: span.id,
233
+ label: span.name,
234
+ model: span.detail,
235
+ costUsd: span.costUsd,
236
+ status: running ? "running" : span.status === "failed" ? "failed" : "succeeded",
237
+ startedAt: epoch === void 0 ? void 0 : epoch + span.startMs,
238
+ ...cards?.[span.id]
239
+ });
240
+ const parent = span.parentId ? byId.get(span.parentId) : void 0;
241
+ const spawner = parent && agentOf(parent, byId);
242
+ if (spawner?.id) edges.push({
243
+ from: spawner.id,
244
+ to: span.id,
245
+ kind: "spawn"
246
+ });
247
+ }
248
+ return {
249
+ nodes,
250
+ edges
251
+ };
252
+ }
222
253
  function timelineItems(entries, streaming) {
223
254
  return entries.map((entry, index) => {
224
255
  if (entry.kind === "message") return {
@@ -258,7 +289,7 @@ function NotTimeIndexed({ label }) {
258
289
  * streaming in a right-hand drawer, and the page's code workspace and scoreboard following the time cursor. Scrubbing is time travel:
259
290
  * every panel shows what was true at the cursor, and the conversation shows what had been said by then.
260
291
  */
261
- function TraceWorkspace({ trace, streamUrl, events, onTimeChange, files, scoreboard, selectedAgentId, onSelectAgent, className, ...waterfall }) {
292
+ function TraceWorkspace({ trace, streamUrl, events, onTimeChange, files, scoreboard, selectedAgentId, onSelectAgent, agentCards, className, ...waterfall }) {
262
293
  const byId = useMemo(() => new Map(trace.spans.flatMap((span) => span.id ? [[span.id, span]] : [])), [trace]);
263
294
  const [ownSelection, setOwnSelection] = useState();
264
295
  const selected = selectedAgentId ?? ownSelection;
@@ -278,6 +309,15 @@ function TraceWorkspace({ trace, streamUrl, events, onTimeChange, files, scorebo
278
309
  agent,
279
310
  stream.entries
280
311
  ]);
312
+ const [view, setView] = useState("timeline");
313
+ const graph = useMemo(() => view === "graph" ? agentGraphAt(trace.spans, byId, cursor, waterfall.startedAt, agentCards) : void 0, [
314
+ view,
315
+ trace,
316
+ byId,
317
+ cursor,
318
+ waterfall.startedAt,
319
+ agentCards
320
+ ]);
281
321
  const shown = cursor === null || origin === void 0 ? stream.entries : stream.entries.filter((entry) => entry.at - origin <= cursor);
282
322
  const items = useMemo(() => timelineItems(shown, cursor === null && stream.alive), [
283
323
  shown,
@@ -300,20 +340,44 @@ function TraceWorkspace({ trace, streamUrl, events, onTimeChange, files, scorebo
300
340
  return /* @__PURE__ */ jsxs("div", {
301
341
  className: cn("sandbox-trace-workspace flex min-h-0 flex-col gap-3", className),
302
342
  children: [
303
- /* @__PURE__ */ jsx(TraceWaterfall, {
304
- ...waterfall,
305
- trace,
306
- markers: events,
307
- selectedId: agent?.id,
308
- onDeselect: () => select(void 0),
309
- onSelect: (span) => {
310
- const owner = agentOf(span, byId);
311
- if (owner?.id) select(owner.id);
312
- },
313
- onTimeChange: (t) => {
314
- setCursor(t);
315
- onTimeChange?.(t);
316
- }
343
+ /* @__PURE__ */ jsx("div", {
344
+ role: "group",
345
+ "aria-label": "Run view",
346
+ className: "flex gap-1 self-end rounded-lg border border-border bg-card p-0.5 text-sm",
347
+ children: ["timeline", "graph"].map((option) => /* @__PURE__ */ jsx("button", {
348
+ type: "button",
349
+ "aria-pressed": view === option,
350
+ onClick: () => setView(option),
351
+ className: "rounded-md px-3 py-1 capitalize text-muted-foreground aria-pressed:bg-muted aria-pressed:text-foreground",
352
+ children: option
353
+ }, option))
354
+ }),
355
+ graph && /* @__PURE__ */ jsx(AgentGraph, {
356
+ nodes: graph.nodes,
357
+ edges: graph.edges,
358
+ selectedId: agent?.id ?? null,
359
+ onSelect: select,
360
+ live: cursor === null && graph.nodes.some((node) => node.status === "running"),
361
+ now: cursor !== null && waterfall.startedAt !== void 0 ? waterfall.startedAt + cursor : void 0,
362
+ className: "h-[60vh] min-h-[480px] rounded-xl border border-border bg-card"
363
+ }),
364
+ /* @__PURE__ */ jsx("div", {
365
+ hidden: view === "graph",
366
+ children: /* @__PURE__ */ jsx(TraceWaterfall, {
367
+ ...waterfall,
368
+ trace,
369
+ markers: events,
370
+ selectedId: agent?.id,
371
+ onDeselect: () => select(void 0),
372
+ onSelect: (span) => {
373
+ const owner = agentOf(span, byId);
374
+ if (owner?.id) select(owner.id);
375
+ },
376
+ onTimeChange: (t) => {
377
+ setCursor(t);
378
+ onTimeChange?.(t);
379
+ }
380
+ })
317
381
  }),
318
382
  /* @__PURE__ */ jsx("section", {
319
383
  "aria-label": "Code at the cursor",
package/dist/run.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as ToolCallType, B as TraceEvent, C as TaskListItem, D as ToolCallFeed, E as ToolCallData, F as AgentStreamRow, G as traceSpanMark, H as TraceWorkspaceProps, I as AgentStreamState, L as AgentTranscriptEntry, M as showsTaskPriority, N as taskProgress, O as ToolCallFeedProps, P as taskStatus, R as foldAgentRows, S as TaskList, T as TaskStatus, U as TraceWaterfall, V as TraceWorkspace, W as TraceWaterfallProps, _ as RunPhaseList, a as ApprovalPlanStep, b as RunRowStatus, c as FeedSegment, d as InlineToolItem, f as InlineToolItemProps, g as RunPhase, h as RunGroupProps, i as ApprovalDiffSummary, j as parseToolEvent, k as ToolCallStatus, l as InlineThinkingItem, m as RunGroup, n as ApprovalCardProps, o as ExpandedToolDetail, p as LiveDuration, r as ApprovalDiffFile, s as ExpandedToolDetailProps, t as ApprovalCard, u as InlineThinkingItemProps, v as RunRowShell, w as TaskListProps, x as RunRowStatusDot, y as RunRowShellProps, z as useAgentStream } from "./index-C5h5T0nb.js";
1
+ import { A as ToolCallType, B as TraceEvent, C as TaskListItem, D as ToolCallFeed, E as ToolCallData, F as AgentStreamRow, G as traceSpanMark, H as TraceWorkspaceProps, I as AgentStreamState, L as AgentTranscriptEntry, M as showsTaskPriority, N as taskProgress, O as ToolCallFeedProps, P as taskStatus, R as foldAgentRows, S as TaskList, T as TaskStatus, U as TraceWaterfall, V as TraceWorkspace, W as TraceWaterfallProps, _ as RunPhaseList, a as ApprovalPlanStep, b as RunRowStatus, c as FeedSegment, d as InlineToolItem, f as InlineToolItemProps, g as RunPhase, h as RunGroupProps, i as ApprovalDiffSummary, j as parseToolEvent, k as ToolCallStatus, l as InlineThinkingItem, m as RunGroup, n as ApprovalCardProps, o as ExpandedToolDetail, p as LiveDuration, r as ApprovalDiffFile, s as ExpandedToolDetailProps, t as ApprovalCard, u as InlineThinkingItemProps, v as RunRowShell, w as TaskListProps, x as RunRowStatusDot, y as RunRowShellProps, z as useAgentStream } from "./index-D6gtWRHq.js";
2
2
  export { type AgentStreamRow, type AgentStreamState, type AgentTranscriptEntry, ApprovalCard, type ApprovalCardProps, type ApprovalDiffFile, ApprovalDiffSummary, type ApprovalPlanStep, ExpandedToolDetail, type ExpandedToolDetailProps, type FeedSegment, InlineThinkingItem, type InlineThinkingItemProps, InlineToolItem, type InlineToolItemProps, LiveDuration, RunGroup, type RunGroupProps, type RunPhase, RunPhaseList, RunRowShell, type RunRowShellProps, type RunRowStatus, RunRowStatusDot, TaskList, type TaskListItem, type TaskListProps, type TaskStatus, type ToolCallData, ToolCallFeed, type ToolCallFeedProps, type ToolCallStatus, type ToolCallType, type TraceEvent, TraceWaterfall, type TraceWaterfallProps, TraceWorkspace, type TraceWorkspaceProps, foldAgentRows, parseToolEvent, showsTaskPriority, taskProgress, taskStatus, traceSpanMark, useAgentStream };
package/dist/run.js CHANGED
@@ -1 +1 @@
1
- export { t as ApprovalCard, n as ApprovalDiffSummary, r as ExpandedToolDetail, i as InlineThinkingItem, a as InlineToolItem, o as LiveDuration, s as RunGroup, c as RunPhaseList, l as RunRowShell, u as RunRowStatusDot, d as TaskList, f as ToolCallFeed, b as TraceWaterfall, _ as TraceWorkspace, v as foldAgentRows, p as parseToolEvent, m as showsTaskPriority, h as taskProgress, g as taskStatus, x as traceSpanMark, y as useAgentStream } from "./run-CliTxkfw.js";
1
+ export { t as ApprovalCard, n as ApprovalDiffSummary, r as ExpandedToolDetail, i as InlineThinkingItem, a as InlineToolItem, o as LiveDuration, s as RunGroup, c as RunPhaseList, l as RunRowShell, u as RunRowStatusDot, d as TaskList, f as ToolCallFeed, b as TraceWaterfall, _ as TraceWorkspace, v as foldAgentRows, p as parseToolEvent, m as showsTaskPriority, h as taskProgress, g as taskStatus, x as traceSpanMark, y as useAgentStream } from "./run-CC-DESx8.js";
package/dist/styles.css CHANGED
@@ -835,6 +835,9 @@
835
835
  width: 100%;
836
836
  height: 100%;
837
837
  }
838
+ .\!h-1 {
839
+ height: var(--spacing) !important;
840
+ }
838
841
  .\!h-2 {
839
842
  height: calc(var(--spacing) * 2) !important;
840
843
  }
@@ -961,6 +964,9 @@
961
964
  .h-\[36rem\] {
962
965
  height: 36rem;
963
966
  }
967
+ .h-\[60vh\] {
968
+ height: 60vh;
969
+ }
964
970
  .h-\[70vh\] {
965
971
  height: 70vh;
966
972
  }
@@ -1201,12 +1207,18 @@
1201
1207
  .min-h-\[200px\] {
1202
1208
  min-height: 200px;
1203
1209
  }
1210
+ .min-h-\[480px\] {
1211
+ min-height: 480px;
1212
+ }
1204
1213
  .min-h-full {
1205
1214
  min-height: 100%;
1206
1215
  }
1207
1216
  .min-h-screen {
1208
1217
  min-height: 100vh;
1209
1218
  }
1219
+ .\!w-1 {
1220
+ width: var(--spacing) !important;
1221
+ }
1210
1222
  .\!w-2 {
1211
1223
  width: calc(var(--spacing) * 2) !important;
1212
1224
  }
@@ -1729,6 +1741,9 @@
1729
1741
  .flex-none {
1730
1742
  flex: none;
1731
1743
  }
1744
+ .flex-shrink {
1745
+ flex-shrink: 1;
1746
+ }
1732
1747
  .flex-shrink-0 {
1733
1748
  flex-shrink: 0;
1734
1749
  }
@@ -2112,6 +2127,9 @@
2112
2127
  .self-center {
2113
2128
  align-self: center;
2114
2129
  }
2130
+ .self-end {
2131
+ align-self: flex-end;
2132
+ }
2115
2133
  .self-start {
2116
2134
  align-self: flex-start;
2117
2135
  }
@@ -3634,6 +3652,10 @@
3634
3652
  --tw-leading: 15px;
3635
3653
  line-height: 15px;
3636
3654
  }
3655
+ .leading-\[18px\] {
3656
+ --tw-leading: 18px;
3657
+ line-height: 18px;
3658
+ }
3637
3659
  .leading-\[inherit\] {
3638
3660
  --tw-leading: inherit;
3639
3661
  line-height: inherit;
@@ -3686,6 +3708,10 @@
3686
3708
  --tw-font-weight: var(--font-weight-semibold);
3687
3709
  font-weight: var(--font-weight-semibold);
3688
3710
  }
3711
+ .tracking-\[-0\.01em\] {
3712
+ --tw-tracking: -0.01em;
3713
+ letter-spacing: -0.01em;
3714
+ }
3689
3715
  .tracking-\[0\.1em\] {
3690
3716
  --tw-tracking: 0.1em;
3691
3717
  letter-spacing: 0.1em;
@@ -4416,6 +4442,10 @@
4416
4442
  --tw-ease: var(--ease-out);
4417
4443
  transition-timing-function: var(--ease-out);
4418
4444
  }
4445
+ .\!outline-none {
4446
+ --tw-outline-style: none !important;
4447
+ outline-style: none !important;
4448
+ }
4419
4449
  .outline-none {
4420
4450
  --tw-outline-style: none;
4421
4451
  outline-style: none;
@@ -4430,6 +4460,9 @@
4430
4460
  .\[-webkit-mask-image\:linear-gradient\(to_right\,transparent\,black_16px\,black_calc\(100\%-16px\)\,transparent\)\] {
4431
4461
  -webkit-mask-image: linear-gradient(to right,transparent,black 16px,black calc(100% - 16px),transparent);
4432
4462
  }
4463
+ .\[animation-duration\:1\.6s\] {
4464
+ animation-duration: 1.6s;
4465
+ }
4433
4466
  .\[transition\:color_var\(--motion-control\)\,background-color_var\(--motion-control\)\,border-color_var\(--motion-control\)\,box-shadow_var\(--motion-control\)\,transform_var\(--motion-control\)\,scale_var\(--motion-control\)\,opacity_var\(--motion-control\)\] {
4434
4467
  transition: color var(--motion-control),background-color var(--motion-control),border-color var(--motion-control),box-shadow var(--motion-control),transform var(--motion-control),scale var(--motion-control),opacity var(--motion-control);
4435
4468
  }
@@ -4507,6 +4540,16 @@
4507
4540
  background-color: color-mix(in oklab, hsl(var(--primary)) 30%, transparent);
4508
4541
  }
4509
4542
  }
4543
+ .group-focus-visible\/agent\:outline-2:is(:where(.group\/agent):focus-visible *) {
4544
+ outline-style: var(--tw-outline-style);
4545
+ outline-width: 2px;
4546
+ }
4547
+ .group-focus-visible\/agent\:outline-offset-4:is(:where(.group\/agent):focus-visible *) {
4548
+ outline-offset: 4px;
4549
+ }
4550
+ .group-focus-visible\/agent\:outline-ring:is(:where(.group\/agent):focus-visible *) {
4551
+ outline-color: hsl(var(--ring));
4552
+ }
4510
4553
  .group-data-\[state\=indeterminate\]\/checkbox\:block:is(:where(.group\/checkbox)[data-state="indeterminate"] *) {
4511
4554
  display: block;
4512
4555
  }
@@ -4559,10 +4602,18 @@
4559
4602
  --tw-content: '';
4560
4603
  content: var(--tw-content);
4561
4604
  }
4605
+ .after\:pointer-events-none::after {
4606
+ content: var(--tw-content);
4607
+ pointer-events: none;
4608
+ }
4562
4609
  .after\:absolute::after {
4563
4610
  content: var(--tw-content);
4564
4611
  position: absolute;
4565
4612
  }
4613
+ .after\:inset-0::after {
4614
+ content: var(--tw-content);
4615
+ inset: 0px;
4616
+ }
4566
4617
  .after\:top-0::after {
4567
4618
  content: var(--tw-content);
4568
4619
  top: 0px;
@@ -4579,10 +4630,39 @@
4579
4630
  content: var(--tw-content);
4580
4631
  height: 2px;
4581
4632
  }
4633
+ .after\:rounded-xl::after {
4634
+ content: var(--tw-content);
4635
+ border-radius: var(--radius-xl);
4636
+ }
4582
4637
  .after\:bg-primary::after {
4583
4638
  content: var(--tw-content);
4584
4639
  background-color: hsl(var(--primary));
4585
4640
  }
4641
+ .after\:opacity-0::after {
4642
+ content: var(--tw-content);
4643
+ opacity: 0%;
4644
+ }
4645
+ .after\:shadow-\[0_10px_28px_-10px_hsl\(var\(--foreground\)\/0\.45\)\]::after {
4646
+ content: var(--tw-content);
4647
+ --tw-shadow: 0 10px 28px -10px var(--tw-shadow-color, hsl(var(--foreground)/0.45));
4648
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
4649
+ }
4650
+ .after\:transition-opacity::after {
4651
+ content: var(--tw-content);
4652
+ transition-property: opacity;
4653
+ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
4654
+ transition-duration: var(--tw-duration, var(--default-transition-duration));
4655
+ }
4656
+ .after\:duration-150::after {
4657
+ content: var(--tw-content);
4658
+ --tw-duration: 150ms;
4659
+ transition-duration: 150ms;
4660
+ }
4661
+ .after\:ease-out::after {
4662
+ content: var(--tw-content);
4663
+ --tw-ease: var(--ease-out);
4664
+ transition-timing-function: var(--ease-out);
4665
+ }
4586
4666
  .first\:pt-0:first-child {
4587
4667
  padding-top: 0px;
4588
4668
  }
@@ -4608,6 +4688,10 @@
4608
4688
  --tw-translate-y: calc(var(--spacing) * -0.5);
4609
4689
  translate: var(--tw-translate-x) var(--tw-translate-y);
4610
4690
  }
4691
+ .hover\:-translate-y-px:hover {
4692
+ --tw-translate-y: -1px;
4693
+ translate: var(--tw-translate-x) var(--tw-translate-y);
4694
+ }
4611
4695
  .hover\:border-\[var\(--border-accent\)\]:hover {
4612
4696
  border-color: var(--border-accent);
4613
4697
  }
@@ -5041,6 +5125,10 @@
5041
5125
  --tw-brightness: brightness(110%);
5042
5126
  filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
5043
5127
  }
5128
+ .hover\:after\:opacity-100:hover::after {
5129
+ content: var(--tw-content);
5130
+ opacity: 100%;
5131
+ }
5044
5132
  }
5045
5133
  .focus\:border-\[var\(--focus-border\)\]:focus {
5046
5134
  border-color: var(--focus-border);
@@ -5297,9 +5385,15 @@
5297
5385
  .aria-pressed\:bg-\[var\(--ix-sel-bg\)\][aria-pressed="true"] {
5298
5386
  background-color: var(--ix-sel-bg);
5299
5387
  }
5388
+ .aria-pressed\:bg-muted[aria-pressed="true"] {
5389
+ background-color: hsl(var(--muted));
5390
+ }
5300
5391
  .aria-pressed\:text-\[var\(--accent-text\)\][aria-pressed="true"] {
5301
5392
  color: var(--accent-text);
5302
5393
  }
5394
+ .aria-pressed\:text-foreground[aria-pressed="true"] {
5395
+ color: hsl(var(--foreground));
5396
+ }
5303
5397
  .aria-pressed\:shadow-\[inset_0_0_0_1px_var\(--ix-sel-ring\)\][aria-pressed="true"] {
5304
5398
  --tw-shadow: inset 0 0 0 1px var(--tw-shadow-color, var(--ix-sel-ring));
5305
5399
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
@@ -5574,6 +5668,11 @@
5574
5668
  }
5575
5669
  }
5576
5670
  }
5671
+ @media (prefers-reduced-motion: no-preference) {
5672
+ .motion-safe\:animate-spin {
5673
+ animation: var(--animate-spin);
5674
+ }
5675
+ }
5577
5676
  @media (prefers-reduced-motion: reduce) {
5578
5677
  .motion-reduce\:not-sr-only {
5579
5678
  position: static;
@@ -5594,6 +5693,16 @@
5594
5693
  .motion-reduce\:transition-none {
5595
5694
  transition-property: none;
5596
5695
  }
5696
+ .motion-reduce\:after\:transition-none::after {
5697
+ content: var(--tw-content);
5698
+ transition-property: none;
5699
+ }
5700
+ @media (hover: hover) {
5701
+ .motion-reduce\:hover\:translate-y-0:hover {
5702
+ --tw-translate-y: 0px;
5703
+ translate: var(--tw-translate-x) var(--tw-translate-y);
5704
+ }
5705
+ }
5597
5706
  .motion-reduce\:active\:scale-100:active {
5598
5707
  --tw-scale-x: 100%;
5599
5708
  --tw-scale-y: 100%;
@@ -6384,11 +6493,6 @@
6384
6493
  .tangle-prose .\[\.tangle-prose_\&\]\:no-underline\! {
6385
6494
  text-decoration-line: none !important;
6386
6495
  }
6387
- @media (hover:hover) {
6388
- .\[\@media\(hover\:hover\)\]\:opacity-0 {
6389
- opacity: 0%;
6390
- }
6391
- }
6392
6496
  @media (pointer:coarse) {
6393
6497
  .\[\@media\(pointer\:coarse\)\]\:min-h-10 {
6394
6498
  min-height: calc(var(--spacing) * 10);
@@ -1,3 +1,4 @@
1
+ import { t as revealInScroller } from "./reveal-in-scroller-CzKwuqCG.js";
1
2
  import { jsx, jsxs } from "react/jsx-runtime";
2
3
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
4
  import { ChevronRight, File, FileCode, FileImage, FileJson, FileSpreadsheet, FileText, Folder, FolderOpen } from "lucide-react";
@@ -202,7 +203,8 @@ function VaultTree({ root, selectedPath, activeFolder, onSelect, onFolderToggle,
202
203
  const reveal = pendingRevealRef.current;
203
204
  if (reveal && rowRefs.current.has(reveal)) {
204
205
  pendingRevealRef.current = null;
205
- rowRefs.current.get(reveal)?.scrollIntoView?.({ block: "nearest" });
206
+ const row = rowRefs.current.get(reveal);
207
+ if (row) revealInScroller(row);
206
208
  }
207
209
  const focus = pendingFocusRef.current;
208
210
  if (focus && rowRefs.current.has(focus)) {
@@ -1 +1 @@
1
- export { r as VAULT_TREE_CHILD_PAGE, i as VaultTree, t as fileTreeFromPaths, n as filterFileNodes } from "./tree-data-YXtcK6Ld.js";
1
+ export { r as VAULT_TREE_CHILD_PAGE, i as VaultTree, t as fileTreeFromPaths, n as filterFileNodes } from "./tree-data-Dmiu8aMf.js";
@@ -1 +1 @@
1
- export { t as DiffView } from "../diff-view-A0O0Z_SR.js";
1
+ export { t as DiffView } from "../diff-view-B9mNeTLF.js";
@@ -2,7 +2,7 @@ import { t as cn$1 } from "./utils-BER_bdgE.js";
2
2
  import { a as PortsList } from "./dashboard-ClKA3opr.js";
3
3
  import { n as TerminalView } from "./terminal-nUCznZRj.js";
4
4
  import { RichFileTree } from "./files.js";
5
- import { a as CodeSurface, n as buildUnifiedPatch, r as computeDiffStats, t as DiffView } from "./diff-view-A0O0Z_SR.js";
5
+ import { a as CodeSurface, n as buildUnifiedPatch, r as computeDiffStats, t as DiffView } from "./diff-view-B9mNeTLF.js";
6
6
  import { n as PreviewView } from "./embedded-app-view-DXsoPale.js";
7
7
  import { Button, Skeleton, Textarea } from "@tangle-network/ui/primitives";
8
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
package/dist/workbench.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as DiffStatsBadge, c as PillTabs, i as FileBreadcrumb, n as SandboxArtifactPane, o as GitStatusBadge, r as CodeView, s as PanelHeader, t as ChangesPane } from "./workbench-B3JL1qbt.js";
2
- import { a as CodeSurface, i as CODE_THEME, n as buildUnifiedPatch, r as computeDiffStats, t as DiffView } from "./diff-view-A0O0Z_SR.js";
1
+ import { a as DiffStatsBadge, c as PillTabs, i as FileBreadcrumb, n as SandboxArtifactPane, o as GitStatusBadge, r as CodeView, s as PanelHeader, t as ChangesPane } from "./workbench-DOgYO3Zg.js";
2
+ import { a as CodeSurface, i as CODE_THEME, n as buildUnifiedPatch, r as computeDiffStats, t as DiffView } from "./diff-view-B9mNeTLF.js";
3
3
  import { n as PreviewView, t as EmbeddedAppView } from "./embedded-app-view-DXsoPale.js";
4
4
  export { CODE_THEME, ChangesPane, CodeSurface, CodeView, DiffStatsBadge, DiffView, EmbeddedAppView, FileBreadcrumb, GitStatusBadge, PanelHeader, PillTabs, PreviewView, SandboxArtifactPane, buildUnifiedPatch, computeDiffStats };
@@ -1,6 +1,7 @@
1
1
  import { n as ModelBrandStack, o as modelBrandFor, t as ModelBrandIdentity } from "./model-brand-ZwVS49Fq.js";
2
+ import { a as AgentGraphTool, c as AgentGraphEdge, d as AgentGraphNode, f as AgentGraphStatus, i as AgentGraphCallKind, l as AgentGraphEdgeKind, n as AgentGraphProps, o as AgentGraphActivity, r as AgentGraphCall, s as AgentGraphDirection, t as AgentGraph, u as AgentGraphEvent } from "./AgentGraph-DL-QLjkw.js";
2
3
  import { StatusTone } from "@tangle-network/ui/primitives";
3
- import { ReactElement } from "react";
4
+ import { Component, ReactElement, ReactNode } from "react";
4
5
  import { LucideIcon } from "lucide-react";
5
6
  import "@xyflow/react";
6
7
  import "@xyflow/react/dist/style.css";
@@ -670,4 +671,4 @@ export declare function NodeOutputBody({ shape, rows, tone }: {
670
671
  rows?: number | "none";
671
672
  tone?: "default" | "error";
672
673
  }): ReactElement | null;
673
- export { type ActionPathParts, type BuildWorkflowGraphOptions, type LeadCase, type ModelBrandIdentity, ModelBrandStack, StatusPill as NodeStatusPill, type OutputShape, type WfEdge, type WfEdgeKind, type WfEdgeSpec, type WfGraph, type WfNode, type WfNodeData, type WfNodeState, type WfNodeStatus, type WfNodeTone, type WfProblem, type WfProblemSeverity, WorkflowGraph as WorkflowGraphLazy, type WorkflowGraphProps, modelBrandFor };
674
+ export { type ActionPathParts, AgentGraph, type AgentGraphActivity, type AgentGraphCall, type AgentGraphCallKind, type AgentGraphDirection, type AgentGraphEdge, type AgentGraphEdgeKind, type AgentGraphEvent, type AgentGraphNode, type AgentGraphProps, type AgentGraphStatus, type AgentGraphTool, type BuildWorkflowGraphOptions, type LeadCase, type ModelBrandIdentity, ModelBrandStack, StatusPill as NodeStatusPill, type OutputShape, type WfEdge, type WfEdgeKind, type WfEdgeSpec, type WfGraph, type WfNode, type WfNodeData, type WfNodeState, type WfNodeStatus, type WfNodeTone, type WfProblem, type WfProblemSeverity, WorkflowGraph as WorkflowGraphLazy, type WorkflowGraphProps, modelBrandFor };
package/dist/workflows.js CHANGED
@@ -1,83 +1,4 @@
1
1
  import { i as modelBrandFor, t as ModelBrandStack } from "./model-brand-bTcMjQtB.js";
2
- import { A as triggerNodeIndex, D as buildWorkflowGraph, E as branchNodeId, F as parseActionPath, I as shortModel, N as actionPathLabel, P as humanizeIdentifier, T as actionNodeId, a as NodeMark, d as STATUS_LABEL, f as STATUS_PILL, h as StatusPill, i as KIND_ICON, k as triggerNodeId, n as classifyOutput, p as STATUS_TONE, r as condenseText, t as NodeOutputBody, u as STATUS_COLOR, w as TRIGGER_NODE_ID } from "./node-output-udnwhShN.js";
3
- import { jsx, jsxs } from "react/jsx-runtime";
4
- import { Component, Suspense, lazy, useMemo, useState } from "react";
5
- // src/workflows/WorkflowGraphLazy.tsx
6
- /**
7
- * Lazy + error-isolated boundary for {@link WorkflowGraph}. React Flow (~50KB)
8
- * is only needed on the workflow detail page and on workflow proposal cards, so
9
- * it's code-split out of the always-loaded app shell. The Suspense fallback
10
- * keeps the caller's height so layout doesn't jump; the error boundary degrades
11
- * to the raw YAML if the chunk fails
12
- * to load (offline) or React Flow throws, instead of crashing the panel tree.
13
- *
14
- * The chunk import auto-retries a transient failure (a flaky network or an
15
- * HMR/cache miss) before degrading, and the fallback offers a manual retry that
16
- * re-attempts the import — so a recoverable failure isn't permanently pinned to
17
- * the YAML view. A chunk that is gone for good (e.g. an old hash after a deploy)
18
- * still degrades to the fully-legible YAML; the host can recover those globally
19
- * via a Vite `vite:preloadError` reload guard.
20
- */
21
- /** Re-run `factory` up to `retries` times with a short backoff before giving up.
22
- * Covers a transient dynamic-import rejection (network blip, a chunk briefly
23
- * unavailable behind a CDN) without bothering the user. Exported for tests. */
24
- function retryImport(factory, retries = 2, delayMs = 350) {
25
- return factory().catch((err) => {
26
- if (retries <= 0) throw err;
27
- return new Promise((resolve, reject) => {
28
- setTimeout(() => retryImport(factory, retries - 1, delayMs).then(resolve, reject), delayMs);
29
- });
30
- });
31
- }
32
- function lazyWorkflowGraph() {
33
- return lazy(() => retryImport(() => import("./WorkflowGraph-DXuWXMw9.js").then((m) => ({ default: m.WorkflowGraph }))));
34
- }
35
- var GraphErrorBoundary = class extends Component {
36
- state = { hasError: false };
37
- static getDerivedStateFromError() {
38
- return { hasError: true };
39
- }
40
- render() {
41
- return this.state.hasError ? this.props.fallback : this.props.children;
42
- }
43
- };
44
- /** Graceful degradation when the graph can't render: the workflow is still
45
- * fully legible as YAML, with a retry for a recoverable load failure. */
46
- function GraphFallback({ yaml, className, onRetry }) {
47
- return /* @__PURE__ */ jsxs("div", {
48
- className: `overflow-auto rounded-lg border border-border bg-background p-2 ${className ?? ""}`,
49
- children: [/* @__PURE__ */ jsxs("div", {
50
- className: "mb-1 flex items-center justify-between gap-2",
51
- children: [/* @__PURE__ */ jsx("p", {
52
- className: "text-muted-foreground text-xs",
53
- children: "Couldn't render the graph — showing the definition."
54
- }), /* @__PURE__ */ jsx("button", {
55
- type: "button",
56
- onClick: onRetry,
57
- className: "shrink-0 rounded border border-border px-1.5 py-0.5 text-muted-foreground text-xs transition hover:text-foreground",
58
- children: "Retry"
59
- })]
60
- }), /* @__PURE__ */ jsx("pre", {
61
- className: "text-foreground text-xs",
62
- children: /* @__PURE__ */ jsx("code", { children: yaml })
63
- })]
64
- });
65
- }
66
- function WorkflowGraph(props) {
67
- const [attempt, setAttempt] = useState(0);
68
- const Impl = useMemo(() => lazyWorkflowGraph(), [attempt]);
69
- return /* @__PURE__ */ jsx(GraphErrorBoundary, {
70
- fallback: /* @__PURE__ */ jsx(GraphFallback, {
71
- ...props,
72
- onRetry: () => setAttempt((a) => a + 1)
73
- }),
74
- children: /* @__PURE__ */ jsx(Suspense, {
75
- fallback: /* @__PURE__ */ jsx("div", {
76
- className: `flex items-center justify-center rounded-lg border border-border border-dashed text-text-muted text-xs ${props.className ?? ""}`,
77
- children: "Loading graph…"
78
- }),
79
- children: /* @__PURE__ */ jsx(Impl, { ...props })
80
- })
81
- }, `${props.yaml}::${attempt}`);
82
- }
83
- export { KIND_ICON, ModelBrandStack, NodeMark, NodeOutputBody, StatusPill as NodeStatusPill, STATUS_COLOR, STATUS_LABEL, STATUS_PILL, STATUS_TONE, TRIGGER_NODE_ID, WorkflowGraph as WorkflowGraphLazy, actionNodeId, actionPathLabel, branchNodeId, buildWorkflowGraph, classifyOutput, condenseText, humanizeIdentifier, modelBrandFor, parseActionPath, shortModel, triggerNodeId, triggerNodeIndex };
2
+ import { A as buildWorkflowGraph, D as TRIGGER_NODE_ID, I as actionPathLabel, L as humanizeIdentifier, M as triggerNodeId, N as triggerNodeIndex, O as actionNodeId, R as parseActionPath, c as NodeMark, g as STATUS_TONE, h as STATUS_PILL, k as branchNodeId, m as STATUS_LABEL, n as WorkflowGraph, p as STATUS_COLOR, s as KIND_ICON, t as AgentGraph, v as StatusPill, z as shortModel } from "./AgentGraph-Beld8p6x.js";
3
+ import { n as classifyOutput, r as condenseText, t as NodeOutputBody } from "./node-output-DlySTwxr.js";
4
+ export { AgentGraph, KIND_ICON, ModelBrandStack, NodeMark, NodeOutputBody, StatusPill as NodeStatusPill, STATUS_COLOR, STATUS_LABEL, STATUS_PILL, STATUS_TONE, TRIGGER_NODE_ID, WorkflowGraph as WorkflowGraphLazy, actionNodeId, actionPathLabel, branchNodeId, buildWorkflowGraph, classifyOutput, condenseText, humanizeIdentifier, modelBrandFor, parseActionPath, shortModel, triggerNodeId, triggerNodeIndex };
@@ -1,7 +1,7 @@
1
1
  import { t as cn$1 } from "./utils-BER_bdgE.js";
2
2
  import { r as ShellHeader } from "./shell-header-CwqDzC4I.js";
3
3
  import { t as MOTION_CONTROL } from "./motion-Bn7ESHrj.js";
4
- import { i as VaultTree, n as filterFileNodes, t as fileTreeFromPaths } from "./tree-data-YXtcK6Ld.js";
4
+ import { i as VaultTree, n as filterFileNodes, t as fileTreeFromPaths } from "./tree-data-Dmiu8aMf.js";
5
5
  import { ArtifactPane, ArtifactPane as ArtifactPane$1, Button, EmptyState, Input, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@tangle-network/ui/primitives";
6
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
7
  import { Markdown } from "@tangle-network/ui/markdown";
package/dist/workspace.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { i as WorkspacePaneHeader, n as SHELL_INSET_GUTTER, r as ShellHeader, t as SHELL_HEADER_HEIGHT } from "./shell-header-CwqDzC4I.js";
2
- import { C as WorkspaceSurfaceTitle, S as WorkspaceSurfaceFrame, _ as StatusBar, a as TaskBoard, b as WorkspaceLayout, c as createShellShouldRevalidate, d as SESSION_CREATED_EVENT, f as dispatchSessionCreated, g as TerminalPanel, h as RuntimePane, i as CalendarView, l as shellShouldRevalidate, m as formatRelativeAge, n as WorkspaceFilesPane, o as SandboxWorkbench, p as useOptimisticSessionItems, r as ApprovalQueue, s as WorkspaceArtifactView, t as ArtifactPane, u as SessionSidebar, v as StatusBanner, x as WorkspaceSurface, y as DirectoryPane } from "./workspace-DRhi6S3o.js";
2
+ import { C as WorkspaceSurfaceTitle, S as WorkspaceSurfaceFrame, _ as StatusBar, a as TaskBoard, b as WorkspaceLayout, c as createShellShouldRevalidate, d as SESSION_CREATED_EVENT, f as dispatchSessionCreated, g as TerminalPanel, h as RuntimePane, i as CalendarView, l as shellShouldRevalidate, m as formatRelativeAge, n as WorkspaceFilesPane, o as SandboxWorkbench, p as useOptimisticSessionItems, r as ApprovalQueue, s as WorkspaceArtifactView, t as ArtifactPane, u as SessionSidebar, v as StatusBanner, x as WorkspaceSurface, y as DirectoryPane } from "./workspace-C9TH6A2O.js";
3
3
  export { ApprovalQueue, ArtifactPane, CalendarView, DirectoryPane, RuntimePane, SESSION_CREATED_EVENT, SHELL_HEADER_HEIGHT, SHELL_INSET_GUTTER, SandboxWorkbench, SessionSidebar, ShellHeader, StatusBanner, StatusBar, TaskBoard, TerminalPanel, WorkspaceArtifactView, WorkspaceFilesPane, WorkspaceLayout, WorkspacePaneHeader, WorkspaceSurface, WorkspaceSurfaceFrame, WorkspaceSurfaceTitle, createShellShouldRevalidate, dispatchSessionCreated, formatRelativeAge, shellShouldRevalidate, useOptimisticSessionItems };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-ui",
3
- "version": "0.138.1",
3
+ "version": "0.139.0",
4
4
  "license": "MIT",
5
5
  "description": "Unified UI component library for Tangle Sandbox — primitives, chat, dashboard, terminal, editor, and workspace components",
6
6
  "repository": {
@@ -138,7 +138,7 @@
138
138
  "@nanostores/react": ">=0.8.4 <2.0.0",
139
139
  "@tangle-network/agent-interface": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^5.2.0",
140
140
  "@tangle-network/brand": "^1.26.2",
141
- "@tangle-network/charts": "^0.20.3",
141
+ "@tangle-network/charts": "^0.21.4",
142
142
  "@tangle-network/ui": "^11.42.0",
143
143
  "@tanstack/react-query": "^5.0.0",
144
144
  "@tiptap/core": ">=3.20.4 <4.0.0",
@@ -237,7 +237,7 @@
237
237
  "@tailwindcss/postcss": "^4.3.3",
238
238
  "@tangle-network/agent-interface": "5.7.1",
239
239
  "@tangle-network/brand": "1.26.2",
240
- "@tangle-network/charts": "^0.20.3",
240
+ "@tangle-network/charts": "^0.21.4",
241
241
  "@tangle-network/ui": "11.42.0",
242
242
  "@tanstack/react-query": "^5.104.5",
243
243
  "@testing-library/dom": "^10.4.2",