@tangle-network/sandbox-ui 0.138.2 → 0.139.1

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.
@@ -1,6 +1,8 @@
1
- import { A as triggerNodeIndex, B as fmtTokens, C as COMPACT_NODE_SIZE, D as buildWorkflowGraph, I as shortModel, L as clampPreview, M as worstSeverity, O as isStructuralKind, R as fmtCost, S as statusBorder, _ as emptySlotLabel, a as NodeMark, b as problemSurface, c as RESTING_BORDER, d as STATUS_LABEL, g as edgeColor, h as StatusPill, j as wfEdgeId, l as RESTING_SHADOW, m as StatusFooter, n as classifyOutput, o as ProblemMarker, s as ProblemMessages, t as NodeOutputBody, u as STATUS_COLOR, v as kindAccent, x as problemTitle, y as problemBorder, z as fmtDuration } from "./node-output-udnwhShN.js";
1
+ import { A as buildWorkflowGraph, B as clampPreview, C as problemSurface, E as COMPACT_NODE_SIZE, F as worstSeverity, H as fmtDuration, N as triggerNodeIndex, P as wfEdgeId, S as problemBorder, T as statusBorder, V as fmtCost, W as fmtTokens, _ as StatusFooter, a as useColorMode, b as emptySlotLabel, c as NodeMark, d as RESTING_BORDER, f as RESTING_SHADOW, i as motionAllowed, j as isStructuralKind, l as ProblemMarker, m as STATUS_LABEL, p as STATUS_COLOR, r as SELECTION_OUTLINE, u as ProblemMessages, v as StatusPill, w as problemTitle, x as kindAccent, y as edgeColor, z as shortModel } from "./AgentGraph-Beld8p6x.js";
2
+ import { n as classifyOutput, t as NodeOutputBody } from "./node-output-DlySTwxr.js";
3
+ import { t as loadElk } from "./elk-loader-Dl9S7jQk.js";
2
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
- import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
5
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
4
6
  import { Expand, Maximize2, Minimize2, Plus, Shrink, X } from "lucide-react";
5
7
  import { Background, BaseEdge, Controls, EdgeLabelRenderer, Handle, MarkerType, MiniMap, Panel, Position, ReactFlow, ViewportPortal, getSmoothStepPath, getViewportForBounds, useEdgesState, useNodesState, useStore } from "@xyflow/react";
6
8
  import "@xyflow/react/dist/style.css";
@@ -292,16 +294,6 @@ function clearOfNodeBoxes(point, boxes, direction, half) {
292
294
  return Math.abs(up) <= Math.abs(down) ? up : down;
293
295
  }
294
296
  // src/workflows/elk-layout.ts
295
- /** One ELK instance per page. `null` once loading failed, so a host without
296
- * the peer pays for one failed import, not one per render. */
297
- let elkInstance;
298
- function loadElk() {
299
- elkInstance ??= import("elkjs/lib/elk.bundled.js").then((mod) => {
300
- const Elk = mod.default;
301
- return new Elk();
302
- }).catch(() => null);
303
- return elkInstance;
304
- }
305
297
  /**
306
298
  * Whether the graph is worth the ELK pass: anything but a plain line. A line
307
299
  * has nothing to order or route, and `model.ts` folds a long one into rows
@@ -992,46 +984,10 @@ const DENSITY_FLIP_AT = {
992
984
  grow: .12,
993
985
  shrink: .75
994
986
  };
995
- /** Motion is opt-OUT, so it is only used where the reader's preference can be
996
- * read and says nothing against it. Somewhere without `matchMedia` cannot say
997
- * a reader tolerates movement, so it gets none. */
998
- function motionAllowed() {
999
- return typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches === false;
1000
- }
1001
987
  const lerp = (a, b, t) => a + (b - a) * t;
1002
988
  /** The layout tween's easing — gentle into and out of the motion, so neither
1003
989
  * end of the morph reads as a snap. */
1004
990
  const easeInOutCubic = (t) => t < .5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2;
