@invergent/agent-chat-react 2.1.3 → 2.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -882,7 +882,7 @@ var ConversationEmptyState = ({
882
882
  icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center size-14 rounded-2xl bg-muted/60 text-muted-foreground/60", children: icon }),
883
883
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
884
884
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-semibold text-base text-foreground/80", children: title }),
885
- description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground/60 text-sm max-w-sm", children: description })
885
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground/60 text-sm max-w-sm", children: description })
886
886
  ] })
887
887
  ] })
888
888
  }
@@ -1008,7 +1008,7 @@ var ShimmerComponent = ({
1008
1008
  return /* @__PURE__ */ jsxRuntime.jsx(
1009
1009
  Component,
1010
1010
  {
1011
- className: cn("shimmer text-muted-foreground", className),
1011
+ className: cn("shimmer text-foreground/70", className),
1012
1012
  style: {
1013
1013
  "--shimmer-duration": duration * 1e3,
1014
1014
  "--shimmer-spread": `${dynamicSpread}px`
@@ -1110,12 +1110,12 @@ var ReasoningTrigger = react.memo(
1110
1110
  CollapsibleTrigger,
1111
1111
  {
1112
1112
  className: cn(
1113
- "flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground",
1113
+ "flex w-full items-center gap-2 text-foreground/70 text-sm transition-colors hover:text-foreground",
1114
1114
  className
1115
1115
  ),
1116
1116
  ...props,
1117
1117
  children: children ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1118
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foregound text-sm", children: getThinkingMessage(isStreaming, duration) }),
1118
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foregound/70 text-sm", children: getThinkingMessage(isStreaming, duration) }),
1119
1119
  /* @__PURE__ */ jsxRuntime.jsx(
1120
1120
  lucideReact.ChevronDownIcon,
1121
1121
  {
@@ -1137,7 +1137,7 @@ var ReasoningContent = react.memo(
1137
1137
  {
1138
1138
  className: cn(
1139
1139
  "mt-4 text-sm",
1140
- "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-foreground/60 italic outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
1140
+ "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-foreground/70 italic outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
1141
1141
  className
1142
1142
  ),
1143
1143
  ...props,
@@ -6392,36 +6392,6 @@ function ChatComposerInner({
6392
6392
  }
6393
6393
  )
6394
6394
  ] }),
6395
- onViewModeChange && /* @__PURE__ */ jsxRuntime.jsxs(
6396
- "div",
6397
- {
6398
- role: "group",
6399
- "aria-label": "Chat view mode",
6400
- className: "inline-flex overflow-hidden rounded-md border border-border",
6401
- children: [
6402
- /* @__PURE__ */ jsxRuntime.jsx(
6403
- "button",
6404
- {
6405
- type: "button",
6406
- "aria-pressed": viewMode === "simple",
6407
- onClick: () => onViewModeChange("simple"),
6408
- className: viewMode === "simple" ? "bg-accent px-2 py-1 text-xs text-foreground" : "px-2 py-1 text-xs text-muted-foreground hover:text-foreground",
6409
- children: "Simple"
6410
- }
6411
- ),
6412
- /* @__PURE__ */ jsxRuntime.jsx(
6413
- "button",
6414
- {
6415
- type: "button",
6416
- "aria-pressed": viewMode === "expert",
6417
- onClick: () => onViewModeChange("expert"),
6418
- className: viewMode === "expert" ? "bg-accent px-2 py-1 text-xs text-foreground" : "px-2 py-1 text-xs text-muted-foreground hover:text-foreground",
6419
- children: "Expert"
6420
- }
6421
- )
6422
- ]
6423
- }
6424
- ),
6425
6395
  canShowBrowser && onToggleBrowser && /* @__PURE__ */ jsxRuntime.jsx(
6426
6396
  PromptInputButton,
6427
6397
  {
@@ -6501,7 +6471,46 @@ function ChatComposerInner({
6501
6471
  }
6502
6472
  )
6503
6473
  ] }),
6504
- /* @__PURE__ */ jsxRuntime.jsx(PromptInputSubmit, { status, onStop })
6474
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
6475
+ onViewModeChange && /* @__PURE__ */ jsxRuntime.jsxs(
6476
+ "div",
6477
+ {
6478
+ role: "group",
6479
+ "aria-label": "Chat view mode",
6480
+ className: "inline-flex overflow-hidden rounded-md border border-border",
6481
+ children: [
6482
+ /* @__PURE__ */ jsxRuntime.jsx(
6483
+ "button",
6484
+ {
6485
+ type: "button",
6486
+ "aria-pressed": viewMode === "simple",
6487
+ onClick: () => onViewModeChange("simple"),
6488
+ className: viewMode === "simple" ? "bg-accent px-2 py-1 text-xs text-foreground" : "px-2 py-1 text-xs text-muted-foreground hover:text-foreground",
6489
+ children: "Simple"
6490
+ }
6491
+ ),
6492
+ /* @__PURE__ */ jsxRuntime.jsx(
6493
+ "button",
6494
+ {
6495
+ type: "button",
6496
+ "aria-pressed": viewMode === "expert",
6497
+ onClick: () => onViewModeChange("expert"),
6498
+ className: viewMode === "expert" ? "bg-accent px-2 py-1 text-xs text-foreground" : "px-2 py-1 text-xs text-muted-foreground hover:text-foreground",
6499
+ children: "Advanced"
6500
+ }
6501
+ )
6502
+ ]
6503
+ }
6504
+ ),
6505
+ /* @__PURE__ */ jsxRuntime.jsx(
6506
+ PromptInputSubmit,
6507
+ {
6508
+ status,
6509
+ onStop,
6510
+ className: "md:size-8"
6511
+ }
6512
+ )
6513
+ ] })
6505
6514
  ] })
6506
6515
  ]
