@tangle-network/agent-app 0.45.46 → 0.45.48

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 (79) hide show
  1. package/dist/{DesignCanvas-P2ZVK6FM.js → DesignCanvas-QY2CA5GI.js} +2 -2
  2. package/dist/{DesignCanvasEditor-DGNCA54P.js → DesignCanvasEditor-CJ7PLX7A.js} +3 -3
  3. package/dist/{IntakeInterview-3ZIQMZS6.js → IntakeInterview-NJXKH35Q.js} +2 -2
  4. package/dist/InvitationsPanel-F2VY4TSL.js +9 -0
  5. package/dist/InviteAcceptPage-UT4452KT.js +7 -0
  6. package/dist/MembersPanel-N5CBOUXC.js +9 -0
  7. package/dist/{TimelineEditor-OTNPJ3SN.js → TimelineEditor-IYNKBSUX.js} +2 -2
  8. package/dist/assistant/index.d.ts +35 -10
  9. package/dist/assistant/index.js +234 -89
  10. package/dist/assistant/index.js.map +1 -1
  11. package/dist/chat-react/index.js +2 -1
  12. package/dist/chat-react/index.js.map +1 -1
  13. package/dist/{chunk-IUSO2XRE.js → chunk-5BACNOVR.js} +13 -14
  14. package/dist/chunk-5BACNOVR.js.map +1 -0
  15. package/dist/chunk-AULM4X7U.js +77 -0
  16. package/dist/chunk-AULM4X7U.js.map +1 -0
  17. package/dist/{chunk-UM6ODCLN.js → chunk-C7AQW6US.js} +346 -249
  18. package/dist/chunk-C7AQW6US.js.map +1 -0
  19. package/dist/{chunk-VCPZ3HTN.js → chunk-DB2D2JBQ.js} +51 -27
  20. package/dist/chunk-DB2D2JBQ.js.map +1 -0
  21. package/dist/{chunk-TL37E5YY.js → chunk-DS2WE62K.js} +3 -3
  22. package/dist/{chunk-TL37E5YY.js.map → chunk-DS2WE62K.js.map} +1 -1
  23. package/dist/{chunk-PE67O2LH.js → chunk-GT4GTRGQ.js} +18 -13
  24. package/dist/chunk-GT4GTRGQ.js.map +1 -0
  25. package/dist/{chunk-BT4QFCTB.js → chunk-HSBJB46C.js} +13 -1
  26. package/dist/chunk-HSBJB46C.js.map +1 -0
  27. package/dist/{chunk-54FYYXAX.js → chunk-J6OJTFNE.js} +13 -10
  28. package/dist/chunk-J6OJTFNE.js.map +1 -0
  29. package/dist/chunk-MLG6XKPV.js +44 -0
  30. package/dist/chunk-MLG6XKPV.js.map +1 -0
  31. package/dist/{chunk-F4XLTVQ3.js → chunk-R6KGLGEJ.js} +18 -17
  32. package/dist/chunk-R6KGLGEJ.js.map +1 -0
  33. package/dist/{chunk-B62EZF52.js → chunk-RILGAFEL.js} +3 -3
  34. package/dist/{chunk-65OZT566.js → chunk-T7XPIBCX.js} +16 -14
  35. package/dist/chunk-T7XPIBCX.js.map +1 -0
  36. package/dist/{chunk-VOJB7MVG.js → chunk-XPFNEKHS.js} +70 -28
  37. package/dist/chunk-XPFNEKHS.js.map +1 -0
  38. package/dist/{chunk-GNPN6ED4.js → chunk-XVRHISF3.js} +127 -165
  39. package/dist/chunk-XVRHISF3.js.map +1 -0
  40. package/dist/design-canvas-react/index.js +14 -12
  41. package/dist/design-canvas-react/index.js.map +1 -1
  42. package/dist/design-canvas-react/lazy.js +1 -1
  43. package/dist/intakes-react/index.js +1 -1
  44. package/dist/intakes-react/lazy.js +1 -1
  45. package/dist/sequences-react/index.js +2 -2
  46. package/dist/studio/index.d.ts +13 -1
  47. package/dist/studio/index.js +13 -1
  48. package/dist/studio-react/index.js +100 -63
  49. package/dist/studio-react/index.js.map +1 -1
  50. package/dist/studio-react/studio.css +0 -56
  51. package/dist/teams-react/index.js +4 -3
  52. package/dist/teams-react/lazy.js +3 -3
  53. package/dist/theme/tokens.css +173 -0
  54. package/dist/web-react/index.d.ts +15 -11
  55. package/dist/web-react/index.js +6 -4
  56. package/dist/work-product-react/index.js +3 -21
  57. package/dist/work-product-react/index.js.map +1 -1
  58. package/package.json +3 -3
  59. package/dist/InvitationsPanel-F56UOQXA.js +0 -8
  60. package/dist/InviteAcceptPage-P3QJC3C6.js +0 -7
  61. package/dist/MembersPanel-XNLF3SA4.js +0 -8
  62. package/dist/chunk-54FYYXAX.js.map +0 -1
  63. package/dist/chunk-65OZT566.js.map +0 -1
  64. package/dist/chunk-BT4QFCTB.js.map +0 -1
  65. package/dist/chunk-F4XLTVQ3.js.map +0 -1
  66. package/dist/chunk-GNPN6ED4.js.map +0 -1
  67. package/dist/chunk-IUSO2XRE.js.map +0 -1
  68. package/dist/chunk-PE67O2LH.js.map +0 -1
  69. package/dist/chunk-UM6ODCLN.js.map +0 -1
  70. package/dist/chunk-VCPZ3HTN.js.map +0 -1
  71. package/dist/chunk-VOJB7MVG.js.map +0 -1
  72. /package/dist/{DesignCanvas-P2ZVK6FM.js.map → DesignCanvas-QY2CA5GI.js.map} +0 -0
  73. /package/dist/{DesignCanvasEditor-DGNCA54P.js.map → DesignCanvasEditor-CJ7PLX7A.js.map} +0 -0
  74. /package/dist/{IntakeInterview-3ZIQMZS6.js.map → IntakeInterview-NJXKH35Q.js.map} +0 -0
  75. /package/dist/{InvitationsPanel-F56UOQXA.js.map → InvitationsPanel-F2VY4TSL.js.map} +0 -0
  76. /package/dist/{InviteAcceptPage-P3QJC3C6.js.map → InviteAcceptPage-UT4452KT.js.map} +0 -0
  77. /package/dist/{MembersPanel-XNLF3SA4.js.map → MembersPanel-N5CBOUXC.js.map} +0 -0
  78. /package/dist/{TimelineEditor-OTNPJ3SN.js.map → TimelineEditor-IYNKBSUX.js.map} +0 -0
  79. /package/dist/{chunk-B62EZF52.js.map → chunk-RILGAFEL.js.map} +0 -0
