@tangle-network/agent-app 0.45.49 → 0.45.51

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.
@@ -13,6 +13,9 @@ import {
13
13
  usePending,
14
14
  usePopover
15
15
  } from "./chunk-CJHIAZKK.js";
16
+ import {
17
+ AsyncView
18
+ } from "./chunk-3UBAO3N5.js";
16
19
  import {
17
20
  UNTITLED_SESSION_LABEL,
18
21
  mergeSessionPages,
@@ -37,7 +40,7 @@ import {
37
40
  } from "./chunk-YJMCRXQQ.js";
38
41
 
39
42
  // src/web-react/index.tsx
40
- import { useEffect as useEffect11, useMemo as useMemo7, useRef as useRef11, useState as useState14, memo } from "react";
43
+ import { useEffect as useEffect12, useId as useId4, useMemo as useMemo7, useRef as useRef12, useState as useState16, memo } from "react";
41
44
  import { InlineToolItem } from "@tangle-network/ui/run";
42
45
 
43
46
  // src/web-react/smooth-text.ts
@@ -80,6 +83,22 @@ function useSmoothText(target, enabled, opts) {
80
83
  return target.slice(0, Math.floor(shownRef.current));
81
84
  }
82
85
 
86
+ // src/web-react/inert.ts
87
+ function inertProps(inert) {
88
+ if (!inert) return {};
89
+ return { inert: "1" };
90
+ }
91
+
92
+ // src/web-react/motion.ts
93
+ import { useState as useState2 } from "react";
94
+ function staggerStyle(index, base) {
95
+ return { ...base, "--stagger-index": index };
96
+ }
97
+ function useArrivalStyle(index) {
98
+ const [frozen] = useState2(index);
99
+ return staggerStyle(frozen);
100
+ }
101
+
83
102
  // src/web-react/brand-mark.tsx
84
103
  import { lazy, Suspense } from "react";
85
104
  import { jsx } from "react/jsx-runtime";
@@ -99,10 +118,10 @@ function BrandMark({ size = 24, className }) {
99
118
  }
100
119
 
101
120
  // src/web-react/durable-plan-card.tsx
102
- import { useEffect as useEffect3, useLayoutEffect, useRef as useRef3, useState as useState3 } from "react";
121
+ import { useEffect as useEffect3, useLayoutEffect, useRef as useRef3, useState as useState4 } from "react";
103
122
 
104
123
  // src/web-react/interaction-question-card.tsx
105
- import { useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
124
+ import { useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState3 } from "react";
106
125
 
107
126
  // src/web-react/interaction-card-support.ts
108
127
  function interactionStatusLabels(labels) {
@@ -310,7 +329,8 @@ function QuestionOptionList({
310
329
  "label",
311
330
  {
312
331
  htmlFor: inputId,
313
- className: `flex gap-2 rounded-lg border p-3 transition-colors ${highlighted ? "border-primary bg-primary/5" : "border-strong"} ${disabled ? "cursor-default" : "cursor-pointer hover:bg-accent"}`,
332
+ style: staggerStyle(optionIndex),
333
+ className: `agent-arrive flex gap-2 rounded-lg border p-3 transition-colors ${highlighted ? "border-primary bg-primary/5" : "border-strong"} ${disabled ? "cursor-default" : "cursor-pointer hover:bg-accent"}`,
314
334
  children: [
315
335
  /* @__PURE__ */ jsx2(
316
336
  "input",
@@ -376,13 +396,13 @@ function InteractionQuestionCard({
376
396
  renderMarkdown,
377
397
  className
378
398
  }) {
379
- const [values, setValues] = useState2(() => fieldValuesFromAnswers(interaction.fields, interaction.answers));
380
- const [submitting, setSubmitting] = useState2(false);
381
- const [localStatus, setLocalStatus] = useState2(null);
382
- const [lateAnswerSent, setLateAnswerSent] = useState2(false);
383
- const [error, setError] = useState2(null);
399
+ const [values, setValues] = useState3(() => fieldValuesFromAnswers(interaction.fields, interaction.answers));
400
+ const [submitting, setSubmitting] = useState3(false);
401
+ const [localStatus, setLocalStatus] = useState3(null);
402
+ const [lateAnswerSent, setLateAnswerSent] = useState3(false);
403
+ const [error, setError] = useState3(null);
384
404
  const submitInFlightRef = useRef2(false);
385
- const [askId, setAskId] = useState2(interaction.id);
405
+ const [askId, setAskId] = useState3(interaction.id);
386
406
  if (askId !== interaction.id) {
387
407
  setAskId(interaction.id);
388
408
  setValues(fieldValuesFromAnswers(interaction.fields, interaction.answers));
@@ -468,10 +488,17 @@ function InteractionQuestionCard({
468
488
  submitLabel = "Submitting\u2026";
469
489
  }
470
490
  return (
491
+ // The card LANDS. This is the moment the run stopped and handed the turn
492
+ // back — a surface that blinks into place reads as chrome that was always
493
+ // there, which is exactly the wrong reading for the one thing on screen
494
+ // waiting on the reader. `.agent-arrive` runs once on mount; a status
495
+ // change (answered, expired, a failed submit) re-renders the same DOM node
496
+ // and therefore does NOT replay it.
497
+ //
471
498
  // `dark:[color-scheme:dark]` keeps the native radios/checkboxes on the
472
499
  // dark control scheme — without it they paint light-scheme white on the
473
500
  // dark card.
474
- /* @__PURE__ */ jsxs("div", { className: `rounded-xl border border-card-edge bg-card p-4 dark:[color-scheme:dark] ${className ?? ""}`, children: [
501
+ /* @__PURE__ */ jsxs("div", { className: `agent-arrive rounded-xl border border-card-edge bg-card p-4 dark:[color-scheme:dark] ${className ?? ""}`, children: [
475
502
  /* @__PURE__ */ jsxs("div", { className: "mb-3 flex flex-wrap items-center gap-2", children: [
476
503
  /* @__PURE__ */ jsx2(InteractionBadge, { variant: "outline", children: kindLabel ?? "Question" }),
477
504
  /* @__PURE__ */ jsx2(InteractionBadge, { variant: answered ? "default" : status === "expired" || status === "declined" ? "destructive" : "outline", children: STATUS_LABELS[status] })
@@ -607,14 +634,14 @@ function DurablePlanCard({
607
634
  renderMarkdown,
608
635
  className
609
636
  }) {
610
- const [feedback, setFeedback] = useState3("");
611
- const [expanded, setExpanded] = useState3(false);
612
- const [localError, setLocalError] = useState3(null);
637
+ const [feedback, setFeedback] = useState4("");
638
+ const [expanded, setExpanded] = useState4(false);
639
+ const [localError, setLocalError] = useState4(null);
613
640
  useEffect3(() => setLocalError(null), [plan.planId, plan.revision, plan.status]);
614
641
  const actionable = plan.status === "pending";
615
642
  const disabled = !canWrite || !actionable || deciding !== null;
616
643
  const bodyRef = useRef3(null);
617
- const [overflows, setOverflows] = useState3(false);
644
+ const [overflows, setOverflows] = useState4(false);
618
645
  useLayoutEffect(() => {
619
646
  const el = bodyRef.current;
620
647
  if (el) setOverflows(el.scrollHeight > COLLAPSED_MAX_HEIGHT);
@@ -685,7 +712,7 @@ function DurablePlanCard({
685
712
  }
686
713
 
687
714
  // src/web-react/interaction-plan-card.tsx
688
- import { useLayoutEffect as useLayoutEffect2, useMemo as useMemo2, useRef as useRef4, useState as useState4 } from "react";
715
+ import { useLayoutEffect as useLayoutEffect2, useMemo as useMemo2, useRef as useRef4, useState as useState5 } from "react";
689
716
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
690
717
  function CheckGlyph2({ className }) {
691
718
  return /* @__PURE__ */ jsx4("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx4("path", { d: "M20 6 9 17l-5-5" }) });
@@ -714,7 +741,7 @@ function submittedFieldText(field, values) {
714
741
  }
715
742
  function useBodyOverflows(body, renderMarkdown) {
716
743
  const bodyRef = useRef4(null);
717
- const [overflows, setOverflows] = useState4(false);
744
+ const [overflows, setOverflows] = useState5(false);
718
745
  useLayoutEffect2(() => {
719
746
  const el = bodyRef.current;
720
747
  if (el) setOverflows(el.scrollHeight > COLLAPSED_MAX_HEIGHT2);
@@ -731,12 +758,12 @@ function InteractionPlanCard({
731
758
  renderMarkdown,
732
759
  className
733
760
  }) {
734
- const [values, setValues] = useState4({});
735
- const [expanded, setExpanded] = useState4(false);
736
- const [submitting, setSubmitting] = useState4(null);
737
- const [localStatus, setLocalStatus] = useState4(null);
738
- const [reRequested, setReRequested] = useState4(false);
739
- const [error, setError] = useState4(null);
761
+ const [values, setValues] = useState5({});
762
+ const [expanded, setExpanded] = useState5(false);
763
+ const [submitting, setSubmitting] = useState5(null);
764
+ const [localStatus, setLocalStatus] = useState5(null);
765
+ const [reRequested, setReRequested] = useState5(false);
766
+ const [error, setError] = useState5(null);
740
767
  const submitInFlightRef = useRef4(false);
741
768
  const { bodyRef, overflows } = useBodyOverflows(interaction.body, renderMarkdown);
742
769
  const status = isTerminalInteractionStatus(interaction.status) ? interaction.status : localStatus ?? interaction.status;
@@ -800,85 +827,105 @@ function InteractionPlanCard({
800
827
  const terminalNote = TERMINAL_NOTES2[status];
801
828
  const approved = status === "answered";
802
829
  const submittedValues = interaction.answers ? fieldValuesFromAnswers(interaction.fields, interaction.answers) : values;
803
- return /* @__PURE__ */ jsxs3("div", { className: `rounded-xl border border-card-edge bg-card p-4 ${className ?? ""}`, children: [
804
- /* @__PURE__ */ jsxs3("div", { className: "mb-3 flex flex-wrap items-center gap-2", children: [
805
- /* @__PURE__ */ jsx4(InteractionBadge, { variant: "outline", children: "Plan" }),
806
- /* @__PURE__ */ jsx4(InteractionBadge, { variant: approved ? "default" : status === "expired" || status === "declined" ? "destructive" : "outline", children: STATUS_LABELS2[status] })
807
- ] }),
808
- interaction.title.trim() && /* @__PURE__ */ jsx4("p", { className: "mb-3 text-[15px] font-semibold leading-snug text-foreground", children: interaction.title }),
809
- interaction.body && /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
810
- /* @__PURE__ */ jsx4(
811
- "div",
812
- {
813
- ref: bodyRef,
814
- className: "overflow-hidden text-sm text-foreground",
815
- style: expanded || !overflows ? void 0 : { maxHeight: COLLAPSED_MAX_HEIGHT2 },
816
- children: renderMarkdown ? renderMarkdown(interaction.body) : /* @__PURE__ */ jsx4("p", { className: "whitespace-pre-wrap leading-5", children: interaction.body })
817
- }
818
- ),
819
- overflows && !expanded && /* @__PURE__ */ jsx4("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-12 bg-gradient-to-t from-card to-transparent" }),
820
- overflows && /* @__PURE__ */ jsxs3(
821
- "button",
822
- {
823
- type: "button",
824
- onClick: () => setExpanded((prev) => !prev),
825
- className: "relative z-10 mt-1 inline-flex items-center gap-1 text-xs text-muted-foreground transition hover:text-foreground",
826
- children: [
827
- /* @__PURE__ */ jsx4(ChevronDownGlyph, { className: `h-3 w-3 transition-transform ${expanded ? "rotate-180" : ""}` }),
828
- expanded ? "Collapse plan" : "Show full plan"
829
- ]
830
- }
831
- )
832
- ] }),
833
- interaction.fields.length > 0 && status === "pending" && /* @__PURE__ */ jsx4("div", { className: "mt-3 space-y-4", children: interaction.fields.map((field) => /* @__PURE__ */ jsxs3("fieldset", { className: "space-y-2", children: [
834
- /* @__PURE__ */ jsx4("p", { className: "text-sm font-medium leading-5 text-foreground", children: field.label }),
835
- fieldAcceptsFreeText(field) ? /* @__PURE__ */ jsx4(
836
- "textarea",
837
- {
838
- value: values[field.name]?.text ?? "",
839
- disabled,
840
- "aria-label": field.label,
841
- onChange: (event) => setValues((prev) => ({ ...prev, [field.name]: { ...prev[field.name], text: event.target.value } })),
842
- rows: 2,
843
- placeholder: field.type === "text" ? field.placeholder ?? "Optional feedback for the agent" : void 0,
844
- className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground focus:border-primary disabled:opacity-50"
845
- }
846
- ) : /* @__PURE__ */ jsx4(
847
- "input",
848
- {
849
- type: "text",
850
- value: values[field.name]?.text ?? "",
851
- disabled,
852
- "aria-label": field.label,
853
- onChange: (event) => setValues((prev) => ({ ...prev, [field.name]: { ...prev[field.name], text: event.target.value } })),
854
- className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground focus:border-primary disabled:opacity-50"
855
- }
856
- )
857
- ] }, field.name)) }),
858
- interaction.fields.length > 0 && status !== "pending" && /* @__PURE__ */ jsx4("div", { className: "mt-3 space-y-2", children: interaction.fields.map((field) => {
859
- const text = submittedFieldText(field, submittedValues);
860
- if (!text) return null;
861
- return /* @__PURE__ */ jsxs3("div", { children: [
862
- /* @__PURE__ */ jsx4("p", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
863
- /* @__PURE__ */ jsx4("p", { className: "mt-0.5 whitespace-pre-wrap text-sm text-foreground", children: text })
864
- ] }, field.name);
865
- }) }),
866
- error && /* @__PURE__ */ jsx4("p", { className: "mt-3 text-xs text-destructive", children: error }),
867
- terminalNote && /* @__PURE__ */ jsx4("p", { className: "mt-3 text-xs text-muted-foreground", children: terminalNote }),
868
- canReRequest && /* @__PURE__ */ jsx4("div", { className: "mt-4 flex items-center justify-end", children: /* @__PURE__ */ jsx4(InteractionActionButton, { variant: "outline", onClick: () => void requestReSubmission(), disabled: submitting !== null, children: submitting === "requesting" ? "Asking\u2026" : reRequestLabel ?? DEFAULT_RE_REQUEST_LABEL }) }),
869
- reRequested && /* @__PURE__ */ jsx4("div", { className: "mt-4 flex items-center justify-end", children: /* @__PURE__ */ jsxs3("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [
870
- /* @__PURE__ */ jsx4(CheckGlyph2, { className: "h-3 w-3" }),
871
- "Re-submission requested"
872
- ] }) }),
873
- status === "pending" && /* @__PURE__ */ jsxs3("div", { className: "mt-4 flex items-center justify-end gap-2", children: [
874
- /* @__PURE__ */ jsx4(InteractionActionButton, { variant: "outline", onClick: () => void submit("declined"), disabled, children: submitting === "reject" ? "Sending\u2026" : "Request changes" }),
875
- /* @__PURE__ */ jsx4(InteractionActionButton, { onClick: () => void submit("accepted"), disabled: disabled || approveData === null, children: submitting === "approve" ? "Approving\u2026" : "Approve plan" })
876
- ] }),
877
- approved && /* @__PURE__ */ jsx4("div", { className: "mt-4 flex items-center justify-end", children: /* @__PURE__ */ jsxs3("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [
878
- /* @__PURE__ */ jsx4(CheckGlyph2, { className: "h-3 w-3" }),
879
- "Approved"
880
- ] }) })
881
- ] });
830
+ return (
831
+ // Same arrival as the question card: an approval is the run stopping, and
832
+ // the card that carries it should land rather than appear. Once on screen
833
+ // it never re-animates approving, rejecting or a 410 changes state on the
834
+ // same DOM node, and a CSS animation does not replay on a re-render.
835
+ /* @__PURE__ */ jsxs3("div", { className: `agent-arrive rounded-xl border border-card-edge bg-card p-4 ${className ?? ""}`, children: [
836
+ /* @__PURE__ */ jsxs3("div", { className: "mb-3 flex flex-wrap items-center gap-2", children: [
837
+ /* @__PURE__ */ jsx4(InteractionBadge, { variant: "outline", children: "Plan" }),
838
+ /* @__PURE__ */ jsx4(InteractionBadge, { variant: approved ? "default" : status === "expired" || status === "declined" ? "destructive" : "outline", children: STATUS_LABELS2[status] })
839
+ ] }),
840
+ interaction.title.trim() && /* @__PURE__ */ jsx4("p", { className: "mb-3 text-[15px] font-semibold leading-snug text-foreground", children: interaction.title }),
841
+ interaction.body && /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
842
+ /* @__PURE__ */ jsx4(
843
+ "div",
844
+ {
845
+ ref: bodyRef,
846
+ className: "overflow-hidden text-sm text-foreground",
847
+ style: expanded || !overflows ? void 0 : { maxHeight: COLLAPSED_MAX_HEIGHT2 },
848
+ children: renderMarkdown ? renderMarkdown(interaction.body) : /* @__PURE__ */ jsx4("p", { className: "whitespace-pre-wrap leading-5", children: interaction.body })
849
+ }
850
+ ),
851
+ overflows && !expanded && /* @__PURE__ */ jsx4("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-12 bg-gradient-to-t from-card to-transparent" }),
852
+ overflows && /* @__PURE__ */ jsxs3(
853
+ "button",
854
+ {
855
+ type: "button",
856
+ onClick: () => setExpanded((prev) => !prev),
857
+ className: "relative z-10 mt-1 inline-flex items-center gap-1 text-xs text-muted-foreground transition hover:text-foreground",
858
+ children: [
859
+ /* @__PURE__ */ jsx4(ChevronDownGlyph, { className: `h-3 w-3 transition-transform ${expanded ? "rotate-180" : ""}` }),
860
+ expanded ? "Collapse plan" : "Show full plan"
861
+ ]
862
+ }
863
+ )
864
+ ] }),
865
+ interaction.fields.length > 0 && status === "pending" && // The fields do NOT carry their own `.agent-arrive`. One level per
866
+ // surface: the card is the thing that was not there a moment ago, and a
867
+ // second entrance nested inside a travelling parent composes two
868
+ // translations and two opacity ramps over the same pixels the card
869
+ // lands while its contents are still arriving into it, which reads as
870
+ // instability rather than as sequence.
871
+ //
872
+ // The card level is the one that survives, because a stagger is a claim
873
+ // that these appeared one after another and inside a landing card that
874
+ // claim is false — they all appeared with it. The question card keeps
875
+ // its option rows staggered for the opposite reason: those are the
876
+ // CHOICES being offered, and telling the eye there are three of them
877
+ // before it has read any is information about the decision. A form's
878
+ // fields carry no such count to announce.
879
+ /* @__PURE__ */ jsx4("div", { className: "mt-3 space-y-4", children: interaction.fields.map((field) => /* @__PURE__ */ jsxs3("fieldset", { className: "space-y-2", children: [
880
+ /* @__PURE__ */ jsx4("p", { className: "text-sm font-medium leading-5 text-foreground", children: field.label }),
881
+ fieldAcceptsFreeText(field) ? /* @__PURE__ */ jsx4(
882
+ "textarea",
883
+ {
884
+ value: values[field.name]?.text ?? "",
885
+ disabled,
886
+ "aria-label": field.label,
887
+ onChange: (event) => setValues((prev) => ({ ...prev, [field.name]: { ...prev[field.name], text: event.target.value } })),
888
+ rows: 2,
889
+ placeholder: field.type === "text" ? field.placeholder ?? "Optional feedback for the agent" : void 0,
890
+ className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground focus:border-primary disabled:opacity-50"
891
+ }
892
+ ) : /* @__PURE__ */ jsx4(
893
+ "input",
894
+ {
895
+ type: "text",
896
+ value: values[field.name]?.text ?? "",
897
+ disabled,
898
+ "aria-label": field.label,
899
+ onChange: (event) => setValues((prev) => ({ ...prev, [field.name]: { ...prev[field.name], text: event.target.value } })),
900
+ className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground focus:border-primary disabled:opacity-50"
901
+ }
902
+ )
903
+ ] }, field.name)) }),
904
+ interaction.fields.length > 0 && status !== "pending" && /* @__PURE__ */ jsx4("div", { className: "mt-3 space-y-2", children: interaction.fields.map((field) => {
905
+ const text = submittedFieldText(field, submittedValues);
906
+ if (!text) return null;
907
+ return /* @__PURE__ */ jsxs3("div", { children: [
908
+ /* @__PURE__ */ jsx4("p", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
909
+ /* @__PURE__ */ jsx4("p", { className: "mt-0.5 whitespace-pre-wrap text-sm text-foreground", children: text })
910
+ ] }, field.name);
911
+ }) }),
912
+ error && /* @__PURE__ */ jsx4("p", { className: "mt-3 text-xs text-destructive", children: error }),
913
+ terminalNote && /* @__PURE__ */ jsx4("p", { className: "mt-3 text-xs text-muted-foreground", children: terminalNote }),
914
+ canReRequest && /* @__PURE__ */ jsx4("div", { className: "mt-4 flex items-center justify-end", children: /* @__PURE__ */ jsx4(InteractionActionButton, { variant: "outline", onClick: () => void requestReSubmission(), disabled: submitting !== null, children: submitting === "requesting" ? "Asking\u2026" : reRequestLabel ?? DEFAULT_RE_REQUEST_LABEL }) }),
915
+ reRequested && /* @__PURE__ */ jsx4("div", { className: "mt-4 flex items-center justify-end", children: /* @__PURE__ */ jsxs3("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [
916
+ /* @__PURE__ */ jsx4(CheckGlyph2, { className: "h-3 w-3" }),
917
+ "Re-submission requested"
918
+ ] }) }),
919
+ status === "pending" && /* @__PURE__ */ jsxs3("div", { className: "mt-4 flex items-center justify-end gap-2", children: [
920
+ /* @__PURE__ */ jsx4(InteractionActionButton, { variant: "outline", onClick: () => void submit("declined"), disabled, children: submitting === "reject" ? "Sending\u2026" : "Request changes" }),
921
+ /* @__PURE__ */ jsx4(InteractionActionButton, { onClick: () => void submit("accepted"), disabled: disabled || approveData === null, children: submitting === "approve" ? "Approving\u2026" : "Approve plan" })
922
+ ] }),
923
+ approved && /* @__PURE__ */ jsx4("div", { className: "mt-4 flex items-center justify-end", children: /* @__PURE__ */ jsxs3("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [
924
+ /* @__PURE__ */ jsx4(CheckGlyph2, { className: "h-3 w-3" }),
925
+ "Approved"
926
+ ] }) })
927
+ ] })
928
+ );
882
929
  }
883
930
 
884
931
  // src/web-react/durable-chat-cards.tsx
@@ -968,7 +1015,7 @@ function DurableChatCards({
968
1015
  }
969
1016
 
970
1017
  // src/web-react/message-attachments.tsx
971
- import { useCallback, useEffect as useEffect4, useState as useState5 } from "react";
1018
+ import { useCallback, useEffect as useEffect4, useState as useState6 } from "react";
972
1019
  import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
973
1020
  function FileGlyph({ className }) {
974
1021
  return /* @__PURE__ */ jsxs4("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
@@ -1043,7 +1090,7 @@ function triggerAttachmentDownload(name, blob) {
1043
1090
  }
1044
1091
  }
1045
1092
  function useAttachmentObjectUrl(blob) {
1046
- const [url, setUrl] = useState5(null);
1093
+ const [url, setUrl] = useState6(null);
1047
1094
  useEffect4(() => {
1048
1095
  if (!blob) {
1049
1096
  setUrl(null);
@@ -1090,7 +1137,7 @@ function AttachmentUnavailable({ shape }) {
1090
1137
  function AttachmentThumbnail({ part, resolveFileUrl, fetchFile }) {
1091
1138
  const url = resolveFileUrl(part);
1092
1139
  const displayName = attachmentDisplayName(part);
1093
- const [result, setResult] = useState5(null);
1140
+ const [result, setResult] = useState6(null);
1094
1141
  useEffect4(() => {
1095
1142
  if (!displayName) return;
1096
1143
  let cancelled = false;
@@ -1129,8 +1176,8 @@ function AttachmentThumbnail({ part, resolveFileUrl, fetchFile }) {
1129
1176
  }
1130
1177
  function AttachmentChip({ part, resolveFileUrl, fetchFile }) {
1131
1178
  const displayName = attachmentDisplayName(part);
1132
- const [status, setStatus] = useState5("idle");
1133
- const [errorMessage, setErrorMessage] = useState5(null);
1179
+ const [status, setStatus] = useState6("idle");
1180
+ const [errorMessage, setErrorMessage] = useState6(null);
1134
1181
  const handleClick = useCallback(() => {
1135
1182
  if (!displayName || status === "loading") return;
1136
1183
  setStatus("loading");
@@ -1369,7 +1416,7 @@ import {
1369
1416
  useCallback as useCallback2,
1370
1417
  useEffect as useEffect5,
1371
1418
  useRef as useRef5,
1372
- useState as useState6
1419
+ useState as useState7
1373
1420
  } from "react";
1374
1421
  import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1375
1422
  var IS_APPLE_PLATFORM = typeof navigator !== "undefined" && /Mac|iPhone|iPad|iPod/i.test(navigator.platform);
@@ -1441,14 +1488,14 @@ function ChatComposer({
1441
1488
  className
1442
1489
  }) {
1443
1490
  const isControlled = value !== void 0;
1444
- const [internal, setInternal] = useState6(initialValue ?? "");
1491
+ const [internal, setInternal] = useState7(initialValue ?? "");
1445
1492
  const text = isControlled ? value : internal;
1446
1493
  const textRef = useRef5(text);
1447
1494
  textRef.current = text;
1448
1495
  const textareaRef = useRef5(null);
1449
1496
  const fileInputRef = useRef5(null);
1450
1497
  const folderInputRef = useRef5(null);
1451
- const [dragOver, setDragOver] = useState6(false);
1498
+ const [dragOver, setDragOver] = useState7(false);
1452
1499
  const dragDepth = useRef5(0);
1453
1500
  const setText = useCallback2(
1454
1501
  (next) => {
@@ -1514,7 +1561,7 @@ function ChatComposer({
1514
1561
  const readyFileCount = pendingFiles.filter((f) => f.status === "ready").length;
1515
1562
  const hasSendable = text.trim().length > 0 || readyFileCount > 0;
1516
1563
  const canSend = hasSendable && !isStreaming && !disabled;
1517
- const [failedSend, setFailedSend] = useState6(null);
1564
+ const [failedSend, setFailedSend] = useState7(null);
1518
1565
  const failSend = useCallback2(
1519
1566
  (error, draft, trimmed, parts, caret) => {
1520
1567
  const message = sendFailureText(error, sendFailureMessage);
@@ -1822,7 +1869,7 @@ function ChatComposer({
1822
1869
  }
1823
1870
 
1824
1871
  // src/web-react/durable-plan-flow.ts
1825
- import { useCallback as useCallback3, useEffect as useEffect6, useRef as useRef6, useState as useState7 } from "react";
1872
+ import { useCallback as useCallback3, useEffect as useEffect6, useRef as useRef6, useState as useState8 } from "react";
1826
1873
  var DurablePlanClientError = class extends Error {
1827
1874
  constructor(message, status, code, currentPlan) {
1828
1875
  super(message);
@@ -1909,10 +1956,10 @@ function createDurablePlanDecisionClient(options) {
1909
1956
  };
1910
1957
  }
1911
1958
  function useDurablePlanFlow(options) {
1912
- const [plan, setPlan] = useState7(options.plan);
1913
- const [deciding, setDeciding] = useState7(null);
1914
- const [restoring, setRestoring] = useState7(false);
1915
- const [error, setError] = useState7(null);
1959
+ const [plan, setPlan] = useState8(options.plan);
1960
+ const [deciding, setDeciding] = useState8(null);
1961
+ const [restoring, setRestoring] = useState8(false);
1962
+ const [error, setError] = useState8(null);
1916
1963
  const attachments = useRef6(/* @__PURE__ */ new Map());
1917
1964
  const decisionInFlight = useRef6(false);
1918
1965
  useEffect6(() => setPlan(options.plan), [options.plan]);
@@ -2084,7 +2131,7 @@ function createDurableInteractionAnswerSubmitter(options) {
2084
2131
  }
2085
2132
 
2086
2133
  // src/web-react/use-chat-interactions.ts
2087
- import { useCallback as useCallback4, useMemo as useMemo3, useState as useState8 } from "react";
2134
+ import { useCallback as useCallback4, useMemo as useMemo3, useState as useState9 } from "react";
2088
2135
  function hasPendingContentDuplicate(list, interaction) {
2089
2136
  if (interaction.status !== "pending") return false;
2090
2137
  const signature = questionInteractionContentSignature(interaction);
@@ -2163,7 +2210,7 @@ function hydrateChatInteractions(list, persisted) {
2163
2210
  return persisted.reduce(upsertChatInteraction, list);
2164
2211
  }
2165
2212
  function useChatInteractions(options = {}) {
2166
- const [interactions, setInteractions] = useState8([]);
2213
+ const [interactions, setInteractions] = useState9([]);
2167
2214
  const upsert = useCallback4((interaction) => {
2168
2215
  setInteractions((prev) => upsertChatInteraction(prev, interaction));
2169
2216
  }, []);
@@ -2190,7 +2237,7 @@ function useChatInteractions(options = {}) {
2190
2237
  }
2191
2238
 
2192
2239
  // src/web-react/use-file-mentions.ts
2193
- import { useCallback as useCallback5, useMemo as useMemo4, useRef as useRef7, useState as useState9 } from "react";
2240
+ import { useCallback as useCallback5, useMemo as useMemo4, useRef as useRef7, useState as useState10 } from "react";
2194
2241
  var FILE_MENTION_KIND = "file";
2195
2242
  function toMentionItem(file) {
2196
2243
  return { id: file.path, label: file.name, detail: file.path, kind: FILE_MENTION_KIND };
@@ -2248,11 +2295,11 @@ function useFileMentions(options) {
2248
2295
  emptyText = DEFAULT_MENTION_EMPTY_TEXT
2249
2296
  } = options;
2250
2297
  const fetchImpl = options.fetchImpl ?? fetch;
2251
- const [state, setState] = useState9({ kind: "idle" });
2298
+ const [state, setState] = useState10({ kind: "idle" });
2252
2299
  const stateRef = useRef7(state);
2253
2300
  stateRef.current = state;
2254
2301
  const inFlightRef = useRef7(null);
2255
- const [mentions, setMentions] = useState9([]);
2302
+ const [mentions, setMentions] = useState10([]);
2256
2303
  const load = useCallback5(() => {
2257
2304
  if (inFlightRef.current) return inFlightRef.current;
2258
2305
  if (stateRef.current.kind === "idle") {
@@ -2361,7 +2408,7 @@ function segmentMentionContent(content, parts) {
2361
2408
  }
2362
2409
 
2363
2410
  // src/web-react/mission-activity.tsx
2364
- import { useCallback as useCallback6, useEffect as useEffect7, useState as useState10 } from "react";
2411
+ import { useCallback as useCallback6, useEffect as useEffect7, useState as useState11 } from "react";
2365
2412
  import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
2366
2413
  var LIVE_STATUSES = /* @__PURE__ */ new Set(["pending", "running"]);
2367
2414
  var OK_STATUSES = /* @__PURE__ */ new Set(["completed", "done", "succeeded"]);
@@ -2421,7 +2468,7 @@ function CopyGlyph({ className }) {
2421
2468
  ] });
2422
2469
  }
2423
2470
  function TraceIdCopy({ traceId }) {
2424
- const [copied, setCopied] = useState10(false);
2471
+ const [copied, setCopied] = useState11(false);
2425
2472
  const copy = useCallback6(() => {
2426
2473
  void navigator.clipboard?.writeText(traceId).then(
2427
2474
  () => {
@@ -2454,12 +2501,21 @@ function StatusDot({ tone }) {
2454
2501
  "span",
2455
2502
  {
2456
2503
  "aria-hidden": true,
2457
- className: `h-2 w-2 shrink-0 rounded-full ${tone === "live" ? "animate-pulse bg-warning" : tone === "ok" ? "bg-success" : tone === "error" ? "bg-destructive" : "bg-muted-foreground/40"}`
2504
+ className: `h-2 w-2 shrink-0 rounded-full ${tone === "live" ? "bg-warning" : tone === "ok" ? "bg-success" : tone === "error" ? "bg-destructive" : "bg-muted-foreground/40"}`
2458
2505
  }
2459
2506
  ),
2460
2507
  /* @__PURE__ */ jsx8("span", { className: "sr-only", children: tone })
2461
2508
  ] });
2462
2509
  }
2510
+ function RunLabel({ tool, detail, live }) {
2511
+ return /* @__PURE__ */ jsxs6("span", { className: "min-w-0 flex-1 truncate", children: [
2512
+ /* @__PURE__ */ jsx8("span", { className: live ? "agent-shimmer font-medium" : "font-medium", "data-motion": live ? "essential" : void 0, children: tool }),
2513
+ /* @__PURE__ */ jsxs6("span", { className: "text-muted-foreground", children: [
2514
+ " \u2014 ",
2515
+ detail
2516
+ ] })
2517
+ ] });
2518
+ }
2463
2519
  var BAR_CLASS = {
2464
2520
  pipeline: "bg-muted-foreground/30",
2465
2521
  model: "bg-primary/60",
@@ -2488,31 +2544,27 @@ function FlowWaterfall({ trace }) {
2488
2544
  ] })
2489
2545
  ] });
2490
2546
  }
2547
+ function LaneRow({ run, staggerIndex }) {
2548
+ const arrival = useArrivalStyle(staggerIndex);
2549
+ const tone = activityTone(run.status);
2550
+ const cost = formatActivityCost(run.costUsd);
2551
+ const duration = formatActivityDuration(run.durationMs);
2552
+ return /* @__PURE__ */ jsxs6("div", { className: "agent-arrive flex items-center gap-2 py-1 text-xs", style: arrival, children: [
2553
+ /* @__PURE__ */ jsx8(StatusDot, { tone }),
2554
+ /* @__PURE__ */ jsx8(RunLabel, { tool: run.tool, detail: run.detail, live: tone === "live" }),
2555
+ tone === "live" && (run.iteration !== void 0 || run.phase !== void 0) && /* @__PURE__ */ jsx8("span", { className: "shrink-0 rounded-full bg-warning/10 px-1.5 py-0.5 font-mono text-xs text-warning", children: [run.iteration !== void 0 ? `iter ${run.iteration}` : null, run.phase ?? null].filter(Boolean).join(" \xB7 ") }),
2556
+ /* @__PURE__ */ jsxs6("span", { className: "flex shrink-0 items-center gap-1.5 font-mono text-xs tabular-nums text-muted-foreground/70", children: [
2557
+ tone !== "live" && tone !== "ok" && /* @__PURE__ */ jsx8("span", { children: run.status }),
2558
+ cost && /* @__PURE__ */ jsx8("span", { children: cost }),
2559
+ duration && /* @__PURE__ */ jsx8("span", { children: duration })
2560
+ ] })
2561
+ ] });
2562
+ }
2491
2563
  function MissionActivityLane({ activity, startedAt, nowMs }) {
2492
- const [expanded, setExpanded] = useState10(false);
2564
+ const [expanded, setExpanded] = useState11(false);
2493
2565
  if (activity.length === 0) return null;
2494
2566
  return /* @__PURE__ */ jsxs6("div", { className: "mt-1 border-l border-border pl-3", children: [
2495
- activity.map((run) => {
2496
- const tone = activityTone(run.status);
2497
- const cost = formatActivityCost(run.costUsd);
2498
- const duration = formatActivityDuration(run.durationMs);
2499
- return /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 py-1 text-xs", children: [
2500
- /* @__PURE__ */ jsx8(StatusDot, { tone }),
2501
- /* @__PURE__ */ jsxs6("span", { className: "min-w-0 flex-1 truncate", children: [
2502
- /* @__PURE__ */ jsx8("span", { className: "font-medium", children: run.tool }),
2503
- /* @__PURE__ */ jsxs6("span", { className: "text-muted-foreground", children: [
2504
- " \u2014 ",
2505
- run.detail
2506
- ] })
2507
- ] }),
2508
- tone === "live" && (run.iteration !== void 0 || run.phase !== void 0) && /* @__PURE__ */ jsx8("span", { className: "shrink-0 rounded-full bg-warning/10 px-1.5 py-0.5 font-mono text-xs text-warning", children: [run.iteration !== void 0 ? `iter ${run.iteration}` : null, run.phase ?? null].filter(Boolean).join(" \xB7 ") }),
2509
- /* @__PURE__ */ jsxs6("span", { className: "flex shrink-0 items-center gap-1.5 font-mono text-xs tabular-nums text-muted-foreground/70", children: [
2510
- tone !== "live" && tone !== "ok" && /* @__PURE__ */ jsx8("span", { children: run.status }),
2511
- cost && /* @__PURE__ */ jsx8("span", { children: cost }),
2512
- duration && /* @__PURE__ */ jsx8("span", { children: duration })
2513
- ] })
2514
- ] }, run.taskId);
2515
- }),
2567
+ activity.map((run, index) => /* @__PURE__ */ jsx8(LaneRow, { run, staggerIndex: index }, run.taskId)),
2516
2568
  /* @__PURE__ */ jsxs6(
2517
2569
  "button",
2518
2570
  {
@@ -2538,22 +2590,18 @@ function MissionActivityLane({ activity, startedAt, nowMs }) {
2538
2590
  }
2539
2591
  function ActivityRow({
2540
2592
  record,
2541
- renderMissionRef
2593
+ renderMissionRef,
2594
+ staggerIndex
2542
2595
  }) {
2543
- const [open, setOpen] = useState10(false);
2596
+ const arrival = useArrivalStyle(staggerIndex);
2597
+ const [open, setOpen] = useState11(false);
2544
2598
  const tone = activityTone(record.status);
2545
2599
  const cost = formatActivityCost(record.costUsd);
2546
2600
  const duration = formatActivityDuration(record.durationMs);
2547
- return /* @__PURE__ */ jsxs6("div", { className: "rounded-lg border border-card-edge bg-card", children: [
2601
+ return /* @__PURE__ */ jsxs6("div", { className: "agent-arrive rounded-lg border border-card-edge bg-card", style: arrival, children: [
2548
2602
  /* @__PURE__ */ jsxs6("button", { type: "button", onClick: () => setOpen((v) => !v), className: "flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm", children: [
2549
2603
  /* @__PURE__ */ jsx8(StatusDot, { tone }),
2550
- /* @__PURE__ */ jsxs6("span", { className: "min-w-0 flex-1 truncate", children: [
2551
- /* @__PURE__ */ jsx8("span", { className: "font-medium", children: record.tool }),
2552
- /* @__PURE__ */ jsxs6("span", { className: "text-muted-foreground", children: [
2553
- " \u2014 ",
2554
- record.detail
2555
- ] })
2556
- ] }),
2604
+ /* @__PURE__ */ jsx8(RunLabel, { tool: record.tool, detail: record.detail, live: tone === "live" }),
2557
2605
  tone === "live" && (record.iteration !== void 0 || record.phase !== void 0) && /* @__PURE__ */ jsx8("span", { className: "shrink-0 rounded-full bg-warning/10 px-2 py-0.5 font-mono text-xs text-warning", children: [record.iteration !== void 0 ? `iter ${record.iteration}` : null, record.phase ?? null].filter(Boolean).join(" \xB7 ") }),
2558
2606
  /* @__PURE__ */ jsx8(
2559
2607
  "span",
@@ -2586,10 +2634,10 @@ function ActivityRow({
2586
2634
  ] });
2587
2635
  }
2588
2636
  function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent activity", emptyLabel = "No agent runs yet." }) {
2589
- const [rows, setRows] = useState10([]);
2590
- const [cursor, setCursor] = useState10(void 0);
2591
- const [status, setStatus] = useState10("loading");
2592
- const [error, setError] = useState10(null);
2637
+ const [rows, setRows] = useState11([]);
2638
+ const [cursor, setCursor] = useState11(void 0);
2639
+ const [status, setStatus] = useState11("loading");
2640
+ const [error, setError] = useState11(null);
2593
2641
  const load = useCallback6(
2594
2642
  async (from) => {
2595
2643
  setStatus("loading");
@@ -2628,7 +2676,7 @@ function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent ac
2628
2676
  status === "error" && /* @__PURE__ */ jsx8("p", { role: "alert", className: "rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive", children: error }),
2629
2677
  status === "ready" && rows.length === 0 && /* @__PURE__ */ jsx8("p", { className: "px-1 text-sm text-muted-foreground", children: emptyLabel }),
2630
2678
  /* @__PURE__ */ jsx8("span", { role: "status", "aria-live": "polite", "aria-busy": loading, className: "sr-only", children: loading ? "Loading activity\u2026" : "" }),
2631
- /* @__PURE__ */ jsx8("div", { className: "space-y-1.5", "aria-busy": loading, children: rows.map((record) => /* @__PURE__ */ jsx8(ActivityRow, { record, renderMissionRef }, record.taskId)) }),
2679
+ /* @__PURE__ */ jsx8("div", { className: "space-y-1.5", "aria-busy": loading, children: rows.map((record, index) => /* @__PURE__ */ jsx8(ActivityRow, { record, renderMissionRef, staggerIndex: index }, record.taskId)) }),
2632
2680
  cursor && /* @__PURE__ */ jsx8(
2633
2681
  "button",
2634
2682
  {
@@ -2643,7 +2691,7 @@ function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent ac
2643
2691
  }
2644
2692
 
2645
2693
  // src/web-react/provenance.tsx
2646
- import { useCallback as useCallback7, useEffect as useEffect8, useId, useRef as useRef8, useState as useState11 } from "react";
2694
+ import { useCallback as useCallback7, useEffect as useEffect8, useId, useRef as useRef8, useState as useState12 } from "react";
2647
2695
 
2648
2696
  // src/web-react/provenance-model.ts
2649
2697
  var PROVENANCE_BASES = ["extracted", "entered", "computed", "asserted"];
@@ -2937,7 +2985,7 @@ function ProvenanceValue({
2937
2985
  missingValueLabel = DEFAULT_MISSING_VALUE_LABEL,
2938
2986
  className
2939
2987
  }) {
2940
- const [open, setOpen] = useState11(defaultOpen);
2988
+ const [open, setOpen] = useState12(defaultOpen);
2941
2989
  const triggerRef = useRef8(null);
2942
2990
  const rootRef = useRef8(null);
2943
2991
  const panelId = useId();
@@ -3223,7 +3271,7 @@ import {
3223
3271
  useId as useId2,
3224
3272
  useMemo as useMemo5,
3225
3273
  useRef as useRef9,
3226
- useState as useState12
3274
+ useState as useState13
3227
3275
  } from "react";
3228
3276
  import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
3229
3277
  function rethrowAsync(error) {
@@ -3232,7 +3280,7 @@ function rethrowAsync(error) {
3232
3280
  });
3233
3281
  }
3234
3282
  function useInfiniteScroll(onLoadMore, { enabled, root, rootMargin = "300px" }) {
3235
- const [sentinel, setSentinel] = useState12(null);
3283
+ const [sentinel, setSentinel] = useState13(null);
3236
3284
  const sentinelRef = useCallback8((node) => setSentinel(node), []);
3237
3285
  const onLoadMoreRef = useRef9(onLoadMore);
3238
3286
  useEffect9(() => {
@@ -3267,10 +3315,10 @@ function useSessionHistory({
3267
3315
  initialPage,
3268
3316
  defaultSort = "newest"
3269
3317
  }) {
3270
- const [items, setItems] = useState12(initialPage.items);
3271
- const [nextCursor, setNextCursor] = useState12(initialPage.nextCursor ?? null);
3272
- const [phase, setPhase] = useState12("idle");
3273
- const [reloadKey, setReloadKey] = useState12(0);
3318
+ const [items, setItems] = useState13(initialPage.items);
3319
+ const [nextCursor, setNextCursor] = useState13(initialPage.nextCursor ?? null);
3320
+ const [phase, setPhase] = useState13("idle");
3321
+ const [reloadKey, setReloadKey] = useState13(0);
3274
3322
  const seqRef = useRef9(0);
3275
3323
  const resetAbortRef = useRef9(null);
3276
3324
  const loadMoreAbortRef = useRef9(null);
@@ -3388,11 +3436,11 @@ function useSessionActions({
3388
3436
  labels
3389
3437
  }) {
3390
3438
  const text = { ...DEFAULT_LABELS, ...labels };
3391
- const [renameTarget, setRenameTarget] = useState12(null);
3392
- const [renameValue, setRenameValue] = useState12("");
3393
- const [deleteTarget, setDeleteTarget] = useState12(null);
3394
- const [busy, setBusy] = useState12(false);
3395
- const [error, setError] = useState12(null);
3439
+ const [renameTarget, setRenameTarget] = useState13(null);
3440
+ const [renameValue, setRenameValue] = useState13("");
3441
+ const [deleteTarget, setDeleteTarget] = useState13(null);
3442
+ const [busy, setBusy] = useState13(false);
3443
+ const [error, setError] = useState13(null);
3396
3444
  const openRename = useCallback8((session) => {
3397
3445
  setError(null);
3398
3446
  setRenameTarget(session);
@@ -3618,11 +3666,11 @@ function SessionHistoryPanel({
3618
3666
  const searchTerm = query.trim();
3619
3667
  const isSearching = searchTerm.length > 0;
3620
3668
  const column = contentWidth === "full" ? "w-full" : "mx-auto w-full max-w-4xl";
3621
- const [selectedIds, setSelectedIds] = useState12(/* @__PURE__ */ new Set());
3622
- const [ageDays, setAgeDays] = useState12("30");
3623
- const [bulkTarget, setBulkTarget] = useState12(null);
3624
- const [bulkBusy, setBulkBusy] = useState12(false);
3625
- const [bulkError, setBulkError] = useState12(null);
3669
+ const [selectedIds, setSelectedIds] = useState13(/* @__PURE__ */ new Set());
3670
+ const [ageDays, setAgeDays] = useState13("30");
3671
+ const [bulkTarget, setBulkTarget] = useState13(null);
3672
+ const [bulkBusy, setBulkBusy] = useState13(false);
3673
+ const [bulkError, setBulkError] = useState13(null);
3626
3674
  useEffect9(() => {
3627
3675
  setSelectedIds(/* @__PURE__ */ new Set());
3628
3676
  }, [searchTerm, sort]);
@@ -3902,7 +3950,7 @@ function SessionRow({
3902
3950
  selected,
3903
3951
  onSelectedChange
3904
3952
  }) {
3905
- const [menuOpen, setMenuOpen] = useState12(false);
3953
+ const [menuOpen, setMenuOpen] = useState13(false);
3906
3954
  const panelId = useId2();
3907
3955
  const { containerRef, triggerRef, panelRef, triggerProps } = usePopover(menuOpen, setMenuOpen);
3908
3956
  const extras = extraActions?.(session) ?? [];
@@ -4011,7 +4059,7 @@ import {
4011
4059
  useId as useId3,
4012
4060
  useMemo as useMemo6,
4013
4061
  useRef as useRef10,
4014
- useState as useState13
4062
+ useState as useState14
4015
4063
  } from "react";
4016
4064
 
4017
4065
  // src/web-react/record-grid-model.ts
@@ -4396,19 +4444,19 @@ function RecordGrid({
4396
4444
  className
4397
4445
  }) {
4398
4446
  const fieldPrefix = useId3();
4399
- const [overlay, setOverlay] = useState13(EMPTY_RECORD_GRID_OVERLAY);
4400
- const [editing, setEditingState] = useState13(null);
4401
- const [cellErrors, setCellErrors] = useState13({});
4402
- const [rowErrors, setRowErrors] = useState13({});
4403
- const [pendingRows, setPendingRows] = useState13({});
4404
- const [focus, setFocus] = useState13(null);
4405
- const [openSource, setOpenSource] = useState13(null);
4406
- const [confirmDelete, setConfirmDelete] = useState13(null);
4407
- const [adding, setAdding] = useState13(false);
4408
- const [draft, setDraft] = useState13({ ...newRowDefaults ?? {} });
4409
- const [draftErrors, setDraftErrors] = useState13({});
4410
- const [draftError, setDraftError] = useState13(null);
4411
- const [creating, setCreating] = useState13(false);
4447
+ const [overlay, setOverlay] = useState14(EMPTY_RECORD_GRID_OVERLAY);
4448
+ const [editing, setEditingState] = useState14(null);
4449
+ const [cellErrors, setCellErrors] = useState14({});
4450
+ const [rowErrors, setRowErrors] = useState14({});
4451
+ const [pendingRows, setPendingRows] = useState14({});
4452
+ const [focus, setFocus] = useState14(null);
4453
+ const [openSource, setOpenSource] = useState14(null);
4454
+ const [confirmDelete, setConfirmDelete] = useState14(null);
4455
+ const [adding, setAdding] = useState14(false);
4456
+ const [draft, setDraft] = useState14({ ...newRowDefaults ?? {} });
4457
+ const [draftErrors, setDraftErrors] = useState14({});
4458
+ const [draftError, setDraftError] = useState14(null);
4459
+ const [creating, setCreating] = useState14(false);
4412
4460
  const cellRefs = useRef10(/* @__PURE__ */ new Map());
4413
4461
  const settling = useRef10(false);
4414
4462
  const draftCounter = useRef10(0);
@@ -5243,8 +5291,594 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
5243
5291
  );
5244
5292
  }
5245
5293
 
5294
+ // src/web-react/class-names.ts
5295
+ function joinClasses(...parts) {
5296
+ const kept = [];
5297
+ for (const part of parts) {
5298
+ if (typeof part !== "string") continue;
5299
+ const trimmed = part.trim();
5300
+ if (trimmed.length > 0) kept.push(trimmed);
5301
+ }
5302
+ return kept.join(" ");
5303
+ }
5304
+
5305
+ // src/web-react/sparkline.tsx
5306
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
5307
+ var DEFAULT_SPARKLINE_WIDTH = 96;
5308
+ var DEFAULT_SPARKLINE_HEIGHT = 24;
5309
+ var DEFAULT_INSET = 2.5;
5310
+ var STROKE_WIDTH = 1.5;
5311
+ var DOT_RADIUS = 1.75;
5312
+ var DEFAULT_SPARKLINE_LABEL = "Trend";
5313
+ var DEFAULT_SPARKLINE_EMPTY_LABEL = "No history yet";
5314
+ var DEFAULT_SPARKLINE_UNAVAILABLE_LABEL = "No readings available";
5315
+ var NUMBER_FORMAT = new Intl.NumberFormat("en-US", { maximumFractionDigits: 2 });
5316
+ function formatSparklineValue(value) {
5317
+ return NUMBER_FORMAT.format(value);
5318
+ }
5319
+ function isReading(value) {
5320
+ return typeof value === "number" && Number.isFinite(value);
5321
+ }
5322
+ function sparklineReadings(values) {
5323
+ return values.filter(isReading);
5324
+ }
5325
+ function round(value) {
5326
+ return Math.round(value * 100) / 100;
5327
+ }
5328
+ function sparklineGeometry(values, { width = DEFAULT_SPARKLINE_WIDTH, height = DEFAULT_SPARKLINE_HEIGHT, inset = DEFAULT_INSET } = {}) {
5329
+ const samples = values.length;
5330
+ const plotted = [];
5331
+ for (let index = 0; index < samples; index += 1) {
5332
+ const value = values[index];
5333
+ if (isReading(value)) plotted.push({ index, value });
5334
+ }
5335
+ const readings = plotted.map((entry) => entry.value);
5336
+ const gaps = samples - readings.length;
5337
+ if (readings.length === 0) {
5338
+ return { readings, points: [], segments: [], gaps, min: 0, max: 0, first: 0, last: 0, direction: "flat" };
5339
+ }
5340
+ let min = readings[0];
5341
+ let max = readings[0];
5342
+ for (const value of readings) {
5343
+ if (value < min) min = value;
5344
+ if (value > max) max = value;
5345
+ }
5346
+ const first = readings[0];
5347
+ const last = readings[readings.length - 1];
5348
+ const span = max - min;
5349
+ const top = inset;
5350
+ const bottom = height - inset;
5351
+ const left = inset;
5352
+ const right = width - inset;
5353
+ const points = plotted.map(({ index, value }) => ({
5354
+ // A series of ONE SAMPLE sits in the middle rather than at the left edge,
5355
+ // where it reads as the start of a line whose rest failed to render. A
5356
+ // single reading among several samples keeps its own position — that is the
5357
+ // one thing that says where in the window the reading is.
5358
+ x: round(samples <= 1 ? width / 2 : left + (right - left) * index / (samples - 1)),
5359
+ // `span === 0` is the stable metric. Mid-height is the honest render of it;
5360
+ // dividing by the span here is the NaN that erases the whole polyline.
5361
+ y: round(span === 0 ? height / 2 : bottom - (bottom - top) * (value - min) / span)
5362
+ }));
5363
+ const segments = [];
5364
+ let run = [];
5365
+ let previous = Number.NEGATIVE_INFINITY;
5366
+ plotted.forEach(({ index }, position) => {
5367
+ if (index !== previous + 1 && run.length > 0) {
5368
+ segments.push(run);
5369
+ run = [];
5370
+ }
5371
+ run.push(points[position]);
5372
+ previous = index;
5373
+ });
5374
+ if (run.length > 0) segments.push(run);
5375
+ return {
5376
+ readings,
5377
+ points,
5378
+ segments,
5379
+ gaps,
5380
+ min,
5381
+ max,
5382
+ first,
5383
+ last,
5384
+ direction: last > first ? "rising" : last < first ? "falling" : "flat"
5385
+ };
5386
+ }
5387
+ function sparklinePointsAttribute(points) {
5388
+ return points.map((point) => `${point.x},${point.y}`).join(" ");
5389
+ }
5390
+ function sparklineLabel(values, { label = DEFAULT_SPARKLINE_LABEL, format = formatSparklineValue } = {}) {
5391
+ const { readings, gaps, min, max, first, last, direction } = sparklineGeometry(values);
5392
+ const missing = gaps === 0 ? "" : `, ${gaps} not available`;
5393
+ if (readings.length === 0) return gaps === 0 ? `${label}: no readings yet` : `${label}: no readings${missing}`;
5394
+ if (readings.length === 1) return `${label}: one reading${missing}, ${format(first)}`;
5395
+ if (max === min) return `${label}: ${readings.length} readings${missing}, unchanged at ${format(first)}`;
5396
+ const movement = direction === "flat" ? "net unchanged" : direction;
5397
+ return `${label}: ${readings.length} readings${missing}, range ${format(min)} to ${format(max)}, ${movement} from ${format(first)} to ${format(last)}`;
5398
+ }
5399
+ function Sparkline({
5400
+ values,
5401
+ label = DEFAULT_SPARKLINE_LABEL,
5402
+ format = formatSparklineValue,
5403
+ width = DEFAULT_SPARKLINE_WIDTH,
5404
+ height = DEFAULT_SPARKLINE_HEIGHT,
5405
+ emptyLabel = DEFAULT_SPARKLINE_EMPTY_LABEL,
5406
+ unavailableLabel = DEFAULT_SPARKLINE_UNAVAILABLE_LABEL,
5407
+ className
5408
+ }) {
5409
+ const geometry = sparklineGeometry(values, { width, height });
5410
+ const accessibleName = sparklineLabel(values, { label, format });
5411
+ if (geometry.points.length === 0) {
5412
+ return /* @__PURE__ */ jsxs11(
5413
+ "span",
5414
+ {
5415
+ "data-sparkline": geometry.gaps > 0 ? "unavailable" : "empty",
5416
+ className: joinClasses("text-[11px] text-muted-foreground", className),
5417
+ children: [
5418
+ /* @__PURE__ */ jsx13("span", { className: "sr-only", children: accessibleName }),
5419
+ /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", children: geometry.gaps > 0 ? unavailableLabel : emptyLabel })
5420
+ ]
5421
+ }
5422
+ );
5423
+ }
5424
+ const drawsLine = geometry.segments.some((segment) => segment.length > 1);
5425
+ const end = geometry.points[geometry.points.length - 1];
5426
+ return /* @__PURE__ */ jsxs11(
5427
+ "svg",
5428
+ {
5429
+ role: "img",
5430
+ "aria-label": accessibleName,
5431
+ "data-sparkline": drawsLine ? "line" : "point",
5432
+ "data-direction": geometry.direction,
5433
+ "data-gaps": geometry.gaps > 0 ? geometry.gaps : void 0,
5434
+ width,
5435
+ height,
5436
+ viewBox: `0 0 ${width} ${height}`,
5437
+ className,
5438
+ focusable: "false",
5439
+ children: [
5440
+ geometry.segments.map((segment, index) => {
5441
+ const key = `segment-${index}`;
5442
+ if (segment.length > 1) {
5443
+ return /* @__PURE__ */ jsx13(
5444
+ "polyline",
5445
+ {
5446
+ points: sparklinePointsAttribute(segment),
5447
+ fill: "none",
5448
+ stroke: "currentColor",
5449
+ strokeWidth: STROKE_WIDTH,
5450
+ strokeLinecap: "round",
5451
+ strokeLinejoin: "round",
5452
+ vectorEffect: "non-scaling-stroke"
5453
+ },
5454
+ key
5455
+ );
5456
+ }
5457
+ const only = segment[0];
5458
+ if (only.x === end.x && only.y === end.y) return null;
5459
+ return /* @__PURE__ */ jsx13("circle", { cx: only.x, cy: only.y, r: DOT_RADIUS, fill: "currentColor" }, key);
5460
+ }),
5461
+ /* @__PURE__ */ jsx13("circle", { cx: end.x, cy: end.y, r: DOT_RADIUS, fill: "currentColor" })
5462
+ ]
5463
+ }
5464
+ );
5465
+ }
5466
+
5467
+ // src/web-react/insight-card.tsx
5468
+ import {
5469
+ isValidElement as isValidElement2,
5470
+ useCallback as useCallback10,
5471
+ useEffect as useEffect11,
5472
+ useRef as useRef11,
5473
+ useState as useState15
5474
+ } from "react";
5475
+ import { Fragment as Fragment7, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
5476
+ function insightDelta(value, previous) {
5477
+ if (typeof value !== "number" || !Number.isFinite(value)) return null;
5478
+ if (typeof previous !== "number" || !Number.isFinite(previous)) return null;
5479
+ const absolute = value - previous;
5480
+ return {
5481
+ previous,
5482
+ absolute,
5483
+ percent: previous === 0 ? null : absolute / previous,
5484
+ direction: absolute > 0 ? "up" : absolute < 0 ? "down" : "flat"
5485
+ };
5486
+ }
5487
+ function insightDeltaTone(direction, polarity = "neutral") {
5488
+ if (direction === "flat" || polarity === "neutral") return "neutral";
5489
+ const welcome = polarity === "higher-is-better" ? "up" : "down";
5490
+ return direction === welcome ? "positive" : "negative";
5491
+ }
5492
+ function formatInsightDelta(delta, format = formatSparklineValue) {
5493
+ const from = format(delta.previous);
5494
+ if (delta.direction === "flat") return `No change from ${from}`;
5495
+ const word = delta.direction === "up" ? "Up" : "Down";
5496
+ const magnitude = delta.percent === null ? format(Math.abs(delta.absolute)) : `${(Math.abs(delta.percent) * 100).toFixed(1)}%`;
5497
+ return `${word} ${magnitude} from ${from}`;
5498
+ }
5499
+ var TONE_CLASS = {
5500
+ positive: "text-success",
5501
+ negative: "text-destructive",
5502
+ neutral: "text-muted-foreground"
5503
+ };
5504
+ var DIRECTION_GLYPH = { up: "\u2191", down: "\u2193", flat: "\u2192" };
5505
+ var INSIGHT_UNAVAILABLE_GLYPH = "\u2014";
5506
+ var INSIGHT_UNAVAILABLE_LABEL = "Not available";
5507
+ function InsightCard({
5508
+ title,
5509
+ value,
5510
+ unit,
5511
+ previous,
5512
+ polarity = "neutral",
5513
+ format = formatSparklineValue,
5514
+ series,
5515
+ seriesLabel,
5516
+ description,
5517
+ action,
5518
+ live = false,
5519
+ liveLabel = "Updating",
5520
+ className,
5521
+ style
5522
+ }) {
5523
+ const delta = insightDelta(value, previous);
5524
+ const tone = delta ? insightDeltaTone(delta.direction, polarity) : "neutral";
5525
+ const unavailable = typeof value === "number" && !Number.isFinite(value);
5526
+ const shown = typeof value === "number" ? format(value) : value;
5527
+ return /* @__PURE__ */ jsxs12(
5528
+ "article",
5529
+ {
5530
+ "data-insight-card": "",
5531
+ "data-tone": tone,
5532
+ className: joinClasses("agent-arrive flex h-full flex-col rounded-xl border border-card-edge bg-card p-4", className),
5533
+ style,
5534
+ children: [
5535
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-baseline justify-between gap-2", children: [
5536
+ /* @__PURE__ */ jsx14("h3", { className: "text-[13px] font-medium text-muted-foreground", children: title }),
5537
+ live ? (
5538
+ // No `data-motion` opt-out: the word is the signal and the sweep is
5539
+ // emphasis, so the reduced-motion floor reaches this like everything
5540
+ // else and leaves a static, legible label.
5541
+ /* @__PURE__ */ jsx14("span", { className: "agent-shimmer shrink-0 text-[11px] font-medium", "data-insight-live": "", children: liveLabel })
5542
+ ) : null
5543
+ ] }),
5544
+ /* @__PURE__ */ jsx14("p", { className: "mt-1 flex items-baseline gap-1", children: unavailable ? /* @__PURE__ */ jsxs12("span", { "data-insight-value": "unavailable", className: "text-xl font-semibold text-muted-foreground", children: [
5545
+ /* @__PURE__ */ jsx14("span", { "aria-hidden": "true", children: INSIGHT_UNAVAILABLE_GLYPH }),
5546
+ /* @__PURE__ */ jsx14("span", { className: "sr-only", children: INSIGHT_UNAVAILABLE_LABEL })
5547
+ ] }) : /* @__PURE__ */ jsxs12(Fragment7, { children: [
5548
+ /* @__PURE__ */ jsx14("span", { className: "text-xl font-semibold tabular-nums text-foreground", children: shown }),
5549
+ unit ? /* @__PURE__ */ jsx14("span", { className: "text-[11px] text-muted-foreground", children: unit }) : null
5550
+ ] }) }),
5551
+ delta ? /* @__PURE__ */ jsxs12("p", { "data-insight-delta": delta.direction, className: `mt-0.5 text-[11px] font-medium ${TONE_CLASS[tone]}`, children: [
5552
+ /* @__PURE__ */ jsxs12("span", { "aria-hidden": "true", children: [
5553
+ DIRECTION_GLYPH[delta.direction],
5554
+ " "
5555
+ ] }),
5556
+ formatInsightDelta(delta, format)
5557
+ ] }) : null,
5558
+ description ? /* @__PURE__ */ jsx14("p", { className: "mt-1 text-[11px] text-muted-foreground", children: description }) : null,
5559
+ series ? /* @__PURE__ */ jsx14("div", { className: "mt-2 text-muted-foreground", children: /* @__PURE__ */ jsx14(Sparkline, { values: series, label: seriesLabel ?? title, format }) }) : null,
5560
+ action ? /* @__PURE__ */ jsx14("div", { className: "mt-3", children: renderInsightAction(action) }) : null
5561
+ ]
5562
+ }
5563
+ );
5564
+ }
5565
+ function renderInsightAction(action) {
5566
+ if (isValidElement2(action)) return action;
5567
+ return /* @__PURE__ */ jsx14(
5568
+ "button",
5569
+ {
5570
+ type: "button",
5571
+ onClick: action.onClick,
5572
+ className: "h-8 rounded-md border border-border px-3 text-xs font-medium text-foreground transition hover:bg-accent",
5573
+ children: action.label
5574
+ }
5575
+ );
5576
+ }
5577
+ var DEFAULT_INSIGHT_PAGE_SIZE = 3;
5578
+ var MAX_PAGE_DOTS = 8;
5579
+ var PAGE_SIZE_FAULT_REASON = {
5580
+ "not-a-number": "A page size that is not a number cannot count cards at all.",
5581
+ "below-one": "A page size below one card gives the deck a page nothing fits on.",
5582
+ fractional: "A fractional page size hides cards on no page at all."
5583
+ };
5584
+ var MAX_NAMED_PAGE_SIZES = 8;
5585
+ var warnedPageSizes = {
5586
+ "not-a-number": { named: /* @__PURE__ */ new Set(), latched: false },
5587
+ "below-one": { named: /* @__PURE__ */ new Set(), latched: false },
5588
+ fractional: { named: /* @__PURE__ */ new Set(), latched: false }
5589
+ };
5590
+ function pageSizeFault(pageSize) {
5591
+ if (!Number.isFinite(pageSize)) return "not-a-number";
5592
+ if (pageSize < 1) return "below-one";
5593
+ return "fractional";
5594
+ }
5595
+ function warnPageSize(pageSize) {
5596
+ const fault = pageSizeFault(pageSize);
5597
+ const record = warnedPageSizes[fault];
5598
+ if (record.latched || record.named.has(pageSize)) return;
5599
+ record.named.add(pageSize);
5600
+ console.warn(
5601
+ `[insight-card] pageSize must be a whole number of cards, 1 or more \u2014 received ${String(pageSize)}. Using ${DEFAULT_INSIGHT_PAGE_SIZE}. ${PAGE_SIZE_FAULT_REASON[fault]}`
5602
+ );
5603
+ if (record.named.size >= MAX_NAMED_PAGE_SIZES) {
5604
+ record.named.clear();
5605
+ record.latched = true;
5606
+ console.warn(`[insight-card] further "${fault}" pageSize warnings are suppressed.`);
5607
+ }
5608
+ }
5609
+ function insightPageSize(pageSize = DEFAULT_INSIGHT_PAGE_SIZE) {
5610
+ if (Number.isInteger(pageSize) && pageSize >= 1) return pageSize;
5611
+ warnPageSize(pageSize);
5612
+ return DEFAULT_INSIGHT_PAGE_SIZE;
5613
+ }
5614
+ function insightPageCount(total, pageSize = DEFAULT_INSIGHT_PAGE_SIZE) {
5615
+ const size = insightPageSize(pageSize);
5616
+ const counted = Number.isFinite(total) && total > 0 ? total : 0;
5617
+ return Math.max(1, Math.ceil(counted / size));
5618
+ }
5619
+ function insightPageSlice(items, page, pageSize = DEFAULT_INSIGHT_PAGE_SIZE) {
5620
+ const size = insightPageSize(pageSize);
5621
+ const count = insightPageCount(items.length, size);
5622
+ const requested = Number.isFinite(page) ? Math.floor(page) : 0;
5623
+ const safe = Math.min(Math.max(requested, 0), count - 1);
5624
+ return items.slice(safe * size, safe * size + size);
5625
+ }
5626
+ function InsightDeck({
5627
+ state,
5628
+ empty,
5629
+ label = "Insights",
5630
+ pageSize = DEFAULT_INSIGHT_PAGE_SIZE,
5631
+ loadingLabel = "Loading insights\u2026",
5632
+ retryLabel,
5633
+ className,
5634
+ onPageChange
5635
+ }) {
5636
+ const [page, setPage] = useState15(0);
5637
+ const [held, setHeld] = useState15(null);
5638
+ const answered = state.status === "error" || state.status === "empty";
5639
+ const carried = state.status === "ready" ? state.value : answered ? null : held;
5640
+ if (carried !== held) setHeld(carried);
5641
+ const shown = carried !== null && state.status !== "ready" ? { status: "ready", value: carried, retry: state.retry } : state;
5642
+ const refreshing = shown !== state;
5643
+ const reported = useRef11(0);
5644
+ const settlePage = useCallback10(
5645
+ (next) => {
5646
+ if (reported.current === next) return;
5647
+ reported.current = next;
5648
+ onPageChange?.(next);
5649
+ },
5650
+ [onPageChange]
5651
+ );
5652
+ return /* @__PURE__ */ jsx14(
5653
+ AsyncView,
5654
+ {
5655
+ state: shown,
5656
+ empty,
5657
+ loadingLabel,
5658
+ retryLabel,
5659
+ className,
5660
+ children: (insights) => /* @__PURE__ */ jsx14(
5661
+ InsightPages,
5662
+ {
5663
+ insights,
5664
+ label,
5665
+ pageSize,
5666
+ className,
5667
+ page,
5668
+ busy: refreshing,
5669
+ onSelectPage: setPage,
5670
+ onPageSettled: settlePage
5671
+ }
5672
+ )
5673
+ }
5674
+ );
5675
+ }
5676
+ var EDITABLE_TAG = /^(INPUT|TEXTAREA|SELECT)$/;
5677
+ var ARROW_KEY_ROLES = /* @__PURE__ */ new Set([
5678
+ "application",
5679
+ "combobox",
5680
+ "grid",
5681
+ "gridcell",
5682
+ "listbox",
5683
+ "menu",
5684
+ "menubar",
5685
+ "menuitem",
5686
+ "menuitemcheckbox",
5687
+ "menuitemradio",
5688
+ "option",
5689
+ "radiogroup",
5690
+ "row",
5691
+ "scrollbar",
5692
+ "searchbox",
5693
+ "slider",
5694
+ "spinbutton",
5695
+ "tab",
5696
+ "tablist",
5697
+ "textbox",
5698
+ "tree",
5699
+ "treegrid",
5700
+ "treeitem"
5701
+ ]);
5702
+ function ownsArrowKeys(target, boundary) {
5703
+ let node = target instanceof Element ? target : null;
5704
+ while (node !== null && node !== boundary) {
5705
+ if (EDITABLE_TAG.test(node.tagName)) return true;
5706
+ if (node instanceof HTMLElement && node.isContentEditable) return true;
5707
+ const role = node.getAttribute("role");
5708
+ if (role !== null && role.split(/\s+/).some((token) => ARROW_KEY_ROLES.has(token))) return true;
5709
+ node = node.parentElement;
5710
+ }
5711
+ return false;
5712
+ }
5713
+ function InsightPages({
5714
+ insights,
5715
+ label,
5716
+ pageSize,
5717
+ className,
5718
+ page,
5719
+ busy,
5720
+ onSelectPage,
5721
+ onPageSettled
5722
+ }) {
5723
+ const size = insightPageSize(pageSize);
5724
+ const pageCount = insightPageCount(insights.length, size);
5725
+ const current = Math.min(Math.max(page, 0), pageCount - 1);
5726
+ const visible = insightPageSlice(insights, current, size);
5727
+ const sectionRef = useRef11(null);
5728
+ const listRef = useRef11(null);
5729
+ const recoverFocus = useRef11(false);
5730
+ useEffect11(() => {
5731
+ onPageSettled(current);
5732
+ }, [current, onPageSettled]);
5733
+ useEffect11(() => {
5734
+ if (!recoverFocus.current) return;
5735
+ recoverFocus.current = false;
5736
+ sectionRef.current?.focus();
5737
+ }, [current]);
5738
+ const goTo = useCallback10(
5739
+ (next) => {
5740
+ const clamped = Math.min(Math.max(next, 0), pageCount - 1);
5741
+ if (clamped === current) return false;
5742
+ const active = typeof document === "undefined" ? null : document.activeElement;
5743
+ recoverFocus.current = active instanceof Node && (listRef.current?.contains(active) ?? false);
5744
+ onSelectPage(clamped);
5745
+ return true;
5746
+ },
5747
+ [current, onSelectPage, pageCount]
5748
+ );
5749
+ const onKeyDown = (event) => {
5750
+ if (event.defaultPrevented) return;
5751
+ if (ownsArrowKeys(event.target, event.currentTarget)) return;
5752
+ let moved = false;
5753
+ switch (event.key) {
5754
+ case "ArrowRight":
5755
+ case "PageDown":
5756
+ moved = goTo(current + 1);
5757
+ break;
5758
+ case "ArrowLeft":
5759
+ case "PageUp":
5760
+ moved = goTo(current - 1);
5761
+ break;
5762
+ case "Home":
5763
+ moved = goTo(0);
5764
+ break;
5765
+ case "End":
5766
+ moved = goTo(pageCount - 1);
5767
+ break;
5768
+ default:
5769
+ return;
5770
+ }
5771
+ if (moved) event.preventDefault();
5772
+ };
5773
+ return /* @__PURE__ */ jsxs12(
5774
+ "section",
5775
+ {
5776
+ ref: sectionRef,
5777
+ "aria-label": label,
5778
+ "data-insight-deck": "",
5779
+ "aria-busy": busy,
5780
+ className: joinClasses("space-y-3", className),
5781
+ onKeyDown,
5782
+ tabIndex: pageCount > 1 ? 0 : void 0,
5783
+ "aria-keyshortcuts": pageCount > 1 ? "ArrowLeft ArrowRight PageUp PageDown Home End" : void 0,
5784
+ children: [
5785
+ /* @__PURE__ */ jsx14("ul", { ref: listRef, className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: visible.map(({ id, style, ...card }, index) => (
5786
+ // The page index is in the key on purpose: a page turn is an arrival,
5787
+ // and reusing the node would swap the text under a card that never
5788
+ // moved. Remounting replays `.agent-arrive` with the new stagger.
5789
+ //
5790
+ // A REFRESH is the other case and the key is why it behaves the other
5791
+ // way: the page has not changed and the id is stable, so the key
5792
+ // matches, React keeps the node, and a card that was already settled
5793
+ // does not arrive a second time. The key does BOTH jobs — but only
5794
+ // because the deck now keeps this subtree mounted across a reload
5795
+ // (see `InsightDeck`); a key is never compared across a teardown.
5796
+ /* @__PURE__ */ jsx14("li", { children: /* @__PURE__ */ jsx14(InsightCard, { ...card, style: staggerStyle(index, style) }) }, `${current}:${id}`)
5797
+ )) }),
5798
+ /* @__PURE__ */ jsxs12("div", { className: pageCount > 1 ? "flex items-center justify-between gap-2" : void 0, children: [
5799
+ /* @__PURE__ */ jsxs12(
5800
+ "p",
5801
+ {
5802
+ role: "status",
5803
+ "aria-live": "polite",
5804
+ className: pageCount > 1 ? "text-[11px] text-muted-foreground" : "sr-only",
5805
+ children: [
5806
+ "Page ",
5807
+ current + 1,
5808
+ " of ",
5809
+ pageCount
5810
+ ]
5811
+ }
5812
+ ),
5813
+ pageCount > 1 ? /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1", children: [
5814
+ /* @__PURE__ */ jsx14(PagerButton, { label: "Previous insights", glyph: "\u2039", atEnd: current === 0, onClick: () => goTo(current - 1) }),
5815
+ pageCount <= MAX_PAGE_DOTS ? Array.from({ length: pageCount }, (_, index) => (
5816
+ // WCAG 2.2 SC 2.5.8 wants a 24x24 CSS px target. The dot stays
5817
+ // 8px because a 24px dot is a different control; the BUTTON
5818
+ // around it carries the target, so the padding is the hit area
5819
+ // and the span is the graphic. The Spacing exception cannot
5820
+ // rescue the bare dot — at a 12px pitch the 24px circle around
5821
+ // each centre overlaps its neighbour's.
5822
+ /* @__PURE__ */ jsx14(
5823
+ "button",
5824
+ {
5825
+ type: "button",
5826
+ "aria-label": `Page ${index + 1} of ${pageCount}`,
5827
+ "aria-current": index === current ? "page" : void 0,
5828
+ onClick: () => goTo(index),
5829
+ className: "group flex h-6 w-6 shrink-0 items-center justify-center rounded-full",
5830
+ children: /* @__PURE__ */ jsx14(
5831
+ "span",
5832
+ {
5833
+ "aria-hidden": "true",
5834
+ className: joinClasses(
5835
+ "block rounded-full transition",
5836
+ index === current ? "h-2 w-4 bg-foreground" : "h-2 w-2 bg-muted-foreground group-hover:bg-foreground"
5837
+ )
5838
+ }
5839
+ )
5840
+ },
5841
+ index
5842
+ )
5843
+ )) : null,
5844
+ /* @__PURE__ */ jsx14(
5845
+ PagerButton,
5846
+ {
5847
+ label: "Next insights",
5848
+ glyph: "\u203A",
5849
+ atEnd: current === pageCount - 1,
5850
+ onClick: () => goTo(current + 1)
5851
+ }
5852
+ )
5853
+ ] }) : null
5854
+ ] })
5855
+ ]
5856
+ }
5857
+ );
5858
+ }
5859
+ function PagerButton({
5860
+ label,
5861
+ glyph,
5862
+ atEnd,
5863
+ onClick
5864
+ }) {
5865
+ return /* @__PURE__ */ jsx14(
5866
+ "button",
5867
+ {
5868
+ type: "button",
5869
+ "aria-label": label,
5870
+ "aria-disabled": atEnd,
5871
+ onClick: () => {
5872
+ if (!atEnd) onClick();
5873
+ },
5874
+ className: `flex h-6 w-6 items-center justify-center rounded-md border border-border text-xs text-muted-foreground transition ${atEnd ? "opacity-40" : "hover:bg-accent hover:text-foreground"}`,
5875
+ children: /* @__PURE__ */ jsx14("span", { "aria-hidden": "true", children: glyph })
5876
+ }
5877
+ );
5878
+ }
5879
+
5246
5880
  // src/web-react/index.tsx
5247
- import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
5881
+ import { Fragment as Fragment8, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
5248
5882
  function formatModelCost(msg, models) {
5249
5883
  if (msg.promptTokens == null && msg.completionTokens == null) return null;
5250
5884
  const pricing = models.find((m) => m.id === msg.modelUsed)?.pricing;
@@ -5258,41 +5892,41 @@ function formatTokensPerSecond(msg) {
5258
5892
  return `${Math.round(msg.completionTokens / (msg.durationMs / 1e3))} tok/s`;
5259
5893
  }
5260
5894
  function RunDrillIn({ run, onClose }) {
5261
- return /* @__PURE__ */ jsxs11("div", { className: `fixed inset-y-0 right-0 z-50 flex w-[480px] max-w-full flex-col border-l border-card-edge bg-popover ${OVERLAY_SHADOW}`, children: [
5262
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 border-b border-border px-4 py-3", children: [
5263
- /* @__PURE__ */ jsx13(
5895
+ return /* @__PURE__ */ jsxs13("div", { className: `fixed inset-y-0 right-0 z-50 flex w-[480px] max-w-full flex-col border-l border-card-edge bg-popover ${OVERLAY_SHADOW}`, children: [
5896
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 border-b border-border px-4 py-3", children: [
5897
+ /* @__PURE__ */ jsx15(
5264
5898
  "span",
5265
5899
  {
5266
5900
  className: `h-2 w-2 shrink-0 rounded-full ${run.status === "running" ? "bg-warning" : run.status === "error" ? "bg-destructive" : "bg-success"}`
5267
5901
  }
5268
5902
  ),
5269
- /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1", children: [
5270
- /* @__PURE__ */ jsx13("p", { className: "truncate text-[15px] font-semibold", children: run.title }),
5271
- /* @__PURE__ */ jsx13("p", { className: "truncate font-mono text-xs text-muted-foreground", children: run.toolName })
5903
+ /* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1", children: [
5904
+ /* @__PURE__ */ jsx15("p", { className: "truncate text-[15px] font-semibold", children: run.title }),
5905
+ /* @__PURE__ */ jsx15("p", { className: "truncate font-mono text-xs text-muted-foreground", children: run.toolName })
5272
5906
  ] }),
5273
- /* @__PURE__ */ jsx13(
5907
+ /* @__PURE__ */ jsx15(
5274
5908
  "button",
5275
5909
  {
5276
5910
  type: "button",
5277
5911
  onClick: onClose,
5278
5912
  "aria-label": "Close",
5279
5913
  className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent hover:text-foreground",
5280
- children: /* @__PURE__ */ jsx13("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx13("path", { d: "M18 6 6 18M6 6l12 12" }) })
5914
+ children: /* @__PURE__ */ jsx15("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx15("path", { d: "M18 6 6 18M6 6l12 12" }) })
5281
5915
  }
5282
5916
  )
5283
5917
  ] }),
5284
- /* @__PURE__ */ jsxs11("div", { className: "flex-1 space-y-3 overflow-y-auto p-4", children: [
5285
- run.steps.length === 0 && /* @__PURE__ */ jsx13("p", { className: "text-sm text-muted-foreground", children: "No steps recorded yet." }),
5286
- run.steps.map((step, i) => /* @__PURE__ */ jsxs11("div", { className: "rounded-lg border border-card-edge bg-card", children: [
5287
- /* @__PURE__ */ jsxs11("div", { className: "flex items-baseline gap-2 border-b border-border px-3 py-1.5", children: [
5288
- /* @__PURE__ */ jsx13("span", { className: `font-mono text-xs ${step.status === "error" ? "text-destructive" : "text-muted-foreground"}`, children: step.status === "error" ? "\u2717" : "$" }),
5289
- /* @__PURE__ */ jsx13("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: step.label }),
5290
- /* @__PURE__ */ jsx13("span", { className: "shrink-0 text-xs tabular-nums text-muted-foreground", children: new Date(step.at).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) })
5918
+ /* @__PURE__ */ jsxs13("div", { className: "flex-1 space-y-3 overflow-y-auto p-4", children: [
5919
+ run.steps.length === 0 && /* @__PURE__ */ jsx15("p", { className: "text-sm text-muted-foreground", children: "No steps recorded yet." }),
5920
+ run.steps.map((step, i) => /* @__PURE__ */ jsxs13("div", { className: "rounded-lg border border-card-edge bg-card", children: [
5921
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-baseline gap-2 border-b border-border px-3 py-1.5", children: [
5922
+ /* @__PURE__ */ jsx15("span", { className: `font-mono text-xs ${step.status === "error" ? "text-destructive" : "text-muted-foreground"}`, children: step.status === "error" ? "\u2717" : "$" }),
5923
+ /* @__PURE__ */ jsx15("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: step.label }),
5924
+ /* @__PURE__ */ jsx15("span", { className: "shrink-0 text-xs tabular-nums text-muted-foreground", children: new Date(step.at).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) })
5291
5925
  ] }),
5292
- step.detail && /* @__PURE__ */ jsx13("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap px-3 py-2 font-mono text-xs leading-relaxed text-muted-foreground", children: step.detail })
5926
+ step.detail && /* @__PURE__ */ jsx15("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap px-3 py-2 font-mono text-xs leading-relaxed text-muted-foreground", children: step.detail })
5293
5927
  ] }, i))
5294
5928
  ] }),
5295
- /* @__PURE__ */ jsx13("p", { className: "border-t border-border px-4 py-2 text-xs text-muted-foreground", children: "Read-only transcript \u2014 reply in the main chat." })
5929
+ /* @__PURE__ */ jsx15("p", { className: "border-t border-border px-4 py-2 text-xs text-muted-foreground", children: "Read-only transcript \u2014 reply in the main chat." })
5296
5930
  ] });
5297
5931
  }
5298
5932
  function pendingApprovalOf(call) {
@@ -5308,23 +5942,23 @@ function ChatEmptyState({
5308
5942
  }) {
5309
5943
  const doorCount = Math.min(doors?.length ?? 0, 3);
5310
5944
  const doorsGridClass = doorCount === 1 ? "mx-auto max-w-sm sm:grid-cols-1" : doorCount === 2 ? "sm:grid-cols-2" : "sm:grid-cols-3";
5311
- return /* @__PURE__ */ jsxs11("div", { className: "mx-auto flex w-full max-w-2xl flex-col items-center px-6 py-12 text-center sm:py-20", children: [
5312
- /* @__PURE__ */ jsx13("span", { className: "mb-5 inline-flex h-14 w-14 items-center justify-center rounded-2xl bg-primary/10 ring-1 ring-primary/15", children: /* @__PURE__ */ jsx13(BrandMark, { size: 32, className: "shrink-0" }) }),
5313
- /* @__PURE__ */ jsx13("p", { className: "text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: productName }),
5314
- /* @__PURE__ */ jsx13("h2", { className: "mt-1.5 text-balance text-2xl font-semibold leading-tight text-foreground", children: headline }),
5315
- subline && /* @__PURE__ */ jsx13("p", { className: "mt-3 max-w-md text-[15px] leading-relaxed text-muted-foreground", children: subline }),
5316
- doors && doors.length > 0 && /* @__PURE__ */ jsx13("div", { className: `mt-7 grid w-full gap-2.5 ${doorsGridClass}`, children: doors.slice(0, 3).map((door, i) => /* @__PURE__ */ jsxs11(
5945
+ return /* @__PURE__ */ jsxs13("div", { className: "mx-auto flex w-full max-w-2xl flex-col items-center px-6 py-12 text-center sm:py-20", children: [
5946
+ /* @__PURE__ */ jsx15("span", { className: "mb-5 inline-flex h-14 w-14 items-center justify-center rounded-2xl bg-primary/10 ring-1 ring-primary/15", children: /* @__PURE__ */ jsx15(BrandMark, { size: 32, className: "shrink-0" }) }),
5947
+ /* @__PURE__ */ jsx15("p", { className: "text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: productName }),
5948
+ /* @__PURE__ */ jsx15("h2", { className: "mt-1.5 text-balance text-2xl font-semibold leading-tight text-foreground", children: headline }),
5949
+ subline && /* @__PURE__ */ jsx15("p", { className: "mt-3 max-w-md text-[15px] leading-relaxed text-muted-foreground", children: subline }),
5950
+ doors && doors.length > 0 && /* @__PURE__ */ jsx15("div", { className: `mt-7 grid w-full gap-2.5 ${doorsGridClass}`, children: doors.slice(0, 3).map((door, i) => /* @__PURE__ */ jsxs13(
5317
5951
  "button",
5318
5952
  {
5319
5953
  type: "button",
5320
5954
  onClick: door.onSelect,
5321
5955
  className: "group flex min-h-[44px] flex-col items-start rounded-xl border border-border bg-card px-4 py-3 text-left transition hover:border-primary/40 hover:bg-accent",
5322
5956
  children: [
5323
- /* @__PURE__ */ jsxs11("span", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
5957
+ /* @__PURE__ */ jsxs13("span", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
5324
5958
  door.icon,
5325
5959
  door.label
5326
5960
  ] }),
5327
- door.description && /* @__PURE__ */ jsx13("span", { className: "mt-0.5 text-[12px] leading-snug text-muted-foreground", children: door.description })
5961
+ door.description && /* @__PURE__ */ jsx15("span", { className: "mt-0.5 text-[12px] leading-snug text-muted-foreground", children: door.description })
5328
5962
  ]
5329
5963
  },
5330
5964
  i
@@ -5333,26 +5967,26 @@ function ChatEmptyState({
5333
5967
  }
5334
5968
  function ToolGlyph({ name, className }) {
5335
5969
  if (name.startsWith("sandbox_")) {
5336
- return /* @__PURE__ */ jsxs11("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5337
- /* @__PURE__ */ jsx13("polyline", { points: "4 17 10 11 4 5" }),
5338
- /* @__PURE__ */ jsx13("line", { x1: "12", y1: "19", x2: "20", y2: "19" })
5970
+ return /* @__PURE__ */ jsxs13("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5971
+ /* @__PURE__ */ jsx15("polyline", { points: "4 17 10 11 4 5" }),
5972
+ /* @__PURE__ */ jsx15("line", { x1: "12", y1: "19", x2: "20", y2: "19" })
5339
5973
  ] });
5340
5974
  }
5341
5975
  if (name === "submit_proposal") {
5342
- return /* @__PURE__ */ jsxs11("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5343
- /* @__PURE__ */ jsx13("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
5344
- /* @__PURE__ */ jsx13("path", { d: "M14 2v6h6M9 15l2 2 4-4" })
5976
+ return /* @__PURE__ */ jsxs13("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5977
+ /* @__PURE__ */ jsx15("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
5978
+ /* @__PURE__ */ jsx15("path", { d: "M14 2v6h6M9 15l2 2 4-4" })
5345
5979
  ] });
5346
5980
  }
5347
5981
  if (name === "schedule_followup") {
5348
- return /* @__PURE__ */ jsxs11("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: [
5349
- /* @__PURE__ */ jsx13("circle", { cx: "12", cy: "12", r: "9" }),
5350
- /* @__PURE__ */ jsx13("path", { d: "M12 7v5l3 3" })
5982
+ return /* @__PURE__ */ jsxs13("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: [
5983
+ /* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "9" }),
5984
+ /* @__PURE__ */ jsx15("path", { d: "M12 7v5l3 3" })
5351
5985
  ] });
5352
5986
  }
5353
- return /* @__PURE__ */ jsxs11("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5354
- /* @__PURE__ */ jsx13("path", { d: "M12 3v3m0 12v3M3 12h3m12 0h3" }),
5355
- /* @__PURE__ */ jsx13("circle", { cx: "12", cy: "12", r: "4" })
5987
+ return /* @__PURE__ */ jsxs13("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5988
+ /* @__PURE__ */ jsx15("path", { d: "M12 3v3m0 12v3M3 12h3m12 0h3" }),
5989
+ /* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "4" })
5356
5990
  ] });
5357
5991
  }
5358
5992
  function toolOutcomeOf(call) {
@@ -5438,40 +6072,40 @@ function truncate(v, max = 240) {
5438
6072
  function KvRows({ data }) {
5439
6073
  const entries = Object.entries(data).filter(([, v]) => v !== void 0 && v !== null && v !== "");
5440
6074
  if (!entries.length) return null;
5441
- return /* @__PURE__ */ jsx13("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: entries.map(([k, v]) => /* @__PURE__ */ jsxs11("div", { className: "contents", children: [
5442
- /* @__PURE__ */ jsx13("dt", { className: "font-mono text-xs text-muted-foreground", children: k }),
5443
- /* @__PURE__ */ jsx13("dd", { className: "min-w-0 whitespace-pre-wrap break-words font-mono text-xs text-muted-foreground", children: truncate(v) })
6075
+ return /* @__PURE__ */ jsx15("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: entries.map(([k, v]) => /* @__PURE__ */ jsxs13("div", { className: "contents", children: [
6076
+ /* @__PURE__ */ jsx15("dt", { className: "font-mono text-xs text-muted-foreground", children: k }),
6077
+ /* @__PURE__ */ jsx15("dd", { className: "min-w-0 whitespace-pre-wrap break-words font-mono text-xs text-muted-foreground", children: truncate(v) })
5444
6078
  ] }, k)) });
5445
6079
  }
5446
6080
  function ShellDetail({ call }) {
5447
6081
  const outcome = toolOutcomeOf(call);
5448
6082
  const r = outcome?.result ?? {};
5449
- return /* @__PURE__ */ jsxs11("div", { className: "overflow-hidden rounded-md bg-zinc-900 font-mono text-xs leading-relaxed", children: [
5450
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 px-3 pt-2 text-zinc-400", children: [
5451
- /* @__PURE__ */ jsx13("span", { className: "select-none text-zinc-500", children: "$" }),
5452
- /* @__PURE__ */ jsx13("span", { className: "min-w-0 flex-1 truncate text-zinc-200", children: String(call.args?.command ?? "") }),
5453
- r.exitCode != null && /* @__PURE__ */ jsxs11("span", { className: r.exitCode === 0 ? "text-success" : "text-destructive", children: [
6083
+ return /* @__PURE__ */ jsxs13("div", { className: "overflow-hidden rounded-md bg-zinc-900 font-mono text-xs leading-relaxed", children: [
6084
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 px-3 pt-2 text-zinc-400", children: [
6085
+ /* @__PURE__ */ jsx15("span", { className: "select-none text-zinc-500", children: "$" }),
6086
+ /* @__PURE__ */ jsx15("span", { className: "min-w-0 flex-1 truncate text-zinc-200", children: String(call.args?.command ?? "") }),
6087
+ r.exitCode != null && /* @__PURE__ */ jsxs13("span", { className: r.exitCode === 0 ? "text-success" : "text-destructive", children: [
5454
6088
  "exit ",
5455
6089
  r.exitCode
5456
6090
  ] })
5457
6091
  ] }),
5458
- /* @__PURE__ */ jsx13("pre", { className: "max-h-56 overflow-auto whitespace-pre-wrap px-3 pb-2.5 pt-1.5 text-zinc-300", children: outcome?.ok === false ? outcome.message ?? "failed" : [r.stdout, r.stderr].filter(Boolean).join("\n") || "(no output)" })
6092
+ /* @__PURE__ */ jsx15("pre", { className: "max-h-56 overflow-auto whitespace-pre-wrap px-3 pb-2.5 pt-1.5 text-zinc-300", children: outcome?.ok === false ? outcome.message ?? "failed" : [r.stdout, r.stderr].filter(Boolean).join("\n") || "(no output)" })
5459
6093
  ] });
5460
6094
  }
5461
6095
  function DefaultToolDetail({ call }) {
5462
6096
  const result = call.result;
5463
6097
  const envelope = typeof result === "object" && result !== null ? result : null;
5464
- return /* @__PURE__ */ jsxs11("div", { className: "space-y-2", children: [
5465
- call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */ jsxs11("div", { children: [
5466
- /* @__PURE__ */ jsx13("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Called with" }),
5467
- /* @__PURE__ */ jsx13(KvRows, { data: call.args })
6098
+ return /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
6099
+ call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */ jsxs13("div", { children: [
6100
+ /* @__PURE__ */ jsx15("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Called with" }),
6101
+ /* @__PURE__ */ jsx15(KvRows, { data: call.args })
5468
6102
  ] }),
5469
- envelope ? /* @__PURE__ */ jsxs11("div", { children: [
5470
- /* @__PURE__ */ jsx13("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: envelope.ok === false ? "Failed" : "Result" }),
5471
- envelope.ok === false ? /* @__PURE__ */ jsx13("p", { className: "text-xs text-destructive", children: envelope.message ?? "Tool failed" }) : envelope.result && typeof envelope.result === "object" ? /* @__PURE__ */ jsx13(KvRows, { data: envelope.result }) : envelope.result != null ? /* @__PURE__ */ jsx13("p", { className: "font-mono text-xs text-muted-foreground", children: truncate(envelope.result) }) : null
5472
- ] }) : result != null ? /* @__PURE__ */ jsxs11("div", { children: [
5473
- /* @__PURE__ */ jsx13("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Result" }),
5474
- /* @__PURE__ */ jsx13("p", { className: "font-mono text-xs text-muted-foreground", children: truncate(result) })
6103
+ envelope ? /* @__PURE__ */ jsxs13("div", { children: [
6104
+ /* @__PURE__ */ jsx15("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: envelope.ok === false ? "Failed" : "Result" }),
6105
+ envelope.ok === false ? /* @__PURE__ */ jsx15("p", { className: "text-xs text-destructive", children: envelope.message ?? "Tool failed" }) : envelope.result && typeof envelope.result === "object" ? /* @__PURE__ */ jsx15(KvRows, { data: envelope.result }) : envelope.result != null ? /* @__PURE__ */ jsx15("p", { className: "font-mono text-xs text-muted-foreground", children: truncate(envelope.result) }) : null
6106
+ ] }) : result != null ? /* @__PURE__ */ jsxs13("div", { children: [
6107
+ /* @__PURE__ */ jsx15("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Result" }),
6108
+ /* @__PURE__ */ jsx15("p", { className: "font-mono text-xs text-muted-foreground", children: truncate(result) })
5475
6109
  ] }) : null
5476
6110
  ] });
5477
6111
  }
@@ -5482,24 +6116,24 @@ function ProposalCard({
5482
6116
  approval,
5483
6117
  renderers
5484
6118
  }) {
5485
- const [expanded, setExpanded] = useState14(false);
6119
+ const [expanded, setExpanded] = useState16(false);
5486
6120
  const { summary, meta, typeSlug } = proposalPreview(call);
5487
6121
  const custom = renderers?.[call.name]?.(call, message);
5488
6122
  const { pending: deciding, run: decide } = usePending();
5489
- return /* @__PURE__ */ jsxs11("div", { className: "w-full max-w-full rounded-xl border border-warning/50 bg-warning/[0.06] text-sm shadow-sm ring-1 ring-warning/10", children: [
5490
- /* @__PURE__ */ jsxs11("div", { className: "flex items-start gap-2.5 px-4 pt-3.5", children: [
5491
- /* @__PURE__ */ jsx13("span", { className: "mt-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-warning/15 text-warning", children: /* @__PURE__ */ jsx13(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5" }) }),
5492
- /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1", children: [
5493
- /* @__PURE__ */ jsx13("p", { className: "text-xs font-semibold uppercase tracking-[0.05em] text-warning-strong", children: approval ? "Needs your approval" : "Awaiting approval" }),
5494
- /* @__PURE__ */ jsx13("p", { className: "mt-0.5 text-[15px] font-semibold leading-snug text-foreground", children: friendlyToolTitle(call) }),
5495
- summary && /* @__PURE__ */ jsx13("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: summary }),
5496
- typeSlug && /* @__PURE__ */ jsx13("p", { className: "mt-1 font-mono text-xs text-muted-foreground", children: typeSlug }),
5497
- meta.length > 0 && /* @__PURE__ */ jsx13("div", { className: "mt-1.5 flex flex-wrap items-center gap-1.5", children: meta.map((m, i) => /* @__PURE__ */ jsx13("span", { className: "rounded-full bg-secondary px-2 py-0.5 text-xs font-medium text-muted-foreground", children: m }, i)) })
6123
+ return /* @__PURE__ */ jsxs13("div", { className: "w-full max-w-full rounded-xl border border-warning/50 bg-warning/[0.06] text-sm shadow-sm ring-1 ring-warning/10", children: [
6124
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-start gap-2.5 px-4 pt-3.5", children: [
6125
+ /* @__PURE__ */ jsx15("span", { className: "mt-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-warning/15 text-warning", children: /* @__PURE__ */ jsx15(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5" }) }),
6126
+ /* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1", children: [
6127
+ /* @__PURE__ */ jsx15("p", { className: "text-xs font-semibold uppercase tracking-[0.05em] text-warning-strong", children: approval ? "Needs your approval" : "Awaiting approval" }),
6128
+ /* @__PURE__ */ jsx15("p", { className: "mt-0.5 text-[15px] font-semibold leading-snug text-foreground", children: friendlyToolTitle(call) }),
6129
+ summary && /* @__PURE__ */ jsx15("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: summary }),
6130
+ typeSlug && /* @__PURE__ */ jsx15("p", { className: "mt-1 font-mono text-xs text-muted-foreground", children: typeSlug }),
6131
+ meta.length > 0 && /* @__PURE__ */ jsx15("div", { className: "mt-1.5 flex flex-wrap items-center gap-1.5", children: meta.map((m, i) => /* @__PURE__ */ jsx15("span", { className: "rounded-full bg-secondary px-2 py-0.5 text-xs font-medium text-muted-foreground", children: m }, i)) })
5498
6132
  ] })
5499
6133
  ] }),
5500
- /* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center gap-2 px-4 pb-3.5 pt-3", children: [
5501
- approval && /* @__PURE__ */ jsxs11(Fragment7, { children: [
5502
- /* @__PURE__ */ jsx13(
6134
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center gap-2 px-4 pb-3.5 pt-3", children: [
6135
+ approval && /* @__PURE__ */ jsxs13(Fragment8, { children: [
6136
+ /* @__PURE__ */ jsx15(
5503
6137
  "button",
5504
6138
  {
5505
6139
  type: "button",
@@ -5509,7 +6143,7 @@ function ProposalCard({
5509
6143
  children: "Approve & run"
5510
6144
  }
5511
6145
  ),
5512
- /* @__PURE__ */ jsx13(
6146
+ /* @__PURE__ */ jsx15(
5513
6147
  "button",
5514
6148
  {
5515
6149
  type: "button",
@@ -5520,7 +6154,7 @@ function ProposalCard({
5520
6154
  }
5521
6155
  )
5522
6156
  ] }),
5523
- /* @__PURE__ */ jsxs11(
6157
+ /* @__PURE__ */ jsxs13(
5524
6158
  "button",
5525
6159
  {
5526
6160
  type: "button",
@@ -5529,12 +6163,12 @@ function ProposalCard({
5529
6163
  className: "ml-auto inline-flex items-center gap-1 rounded text-[12px] font-medium text-muted-foreground transition hover:text-foreground",
5530
6164
  children: [
5531
6165
  expanded ? "Hide details" : "View details",
5532
- /* @__PURE__ */ jsx13(ChevronDown, { className: `h-3 w-3 transition-transform ${expanded ? "rotate-180" : ""}` })
6166
+ /* @__PURE__ */ jsx15(ChevronDown, { className: `h-3 w-3 transition-transform ${expanded ? "rotate-180" : ""}` })
5533
6167
  ]
5534
6168
  }
5535
6169
  )
5536
6170
  ] }),
5537
- expanded && /* @__PURE__ */ jsx13("div", { className: "border-t border-warning/20 px-4 py-3 text-xs", children: custom ?? /* @__PURE__ */ jsx13(DefaultToolDetail, { call }) })
6171
+ expanded && /* @__PURE__ */ jsx15("div", { className: "border-t border-warning/20 px-4 py-3 text-xs", children: custom ?? /* @__PURE__ */ jsx15(DefaultToolDetail, { call }) })
5538
6172
  ] });
5539
6173
  }
5540
6174
  function formatFollowupWhen(when) {
@@ -5549,14 +6183,14 @@ function FollowupCard({ call }) {
5549
6183
  const when = typeof a.when === "string" ? a.when : typeof a.at === "string" ? a.at : typeof a.schedule === "string" ? a.schedule : null;
5550
6184
  const failed = toolCallFailed(call);
5551
6185
  const errorText = failed ? toolOutcomeOf(call)?.message ?? "Scheduling failed" : null;
5552
- return /* @__PURE__ */ jsx13("div", { className: "flex items-start gap-2", children: /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1 overflow-hidden rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[var(--md3-surface-container)]", children: [
5553
- /* @__PURE__ */ jsxs11("div", { className: "flex w-full items-center gap-2.5 px-3 py-2", children: [
5554
- /* @__PURE__ */ jsx13("span", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--radius-sm)] border border-border bg-muted text-muted-foreground", children: /* @__PURE__ */ jsx13(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5" }) }),
5555
- /* @__PURE__ */ jsx13("span", { className: "shrink-0 whitespace-nowrap text-xs font-medium text-foreground", children: friendlyToolTitle(call) }),
5556
- when && /* @__PURE__ */ jsx13("span", { title: when, className: "hidden min-w-0 flex-1 truncate font-mono text-xs tabular-nums text-muted-foreground sm:inline", children: formatFollowupWhen(when) }),
5557
- /* @__PURE__ */ jsx13("span", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: call.status === "running" ? /* @__PURE__ */ jsx13("svg", { className: "h-3 w-3 shrink-0 animate-spin text-[var(--accent-text)]", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx13("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }) : /* @__PURE__ */ jsx13("span", { className: `h-1.5 w-1.5 shrink-0 rounded-full ${failed ? "bg-[var(--surface-danger-text)]" : "bg-[var(--surface-success-text)]"}` }) })
6186
+ return /* @__PURE__ */ jsx15("div", { className: "flex items-start gap-2", children: /* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1 overflow-hidden rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[var(--md3-surface-container)]", children: [
6187
+ /* @__PURE__ */ jsxs13("div", { className: "flex w-full items-center gap-2.5 px-3 py-2", children: [
6188
+ /* @__PURE__ */ jsx15("span", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--radius-sm)] border border-border bg-muted text-muted-foreground", children: /* @__PURE__ */ jsx15(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5" }) }),
6189
+ /* @__PURE__ */ jsx15("span", { className: "shrink-0 whitespace-nowrap text-xs font-medium text-foreground", children: friendlyToolTitle(call) }),
6190
+ when && /* @__PURE__ */ jsx15("span", { title: when, className: "hidden min-w-0 flex-1 truncate font-mono text-xs tabular-nums text-muted-foreground sm:inline", children: formatFollowupWhen(when) }),
6191
+ /* @__PURE__ */ jsx15("span", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: call.status === "running" ? /* @__PURE__ */ jsx15("svg", { className: "h-3 w-3 shrink-0 animate-spin text-[var(--accent-text)]", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx15("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }) : /* @__PURE__ */ jsx15("span", { className: `h-1.5 w-1.5 shrink-0 rounded-full ${failed ? "bg-[var(--surface-danger-text)]" : "bg-[var(--surface-success-text)]"}` }) })
5558
6192
  ] }),
5559
- errorText && /* @__PURE__ */ jsx13("div", { className: "border-t border-border px-3 py-2 text-xs text-[var(--surface-danger-text)]", children: errorText })
6193
+ errorText && /* @__PURE__ */ jsx15("div", { className: "border-t border-border px-3 py-2 text-xs text-[var(--surface-danger-text)]", children: errorText })
5560
6194
  ] }) });
5561
6195
  }
5562
6196
  function toolRowTitle(call) {
@@ -5573,52 +6207,59 @@ function ToolCallCard({
5573
6207
  message,
5574
6208
  approval,
5575
6209
  onOpenRun,
5576
- renderers
6210
+ renderers,
6211
+ staggerIndex
5577
6212
  }) {
6213
+ const arrival = useArrivalStyle(staggerIndex ?? 0);
5578
6214
  const pending = call.status === "done" ? pendingApprovalOf(call) : null;
5579
6215
  const kind = blockKindOf(call);
6216
+ const arrive = (row) => /* @__PURE__ */ jsx15("div", { className: "agent-arrive", style: arrival, children: row });
5580
6217
  if (pending) {
5581
- return /* @__PURE__ */ jsx13(
5582
- ProposalCard,
5583
- {
5584
- call,
5585
- message,
5586
- pending,
5587
- approval,
5588
- renderers
5589
- }
6218
+ return arrive(
6219
+ /* @__PURE__ */ jsx15(
6220
+ ProposalCard,
6221
+ {
6222
+ call,
6223
+ message,
6224
+ pending,
6225
+ approval,
6226
+ renderers
6227
+ }
6228
+ )
5590
6229
  );
5591
6230
  }
5592
6231
  if (kind === "followup") {
5593
- return /* @__PURE__ */ jsx13(FollowupCard, { call });
6232
+ return arrive(/* @__PURE__ */ jsx15(FollowupCard, { call }));
5594
6233
  }
5595
6234
  const custom = renderers?.[call.name]?.(call, message);
5596
- return /* @__PURE__ */ jsx13(
5597
- InlineToolItem,
5598
- {
5599
- part: chatToolCallPart(call),
5600
- title: toolRowTitle(call),
5601
- description: toolRowDescription(call),
5602
- renderToolDetail: () => custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */ jsx13(ShellDetail, { call }) : /* @__PURE__ */ jsx13(DefaultToolDetail, { call })),
5603
- actions: onOpenRun && call.name.startsWith("sandbox_") ? /* @__PURE__ */ jsx13(
5604
- "button",
5605
- {
5606
- type: "button",
5607
- onClick: () => onOpenRun(call, message),
5608
- "aria-label": "Open full transcript",
5609
- title: "Open full transcript",
5610
- className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent hover:text-foreground",
5611
- children: /* @__PURE__ */ jsxs11("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5612
- /* @__PURE__ */ jsx13("path", { d: "M7 17 17 7" }),
5613
- /* @__PURE__ */ jsx13("path", { d: "M7 7h10v10" })
5614
- ] })
5615
- }
5616
- ) : void 0
5617
- }
6235
+ return arrive(
6236
+ /* @__PURE__ */ jsx15(
6237
+ InlineToolItem,
6238
+ {
6239
+ part: chatToolCallPart(call),
6240
+ title: toolRowTitle(call),
6241
+ description: toolRowDescription(call),
6242
+ renderToolDetail: () => custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */ jsx15(ShellDetail, { call }) : /* @__PURE__ */ jsx15(DefaultToolDetail, { call })),
6243
+ actions: onOpenRun && call.name.startsWith("sandbox_") ? /* @__PURE__ */ jsx15(
6244
+ "button",
6245
+ {
6246
+ type: "button",
6247
+ onClick: () => onOpenRun(call, message),
6248
+ "aria-label": "Open full transcript",
6249
+ title: "Open full transcript",
6250
+ className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent hover:text-foreground",
6251
+ children: /* @__PURE__ */ jsxs13("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
6252
+ /* @__PURE__ */ jsx15("path", { d: "M7 17 17 7" }),
6253
+ /* @__PURE__ */ jsx15("path", { d: "M7 7h10v10" })
6254
+ ] })
6255
+ }
6256
+ ) : void 0
6257
+ }
6258
+ )
5618
6259
  );
5619
6260
  }
5620
6261
  function StreamingCaret() {
5621
- return /* @__PURE__ */ jsx13(
6262
+ return /* @__PURE__ */ jsx15(
5622
6263
  "span",
5623
6264
  {
5624
6265
  className: "ml-0.5 inline-block h-[1.1em] w-[3px] translate-y-[2px] animate-[agent-caret_1s_step-end_infinite] rounded-sm bg-foreground/70",
@@ -5643,9 +6284,9 @@ function SegmentText({
5643
6284
  // the container on top of that makes the paragraph shimmer while it types.
5644
6285
  // The distinction is what separates "the answer materialised" from "the
5645
6286
  // log was appended to".
5646
- /* @__PURE__ */ jsxs11("div", { className: `${messageClassName}${streaming ? "" : " agent-stream-in"}`, children: [
6287
+ /* @__PURE__ */ jsxs13("div", { className: `${messageClassName}${streaming ? "" : " agent-stream-in"}`, children: [
5647
6288
  body,
5648
- showCaret && /* @__PURE__ */ jsx13(StreamingCaret, {})
6289
+ showCaret && /* @__PURE__ */ jsx15(StreamingCaret, {})
5649
6290
  ] })
5650
6291
  );
5651
6292
  }
@@ -5670,14 +6311,15 @@ function SegmentedBody({
5670
6311
  const leftoverToolCalls = (msg.toolCalls ?? []).filter(
5671
6312
  (tc) => !segmentToolIds.has(tc.id)
5672
6313
  );
5673
- const renderToolCard = (call) => /* @__PURE__ */ jsx13(
6314
+ const renderToolCard = (call, index) => /* @__PURE__ */ jsx15(
5674
6315
  ToolCallCard,
5675
6316
  {
5676
6317
  call,
5677
6318
  message: msg,
5678
6319
  approval,
5679
6320
  onOpenRun: onToolCallClick,
5680
- renderers: toolRenderers
6321
+ renderers: toolRenderers,
6322
+ staggerIndex: index
5681
6323
  },
5682
6324
  `tool-${call.id}`
5683
6325
  );
@@ -5693,34 +6335,44 @@ function SegmentedBody({
5693
6335
  else groups.push({ kind: "tools", index: i, calls: [seg.call] });
5694
6336
  }
5695
6337
  }
5696
- return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-2", children: [
5697
- groups.map(
5698
- (g) => g.kind === "text" ? /* @__PURE__ */ jsx13(
5699
- SegmentText,
5700
- {
5701
- content: g.content,
5702
- streaming: streaming && g.index === lastIndex,
5703
- showCaret: streaming && g.index === lastIndex,
5704
- renderBody,
5705
- messageClassName
5706
- },
5707
- `text-${g.index}`
5708
- ) : !streaming && g.calls.length >= COLLAPSE_TOOL_RUN_AT && !g.calls.some(isImportantTool) ? (
5709
- // The fold is a quiet disclosure line, not a filled box — the
5710
- // canonical rows inside it carry the row chrome.
5711
- /* @__PURE__ */ jsxs11("details", { children: [
5712
- /* @__PURE__ */ jsxs11("summary", { className: "cursor-pointer select-none rounded-md py-0.5 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground", children: [
6338
+ const children = [];
6339
+ for (const g of groups) {
6340
+ if (g.kind === "text") {
6341
+ children.push(
6342
+ /* @__PURE__ */ jsx15(
6343
+ SegmentText,
6344
+ {
6345
+ content: g.content,
6346
+ streaming: streaming && g.index === lastIndex,
6347
+ showCaret: streaming && g.index === lastIndex,
6348
+ renderBody,
6349
+ messageClassName
6350
+ },
6351
+ `text-${g.index}`
6352
+ )
6353
+ );
6354
+ continue;
6355
+ }
6356
+ if (!streaming && g.calls.length >= COLLAPSE_TOOL_RUN_AT && !g.calls.some(isImportantTool)) {
6357
+ children.push(
6358
+ /* @__PURE__ */ jsxs13("details", { children: [
6359
+ /* @__PURE__ */ jsxs13("summary", { className: "cursor-pointer select-none rounded-md py-0.5 text-xs font-medium text-muted-foreground [transition:color_var(--motion-control)] hover:text-foreground", children: [
5713
6360
  "Worked through ",
5714
6361
  g.calls.length,
5715
6362
  " steps"
5716
6363
  ] }),
5717
- /* @__PURE__ */ jsx13("div", { className: "mt-1.5 flex flex-col gap-1.5", children: g.calls.map(renderToolCard) })
5718
- ] }, `tools-${g.index}`)
5719
- ) : /* @__PURE__ */ jsx13("div", { className: "flex flex-col gap-2", children: g.calls.map(renderToolCard) }, `tools-${g.index}`)
5720
- ),
5721
- leftoverToolCalls.map(renderToolCard),
5722
- streaming && segments[lastIndex]?.kind === "tool" && /* @__PURE__ */ jsx13(StreamingCaret, {})
5723
- ] });
6364
+ /* @__PURE__ */ jsx15("div", { className: "mt-1.5 flex flex-col gap-1.5", children: g.calls.map(renderToolCard) })
6365
+ ] }, `tools-fold-${g.index}`)
6366
+ );
6367
+ continue;
6368
+ }
6369
+ g.calls.forEach((call, index) => children.push(renderToolCard(call, index)));
6370
+ }
6371
+ leftoverToolCalls.forEach((call, index) => children.push(renderToolCard(call, index)));
6372
+ if (streaming && segments[lastIndex]?.kind === "tool") {
6373
+ children.push(/* @__PURE__ */ jsx15(StreamingCaret, {}, "streaming-caret"));
6374
+ }
6375
+ return /* @__PURE__ */ jsx15("div", { className: "flex flex-col gap-2", children });
5724
6376
  }
5725
6377
  var QUIET_META_LANE_CLASS = "mt-1 flex h-[18px] items-center gap-2 text-xs tabular-nums text-muted-foreground opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none [@media(hover:none)]:opacity-100";
5726
6378
  function copyTextOf(msg) {
@@ -5729,9 +6381,9 @@ function copyTextOf(msg) {
5729
6381
  return msg.content;
5730
6382
  }
5731
6383
  function CopyMessageButton({ text }) {
5732
- const [copied, setCopied] = useState14(false);
5733
- const timerRef = useRef11(null);
5734
- useEffect11(
6384
+ const [copied, setCopied] = useState16(false);
6385
+ const timerRef = useRef12(null);
6386
+ useEffect12(
5735
6387
  () => () => {
5736
6388
  if (timerRef.current !== null) clearTimeout(timerRef.current);
5737
6389
  },
@@ -5750,7 +6402,7 @@ function CopyMessageButton({ text }) {
5750
6402
  }
5751
6403
  );
5752
6404
  };
5753
- return /* @__PURE__ */ jsx13(
6405
+ return /* @__PURE__ */ jsx15(
5754
6406
  "button",
5755
6407
  {
5756
6408
  type: "button",
@@ -5758,9 +6410,9 @@ function CopyMessageButton({ text }) {
5758
6410
  "aria-label": "Copy message",
5759
6411
  title: "Copy message",
5760
6412
  className: "rounded p-0.5 text-muted-foreground transition hover:bg-accent hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
5761
- children: copied ? /* @__PURE__ */ jsx13("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx13("polyline", { points: "20 6 9 17 4 12" }) }) : /* @__PURE__ */ jsxs11("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5762
- /* @__PURE__ */ jsx13("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
5763
- /* @__PURE__ */ jsx13("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
6413
+ children: copied ? /* @__PURE__ */ jsx15("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx15("polyline", { points: "20 6 9 17 4 12" }) }) : /* @__PURE__ */ jsxs13("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
6414
+ /* @__PURE__ */ jsx15("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
6415
+ /* @__PURE__ */ jsx15("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
5764
6416
  ] })
5765
6417
  }
5766
6418
  );
@@ -5786,46 +6438,88 @@ function AssistantMessageImpl({
5786
6438
  const body = useMemo7(() => renderBody(content), [renderBody, content]);
5787
6439
  const segments = msg.segments;
5788
6440
  const hasAnswerText = content !== "" || (segments?.some((s) => s.kind === "text" && s.content.trim() !== "") ?? false);
5789
- const reasoningScrollRef = useRef11(null);
5790
- const thinkStartRef = useRef11(null);
5791
- const thinkMsRef = useRef11(null);
6441
+ const reasoningScrollRef = useRef12(null);
6442
+ const thinkStartRef = useRef12(null);
6443
+ const thinkMsRef = useRef12(null);
5792
6444
  if (streaming && reasoning && !hasAnswerText && thinkStartRef.current === null) {
5793
6445
  thinkStartRef.current = performance.now();
5794
6446
  }
5795
6447
  if (hasAnswerText && thinkStartRef.current !== null && thinkMsRef.current === null) {
5796
6448
  thinkMsRef.current = performance.now() - thinkStartRef.current;
5797
6449
  }
5798
- useEffect11(() => {
6450
+ useEffect12(() => {
5799
6451
  const el = reasoningScrollRef.current;
5800
6452
  if (el && streaming && !hasAnswerText) el.scrollTop = el.scrollHeight;
5801
6453
  }, [reasoning, streaming, hasAnswerText]);
5802
6454
  const thinkingSeconds = useThinkingSeconds(
5803
6455
  streaming && !!reasoning && !hasAnswerText
5804
6456
  );
6457
+ const reasoningId = useId4();
6458
+ const [reasoningToggled, setReasoningToggled] = useState16(null);
6459
+ const reasoningOpen = reasoningToggled ?? !hasAnswerText;
5805
6460
  const quiet = chrome === "quiet";
5806
- return /* @__PURE__ */ jsxs11("div", { className: `mx-auto w-full max-w-3xl px-6 ${quiet ? "group pb-1 pt-3" : "py-3"}`, children: [
5807
- !quiet && /* @__PURE__ */ jsxs11("div", { className: "mb-1 flex items-baseline gap-2 text-xs tabular-nums text-muted-foreground", children: [
5808
- /* @__PURE__ */ jsx13("span", { className: "font-semibold uppercase tracking-[0.05em]", children: agentLabel }),
5809
- msg.modelUsed && /* @__PURE__ */ jsx13("span", { className: "font-mono normal-case", children: msg.modelUsed }),
5810
- formatTokensPerSecond(msg) && /* @__PURE__ */ jsx13("span", { children: formatTokensPerSecond(msg) }),
5811
- formatModelCost(msg, models) && /* @__PURE__ */ jsx13("span", { children: formatModelCost(msg, models) })
6461
+ return /* @__PURE__ */ jsxs13("div", { className: `mx-auto w-full max-w-3xl px-6 ${quiet ? "group pb-1 pt-3" : "py-3"}`, children: [
6462
+ !quiet && /* @__PURE__ */ jsxs13("div", { className: "mb-1 flex items-baseline gap-2 text-xs tabular-nums text-muted-foreground", children: [
6463
+ /* @__PURE__ */ jsx15("span", { className: "font-semibold uppercase tracking-[0.05em]", children: agentLabel }),
6464
+ msg.modelUsed && /* @__PURE__ */ jsx15("span", { className: "font-mono normal-case", children: msg.modelUsed }),
6465
+ formatTokensPerSecond(msg) && /* @__PURE__ */ jsx15("span", { children: formatTokensPerSecond(msg) }),
6466
+ formatModelCost(msg, models) && /* @__PURE__ */ jsx15("span", { children: formatModelCost(msg, models) })
5812
6467
  ] }),
5813
- reasoning && /* @__PURE__ */ jsxs11("details", { className: "mb-2 rounded-lg border-l-2 border-border bg-secondary px-3 py-2", open: !hasAnswerText, children: [
5814
- /* @__PURE__ */ jsx13("summary", { className: "cursor-pointer select-none text-xs font-medium text-muted-foreground", children: !hasAnswerText ? (
5815
- // A pulse dims the whole word on a loop, which is the same cue a
5816
- // skeleton placeholder uses it reads as "nothing here yet". A
5817
- // sweep travels THROUGH the glyphs, which reads as work in
5818
- // flight, and the elapsed seconds say how much. `essential`
5819
- // because it is the only signal separating a working agent from
5820
- // a stuck one, and reduced-motion still collapses its duration.
5821
- /* @__PURE__ */ jsxs11("span", { className: "agent-shimmer", "data-motion": "essential", children: [
5822
- "Thinking",
5823
- thinkingSeconds >= 1 ? ` \xB7 ${thinkingSeconds}s` : "\u2026"
5824
- ] })
5825
- ) : thinkMsRef.current != null ? `Thought for ${Math.max(1, Math.round(thinkMsRef.current / 1e3))}s` : "Thought process" }),
5826
- /* @__PURE__ */ jsx13("div", { ref: reasoningScrollRef, className: "mt-2 max-h-48 overflow-y-auto whitespace-pre-wrap text-xs leading-relaxed text-muted-foreground", children: reasoning })
6468
+ reasoning && // A button + `.agent-disclose` rather than `<details>`: a native
6469
+ // disclosure has no transition to give, so the trace SNAPPED to full
6470
+ // height the moment the answer arrived the single largest layout jump
6471
+ // in a turn, at the exact moment the reader is trying to start reading.
6472
+ // The grid row animates the content's REAL height (0fr 1fr), which a
6473
+ // max-height guess cannot do without either clipping a long trace or
6474
+ // easing toward a number it never reaches. The keyboard contract
6475
+ // `<details>` supplied for free is restated explicitly: a real
6476
+ // `<button>` (Enter/Space, focusable, in the tab order) carrying
6477
+ // `aria-expanded` and `aria-controls` — which also announces the state
6478
+ // that a `<summary>` leaves to the browser.
6479
+ /* @__PURE__ */ jsxs13("div", { className: "mb-2 rounded-lg border-l-2 border-border bg-secondary px-3 py-2", children: [
6480
+ /* @__PURE__ */ jsxs13(
6481
+ "button",
6482
+ {
6483
+ type: "button",
6484
+ onClick: () => setReasoningToggled(!reasoningOpen),
6485
+ "aria-expanded": reasoningOpen,
6486
+ "aria-controls": reasoningId,
6487
+ className: "flex w-full select-none items-center gap-1.5 text-left text-xs font-medium text-muted-foreground [transition:color_var(--motion-control)] hover:text-foreground",
6488
+ children: [
6489
+ /* @__PURE__ */ jsx15(ChevronDown, { className: `h-3 w-3 shrink-0 [transition:transform_var(--motion-surface)] ${reasoningOpen ? "" : "-rotate-90"}` }),
6490
+ !hasAnswerText ? (
6491
+ // A pulse dims the whole word on a loop, which is the same cue a
6492
+ // skeleton placeholder uses — it reads as "nothing here yet". A
6493
+ // sweep travels THROUGH the glyphs, which reads as work in
6494
+ // flight, and the elapsed seconds say how much. `essential`
6495
+ // because it is the only signal separating a working agent from
6496
+ // a stuck one — and `essential` is an exemption from the blanket
6497
+ // floor, never a licence to sweep forever at someone who asked
6498
+ // for less motion: under `prefers-reduced-motion` tokens.css
6499
+ // stops this animation and leaves a dotted rule under the word
6500
+ // that the settled label ("Thought for 12s") does not carry. The
6501
+ // rule is the only difference — measured in Chromium, both labels
6502
+ // compute this button's own `text-muted-foreground`, so tone
6503
+ // separates neither.
6504
+ /* @__PURE__ */ jsxs13("span", { className: "agent-shimmer", "data-motion": "essential", children: [
6505
+ "Thinking",
6506
+ thinkingSeconds >= 1 ? ` \xB7 ${thinkingSeconds}s` : "\u2026"
6507
+ ] })
6508
+ ) : thinkMsRef.current != null ? `Thought for ${Math.max(1, Math.round(thinkMsRef.current / 1e3))}s` : "Thought process"
6509
+ ]
6510
+ }
6511
+ ),
6512
+ /* @__PURE__ */ jsx15("div", { className: "agent-disclose", "data-open": reasoningOpen ? "true" : "false", children: /* @__PURE__ */ jsx15("div", { ...inertProps(!reasoningOpen), children: /* @__PURE__ */ jsx15(
6513
+ "div",
6514
+ {
6515
+ id: reasoningId,
6516
+ ref: reasoningScrollRef,
6517
+ className: "mt-2 max-h-48 overflow-y-auto whitespace-pre-wrap text-xs leading-relaxed text-muted-foreground",
6518
+ children: reasoning
6519
+ }
6520
+ ) }) })
5827
6521
  ] }),
5828
- segments && segments.length > 0 ? /* @__PURE__ */ jsx13(
6522
+ segments && segments.length > 0 ? /* @__PURE__ */ jsx15(
5829
6523
  SegmentedBody,
5830
6524
  {
5831
6525
  segments,
@@ -5837,24 +6531,25 @@ function AssistantMessageImpl({
5837
6531
  toolRenderers,
5838
6532
  messageClassName
5839
6533
  }
5840
- ) : /* @__PURE__ */ jsxs11(Fragment7, { children: [
5841
- /* @__PURE__ */ jsxs11("div", { className: messageClassName, children: [
6534
+ ) : /* @__PURE__ */ jsxs13(Fragment8, { children: [
6535
+ /* @__PURE__ */ jsxs13("div", { className: messageClassName, children: [
5842
6536
  body,
5843
- streaming && content && !msg.toolCalls?.length && /* @__PURE__ */ jsx13(StreamingCaret, {})
6537
+ streaming && content && !msg.toolCalls?.length && /* @__PURE__ */ jsx15(StreamingCaret, {})
5844
6538
  ] }),
5845
- msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */ jsx13("div", { className: "mt-2 flex flex-col gap-1.5", children: msg.toolCalls.map((tc) => /* @__PURE__ */ jsx13(
6539
+ msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */ jsx15("div", { className: "mt-2 flex flex-col gap-1.5", children: msg.toolCalls.map((tc, index) => /* @__PURE__ */ jsx15(
5846
6540
  ToolCallCard,
5847
6541
  {
5848
6542
  call: tc,
5849
6543
  message: msg,
5850
6544
  approval,
5851
6545
  onOpenRun: onToolCallClick,
5852
- renderers: toolRenderers
6546
+ renderers: toolRenderers,
6547
+ staggerIndex: index
5853
6548
  },
5854
6549
  tc.id
5855
6550
  )) })
5856
6551
  ] }),
5857
- durableCards && msg.parts && /* @__PURE__ */ jsx13(
6552
+ durableCards && msg.parts && /* @__PURE__ */ jsx15(
5858
6553
  DurableChatCards,
5859
6554
  {
5860
6555
  ...durableCards,
@@ -5863,7 +6558,7 @@ function AssistantMessageImpl({
5863
6558
  className: "mt-3"
5864
6559
  }
5865
6560
  ),
5866
- workProductCards && workProductPartsFromMessageParts(msg.parts).map((part) => /* @__PURE__ */ jsx13(
6561
+ workProductCards && workProductPartsFromMessageParts(msg.parts).map((part) => /* @__PURE__ */ jsx15(
5867
6562
  WorkProductCard,
5868
6563
  {
5869
6564
  part,
@@ -5873,7 +6568,7 @@ function AssistantMessageImpl({
5873
6568
  `${part.ref.id}:${part.ref.version}`
5874
6569
  )),
5875
6570
  renderExtras?.(msg),
5876
- resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx13("div", { className: "mt-2", children: /* @__PURE__ */ jsx13(
6571
+ resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx15("div", { className: "mt-2", children: /* @__PURE__ */ jsx15(
5877
6572
  MessageAttachments,
5878
6573
  {
5879
6574
  parts: attachmentPartsFromMessageParts(msg.parts),
@@ -5881,18 +6576,18 @@ function AssistantMessageImpl({
5881
6576
  justify: "start"
5882
6577
  }
5883
6578
  ) }),
5884
- quiet && /* @__PURE__ */ jsxs11("div", { "data-testid": "message-meta-lane", className: QUIET_META_LANE_CLASS, children: [
5885
- /* @__PURE__ */ jsx13(CopyMessageButton, { text: copyTextOf(msg) }),
5886
- msg.modelUsed && /* @__PURE__ */ jsx13("span", { className: "font-mono", children: msg.modelUsed }),
5887
- formatTokensPerSecond(msg) && /* @__PURE__ */ jsx13("span", { children: formatTokensPerSecond(msg) }),
5888
- formatModelCost(msg, models) && /* @__PURE__ */ jsx13("span", { children: formatModelCost(msg, models) })
6579
+ quiet && /* @__PURE__ */ jsxs13("div", { "data-testid": "message-meta-lane", className: QUIET_META_LANE_CLASS, children: [
6580
+ /* @__PURE__ */ jsx15(CopyMessageButton, { text: copyTextOf(msg) }),
6581
+ msg.modelUsed && /* @__PURE__ */ jsx15("span", { className: "font-mono", children: msg.modelUsed }),
6582
+ formatTokensPerSecond(msg) && /* @__PURE__ */ jsx15("span", { children: formatTokensPerSecond(msg) }),
6583
+ formatModelCost(msg, models) && /* @__PURE__ */ jsx15("span", { children: formatModelCost(msg, models) })
5889
6584
  ] })
5890
6585
  ] });
5891
6586
  }
5892
6587
  var AssistantMessage = memo(AssistantMessageImpl);
5893
6588
  function useThinkingSeconds(active) {
5894
- const [seconds, setSeconds] = useState14(0);
5895
- useEffect11(() => {
6589
+ const [seconds, setSeconds] = useState16(0);
6590
+ useEffect12(() => {
5896
6591
  if (!active) return;
5897
6592
  setSeconds(0);
5898
6593
  const id = setInterval(() => setSeconds((s) => s + 1), 1e3);
@@ -5902,23 +6597,23 @@ function useThinkingSeconds(active) {
5902
6597
  }
5903
6598
  function ThinkingRow({ agentLabel, chrome = "labeled" }) {
5904
6599
  const seconds = useThinkingSeconds(true);
5905
- return /* @__PURE__ */ jsxs11("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
5906
- chrome !== "quiet" && /* @__PURE__ */ jsx13("p", { className: "mb-1 text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: agentLabel }),
5907
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 text-[15px] text-muted-foreground", children: [
5908
- /* @__PURE__ */ jsx13("svg", { className: "h-4 w-4 animate-spin", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx13("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }),
6600
+ return /* @__PURE__ */ jsxs13("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
6601
+ chrome !== "quiet" && /* @__PURE__ */ jsx15("p", { className: "mb-1 text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: agentLabel }),
6602
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 text-[15px] text-muted-foreground", children: [
6603
+ /* @__PURE__ */ jsx15("svg", { className: "h-4 w-4 animate-spin", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx15("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }),
5909
6604
  "Thinking",
5910
6605
  seconds >= 3 ? ` \xB7 ${seconds}s` : "..."
5911
6606
  ] })
5912
6607
  ] });
5913
6608
  }
5914
6609
  function StreamErrorRow({ message, onRetry }) {
5915
- return /* @__PURE__ */ jsx13("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: /* @__PURE__ */ jsxs11("div", { role: "alert", className: "flex items-start gap-2.5 rounded-lg border border-destructive/40 bg-destructive/5 px-3 py-2.5 text-sm text-destructive", children: [
5916
- /* @__PURE__ */ jsxs11("svg", { className: "mt-0.5 h-4 w-4 shrink-0", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5917
- /* @__PURE__ */ jsx13("circle", { cx: "12", cy: "12", r: "9" }),
5918
- /* @__PURE__ */ jsx13("path", { d: "M12 8v4m0 4h.01" })
6610
+ return /* @__PURE__ */ jsx15("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: /* @__PURE__ */ jsxs13("div", { role: "alert", className: "flex items-start gap-2.5 rounded-lg border border-destructive/40 bg-destructive/5 px-3 py-2.5 text-sm text-destructive", children: [
6611
+ /* @__PURE__ */ jsxs13("svg", { className: "mt-0.5 h-4 w-4 shrink-0", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
6612
+ /* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "9" }),
6613
+ /* @__PURE__ */ jsx15("path", { d: "M12 8v4m0 4h.01" })
5919
6614
  ] }),
5920
- /* @__PURE__ */ jsx13("span", { className: "min-w-0 flex-1 break-words", children: message }),
5921
- onRetry && /* @__PURE__ */ jsx13(
6615
+ /* @__PURE__ */ jsx15("span", { className: "min-w-0 flex-1 break-words", children: message }),
6616
+ onRetry && /* @__PURE__ */ jsx15(
5922
6617
  "button",
5923
6618
  {
5924
6619
  type: "button",
@@ -5953,32 +6648,32 @@ function ChatMessages({
5953
6648
  }) {
5954
6649
  const messageClassName = messageSize === "large" ? "agent-app-message-copy text-[17px] leading-[1.6]" : "agent-app-message-copy text-base leading-[1.6]";
5955
6650
  const renderBody = useMemo7(
5956
- () => renderMarkdown ?? ((content) => /* @__PURE__ */ jsx13("p", { className: "whitespace-pre-wrap", children: content })),
6651
+ () => renderMarkdown ?? ((content) => /* @__PURE__ */ jsx15("p", { className: "whitespace-pre-wrap", children: content })),
5957
6652
  [renderMarkdown]
5958
6653
  );
5959
6654
  const lastIsUser = messages[messages.length - 1]?.role === "user";
5960
6655
  const quiet = chrome === "quiet";
5961
6656
  if (messages.length === 0 && !loading && !error) {
5962
- const empty = renderEmpty ? renderEmpty() : /* @__PURE__ */ jsx13(ChatEmptyState, { ...emptyState });
5963
- return /* @__PURE__ */ jsxs11(Fragment7, { children: [
6657
+ const empty = renderEmpty ? renderEmpty() : /* @__PURE__ */ jsx15(ChatEmptyState, { ...emptyState });
6658
+ return /* @__PURE__ */ jsxs13(Fragment8, { children: [
5964
6659
  header,
5965
6660
  empty
5966
6661
  ] });
5967
6662
  }
5968
- return /* @__PURE__ */ jsxs11(Fragment7, { children: [
6663
+ return /* @__PURE__ */ jsxs13(Fragment8, { children: [
5969
6664
  header,
5970
6665
  messages.map(
5971
- (msg) => msg.role === "user" ? /* @__PURE__ */ jsxs11("div", { className: `mx-auto w-full max-w-3xl px-6 ${quiet ? "group pb-1 pt-3" : "py-3"}`, children: [
5972
- /* @__PURE__ */ jsxs11("div", { className: `ml-auto w-fit ${quiet ? "max-w-[72%]" : "max-w-[85%]"}`, children: [
5973
- !quiet && /* @__PURE__ */ jsx13("p", { className: "mb-1 text-right text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: userLabel }),
5974
- /* @__PURE__ */ jsx13(
6666
+ (msg) => msg.role === "user" ? /* @__PURE__ */ jsxs13("div", { className: `mx-auto w-full max-w-3xl px-6 ${quiet ? "group pb-1 pt-3" : "py-3"}`, children: [
6667
+ /* @__PURE__ */ jsxs13("div", { className: `ml-auto w-fit ${quiet ? "max-w-[72%]" : "max-w-[85%]"}`, children: [
6668
+ !quiet && /* @__PURE__ */ jsx15("p", { className: "mb-1 text-right text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: userLabel }),
6669
+ /* @__PURE__ */ jsx15(
5975
6670
  "div",
5976
6671
  {
5977
6672
  className: quiet ? `rounded-2xl bg-[color-mix(in_srgb,hsl(var(--secondary))_65%,hsl(var(--background)))] px-4 py-2.5 ${messageClassName}` : `rounded-2xl rounded-tr-md bg-primary/10 px-4 py-2.5 ${messageClassName}`,
5978
- children: /* @__PURE__ */ jsx13("p", { className: "whitespace-pre-wrap", children: msg.content })
6673
+ children: /* @__PURE__ */ jsx15("p", { className: "whitespace-pre-wrap", children: msg.content })
5979
6674
  }
5980
6675
  ),
5981
- resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx13("div", { className: "mt-1.5", children: /* @__PURE__ */ jsx13(
6676
+ resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx15("div", { className: "mt-1.5", children: /* @__PURE__ */ jsx15(
5982
6677
  MessageAttachments,
5983
6678
  {
5984
6679
  parts: attachmentPartsFromMessageParts(msg.parts),
@@ -5987,8 +6682,8 @@ function ChatMessages({
5987
6682
  }
5988
6683
  ) })
5989
6684
  ] }),
5990
- quiet && /* @__PURE__ */ jsx13("div", { "data-testid": "message-meta-lane", className: `${QUIET_META_LANE_CLASS} justify-end`, children: /* @__PURE__ */ jsx13(CopyMessageButton, { text: msg.content }) })
5991
- ] }, msg.id) : /* @__PURE__ */ jsx13(
6685
+ quiet && /* @__PURE__ */ jsx15("div", { "data-testid": "message-meta-lane", className: `${QUIET_META_LANE_CLASS} justify-end`, children: /* @__PURE__ */ jsx15(CopyMessageButton, { text: msg.content }) })
6686
+ ] }, msg.id) : /* @__PURE__ */ jsx15(
5992
6687
  AssistantMessage,
5993
6688
  {
5994
6689
  msg,
@@ -6009,8 +6704,8 @@ function ChatMessages({
6009
6704
  msg.id
6010
6705
  )
6011
6706
  ),
6012
- loading && lastIsUser && /* @__PURE__ */ jsx13(ThinkingRow, { agentLabel, chrome }),
6013
- error && !loading && /* @__PURE__ */ jsx13(StreamErrorRow, { message: error, onRetry })
6707
+ loading && lastIsUser && /* @__PURE__ */ jsx15(ThinkingRow, { agentLabel, chrome }),
6708
+ error && !loading && /* @__PURE__ */ jsx15(StreamErrorRow, { message: error, onRetry })
6014
6709
  ] });
6015
6710
  }
6016
6711
 
@@ -6119,6 +6814,26 @@ export {
6119
6814
  withoutRecordGridRemoved,
6120
6815
  pruneRecordGridOverlay,
6121
6816
  RecordGrid,
6817
+ DEFAULT_SPARKLINE_WIDTH,
6818
+ DEFAULT_SPARKLINE_HEIGHT,
6819
+ DEFAULT_SPARKLINE_LABEL,
6820
+ DEFAULT_SPARKLINE_EMPTY_LABEL,
6821
+ DEFAULT_SPARKLINE_UNAVAILABLE_LABEL,
6822
+ formatSparklineValue,
6823
+ sparklineReadings,
6824
+ sparklineGeometry,
6825
+ sparklinePointsAttribute,
6826
+ sparklineLabel,
6827
+ Sparkline,
6828
+ insightDelta,
6829
+ insightDeltaTone,
6830
+ formatInsightDelta,
6831
+ InsightCard,
6832
+ DEFAULT_INSIGHT_PAGE_SIZE,
6833
+ insightPageSize,
6834
+ insightPageCount,
6835
+ insightPageSlice,
6836
+ InsightDeck,
6122
6837
  formatModelCost,
6123
6838
  formatTokensPerSecond,
6124
6839
  RunDrillIn,
@@ -6128,4 +6843,4 @@ export {
6128
6843
  useThinkingSeconds,
6129
6844
  ChatMessages
6130
6845
  };
6131
- //# sourceMappingURL=chunk-ZAKKG6WI.js.map
6846
+ //# sourceMappingURL=chunk-CXPWUCXC.js.map