6507
6516
  }
@@ -6678,7 +6687,7 @@ function TurnFeedback({ msg }) {
6678
6687
  {
6679
6688
  type: "button",
6680
6689
  variant: "ghost",
6681
- size: "icon-xs",
6690
+ size: "icon-sm",
6682
6691
  "aria-label": "Good response",
6683
6692
  title: alreadyRated && rating === "up" ? "Good response (recorded)" : "Good response",
6684
6693
  disabled: pending !== null || alreadyRated,
@@ -6686,7 +6695,7 @@ function TurnFeedback({ msg }) {
6686
6695
  className: cn(
6687
6696
  rating === "up" ? "text-foreground" : "text-muted-foreground/60"
6688
6697
  ),
6689
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ThumbsUpIcon, { className: "size-3.5" })
6698
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ThumbsUpIcon, { className: "size-4.5" })
6690
6699
  }
6691
6700
  ),
6692
6701
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -6694,7 +6703,7 @@ function TurnFeedback({ msg }) {
6694
6703
  {
6695
6704
  type: "button",
6696
6705
  variant: "ghost",
6697
- size: "icon-xs",
6706
+ size: "icon-sm",
6698
6707
  "aria-label": "Poor response",
6699
6708
  title: alreadyRated && rating === "down" ? "Poor response (recorded)" : "Poor response",
6700
6709
  disabled: pending !== null || reasonDraft !== null || alreadyRated,
@@ -6702,7 +6711,7 @@ function TurnFeedback({ msg }) {
6702
6711
  className: cn(
6703
6712
  rating === "down" ? "text-foreground" : "text-muted-foreground/60"
6704
6713
  ),
6705
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ThumbsDownIcon, { className: "size-3.5" })
6714
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ThumbsDownIcon, { className: "size-4.5" })
6706
6715
  }
6707
6716
  ),