1005
- /** React Flow adds its own .light/.dark class below the graph wrapper. Read
1006
- * that wrapper's inherited scheme so a nested WorkspaceLayout theme wins over
1007
- * the page root without React Flow's class influencing the answer. */
1008
- function currentColorMode(anchor) {
1009
- if (typeof document === "undefined" || typeof window === "undefined") return "light";
1010
- const scheme = window.getComputedStyle(anchor ?? document.documentElement).colorScheme;
1011
- if (scheme.startsWith("dark")) return "dark";
1012
- if (scheme.startsWith("light")) return "light";
1013
- return (anchor ?? document.documentElement).closest(".dark") ? "dark" : "light";
1014
- }
1015
- function useColorMode(wrapperRef, hasGraph) {
1016
- const [mode, setMode] = useState(() => currentColorMode(null));
1017
- useLayoutEffect(() => {
1018
- const anchor = hasGraph ? wrapperRef.current : null;
1019
- const update = () => setMode(currentColorMode(anchor));
1020
- update();
1021
- const observer = new MutationObserver(update);
1022
- for (let el = anchor ?? document.documentElement; el; el = el.parentElement) observer.observe(el, {
1023
- attributes: true,
1024
- attributeFilter: [
1025
- "class",
1026
- "data-theme",
1027
- "data-sandbox-theme",
1028
- "style"
1029
- ]
1030
- });
1031
- return () => observer.disconnect();
1032
- }, [wrapperRef, hasGraph]);
1033
- return mode;
1034
- }
1035
991
  /** Flow direction for the current graph, so the node component can place its
1036
992
  * edge handles on the correct sides (edges enter the leading edge and leave the
1037
993
  * trailing edge) without threading a prop through React Flow's node renderer. */
@@ -1059,14 +1015,6 @@ const SelectedNodeContext = createContext(void 0);
1059
1015
  * for all of its nodes, or none.
1060
1016
  */
1061
1017
  const RunModeContext = createContext(false);