@@ -61,62 +61,6 @@
61
61
  }
62
62
  .animate-row-in { animation: studio-row-in 0.25s ease-out both; }
63
63
 
64
- /* ── Studio: inline split shell (composer ⇆ gallery) ──
65
- The composer is the same card in both states. Toggling the parent's
66
- data-library-open grows the gallery in from the right (flex-grow 0→1) and
67
- narrows the composer from centered to a left rail. max-width:1400px caps the
68
- whole cluster on wide screens so extra width becomes neutral gutter. */
69
- .studio-shell {
70
- display: flex;
71
- align-items: flex-start;
72
- justify-content: center;
73
- width: 100%;
74
- max-width: 1400px;
75
- margin: 0 auto;
76
- }
77
- .studio-shell[data-library-open='true'] { gap: 24px; }
78
-
79
- .studio-composer {
80
- flex: none;
81
- width: 620px;
82
- max-width: 100%;
83
- transition: width 0.32s cubic-bezier(0.32, 0.72, 0, 1);
84
- }
85
- .studio-shell[data-library-open='true'] .studio-composer {
86
- width: 50%;
87
- max-width: 560px;
88
- }
89
-
90
- /* max-height:0 while closed hard-clamps the gallery out of layout — the card
91
- grid's own min track width otherwise generates real height and leaks it into
92
- the page scroll even at opacity:0. */
93
- .studio-gallery {
94
- flex-grow: 0;
95
- flex-basis: 0;
96
- min-width: 0;
97
- max-height: 0;
98
- overflow: hidden;
99
- opacity: 0;
100
- transform: translateX(20px);
101
- pointer-events: none;
102
- transition:
103
- flex-grow 0.32s cubic-bezier(0.32, 0.72, 0, 1),
104
- opacity 0.24s ease,
105
- transform 0.32s cubic-bezier(0.32, 0.72, 0, 1);
106
- }
107
- .studio-shell[data-library-open='true'] .studio-gallery {
108
- flex-grow: 1;
109
- max-height: none;
110
- opacity: 1;
111
- transform: none;
112
- pointer-events: auto;
113
- }
114
-
115
- @media (prefers-reduced-motion: reduce) {
116
- .studio-composer,
117
- .studio-gallery { transition: none; }
118
- }
119
-
120
64
  @media (prefers-reduced-motion: reduce) {
121
65
  .studio-sheet-content[data-state='open'],
122
66
  .studio-sheet-content[data-state='closed'],
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  MembersPanel
3
- } from "../chunk-F4XLTVQ3.js";
3
+ } from "../chunk-R6KGLGEJ.js";
4
4
  import {
5
5
  InvitationsPanel
6
- } from "../chunk-IUSO2XRE.js";
6
+ } from "../chunk-5BACNOVR.js";
7
+ import "../chunk-AULM4X7U.js";
7
8
  import {
8
9
  InviteAcceptPage
9
- } from "../chunk-VCPZ3HTN.js";
10
+ } from "../chunk-DB2D2JBQ.js";
10
11
  import "../chunk-6XIAPIW6.js";