6708
6717
  alreadyRated && msg.userFeedback?.reason && /* @__PURE__ */ jsxRuntime.jsxs(
@@ -7472,7 +7481,8 @@ function FileViewer({
7472
7481
  error,
7473
7482
  downloadUrl,
7474
7483
  onDelete,
7475
- onClose
7484
+ onClose,
7485
+ hideHeader = false
7476
7486
  }) {
7477
7487
  const visible = loading || file !== null || error !== null;
7478
7488
  if (!visible) return null;
@@ -7482,7 +7492,7 @@ function FileViewer({
7482
7492
  const isImage = file?.encoding === "base64" && !isPdf;
7483
7493
  const HeaderIcon = isImage ? lucideReact.ImageIcon : lucideReact.FileTextIcon;
7484
7494
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 flex-col border-t border-line", children: [
7485
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-2 border-b border-line px-3 py-2", children: [
7495
+ !hideHeader && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-2 border-b border-line px-3 py-2", children: [
7486
7496
  /* @__PURE__ */ jsxRuntime.jsx(HeaderIcon, { className: "size-3.5 shrink-0 text-muted-foreground" }),
7487
7497
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
7488
7498
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate text-xs font-medium", children: fileName2 }),
@@ -7527,7 +7537,12 @@ function FileViewer({
7527
7537
  }
7528
7538
  )
7529
7539
  ] }),
7530
- /* @__PURE__ */ jsxRuntime.jsxs(ScrollArea, { className: "min-h-0 flex-1", children: [
7540
+ file && isPdf && file.encoding === "base64" ? (
7541
+ // PDF has its own scrollable container — bypass ScrollArea so
7542
+ // it can grow with the parent's flex height (Radix Viewport's
7543
+ // internal table wrapper sizes to content and breaks h-full).
7544
+ /* @__PURE__ */ jsxRuntime.jsx(PdfPreview, { file, fileName: fileName2 })
7545
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(ScrollArea, { className: "min-h-0 flex-1", children: [
7531
7546
  loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5 p-3", children: Array.from({ length: 10 }).map((_, index) => /* @__PURE__ */ jsxRuntime.jsx(
7532
7547
  Skeleton,
7533
7548
  {
@@ -7543,7 +7558,6 @@ function FileViewer({
7543
7558
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: error })
7544
7559
  ] }),
7545
7560
  file && isPdf && file.encoding !== "base64" && /* @__PURE__ */ jsxRuntime.jsx(FileViewerError, { message: "PDF preview requires base64 file content." }),
7546
- file && isPdf && file.encoding === "base64" && /* @__PURE__ */ jsxRuntime.jsx(PdfPreview, { file, fileName: fileName2 }),
7547
7561
  file && isImage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center p-4", children: /* @__PURE__ */ jsxRuntime.jsx(
7548
7562
  "img",
7549
7563
  {
@@ -7807,7 +7821,7 @@ function PdfPreview({
7807
7821
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircleIcon, { className: "mt-0.5 size-3.5 shrink-0" }),
7808
7822
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: error })
7809
7823
  ] }),
7810
- !error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-[70vh] min-h-[420px] flex-1 bg-muted/20", children: /* @__PURE__ */ jsxRuntime.jsx(
7824
+ !error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative min-h-105 flex-1 bg-muted/20", children: /* @__PURE__ */ jsxRuntime.jsx(
7811
7825
  "div",
7812
7826
  {
7813
7827
  ref: containerRef,
@@ -8008,8 +8022,23 @@ function WorkspaceFilePreviewDialog({
8008
8022
  cancelled = true;
8009
8023
  };
8010
8024
  }, [adapter, sessionId, path, open]);
8011
- return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "flex h-[80vh] w-full max-w-3xl flex-col gap-0 overflow-hidden p-0", children: [
8012
- /* @__PURE__ */ jsxRuntime.jsx(DialogHeader, { className: "border-b border-line px-4 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "truncate text-sm", children: _basename(path) }) }),
8025
+ return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "flex h-[85vh] w-[95vw] max-w-350! flex-col gap-0 overflow-hidden p-0", children: [
8026
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { className: "flex flex-row items-center gap-2 border-b border-line px-4 py-3", children: [
8027
+ /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "min-w-0 flex-1 truncate text-sm", children: _basename(path) }),
8028
+ /* @__PURE__ */ jsxRuntime.jsxs(
8029
+ "a",
8030
+ {
8031
+ href: downloadUrl,
8032
+ download: _basename(path),
8033
+ className: "mr-8 inline-flex shrink-0 items-center gap-1.5 rounded-md border border-border bg-background px-2.5 py-1 text-xs font-medium text-foreground transition-colors hover:bg-muted",
8034
+ "aria-label": `Download ${_basename(path)}`,
8035
+ children: [
8036
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.DownloadIcon, { className: "size-3.5", "aria-hidden": true }),
8037
+ "Download"
8038
+ ]
8039
+ }
8040
+ )
8041
+ ] }),
8013
8042
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: /* @__PURE__ */ jsxRuntime.jsx(
8014
8043
  FileViewer,
8015
8044
  {
@@ -8018,7 +8047,8 @@ function WorkspaceFilePreviewDialog({
8018
8047
  error,
8019
8048
  downloadUrl,
8020
8049
  onDelete: null,
8021
- onClose: () => onOpenChange(false)
8050
+ onClose: () => onOpenChange(false),
8051
+ hideHeader: true
8022
8052
  }
8023
8053
  ) })
8024
8054
  ] }) });