1062
- /** The selected node's ring. An `outline` rather than a border or a box-shadow
1063
- * because both of those are already spoken for — the border carries tone and
1064
- * run status, the shadow carries the running/waiting glow — and an outline
1065
- * composes with both without disturbing the laid-out box. */
1066
- const SELECTION_OUTLINE = {
1067
- outline: "2px solid hsl(var(--primary))",
1068
- outlineOffset: 2
1069
- };
1070
1018
  /** Whether the canvas is currently an EDITOR — read by the node so its
1071
1019
  * connection handles become visible targets rather than the invisible anchors
1072
1020
  * a read-only diagram wants. A handle you cannot see is a handle you cannot
@@ -495,7 +495,7 @@ function ProfileRow({ active, title, subtitle, onSelect, onEdit, onDelete }) {
495
495
  })]
496
496
  })]
497
497
  }), (onEdit || onDelete) && /* @__PURE__ */ jsxs("span", {
498
- className: "flex shrink-0 items-center gap-1 opacity-100 transition-opacity [@media(hover:hover)]:opacity-0 group-hover:opacity-100 group-focus-within:opacity-100",
498
+ className: "flex shrink-0 items-center gap-1",
499
499
  children: [onEdit && /* @__PURE__ */ jsx("button", {
500
500
  type: "button",
501
501
  onClick: onEdit,
package/dist/chat.js CHANGED
@@ -1 +1 @@
1
- export { p as AgentProfilePicker, t as AgentTimeline, u as ArtifactAgentDock, n as ChatContainer, r as ChatMessage, m as DEFAULT_REASONING_LEVEL_OPTIONS, h as HARNESS_REASONING_OPTIONS, i as MessageAuthor, a as MessageList, g as ReasoningLevelPicker, o as TRANSCRIPT_TEXT, s as ThinkingIndicator, c as UserMessage, l as isViewerMessage, d as modelProvider, f as snapHarnessToModel } from "./chat-BYTVLZQW.js";
1
+ export { p as AgentProfilePicker, t as AgentTimeline, u as ArtifactAgentDock, n as ChatContainer, r as ChatMessage, m as DEFAULT_REASONING_LEVEL_OPTIONS, h as HARNESS_REASONING_OPTIONS, i as MessageAuthor, a as MessageList, g as ReasoningLevelPicker, o as TRANSCRIPT_TEXT, s as ThinkingIndicator, c as UserMessage, l as isViewerMessage, d as modelProvider, f as snapHarnessToModel } from "./chat-4OZD23RA.js";
@@ -0,0 +1,12 @@
1
+ // src/workflows/elk-loader.ts
2
+ /** One ELK instance per page. `null` once loading failed, so a host without
3
+ * the peer pays for one failed import, not one per render. */
4
+ let elkInstance;
5
+ function loadElk() {
6
+ elkInstance ??= import("elkjs/lib/elk.bundled.js").then((mod) => {
7
+ const Elk = mod.default;
8
+ return new Elk();
9
+ }).catch(() => null);
10
+ return elkInstance;
11
+ }
12
+ export { loadElk as t };
package/dist/globals.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%;
@@ -5985,6 +6094,11 @@
5985
6094
  grid-template-columns: repeat(3, minmax(0, 1fr));
5986
6095
  }
5987
6096
  }
6097
+ @container settings-section (width >= 34rem) {
6098
+ .\@min-\[34rem\]\/settings-section\:text-right {
6099
+ text-align: right;
6100
+ }
6101
+ }
5988
6102
  @container (width >= 36rem) {
5989
6103
  .\@xl\:grid-cols-4 {
5990
6104
  grid-template-columns: repeat(4, minmax(0, 1fr));
@@ -6384,11 +6498,6 @@
6384
6498
  .tangle-prose .\[\.tangle-prose_\&\]\:no-underline\! {
6385
6499
  text-decoration-line: none !important;
6386
6500
  }
6387
- @media (hover:hover) {
6388
- .\[\@media\(hover\:hover\)\]\:opacity-0 {
6389
- opacity: 0%;
6390
- }
6391
- }
6392
6501
  @media (pointer:coarse) {
6393
6502
  .\[\@media\(pointer\:coarse\)\]\:min-h-10 {
6394
6503
  min-height: calc(var(--spacing) * 10);
@@ -1,3 +1,4 @@
1
+ import { d as AgentGraphNode } from "./AgentGraph-DL-QLjkw.js";
1
2
  import { ReactNode } from "react";
2
3
  import { ApprovalCard, ApprovalCardProps, ApprovalDiffFile, ApprovalDiffSummary, ApprovalPlanStep, ExpandedToolDetail, ExpandedToolDetailProps, FeedSegment, InlineThinkingItem as InlineThinkingItem$1, InlineThinkingItemProps, InlineToolItem, InlineToolItemProps, LiveDuration, RunGroup, RunGroupProps, RunPhase, RunPhaseList, RunRowShell, RunRowShellProps, RunRowStatus, RunRowStatusDot, TaskList, TaskListItem, TaskListProps, TaskStatus, ToolCallData, ToolCallData as ToolCallData$1, ToolCallFeed, ToolCallFeedProps, ToolCallStatus, ToolCallType, parseToolEvent, showsTaskPriority, taskProgress, taskStatus } from "@tangle-network/ui/run";
3
4
  import { FlowWaterfallProps } from "@tangle-network/charts/react";
@@ -31,6 +32,11 @@ interface TraceWorkspaceProps extends Omit<TraceWaterfallProps, "trace" | "marke
31
32
  selectedAgentId?: string;
32
33
  /** Called with the agent the reader selected, or undefined when they close its drawer or press Escape. */
33
34
  onSelectAgent?: (agentId: string | undefined) => void;
35
+ /**
36
+ * What the trace cannot say about a live agent, by agent id: its activity, thinking line, latest events, commits or
37
+ * result. The Graph view draws them on the agent's live card; status, model, cost and lifetime come from the trace.
38
+ */
39
+ agentCards?: Readonly<Record<string, Partial<AgentGraphNode>>>;
34
40
  className?: string;
35
41
  }
36
42
  /**
@@ -38,7 +44,7 @@ interface TraceWorkspaceProps extends Omit<TraceWaterfallProps, "trace" | "marke
38
44
  * streaming in a right-hand drawer, and the page's code workspace and scoreboard following the time cursor. Scrubbing is time travel:
39
45
  * every panel shows what was true at the cursor, and the conversation shows what had been said by then.
40
46
  */
41
- declare function TraceWorkspace({ trace, streamUrl, events, onTimeChange, files, scoreboard, selectedAgentId, onSelectAgent, className, ...waterfall }: TraceWorkspaceProps): import("react").JSX.Element;
47
+ declare function TraceWorkspace({ trace, streamUrl, events, onTimeChange, files, scoreboard, selectedAgentId, onSelectAgent, agentCards, className, ...waterfall }: TraceWorkspaceProps): import("react").JSX.Element;
42
48
  /** One row of an agent's message stream (tangle-tools `/api/discovery/runs/<run>/agents/<agent>/stream`). */
43
49
  interface AgentStreamRow {
44
50
  seq: number;
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@ import { C as ChangedFile, D as SandboxArtifactTerminal, E as SandboxArtifactPan
15
15
  import { n as DiffViewProps, t as DiffView } from "./diff-view-DDHWtR6X.js";
16
16
  import { a as PreviewReadiness, i as PreviewAccess, n as EmbeddedAppView, r as EmbeddedAppViewProps, t as EmbeddedApp } from "./embedded-app-view-Ta5GI4hx.js";
17
17
  import { OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, OpenUIAction, OpenUIActionsNode, OpenUIArtifactRenderer, OpenUIArtifactRendererProps, OpenUIBadgeNode, OpenUICardNode, OpenUICodeNode, OpenUIComponentNode, OpenUIGridNode, OpenUIHeadingNode, OpenUIKeyValueNode, OpenUIMarkdownNode, OpenUIPrimitive, OpenUISchemaIssue, OpenUISchemaValidation, OpenUISeparatorNode, OpenUIStackNode, OpenUIStatNode, OpenUITableNode, OpenUITextNode, findUnsupportedOpenUINode, validateOpenUIJsonArtifact, validateOpenUIJsonNode } from "./openui.js";
18
- 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";
18
+ 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";
19
19
  import { a as VaultTreeProps, i as VaultTree, n as filterFileNodes, r as VAULT_TREE_CHILD_PAGE, t as fileTreeFromPaths } from "./index-y2OPUSoY.js";
20
20
  import { ActiveProjectActivity, ActiveSessionActivityOptions, ActiveSessionConnectionOptions, ActiveSessionConnectionState, ActiveSessionReconnectState, ActiveSessionRecord, ActiveSessionStatus, ActiveSessionTransportMode, ActiveSessionsState, ChatSession, RegisterActiveSessionOptions, SessionProjectKey, activeSessionsAtom, addMessage, addParts, bumpActiveSessionActivity, clearChat, connectSession, disconnectSession, getActiveSession, getAllActiveSessions, getAllProjectActivity, getSessionsByActivity, getSessionsForNavbar, getSessionsForProject, getTotalRunningSessionCount, hasBackgroundRunningSessions, isStreamingAtom, messagesAtom, partMapAtom, registerActiveSession, resetActiveSessions, sessionAtom, setActiveSessionAttention, setActiveSessionConnection, setActiveSessionError, setActiveSessionRunning, setForegroundActiveSession, unregisterActiveSession, updateActiveSessionMeta, updatePart, useActiveSession, useActiveSessions, useActiveSessionsState, useHasBackgroundRunningSessions, useNavbarSessions, useProjectActivity, useProjectSessions, useSessionsByActivity, useTotalRunningSessions } from "./stores.js";
21
21
  import { AgentBranding, CustomToolRenderer, DisplayVariant, FinalTextPart, GroupedMessage, MessageRun, MessageUser, ReasoningPart, Run, RunStats, SessionMessage, SessionPart, TextPart, ToolCategory, ToolDisplayMetadata, ToolPart, ToolState, ToolStatus, ToolTime } from "./types.js";
package/dist/index.js CHANGED
@@ -12,8 +12,8 @@ import { CSV_PREVIEW_ROW_LIMIT, FileArtifactPane, FileCard, FileList, FilePrevie
12
12
  import { a as CodeSurface, i as CODE_THEME, n as buildUnifiedPatch, r as computeDiffStats, t as DiffView } from "./diff-view-B9mNeTLF.js";
13
13
  import { n as PreviewView, t as EmbeddedAppView } from "./embedded-app-view-DXsoPale.js";
14
14
  import { OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, OpenUIArtifactRenderer, findUnsupportedOpenUINode, validateOpenUIJsonArtifact, validateOpenUIJsonNode } from "./openui.js";
15
- import { a as MessageList, c as UserMessage, d as modelProvider, f as snapHarnessToModel, g as ReasoningLevelPicker, h as HARNESS_REASONING_OPTIONS, i as MessageAuthor, l as isViewerMessage, m as DEFAULT_REASONING_LEVEL_OPTIONS, n as ChatContainer, o as TRANSCRIPT_TEXT, p as AgentProfilePicker, r as ChatMessage, s as ThinkingIndicator, t as AgentTimeline, u as ArtifactAgentDock } from "./chat-BYTVLZQW.js";
16
- import { _ as TraceWorkspace, a as InlineToolItem, b as TraceWaterfall, c as RunPhaseList, d as TaskList, f as ToolCallFeed, g as taskStatus, h as taskProgress, i as InlineThinkingItem, l as RunRowShell, m as showsTaskPriority, n as ApprovalDiffSummary, o as LiveDuration, p as parseToolEvent, r as ExpandedToolDetail, s as RunGroup, t as ApprovalCard, u as RunRowStatusDot, v as foldAgentRows, x as traceSpanMark, y as useAgentStream } from "./run-CliTxkfw.js";
15
+ import { a as MessageList, c as UserMessage, d as modelProvider, f as snapHarnessToModel, g as ReasoningLevelPicker, h as HARNESS_REASONING_OPTIONS, i as MessageAuthor, l as isViewerMessage, m as DEFAULT_REASONING_LEVEL_OPTIONS, n as ChatContainer, o as TRANSCRIPT_TEXT, p as AgentProfilePicker, r as ChatMessage, s as ThinkingIndicator, t as AgentTimeline, u as ArtifactAgentDock } from "./chat-4OZD23RA.js";
16
+ import { _ as TraceWorkspace, a as InlineToolItem, b as TraceWaterfall, c as RunPhaseList, d as TaskList, f as ToolCallFeed, g as taskStatus, h as taskProgress, i as InlineThinkingItem, l as RunRowShell, m as showsTaskPriority, n as ApprovalDiffSummary, o as LiveDuration, p as parseToolEvent, r as ExpandedToolDetail, s as RunGroup, t as ApprovalCard, u as RunRowStatusDot, v as foldAgentRows, x as traceSpanMark, y as useAgentStream } from "./run-CC-DESx8.js";
17
17
  import "./vault-tree.js";
18
18
  import { a as TangleLoginButton, i as UserMenu, n as GitHubLoginButton, r as LoginLayout, t as AuthHeader } from "./auth-BDpoZ_2f.js";
19
19
  import { t as AgentMessagingConnection } from "./connections-DymjzHe_.js";
@@ -0,0 +1,178 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ // src/workflows/node-output.tsx
3
+ /** Failure text, in the semantic danger token — which carries a light AND a dark
4
+ * value. A palette shade (`text-red-400`) only ever reads well in one theme. */
5
+ const ERROR_TEXT = { color: "var(--surface-danger-text)" };
6
+ /** Max key/value pairs a shallow-object output renders before it reports
7
+ * `truncated` — the card only has room for a couple rows anyway. */
8
+ const MAX_JSON_ENTRIES = 6;
9
+ /**
10
+ * A line that is pure structure — a code fence (with or without a language tag), a
11
+ * table's rule row, a thematic break — and so carries no words to keep.
12
+ *
13
+ * Every test is a SINGLE quantified character class: unambiguous, and linear in the
14
+ * length of the line. Written as one pattern (`[\s|:-]+\|[\s|:-]*`) the two
15
+ * quantifiers would compete for the same `|`, which is the shape that backtracks.
16
+ * Recognize the charset in one pass instead, then ask the cheap questions — is
17
+ * there a pipe? a dash? — with plain string checks.
18
+ */
19
+ function isStructureOnly(line) {
20
+ if (/^(```|~~~)/.test(line)) return true;
21
+ const isBreak = /^([-*_])\1{2,}$/.test(line);
22
+ if (/^[\s|:-]+$/.test(line) && line.includes("|")) return line.includes("-");
23
+ return isBreak;
24
+ }
25
+ /**
26
+ * Flatten an agent's markdown answer into the sentence a person would read out
27
+ * of it. On a two-line card preview the syntax IS the noise: a `## Heading` mid
28
+ * paragraph, a `**bold**` run and a bullet's `-` all survive the clamp while the
29
+ * words that carry the meaning get pushed past it. Stripping the markup (never
30
+ * the words) is what turns the preview back into prose — the full text, markup
31
+ * and all, is still rendered by the node's detail view.
32
+ *
33
+ * Structure-only lines (a fence, a table rule) are dropped; everything else keeps
34
+ * its text and is joined into one flowing line.
35
+ */
36
+ function condenseText(text) {
37
+ const isListItem = (line) => /^\s*([-*+]\s|\d+[.)]\s)/.test(line);
38
+ return text.split("\n").map((line) => ({
39
+ item: isListItem(line),
40
+ text: line.replace(/^\s{0,3}#{1,6}\s+/, "").replace(/^\s{0,3}>\s?/, "").replace(/^\s*[-*+]\s+(\[[ xX]\]\s+)?/, "").replace(/^\s*\d+[.)]\s+/, "").trim()
41
+ })).filter(({ text: line }) => line !== "" && !isStructureOnly(line)).map(({ item, text: line }, i) => i > 0 && item ? `· ${line}` : line).join(" ").replace(/(?<=^|\s)(\*\*|~~)(?!\s)(.+?)(?<!\s)\1(?=[\s.,:;!?)\]}"']|$)/g, "$2").replace(/(?<![\w*])\*(?!\s)([^*]+?)(?<!\s)\*(?![\w*])/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\s+/g, " ").trim();
42
+ }
43
+ /** A single JSON value as a compact one-line string for the key/value render.
44
+ * Scalars render verbatim; a nested object/array collapses to a shape marker so
45
+ * one row never balloons into a wall of text. */
46
+ function scalar(value) {
47
+ if (value === null) return "null";
48
+ if (typeof value === "string") return value;
49
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
50
+ if (Array.isArray(value)) return `[${value.length} item${value.length === 1 ? "" : "s"}]`;
51
+ if (typeof value === "object") return "{…}";
52
+ return "";
53
+ }
54
+ /**
55
+ * Recover the shape of an output preview string. Only text that *begins* like
56
+ * JSON (`{`/`[`) is parse-attempted, so ordinary prose starting with a brace-free
57
+ * sentence is never mis-parsed. A begins-like-JSON string that fails to parse
58
+ * (the host clamped it mid-value) still renders as `code`, not prose, so it keeps
59
+ * its monospace/data affordance.
60
+ *
61
+ * `condenseMarkdown` says the prose IS markdown and may be flattened for the
62
+ * preview ({@link condenseText}). It is OFF by default, and the caller must only
63
+ * turn it on for text an agent actually authored as markdown. Applied to anything
64
+ * else it does not merely look wrong — it silently REWRITES the text: a stack
65
+ * trace's `__init__.py` loses its underscores, and a shell glob `src/**` pairs
66
+ * with a later `**` and both vanish. An error message is the one string a person
67
+ * reads to find out what broke; it must reach them exactly as it was thrown.
68
+ */
69
+ function classifyOutput(preview, condenseMarkdown = false) {
70
+ let trimmed = preview?.trim() ?? "";
71
+ trimmed = trimmed.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])/g, "").replace(/(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "").trimEnd();
72
+ if (trimmed === "") return { kind: "empty" };
73
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) try {
74
+ const parsed = JSON.parse(trimmed);
75
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
76
+ const all = Object.entries(parsed);
77
+ const entries = all.slice(0, MAX_JSON_ENTRIES).map(([k, v]) => [k, scalar(v)]);
78
+ if (entries.length > 0) return {
79
+ kind: "json",
80
+ entries,
81
+ truncated: all.length > entries.length
82
+ };
83
+ }
84
+ return {
85
+ kind: "code",
86
+ text: trimmed
87
+ };
88
+ } catch {
89
+ return {
90
+ kind: "code",
91
+ text: trimmed
92
+ };
93
+ }
94
+ if (!condenseMarkdown) return {
95
+ kind: "text",
96
+ text: trimmed
97
+ };
98
+ const condensed = condenseText(trimmed);
99
+ return condensed === "" ? { kind: "empty" } : {
100
+ kind: "text",
101
+ text: condensed
102
+ };
103
+ }
104
+ /** Line-clamp utility per row budget, so `code`/`text` shapes honor `rows` the
105
+ * same way the JSON branch does (rather than always clamping to two). Covers the
106
+ * full range a card can reserve; an unsupported count falls back to the two-line
107
+ * clamp, which renders FEWER lines than the caller asked for — so a card whose
108
+ * reservation outgrows this map shows a short body inside a tall well rather
109
+ * than erroring. Extend the map when a design reserves more.
110
+ * Class names are literal so the Tailwind scanner emits each utility. */
111
+ const CLAMP_BY_ROWS = {
112
+ 1: "truncate",
113
+ 2: "line-clamp-2",
114
+ 3: "line-clamp-3",
115
+ 4: "line-clamp-4",
116
+ 5: "line-clamp-5",
117
+ 6: "line-clamp-6"
118
+ };
119
+ /**
120
+ * Render a classified output preview's CONTENT (no surrounding frame — each node
121
+ * design supplies its own container/label). `rows` caps the visible lines so the
122
+ * body stays within a card's reserved output space; `tone="error"` colors it for
123
+ * a failure message.
124
+ *
125
+ * `rows="none"` renders the body UNCLAMPED, for a container that scrolls or is
126
+ * sized by its content — a drawer, a detail panel, a selection overlay. It is a
127
+ * word rather than a large number because there is no number that means "do not
128
+ * clamp": a count outside {@link CLAMP_BY_ROWS} falls back to two lines, so
129
+ * `rows={99}` asks for everything and silently shows the least.
130
+ */
131
+ function NodeOutputBody({ shape, rows = 2, tone = "default" }) {
132
+ const unclamped = rows === "none";
133
+ const clampClass = unclamped ? "" : CLAMP_BY_ROWS[rows] ?? "line-clamp-2";
134
+ const codeWrap = rows === 1 ? "" : "whitespace-pre-wrap break-all";
135
+ if (shape.kind === "empty") return null;
136
+ if (shape.kind === "json") {
137
+ const overflow = unclamped ? shape.truncated : shape.truncated || shape.entries.length > rows;
138
+ const visible = unclamped ? shape.entries : shape.entries.slice(0, overflow ? Math.max(0, rows - 1) : rows);
139
+ const isError = tone === "error";
140
+ const keyStyle = isError ? ERROR_TEXT : void 0;
141
+ const keyClass = isError ? "" : "text-muted-foreground";
142
+ const valueClass = isError ? "" : "text-foreground";
143
+ return /* @__PURE__ */ jsxs("dl", {
144
+ className: "space-y-0.5 font-mono text-[10.5px] leading-snug",
145
+ children: [visible.map(([key, value]) => /* @__PURE__ */ jsxs("div", {
146
+ className: "flex gap-1.5",
147
+ children: [/* @__PURE__ */ jsx("dt", {
148
+ className: `max-w-[45%] shrink-0 truncate ${keyClass}`,
149
+ style: keyStyle,
150
+ title: key,
151
+ children: key
152
+ }), /* @__PURE__ */ jsx("dd", {
153
+ className: `min-w-0 flex-1 truncate ${valueClass}`,
154
+ style: isError ? ERROR_TEXT : void 0,
155
+ title: value,
156
+ children: value
157
+ })]
158
+ }, key)), overflow && /* @__PURE__ */ jsx("div", {
159
+ className: `text-[10px] ${keyClass}`,
160
+ style: keyStyle,
161
+ children: "…"
162
+ })]
163
+ });
164
+ }
165
+ if (shape.kind === "code") return /* @__PURE__ */ jsx("pre", {
166
+ className: `${clampClass} ${codeWrap} font-mono text-[10.5px] leading-snug ${tone === "error" ? "" : "text-foreground"}`,
167
+ style: tone === "error" ? ERROR_TEXT : void 0,
168
+ title: shape.text,
169
+ children: shape.text
170
+ });
171
+ return /* @__PURE__ */ jsx("p", {
172
+ className: `${clampClass} text-[11px] leading-snug ${tone === "error" ? "" : "text-foreground"}`,
173
+ style: tone === "error" ? ERROR_TEXT : void 0,
174
+ title: shape.text,
175
+ children: shape.text
176
+ });
177
+ }
178
+ export { classifyOutput as n, condenseText as r, NodeOutputBody as t };