11
12
  export {
12
13
  InvitationsPanel,
@@ -1,13 +1,13 @@
1
1
  // src/teams-react/lazy.tsx
2
2
  import { lazy } from "react";
3
3
  var MembersPanelLazy = lazy(
4
- () => import("../MembersPanel-XNLF3SA4.js").then((m) => ({ default: m.MembersPanel }))
4
+ () => import("../MembersPanel-N5CBOUXC.js").then((m) => ({ default: m.MembersPanel }))
5
5
  );
6
6
  var InvitationsPanelLazy = lazy(
7
- () => import("../InvitationsPanel-F56UOQXA.js").then((m) => ({ default: m.InvitationsPanel }))
7
+ () => import("../InvitationsPanel-F2VY4TSL.js").then((m) => ({ default: m.InvitationsPanel }))
8
8
  );
9
9
  var InviteAcceptPageLazy = lazy(
10
- () => import("../InviteAcceptPage-P3QJC3C6.js").then((m) => ({ default: m.InviteAcceptPage }))
10
+ () => import("../InviteAcceptPage-UT4452KT.js").then((m) => ({ default: m.InviteAcceptPage }))
11
11
  );
12
12
  export {
13
13
  InvitationsPanelLazy,
@@ -238,6 +238,40 @@
238
238
  --motion-surface: var(--duration-base) var(--ease-entrance);
239
239
  --motion-dismiss: var(--duration-instant) var(--ease-exit);
240
240
 
241
+ /* ── Entrance choreography ───────────────────────────────────────────────
242
+ The durations above answer "how fast does an existing thing change".
243
+ These answer "how does a thing that was not there ARRIVE", which is most
244
+ of what an agent surface does: text streams in, rows appear as work
245
+ completes, a trace expands, a pending label waits.
246
+
247
+ Shipping the ladder without these is why this package had FOUR durations,
248
+ THREE curves, and ZERO keyframes on `/web-react` — every arrival was a
249
+ pop, which reads as cheap no matter how correct the colours are.
250
+
251
+ `--motion-stream` is longer than `base` on purpose: streamed text arrives
252
+ continuously, so each chunk overlaps its neighbours and a fast curve makes
253
+ the paragraph flicker. `--motion-arrive` is the row/card entrance and is
254
+ meant to be staggered by index (see `--stagger-step`). */
255
+ --duration-stream: 420ms;
256
+ --duration-arrive: 600ms;
257
+ --ease-expo: cubic-bezier(0.23, 1, 0.32, 1);
258
+ --motion-stream: var(--duration-stream) var(--ease-expo);
259
+ --motion-arrive: var(--duration-arrive) var(--ease-expo);
260
+ /* Per-item delay in a staggered group. 5 items = 200ms tail, which stays
261
+ under the 250ms an interface can add before it reads as latency. */
262
+ --stagger-step: 50ms;
263
+ /* Position in a staggered group, overridden PER ELEMENT by the caller. It is
264
+ declared here with a zero default rather than read through a `var()`
265
+ fallback so the file never references a token it does not define — an
266
+ undefined `var()` resolves to nothing and paints silently, which is the
267
+ failure the token contract exists to catch. */
268
+ --stagger-index: 0;
269
+ /* How far an arriving surface travels, and how far a streamed chunk resolves
270
+ from. Both are small: motion that announces itself is motion you notice
271
+ twice. */
272
+ --arrive-distance: 8px;
273
+ --stream-blur: 4px;
274
+
241
275
  /* ── Border tiers ────────────────────────────────────────────────────────
242
276
  Three strengths of the SAME border colour, because a divider inside a
243
277
  panel and the edge of a card floated on the page are not the same line,
@@ -389,6 +423,140 @@
389
423
  --shadow-overlay: 0 2px 6px hsl(var(--foreground) / 0.12), 0 16px 40px hsl(var(--foreground) / 0.2);
390
424
  }
391
425
 
426
+ /**
427
+ * Entrance keyframes and the classes that ride them.
428
+ *
429
+ * They live in this file, not in a component, because a product already
430
+ * imports this stylesheet and because a keyframe defined inside a bundled
431
+ * component is a keyframe a precompiled consumer does not get — the same gap
432
+ * that shipped a picker with no text tier.
433
+ *
434
+ * Every duration below is a TOKEN, which is what makes the reduced-motion
435
+ * block underneath cover them without a second media query.
436
+ */
437
+
438
+ /* Streamed text: each chunk resolves out of a small blur instead of popping
439
+ in. This is the single most visible difference between a chat that feels
440
+ alive and one that feels like a log being appended to. */
441
+ @keyframes agent-stream-in {
442
+ from {
443
+ opacity: 0;
444
+ filter: blur(var(--stream-blur));
445
+ }
446
+ to {
447
+ opacity: 1;
448
+ filter: blur(0);
449
+ }
450
+ }
451
+
452
+ /* A row, card or chip that was not there a moment ago. Travels a short
453
+ distance so the eye is told WHERE it came from. */
454
+ @keyframes agent-arrive {
455
+ from {
456
+ opacity: 0;
457
+ transform: translateY(var(--arrive-distance));
458
+ }
459
+ to {
460
+ opacity: 1;
461
+ transform: none;
462
+ }
463
+ }
464
+
465
+ /* A control appearing in place — a chip, a badge, a menu row. No travel,
466
+ because it did not come from anywhere. */
467
+ @keyframes agent-pop-in {
468
+ from {
469
+ opacity: 0;
470
+ transform: scale(0.96);
471
+ }
472
+ to {
473
+ opacity: 1;
474
+ transform: none;
475
+ }
476
+ }
477
+
478
+ /* The insertion caret at the end of streaming text. A hard step blink, not a
479
+ fade: a caret that eases is a caret that reads as a loading placeholder. */
480
+ @keyframes agent-caret {
481
+ 0%,
482
+ 49% {
483
+ opacity: 1;
484
+ }
485
+ 50%,
486
+ 100% {
487
+ opacity: 0;
488
+ }
489
+ }
490
+
491
+ /* A label that is WAITING. The sweep is what separates "the agent is working"
492
+ from "the interface is stuck": a static label cannot tell you which. */
493
+ @keyframes agent-shimmer {
494
+ from {
495
+ background-position: 150% center;
496
+ }
497
+ to {
498
+ background-position: -50% center;
499
+ }
500
+ }
501
+
502
+ .agent-stream-in {
503
+ animation: agent-stream-in var(--motion-stream) both;
504
+ }
505
+
506
+ .agent-arrive {
507
+ animation: agent-arrive var(--motion-arrive) both;
508
+ }
509
+
510
+ .agent-pop-in {
511
+ animation: agent-pop-in var(--motion-control) both;
512
+ }
513
+
514
+ /* Stagger by index: set `--stagger-index` and a group arrives as a sequence
515
+ rather than as a flash. Capped at 8 so a 200-row list does not open with a
516
+ 10-second cascade — past the cap every row shares the last delay. */
517
+ .agent-arrive {
518
+ animation-delay: calc(min(var(--stagger-index), 8) * var(--stagger-step));
519
+ }
520
+
521
+ /* The waiting label. `background-clip: text` over a moving gradient, so the
522
+ shimmer runs THROUGH the glyphs rather than behind them. Marked essential:
523
+ it is the only signal that work is still in flight. */
524
+ .agent-shimmer {
525
+ background: linear-gradient(
526
+ 90deg,
527
+ hsl(var(--muted-foreground)) 0%,
528
+ hsl(var(--foreground)) 45%,
529
+ hsl(var(--muted-foreground)) 60%
530
+ );
531
+ background-size: 250% auto;
532
+ background-clip: text;
533
+ -webkit-background-clip: text;
534
+ color: transparent;
535
+ animation: agent-shimmer 1.4s linear infinite;
536
+ }
537
+
538
+ /* Height-auto disclosure without measuring anything in JavaScript. The row
539
+ animates between 0fr and 1fr; the child needs `min-height: 0` and
540
+ `overflow: hidden` to be clipped while it travels. A max-height guess is the
541
+ usual alternative and it either clips tall content or eases against a number
542
+ the content never reaches. */
543
+ .agent-disclose {
544
+ display: grid;
545
+ grid-template-rows: 0fr;
546
+ transition: grid-template-rows var(--motion-surface), opacity var(--motion-control);
547
+ opacity: 0;
548
+ }
549
+
550
+ .agent-disclose > * {
551
+ min-height: 0;
552
+ overflow: hidden;
553
+ }
554
+
555
+ .agent-disclose[data-open='true'] {
556
+ grid-template-rows: 1fr;
557
+ opacity: 1;
558
+ }
559
+
392
560
  /**
393
561
  * Reduced motion, at the token layer and at the floor.
394
562
  *
@@ -420,6 +588,11 @@
420
588
  --duration-fast: 1ms;
421
589
  --duration-base: 1ms;
422
590
  --duration-slow: 1ms;
591
+ --duration-stream: 1ms;
592
+ --duration-arrive: 1ms;
593
+ /* The stagger is a delay, not a duration, and a collapsed animation with a
594
+ live delay still arrives as a visible cascade. */
595
+ --stagger-step: 0ms;
423
596
  }
424
597
 
425
598
  *:where(:not([data-motion='essential'], [data-motion='essential'] *)) {
@@ -521,11 +521,14 @@ interface QuestionOptionListProps {
521
521
  selectedValues: string[];
522
522
  disabled: boolean;
523
523
  onToggle: (value: string) => void;
524
+ /** Terminal answered state: the selected rows highlight (primary edge, tint,
525
+ * trailing check) so the card shows WHAT was answered, not just that it was. */
526
+ answered?: boolean;
524
527
  }
525
528
  /** The radio/checkbox option rows for a select field. Renders a fragment of
526
529
  * option `<label>` rows so a card keeps its own wrapping layout and appends
527
530
  * its own write-in input. */
528
- declare function QuestionOptionList({ groupName, idPrefix, options, multi, selectedValues, disabled, onToggle, }: QuestionOptionListProps): react.JSX.Element;
531
+ declare function QuestionOptionList({ groupName, idPrefix, options, multi, selectedValues, disabled, onToggle, answered, }: QuestionOptionListProps): react.JSX.Element;
529
532
  interface InteractionQuestionCardProps {
530
533
  interaction: ChatInteraction;
531
534
  /** Viewer-vs-editor gate: false renders everything read-only. */
@@ -542,11 +545,6 @@ interface InteractionQuestionCardProps {
542
545
  onLateAnswer?: (message: string) => boolean | void | Promise<boolean | void>;
543
546
  /** Overrides the kind badge ("Question"). */
544
547
  kindLabel?: string;
545
- /** Overrides the header note ("The agent asked for input"). Set it whenever an
546
- * agent is not the one asking — a host that parks on a human at the graph
547
- * level is not an agent's mid-run question, and a card that claims otherwise
548
- * misreports why the work stopped. */
549
- sourceNote?: string;
550
548
  /** What happens if nobody answers, rendered beside the submit action.
551
549
  *
552
550
  * The caller owns both the clock and the copy: this card holds no timer, so a
@@ -570,7 +568,7 @@ interface InteractionQuestionCardProps {
570
568
  renderMarkdown?: (markdown: string) => ReactNode;
571
569
  className?: string;
572
570
  }
573
- declare function InteractionQuestionCard({ interaction, canWrite, submitAnswer, onResolved, onLateAnswer, kindLabel, sourceNote, timeoutNote, renderMarkdown, className, }: InteractionQuestionCardProps): react.JSX.Element;
571
+ declare function InteractionQuestionCard({ interaction, canWrite, submitAnswer, onResolved, onLateAnswer, kindLabel, timeoutNote, renderMarkdown, className, }: InteractionQuestionCardProps): react.JSX.Element;
574
572
 
575
573
  interface InteractionPlanCardProps {
576
574
  interaction: ChatInteraction;
@@ -1425,7 +1423,7 @@ interface SeatPaywallProps {
1425
1423
  offer?: ProductSeatOffer;
1426
1424
  /** Optional one-line value prop under the headline. */
1427
1425
  tagline?: string;
1428
- /** CTA label. Default "Unlock {product}". */
1426
+ /** CTA label. Default "Continue to checkout". */
1429
1427
  ctaLabel?: string;
1430
1428
  /** Value-prop bullets. Default = product/usage-derived only; pass your own to
1431
1429
  * supply product-specific value props (the shell bakes no GTM copy). */
@@ -1436,7 +1434,10 @@ interface SeatPaywallProps {
1436
1434
  /**
1437
1435
  * Centered card paywall. The price line reads
1438
1436
  * "$100/mo · includes $50/mo of AI usage" so the included allowance anchors the
1439
- * value without ever exposing the ratio.
1437
+ * value without ever exposing the ratio — and says it ONCE: the default
1438
+ * benefits don't restate the usage line the subline already carries, and the
1439
+ * CTA is the next step ("Continue to checkout"), not a third repeat of the
1440
+ * eyebrow + headline's "Unlock {product}".
1440
1441
  */
1441
1442
  declare function SeatPaywall({ product, onCheckout, priceUsd, includedUsageUsd, offer, tagline, ctaLabel, benefits, footnote, }: SeatPaywallProps): ReactNode;
1442
1443
 
@@ -2034,8 +2035,9 @@ interface ChatUiMessage extends ChatMessageMetrics {
2034
2035
  /** Define properties for rendering chat messages with optional models, markdown, extras, and durable cards */
2035
2036
  interface ChatMessagesProps {
2036
2037
  messages: ChatUiMessage[];
2037
- /** Shared reading scale for both user and assistant prose. Defaults to 16px;
2038
- * `large` uses 17px without enlarging labels, tool chrome, or metadata. */
2038
+ /** Shared reading scale for both user and assistant prose. Defaults to 15px
2039
+ * at a 1.6 line height; `large` uses 16px at the same leading without
2040
+ * enlarging labels, tool chrome, or metadata. */
2039
2041
  messageSize?: 'default' | 'large';
2040
2042
  /** Transcript chrome. `labeled` (default) keeps the always-on role label +
2041
2043
  * model/tok-s/cost meta line and the primary-tinted user bubble. `quiet`
@@ -2104,6 +2106,8 @@ interface ChatEmptyDoor {
2104
2106
  label: string;
2105
2107
  description?: string;
2106
2108
  onSelect: () => void;
2109
+ /** Optional glyph rendered left of the label. */
2110
+ icon?: ReactNode;
2107
2111
  }
2108
2112
  /** Define properties for rendering the chat empty state with customizable text and starting doors */
2109
2113
  interface ChatEmptyStateProps {
@@ -111,7 +111,7 @@ import {
111
111
  withoutRecordGridCreated,
112
112
  withoutRecordGridRemoved,
113
113
  withoutRecordGridUpdate
114
- } from "../chunk-UM6ODCLN.js";
114
+ } from "../chunk-C7AQW6US.js";
115
115
  import "../chunk-FBVLEGEG.js";
116
116
  import {
117
117
  EvidenceLineageTable,
@@ -124,7 +124,7 @@ import {
124
124
  reviewQueueStateLabel,
125
125
  workProductPartsFromMessageParts,
126
126
  workProductStatusLabel
127
- } from "../chunk-54FYYXAX.js";
127
+ } from "../chunk-J6OJTFNE.js";
128
128
  import {
129
129
  parseReviewQueueItem
130
130
  } from "../chunk-GEYACSFW.js";
@@ -139,7 +139,6 @@ import {
139
139
  OVERLAY_SHADOW,
140
140
  POPOVER_SURFACE_ATTR,
141
141
  PopoverSurface,
142
- ProviderLogo,
143
142
  effortLevelLabel,
144
143
  effortLevelsFromIds,
145
144
  effortMeterFill,
@@ -147,7 +146,10 @@ import {
147
146
  useComposerAttachments,
148
147
  usePending,
149
148
  usePopover
150
- } from "../chunk-GNPN6ED4.js";
149
+ } from "../chunk-XVRHISF3.js";
150
+ import {
151
+ ProviderLogo
152
+ } from "../chunk-MLG6XKPV.js";
151
153
  import {
152
154
  tabTerminalConnectionId,
153
155
  useSandboxTerminalConnection
@@ -4,7 +4,7 @@ import {
4
4
  ProvenanceStamp,
5
5
  QualityCheckList,
6
6
  workProductStatusLabel
7
- } from "../chunk-54FYYXAX.js";
7
+ } from "../chunk-J6OJTFNE.js";
8
8
  import "../chunk-GEYACSFW.js";
9
9
  import {
10
10
  unresolvedBlockingExceptions
@@ -16,8 +16,7 @@ import {
16
16
  CodeSurface,
17
17
  DiffView,
18
18
  FileBreadcrumb,
19
- PillTabs,
20
- computeDiffStats
19
+ PillTabs
21
20
  } from "@tangle-network/sandbox-ui/workbench";
22
21
  import { jsx, jsxs } from "react/jsx-runtime";
23
22
  function filenameOf(path, fallback) {
@@ -55,10 +54,6 @@ function WorkProductPane({
55
54
  const [compare, setCompare] = useState(null);
56
55
  const [compareError, setCompareError] = useState(null);
57
56
  const diffFilename = filenameOf(artifact?.path, artifact?.title ?? workProduct.scopeKey);
58
- const diffStats = useMemo(
59
- () => hasDiff ? computeDiffStats(baseline ?? "", body) : null,
60
- [hasDiff, baseline, body]
61
- );
62
57
  const loadCompare = useCallback(
63
58
  async (from, to) => {
64
59
  if (!loadVersionBody || !from.artifactPath || !to.artifactPath) return;
@@ -109,20 +104,7 @@ function WorkProductPane({
109
104
  artifact?.path && /* @__PURE__ */ jsx(FileBreadcrumb, { path: artifact.path, className: "border-b border-border px-3 py-2" }),
110
105
  body ? /* @__PURE__ */ jsx(CodeSurface, { code: body, filename: diffFilename }) : artifact?.fields ? /* @__PURE__ */ jsx(CodeSurface, { code: JSON.stringify(artifact.fields, null, 2), filename: `${diffFilename}.json`, language: "json" }) : /* @__PURE__ */ jsx("p", { className: "px-4 py-6 text-center text-xs text-muted-foreground", children: "No artifact body yet." })
111
106
  ] }),
112
- tab === "diff" && hasDiff && /* @__PURE__ */ jsxs("div", { className: "min-h-0 flex-1 overflow-auto rounded-lg border border-border", children: [
113
- diffStats && /* @__PURE__ */ jsxs("p", { className: "border-b border-border px-3 py-2 text-[11px] text-muted-foreground", children: [
114
- /* @__PURE__ */ jsxs("span", { className: "text-success", children: [
115
- "+",
116
- diffStats.added
117
- ] }),
118
- " ",
119
- /* @__PURE__ */ jsxs("span", { className: "text-destructive", children: [
120
- "\u2212",
121
- diffStats.removed
122
- ] })
123
- ] }),
124
- /* @__PURE__ */ jsx(DiffView, { filename: diffFilename, baseline: baseline ?? "", current: body })
125
- ] }),
107
+ tab === "diff" && hasDiff && /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-auto rounded-lg border border-border", children: /* @__PURE__ */ jsx(DiffView, { filename: diffFilename, baseline: baseline ?? "", current: body }) }),
126
108
  tab === "lineage" && /* @__PURE__ */ jsx(EvidenceLineageTable, { evidence: workProduct.evidence, resolveSourceUrl }),
127
109
  tab === "exceptions" && /* @__PURE__ */ jsx(ExceptionList, { exceptions: workProduct.exceptions }),
128
110
  tab === "checks" && /* @__PURE__ */ jsx(QualityCheckList, { checks: workProduct.checks }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/work-product-react/index.tsx"],"sourcesContent":["/**\n * `./work-product-react` — the sandbox-ui-composed review pane. It follows the\n * optional-peer rule: this is the ONLY work-product surface\n * that imports `@tangle-network/sandbox-ui` (its `workbench` primitives:\n * `PillTabs`, `CodeSurface`, `DiffView`, `FileBreadcrumb`,\n * `computeDiffStats`). `/web-react`'s queue/card/lineage components stay\n * sandbox-ui-free; importing THIS subpath requires the otherwise optional\n * sandbox-ui peer.\n *\n * The pane never fetches: bodies arrive as resolved strings\n * (`currentContent`/`baselineContent`) and history compares load through the\n * injected `loadVersionBody(ref)` seam. The default tab is a PROP — tax\n * passes `'lineage'` (lineage before diff for tax), legal passes `'diff'`\n * (the redline IS the artifact), gtm passes `'artifact'`.\n */\n\nimport { useCallback, useMemo, useState } from 'react'\nimport {\n CodeSurface,\n DiffView,\n FileBreadcrumb,\n PillTabs,\n computeDiffStats,\n type PillTabItem,\n} from '@tangle-network/sandbox-ui/workbench'\n\nimport {\n EvidenceLineageTable,\n ExceptionList,\n ProvenanceStamp,\n QualityCheckList,\n workProductStatusLabel,\n} from '../web-react/work-product'\nimport type {\n EvidenceEntry,\n ProfileBacktestSummary,\n WorkProductRecord,\n WorkProductVersionEntry,\n} from '../work-product/types'\nimport { unresolvedBlockingExceptions } from '../work-product/types'\n\nexport type WorkProductPaneTab = 'artifact' | 'diff' | 'lineage' | 'exceptions' | 'checks' | 'history'\n\n/** Properties for the tabbed work-product review pane */\nexport interface WorkProductPaneProps {\n workProduct: WorkProductRecord\n /** Which tab opens first — a product choice, not a heuristic: tax passes\n * 'lineage', legal 'diff', gtm 'artifact'. Default 'artifact'. */\n defaultTab?: WorkProductPaneTab\n /** Resolved artifact body when it lives at `artifact.path` rather than\n * inline. Falls back to `artifact.content`. */\n currentContent?: string\n /** Resolved baseline body for diff-first products. Falls back to\n * `artifact.baseline.content`. */\n baselineContent?: string\n /** Load a frozen version body by its `history[].artifactPath` ref for the\n * vN-1 → vN compare. Omit to hide history compares. */\n loadVersionBody?: (ref: string) => Promise<string | null>\n /** Resolve one evidence entry's source to an openable URL (lineage\n * click-through). */\n resolveSourceUrl?: (entry: EvidenceEntry) => string\n /** Backtest summary for the record's profile hash, rendered on the\n * provenance stamp. */\n backtest?: ProfileBacktestSummary\n className?: string\n}\n\ninterface VersionCompare {\n fromVersion: number\n toVersion: number\n baseline: string\n current: string\n}\n\n/** Trailing path segment for a diff header. */\nfunction filenameOf(path: string | undefined, fallback: string): string {\n if (!path) return fallback\n const segments = path.split('/')\n return segments[segments.length - 1] || fallback\n}\n\n/**\n * The tabbed review pane over one work product: Artifact | Diff | Lineage |\n * Exceptions | Checks | History. Diff renders baseline→current for redline\n * artifacts and vN-1→vN for history compares; lineage is the\n * every-value-traceable table; provenance is stamped across the header.\n */\nexport function WorkProductPane({\n workProduct,\n defaultTab = 'artifact',\n currentContent,\n baselineContent,\n loadVersionBody,\n resolveSourceUrl,\n backtest,\n className,\n}: WorkProductPaneProps) {\n const artifact = workProduct.artifact\n const body = currentContent ?? artifact?.content ?? ''\n const baseline = baselineContent ?? artifact?.baseline?.content\n const hasDiff = baseline !== undefined\n\n const tabs = useMemo(() => {\n const items: PillTabItem<WorkProductPaneTab>[] = [{ value: 'artifact', label: 'Artifact' }]\n if (hasDiff) items.push({ value: 'diff', label: 'Diff' })\n items.push(\n { value: 'lineage', label: `Lineage (${workProduct.evidence.length})` },\n { value: 'exceptions', label: `Exceptions (${workProduct.exceptions.length})` },\n { value: 'checks', label: `Checks (${workProduct.checks.length})` },\n { value: 'history', label: `History (${workProduct.history.length})` },\n )\n return items\n }, [hasDiff, workProduct.evidence.length, workProduct.exceptions.length, workProduct.checks.length, workProduct.history.length])\n\n const initialTab = tabs.some((tab) => tab.value === defaultTab) ? defaultTab : 'artifact'\n const [tab, setTab] = useState<WorkProductPaneTab>(initialTab)\n const [compare, setCompare] = useState<VersionCompare | null>(null)\n const [compareError, setCompareError] = useState<string | null>(null)\n\n const diffFilename = filenameOf(artifact?.path, artifact?.title ?? workProduct.scopeKey)\n const diffStats = useMemo(\n () => (hasDiff ? computeDiffStats(baseline ?? '', body) : null),\n [hasDiff, baseline, body],\n )\n\n const loadCompare = useCallback(\n async (from: WorkProductVersionEntry, to: WorkProductVersionEntry) => {\n if (!loadVersionBody || !from.artifactPath || !to.artifactPath) return\n setCompareError(null)\n try {\n const [fromBody, toBody] = await Promise.all([\n loadVersionBody(from.artifactPath),\n loadVersionBody(to.artifactPath),\n ])\n if (fromBody === null || toBody === null) {\n setCompareError('A version snapshot could not be loaded.')\n return\n }\n setCompare({ fromVersion: from.version, toVersion: to.version, baseline: fromBody, current: toBody })\n } catch (error) {\n setCompareError(error instanceof Error ? error.message : String(error))\n }\n },\n [loadVersionBody],\n )\n\n return (\n <div className={`flex min-h-0 flex-col gap-3 ${className ?? ''}`}>\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-semibold text-foreground\">\n {artifact?.title ?? workProduct.scopeKey}\n <span className=\"ml-1.5 text-[11px] font-normal text-muted-foreground\">v{workProduct.version}</span>\n </p>\n <p className=\"text-[11px] text-muted-foreground\">\n {artifact?.kind && <span className=\"font-mono\">{artifact.kind} · </span>}\n {workProductStatusLabel(workProduct.status)}\n {unresolvedBlockingExceptions(workProduct.exceptions).length > 0 && (\n <span className=\"text-destructive\"> · {unresolvedBlockingExceptions(workProduct.exceptions).length} blocking</span>\n )}\n </p>\n </div>\n <ProvenanceStamp provenance={workProduct.provenance} backtest={backtest} />\n </div>\n\n <PillTabs items={tabs} value={tab} onChange={setTab} aria-label=\"Work product views\" />\n\n {tab === 'artifact' && (\n <div className=\"min-h-0 flex-1 overflow-auto rounded-lg border border-border\">\n {artifact?.path && <FileBreadcrumb path={artifact.path} className=\"border-b border-border px-3 py-2\" />}\n {body ? (\n <CodeSurface code={body} filename={diffFilename} />\n ) : artifact?.fields ? (\n <CodeSurface code={JSON.stringify(artifact.fields, null, 2)} filename={`${diffFilename}.json`} language=\"json\" />\n ) : (\n <p className=\"px-4 py-6 text-center text-xs text-muted-foreground\">No artifact body yet.</p>\n )}\n </div>\n )}\n\n {tab === 'diff' && hasDiff && (\n <div className=\"min-h-0 flex-1 overflow-auto rounded-lg border border-border\">\n {diffStats && (\n <p className=\"border-b border-border px-3 py-2 text-[11px] text-muted-foreground\">\n <span className=\"text-success\">+{diffStats.added}</span>{' '}\n <span className=\"text-destructive\">−{diffStats.removed}</span>\n </p>\n )}\n <DiffView filename={diffFilename} baseline={baseline ?? ''} current={body} />\n </div>\n )}\n\n {tab === 'lineage' && (\n <EvidenceLineageTable evidence={workProduct.evidence} resolveSourceUrl={resolveSourceUrl} />\n )}\n\n {tab === 'exceptions' && <ExceptionList exceptions={workProduct.exceptions} />}\n\n {tab === 'checks' && <QualityCheckList checks={workProduct.checks} />}\n\n {tab === 'history' && (\n <div className=\"space-y-2\">\n {workProduct.history.length === 0 && <p className=\"text-xs text-muted-foreground\">No versions yet.</p>}\n {workProduct.history.map((entry, index) => {\n const prior = workProduct.history\n .slice(0, index)\n .reverse()\n .find((candidate) => candidate.version < entry.version && candidate.artifactPath)\n return (\n <div key={`${entry.version}:${entry.status}:${entry.at}`} className=\"rounded-lg border border-border bg-card px-3 py-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-medium text-foreground\">v{entry.version}</span>\n <span className=\"text-[11px] text-muted-foreground\">{workProductStatusLabel(entry.status)}</span>\n {entry.reviewedBy && <span className=\"text-[11px] text-muted-foreground\">by {entry.reviewedBy}</span>}\n <span className=\"flex-1\" />\n {loadVersionBody && prior?.artifactPath && entry.artifactPath && (\n <button\n type=\"button\"\n onClick={() => void loadCompare(prior, entry)}\n className=\"rounded-md border border-border px-2 py-0.5 text-[11px] font-medium text-foreground transition hover:bg-accent\"\n >\n Compare v{prior.version} → v{entry.version}\n </button>\n )}\n </div>\n {entry.reviewNote && <p className=\"mt-1 text-sm leading-snug text-foreground\">{entry.reviewNote}</p>}\n <ProvenanceStamp provenance={entry.provenance} className=\"mt-1\" />\n </div>\n )\n })}\n {compareError && <p className=\"rounded-md bg-destructive/10 px-3 py-2 text-xs text-destructive\">{compareError}</p>}\n {compare && (\n <div className=\"overflow-auto rounded-lg border border-border\">\n <p className=\"border-b border-border px-3 py-2 text-[11px] text-muted-foreground\">\n v{compare.fromVersion} → v{compare.toVersion}\n </p>\n <DiffView filename={diffFilename} baseline={compare.baseline} current={compare.current} />\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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","names":["tab"]}
1
+ {"version":3,"sources":["../../src/work-product-react/index.tsx"],"sourcesContent":["/**\n * `./work-product-react` — the sandbox-ui-composed review pane. It follows the\n * optional-peer rule: this is the ONLY work-product surface\n * that imports `@tangle-network/sandbox-ui` (its `workbench` primitives:\n * `PillTabs`, `CodeSurface`, `DiffView`, `FileBreadcrumb`).\n * `/web-react`'s queue/card/lineage components stay\n * sandbox-ui-free; importing THIS subpath requires the otherwise optional\n * sandbox-ui peer.\n *\n * The pane never fetches: bodies arrive as resolved strings\n * (`currentContent`/`baselineContent`) and history compares load through the\n * injected `loadVersionBody(ref)` seam. The default tab is a PROP — tax\n * passes `'lineage'` (lineage before diff for tax), legal passes `'diff'`\n * (the redline IS the artifact), gtm passes `'artifact'`.\n */\n\nimport { useCallback, useMemo, useState } from 'react'\nimport {\n CodeSurface,\n DiffView,\n FileBreadcrumb,\n PillTabs,\n type PillTabItem,\n} from '@tangle-network/sandbox-ui/workbench'\n\nimport {\n EvidenceLineageTable,\n ExceptionList,\n ProvenanceStamp,\n QualityCheckList,\n workProductStatusLabel,\n} from '../web-react/work-product'\nimport type {\n EvidenceEntry,\n ProfileBacktestSummary,\n WorkProductRecord,\n WorkProductVersionEntry,\n} from '../work-product/types'\nimport { unresolvedBlockingExceptions } from '../work-product/types'\n\nexport type WorkProductPaneTab = 'artifact' | 'diff' | 'lineage' | 'exceptions' | 'checks' | 'history'\n\n/** Properties for the tabbed work-product review pane */\nexport interface WorkProductPaneProps {\n workProduct: WorkProductRecord\n /** Which tab opens first — a product choice, not a heuristic: tax passes\n * 'lineage', legal 'diff', gtm 'artifact'. Default 'artifact'. */\n defaultTab?: WorkProductPaneTab\n /** Resolved artifact body when it lives at `artifact.path` rather than\n * inline. Falls back to `artifact.content`. */\n currentContent?: string\n /** Resolved baseline body for diff-first products. Falls back to\n * `artifact.baseline.content`. */\n baselineContent?: string\n /** Load a frozen version body by its `history[].artifactPath` ref for the\n * vN-1 → vN compare. Omit to hide history compares. */\n loadVersionBody?: (ref: string) => Promise<string | null>\n /** Resolve one evidence entry's source to an openable URL (lineage\n * click-through). */\n resolveSourceUrl?: (entry: EvidenceEntry) => string\n /** Backtest summary for the record's profile hash, rendered on the\n * provenance stamp. */\n backtest?: ProfileBacktestSummary\n className?: string\n}\n\ninterface VersionCompare {\n fromVersion: number\n toVersion: number\n baseline: string\n current: string\n}\n\n/** Trailing path segment for a diff header. */\nfunction filenameOf(path: string | undefined, fallback: string): string {\n if (!path) return fallback\n const segments = path.split('/')\n return segments[segments.length - 1] || fallback\n}\n\n/**\n * The tabbed review pane over one work product: Artifact | Diff | Lineage |\n * Exceptions | Checks | History. Diff renders baseline→current for redline\n * artifacts and vN-1→vN for history compares; lineage is the\n * every-value-traceable table; provenance is stamped across the header.\n */\nexport function WorkProductPane({\n workProduct,\n defaultTab = 'artifact',\n currentContent,\n baselineContent,\n loadVersionBody,\n resolveSourceUrl,\n backtest,\n className,\n}: WorkProductPaneProps) {\n const artifact = workProduct.artifact\n const body = currentContent ?? artifact?.content ?? ''\n const baseline = baselineContent ?? artifact?.baseline?.content\n const hasDiff = baseline !== undefined\n\n const tabs = useMemo(() => {\n const items: PillTabItem<WorkProductPaneTab>[] = [{ value: 'artifact', label: 'Artifact' }]\n if (hasDiff) items.push({ value: 'diff', label: 'Diff' })\n items.push(\n { value: 'lineage', label: `Lineage (${workProduct.evidence.length})` },\n { value: 'exceptions', label: `Exceptions (${workProduct.exceptions.length})` },\n { value: 'checks', label: `Checks (${workProduct.checks.length})` },\n { value: 'history', label: `History (${workProduct.history.length})` },\n )\n return items\n }, [hasDiff, workProduct.evidence.length, workProduct.exceptions.length, workProduct.checks.length, workProduct.history.length])\n\n const initialTab = tabs.some((tab) => tab.value === defaultTab) ? defaultTab : 'artifact'\n const [tab, setTab] = useState<WorkProductPaneTab>(initialTab)\n const [compare, setCompare] = useState<VersionCompare | null>(null)\n const [compareError, setCompareError] = useState<string | null>(null)\n\n const diffFilename = filenameOf(artifact?.path, artifact?.title ?? workProduct.scopeKey)\n\n const loadCompare = useCallback(\n async (from: WorkProductVersionEntry, to: WorkProductVersionEntry) => {\n if (!loadVersionBody || !from.artifactPath || !to.artifactPath) return\n setCompareError(null)\n try {\n const [fromBody, toBody] = await Promise.all([\n loadVersionBody(from.artifactPath),\n loadVersionBody(to.artifactPath),\n ])\n if (fromBody === null || toBody === null) {\n setCompareError('A version snapshot could not be loaded.')\n return\n }\n setCompare({ fromVersion: from.version, toVersion: to.version, baseline: fromBody, current: toBody })\n } catch (error) {\n setCompareError(error instanceof Error ? error.message : String(error))\n }\n },\n [loadVersionBody],\n )\n\n return (\n <div className={`flex min-h-0 flex-col gap-3 ${className ?? ''}`}>\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-semibold text-foreground\">\n {artifact?.title ?? workProduct.scopeKey}\n <span className=\"ml-1.5 text-[11px] font-normal text-muted-foreground\">v{workProduct.version}</span>\n </p>\n <p className=\"text-[11px] text-muted-foreground\">\n {artifact?.kind && <span className=\"font-mono\">{artifact.kind} · </span>}\n {workProductStatusLabel(workProduct.status)}\n {unresolvedBlockingExceptions(workProduct.exceptions).length > 0 && (\n <span className=\"text-destructive\"> · {unresolvedBlockingExceptions(workProduct.exceptions).length} blocking</span>\n )}\n </p>\n </div>\n <ProvenanceStamp provenance={workProduct.provenance} backtest={backtest} />\n </div>\n\n <PillTabs items={tabs} value={tab} onChange={setTab} aria-label=\"Work product views\" />\n\n {tab === 'artifact' && (\n <div className=\"min-h-0 flex-1 overflow-auto rounded-lg border border-border\">\n {artifact?.path && <FileBreadcrumb path={artifact.path} className=\"border-b border-border px-3 py-2\" />}\n {body ? (\n <CodeSurface code={body} filename={diffFilename} />\n ) : artifact?.fields ? (\n <CodeSurface code={JSON.stringify(artifact.fields, null, 2)} filename={`${diffFilename}.json`} language=\"json\" />\n ) : (\n <p className=\"px-4 py-6 text-center text-xs text-muted-foreground\">No artifact body yet.</p>\n )}\n </div>\n )}\n\n {tab === 'diff' && hasDiff && (\n <div className=\"min-h-0 flex-1 overflow-auto rounded-lg border border-border\">\n {/* DiffView's own file header already carries the +/− counts. */}\n <DiffView filename={diffFilename} baseline={baseline ?? ''} current={body} />\n </div>\n )}\n\n {tab === 'lineage' && (\n <EvidenceLineageTable evidence={workProduct.evidence} resolveSourceUrl={resolveSourceUrl} />\n )}\n\n {tab === 'exceptions' && <ExceptionList exceptions={workProduct.exceptions} />}\n\n {tab === 'checks' && <QualityCheckList checks={workProduct.checks} />}\n\n {tab === 'history' && (\n <div className=\"space-y-2\">\n {workProduct.history.length === 0 && <p className=\"text-xs text-muted-foreground\">No versions yet.</p>}\n {workProduct.history.map((entry, index) => {\n const prior = workProduct.history\n .slice(0, index)\n .reverse()\n .find((candidate) => candidate.version < entry.version && candidate.artifactPath)\n return (\n <div key={`${entry.version}:${entry.status}:${entry.at}`} className=\"rounded-lg border border-border bg-card px-3 py-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-medium text-foreground\">v{entry.version}</span>\n <span className=\"text-[11px] text-muted-foreground\">{workProductStatusLabel(entry.status)}</span>\n {entry.reviewedBy && <span className=\"text-[11px] text-muted-foreground\">by {entry.reviewedBy}</span>}\n <span className=\"flex-1\" />\n {loadVersionBody && prior?.artifactPath && entry.artifactPath && (\n <button\n type=\"button\"\n onClick={() => void loadCompare(prior, entry)}\n className=\"rounded-md border border-border px-2 py-0.5 text-[11px] font-medium text-foreground transition hover:bg-accent\"\n >\n Compare v{prior.version} → v{entry.version}\n </button>\n )}\n </div>\n {entry.reviewNote && <p className=\"mt-1 text-sm leading-snug text-foreground\">{entry.reviewNote}</p>}\n <ProvenanceStamp provenance={entry.provenance} className=\"mt-1\" />\n </div>\n )\n })}\n {compareError && <p className=\"rounded-md bg-destructive/10 px-3 py-2 text-xs text-destructive\">{compareError}</p>}\n {compare && (\n <div className=\"overflow-auto rounded-lg border border-border\">\n <p className=\"border-b border-border px-3 py-2 text-[11px] text-muted-foreground\">\n v{compare.fromVersion} → v{compare.toVersion}\n </p>\n <DiffView filename={diffFilename} baseline={compare.baseline} current={compare.current} />\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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","names":["tab"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-app",
3
- "version": "0.45.46",
3
+ "version": "0.45.48",
4
4
  "packageManager": "pnpm@11.17.0",
5
5
  "description": "Build agent applications with typed chat, tools, sandboxes, integrations, billing, and evaluation.",
6
6
  "keywords": [
@@ -526,7 +526,7 @@
526
526
  "@tangle-network/agent-runtime": "0.126.0",
527
527
  "@tangle-network/brand": "1.3.0",
528
528
  "@tangle-network/sandbox": "0.17.2",
529
- "@tangle-network/sandbox-ui": "0.94.2",
529
+ "@tangle-network/sandbox-ui": "0.99.2",
530
530
  "@tangle-network/ui": "^11.2.2",
531
531
  "@testing-library/dom": "^10.4.1",
532
532
  "@testing-library/react": "^16.3.2",
@@ -578,7 +578,7 @@
578
578
  "@tangle-network/agent-runtime": ">=0.126.0",
579
579
  "@tangle-network/brand": ">=1.1.0",
580
580
  "@tangle-network/sandbox": ">=0.15.2",
581
- "@tangle-network/sandbox-ui": ">=0.91.5",
581
+ "@tangle-network/sandbox-ui": ">=0.99.2",
582
582
  "@tangle-network/ui": ">=11.2.2",
583
583
  "@xyflow/react": ">=12.0.0",
584
584
  "better-auth": ">=1.6.16",
@@ -1,8 +0,0 @@
1
- import {
2
- InvitationsPanel
3
- } from "./chunk-IUSO2XRE.js";
4
- import "./chunk-6XIAPIW6.js";
5
- export {
6
- InvitationsPanel
7
- };
8
- //# sourceMappingURL=InvitationsPanel-F56UOQXA.js.map
@@ -1,7 +0,0 @@
1
- import {
2
- InviteAcceptPage
3
- } from "./chunk-VCPZ3HTN.js";
4
- export {
5
- InviteAcceptPage
6
- };
7
- //# sourceMappingURL=InviteAcceptPage-P3QJC3C6.js.map
@@ -1,8 +0,0 @@
1
- import {
2
- MembersPanel
3
- } from "./chunk-F4XLTVQ3.js";
4
- import "./chunk-6XIAPIW6.js";
5
- export {
6
- MembersPanel
7
- };
8
- //# sourceMappingURL=MembersPanel-XNLF3SA4.js.map