@@ -8045,7 +8075,8 @@ function TurnSummaryCard({
8045
8075
  const hasRecap = summary.recap.trim().length > 0;
8046
8076
  const hasArtifacts = summary.artifacts.length > 0;
8047
8077
  if (!hasRecap && !hasArtifacts) return null;
8048
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 rounded border border-border bg-muted/20 px-3 py-2 text-sm", children: [
8078
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 rounded border border-border bg-muted/50 px-3 py-2 text-sm", children: [
8079
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 text-xs font-semibold uppercase tracking-wide", children: "Summary" }),
8049
8080
  hasRecap && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 whitespace-pre-wrap text-foreground", children: summary.recap }),
8050
8081
  hasArtifacts && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: summary.artifacts.map((artifact, i) => {
8051
8082
  const key = `${artifact.kind}:${artifact.ref}:${i}`;
@@ -8835,7 +8866,7 @@ function IterationGroup({
8835
8866
  type: "button",
8836
8867
  onClick: () => setOpen((prev) => !prev),
8837
8868
  "aria-expanded": open,
8838
- className: "flex w-full items-center gap-2 rounded px-1 py-0.5 text-left text-sm hover:bg-muted/40",
8869
+ className: "flex w-full items-center gap-2 rounded py-0.5 text-left text-sm hover:bg-muted/40",
8839
8870
  children: [
8840
8871
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex-1 truncate", labelTone), children: label }),
8841
8872
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -8863,6 +8894,18 @@ function IterationGroup({
8863
8894
  ] });
8864
8895
  }
8865
8896
  function deriveFileArtifactsFromMessages(messages) {
8897
+ const terminalCommands = [];
8898
+ for (const msg of messages) {
8899
+ if (msg.role !== "assistant" || !msg.toolCalls) continue;
8900
+ for (const tc of msg.toolCalls) {
8901
+ if (tc.toolName !== "terminal") continue;
8902
+ const status = effectiveStatus(tc);
8903
+ if (status === "error" || status === "cancelled") continue;
8904
+ const args = parseArgs(tc.args);
8905
+ const cmd = typeof args?.command === "string" ? args.command : "";
8906
+ if (cmd) terminalCommands.push(cmd);
8907
+ }
8908
+ }
8866
8909
  const seen = /* @__PURE__ */ new Set();
8867
8910
  const out = [];
8868
8911
  for (const msg of messages) {
@@ -8875,6 +8918,8 @@ function deriveFileArtifactsFromMessages(messages) {
8875
8918
  if (tc.toolName === "write_file" || tc.toolName === "patch") {
8876
8919
  const path = typeof args.path === "string" ? args.path : typeof args.file_path === "string" ? args.file_path : "";
8877
8920
  if (!path || seen.has(`file:${path}`)) continue;
8921
+ const executed = terminalCommands.some((cmd) => cmd.includes(path));
8922
+ if (executed) continue;
8878
8923
  seen.add(`file:${path}`);
8879
8924
  out.push({
8880
8925
  kind: "file",
@@ -8915,11 +8960,13 @@ function SimpleAssistantGroup({
8915
8960
  const isTailGroup = lastGlobalIndex === totalMessages - 1;
8916
8961
  const showThinkingShim = isTailGroup && isRunning && (!tail && messages.some((m) => m.role !== "assistant") || tailIsTextOnly && tail.status === "streaming" && !tail.content);
8917
8962
  const showErrorInfo = !!tail && tail.status === "error" && !!tail.errorInfo;
8963
+ const turnComplete = !isRunning && tail?.status === "complete";
8918
8964
  const effectiveTurnSummary = (() => {
8919
8965
  const fromHarness = tail?.turnSummary;
8920
8966
  if (fromHarness && fromHarness.artifacts.length > 0) {
8921
8967
  return fromHarness;
8922
8968
  }
8969
+ if (!turnComplete) return fromHarness;
8923
8970
  const derived = deriveFileArtifactsFromMessages(messages);
8924
8971
  if (derived.length === 0) return fromHarness;
8925
8972
  return {
@@ -9419,6 +9466,27 @@ function findEntry(entries, path) {
9419
9466
  }
9420
9467
  return null;
9421
9468
  }
9469
+ var FILENAME_MAX_CHARS = 42;
9470
+ function truncateFilename(name, max) {
9471
+ if (name.length <= max) return name;
9472
+ const dot = name.lastIndexOf(".");
9473
+ if (dot > 0 && name.length - dot <= 12) {
9474
+ const ext = name.slice(dot);
9475
+ const head = name.slice(0, Math.max(1, max - ext.length - 1));
9476
+ return `${head}\u2026${ext}`;
9477
+ }
9478
+ return `${name.slice(0, max - 1)}\u2026`;
9479
+ }
9480
+ function TruncatedFileName({ name }) {
9481
+ const truncated = truncateFilename(name, FILENAME_MAX_CHARS);
9482
+ const isTruncated = truncated !== name;
9483
+ const node = /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: truncated });
9484
+ if (!isTruncated) return node;
9485
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
9486
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: node }),
9487
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", className: "max-w-md break-all", children: name })
9488
+ ] });
9489
+ }
9422
9490
  function RenderEntries({
9423
9491
  entries,
9424
9492
  onDelete,
@@ -9438,7 +9506,7 @@ function RenderEntries({
9438
9506
  const fileName2 = entry.name;
9439
9507
  return /* @__PURE__ */ jsxRuntime.jsxs(FileTreeFile, { name: entry.name, path: entry.path, children: [
9440
9508
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-4 shrink-0" }),
9441
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: entry.name }),
9509
+ /* @__PURE__ */ jsxRuntime.jsx(TruncatedFileName, { name: entry.name }),
9442
9510
  entry.size != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 shrink-0 text-xs text-muted-foreground/60", children: formatFileSize(entry.size) }),
9443
9511
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-1 flex shrink-0 items-center gap-0 opacity-100 transition-opacity md:opacity-0 md:group-hover:opacity-100", children: [
9444
9512
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -9482,7 +9550,6 @@ function WorkspacePanel({
9482
9550
  }) {
9483
9551
  const fileInputRef = react.useRef(null);
9484
9552
  const [entries, setEntries] = react.useState([]);
9485
- const [rootName, setRootName] = react.useState("workspace");
9486
9553
  const [treeLoading, setTreeLoading] = react.useState(false);
9487
9554
  const [treeError, setTreeError] = react.useState(null);
9488
9555
  const [file, setFile] = react.useState(null);
@@ -9501,7 +9568,6 @@ function WorkspacePanel({
9501
9568
  const fetchTree = react.useCallback(async () => {
9502
9569
  if (!sessionId) {
9503
9570
  setEntries([]);
9504
- setRootName("workspace");
9505
9571
  setExpandedPaths(/* @__PURE__ */ new Set());
9506
9572
  setTreeLoading(false);
9507
9573
  setTreeError(null);
@@ -9516,12 +9582,10 @@ function WorkspacePanel({
9516
9582
  });
9517
9583
  if (sessionIdRef.current !== requestedSessionId) return;
9518
9584
  setEntries(tree.entries);
9519
- setRootName(tree.root || "workspace");
9520
9585
  setExpandedPaths(new Set(collectExpandedPaths(tree.entries)));
9521
9586
  } catch (error) {
9522
9587
  if (sessionIdRef.current !== requestedSessionId) return;
9523
9588
  setEntries([]);
9524
- setRootName("workspace");
9525
9589
  setTreeError(error.message);
9526
9590
  } finally {
9527
9591
  if (sessionIdRef.current === requestedSessionId) {
@@ -9711,10 +9775,7 @@ function WorkspacePanel({
9711
9775
  ),
9712
9776
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-14 items-center gap-2 border-b border-line px-3 py-3", children: [
9713
9777
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FolderOpenIcon, { className: "size-4 shrink-0 text-amber-500" }),
9714
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
9715
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate text-sm font-medium text-foreground", children: rootName }),
9716
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate text-xs text-faint", children: disabled ? "Workspace - Read-only" : "Workspace" })
9717
- ] }),
9778
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate text-sm font-medium text-foreground", children: disabled ? "Workspace - Read-only" : "Workspace" }) }),
9718
9779
  /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
9719
9780
  /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
9720
9781
  Button,
@@ -10834,6 +10895,7 @@ function readTurnMeta(data) {
10834
10895
 
10835
10896
  // src/runtime/use-agent-chat-runtime.ts
10836
10897
  var VIEW_MODE_KEY = "@invergent/agent-chat-react:viewMode";
10898
+ var VIEW_MODE_EVENT = "@invergent/agent-chat-react:viewMode:change";
10837
10899
  function readPersistedViewMode() {
10838
10900
  if (typeof window === "undefined") return null;
10839
10901
  try {
@@ -10849,6 +10911,36 @@ function writePersistedViewMode(mode) {
10849
10911
  window.localStorage.setItem(VIEW_MODE_KEY, mode);
10850
10912
  } catch {
10851
10913
  }
10914
+ try {
10915
+ window.dispatchEvent(
10916
+ new CustomEvent(VIEW_MODE_EVENT, { detail: mode })
10917
+ );
10918
+ } catch {
10919
+ }
10920
+ }
10921
+ function useChatViewMode() {
10922
+ const [mode, setMode] = react.useState(
10923
+ () => readPersistedViewMode() ?? "simple"
10924
+ );
10925
+ react.useEffect(() => {
10926
+ if (typeof window === "undefined") return;
10927
+ const onSameTab = (event) => {
10928
+ const detail = event.detail;
10929
+ if (detail === "simple" || detail === "expert") setMode(detail);
10930
+ };
10931
+ const onCrossTab = (event) => {
10932
+ if (event.key !== VIEW_MODE_KEY) return;
10933
+ const next = event.newValue;
10934
+ if (next === "simple" || next === "expert") setMode(next);
10935
+ };
10936
+ window.addEventListener(VIEW_MODE_EVENT, onSameTab);
10937
+ window.addEventListener("storage", onCrossTab);
10938
+ return () => {
10939
+ window.removeEventListener(VIEW_MODE_EVENT, onSameTab);
10940
+ window.removeEventListener("storage", onCrossTab);
10941
+ };
10942
+ }, []);
10943
+ return mode;
10852
10944
  }
10853
10945
  function useAgentChatRuntime({
10854
10946
  adapter,
@@ -13639,7 +13731,6 @@ function TreeNodeRow({
13639
13731
  const title = entry.title ?? fallbackSessionTitle(entry);
13640
13732
  const subtitle = [
13641
13733
  formatRunKind(entry.runKind),
13642
- entry.model,
13643
13734
  formatSessionTime(entry.updatedAt)
13644
13735
  ].filter(Boolean).join(" \xB7 ");
13645
13736
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -13655,7 +13746,7 @@ function TreeNodeRow({
13655
13746
  className: cn(
13656
13747
  "group flex items-center gap-2 w-full py-2 pr-2 text-left cursor-pointer transition-colors border-l-2",
13657
13748
  "min-h-11 md:min-h-0",
13658
- isActive ? "bg-line text-foreground border-l-primary" : "bg-transparent text-muted-foreground hover:bg-input hover:text-foreground border-l-transparent"
13749
+ isActive ? "bg-line text-foreground border-l-primary" : "bg-transparent text-foreground/80 hover:bg-input hover:text-foreground border-l-transparent"
13659
13750
  ),
13660
13751
  style: { paddingLeft: `${depth * 12 + 12}px` },
13661
13752
  children: [
@@ -13906,6 +13997,7 @@ exports.isTerminalMissionStatus = isTerminalMissionStatus;
13906
13997
  exports.missionTaskBucket = missionTaskBucket;
13907
13998
  exports.useAgentChatAdapterContext = useAgentChatAdapterContext;
13908
13999
  exports.useAgentChatRuntime = useAgentChatRuntime;
14000
+ exports.useChatViewMode = useChatViewMode;
13909
14001
  exports.useInboxUnreadCount = useInboxUnreadCount;
13910
14002
  //# sourceMappingURL=index.cjs.map
13911
14003
  //# sourceMappingURL=index.cjs.map