@invergent/agent-chat-react 2.8.0 → 2.8.2

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.d.cts CHANGED
@@ -1265,6 +1265,10 @@ declare function ScheduledWorkPanel({ adapter, agentId, title, limit, status, hi
1265
1265
  interface SessionTreePanelProps {
1266
1266
  adapter: AgentChatAdapter;
1267
1267
  sessionId?: string | null;
1268
+ /**
1269
+ * ID of the currently highlighted session. Defaults to `sessionId`.
1270
+ * Pass `""` (empty string) to clear the active highlight when `sessionId` is set.
1271
+ */
1268
1272
  activeSessionId?: string;
1269
1273
  agentId?: string;
1270
1274
  title?: string;
package/dist/index.d.ts CHANGED
@@ -1265,6 +1265,10 @@ declare function ScheduledWorkPanel({ adapter, agentId, title, limit, status, hi
1265
1265
  interface SessionTreePanelProps {
1266
1266
  adapter: AgentChatAdapter;
1267
1267
  sessionId?: string | null;
1268
+ /**
1269
+ * ID of the currently highlighted session. Defaults to `sessionId`.
1270
+ * Pass `""` (empty string) to clear the active highlight when `sessionId` is set.
1271
+ */
1268
1272
  activeSessionId?: string;
1269
1273
  agentId?: string;
1270
1274
  title?: string;
package/dist/index.js CHANGED
@@ -4852,25 +4852,6 @@ function Command({
4852
4852
  }
4853
4853
  );
4854
4854
  }
4855
- function CommandInput({
4856
- className,
4857
- ...props
4858
- }) {
4859
- return /* @__PURE__ */ jsx("div", { "data-slot": "command-input-wrapper", className: "p-3", children: /* @__PURE__ */ jsxs(InputGroup, { className: "rounded-lg border-transparent bg-muted px-3", children: [
4860
- /* @__PURE__ */ jsx(
4861
- Command$1.Input,
4862
- {
4863
- "data-slot": "command-input",
4864
- className: cn(
4865
- "w-full px-2 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
4866
- className
4867
- ),
4868
- ...props
4869
- }
4870
- ),
4871
- /* @__PURE__ */ jsx(InputGroupAddon, { children: /* @__PURE__ */ jsx(SearchIcon, { className: "size-3.5 shrink-0 opacity-50" }) })
4872
- ] }) });
4873
- }
4874
4855
  function CommandList({
4875
4856
  className,
4876
4857
  ...props
@@ -6072,6 +6053,168 @@ function Skeleton({ className, ...props }) {
6072
6053
  }
6073
6054
  );
6074
6055
  }
6056
+ var SEARCH_PLACEHOLDER = {
6057
+ commands: "Search commands\u2026",
6058
+ skills: "Search skills\u2026",
6059
+ scheduled: "Search scheduled tasks\u2026",
6060
+ all: "Type a command or search\u2026"
6061
+ };
6062
+ var NAV_HINT = "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc dismiss";
6063
+ var SEARCH_HINT = {
6064
+ commands: NAV_HINT,
6065
+ skills: "Esc dismiss",
6066
+ scheduled: NAV_HINT,
6067
+ all: NAV_HINT
6068
+ };
6069
+ var ROW_CLASS = "grid grid-cols-[120px_1fr] items-baseline gap-3 rounded-md px-3 py-[9px] data-[selected=true]:bg-foreground/[0.06] [&_svg]:hidden";
6070
+ function ComposerCommandMenu({
6071
+ menuMode,
6072
+ searchQuery,
6073
+ onSearchChange,
6074
+ skillsLoading,
6075
+ builtinCommands,
6076
+ adapterCommands,
6077
+ scheduledExamples,
6078
+ onCommandSelect,
6079
+ onEscapeDismiss
6080
+ }) {
6081
+ const controlledSearch = menuMode === "commands" || menuMode === "all";
6082
+ const showCommands = menuMode === "commands" || menuMode === "all";
6083
+ const showSkills = menuMode === "skills" || menuMode === "all";
6084
+ const skillsUnattached = menuMode === "skills" && !skillsLoading && adapterCommands.length === 0;
6085
+ return /* @__PURE__ */ jsx(
6086
+ PopoverContent,
6087
+ {
6088
+ side: "top",
6089
+ align: "start",
6090
+ className: "overflow-hidden rounded-xl p-0",
6091
+ style: { width: "var(--radix-popover-trigger-width)" },
6092
+ onCloseAutoFocus: (e) => e.preventDefault(),
6093
+ onEscapeKeyDown: () => {
6094
+ onEscapeDismiss();
6095
+ },
6096
+ children: /* @__PURE__ */ jsxs(Command, { children: [
6097
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 px-4 py-[13px]", children: [
6098
+ /* @__PURE__ */ jsx(SearchIcon, { className: "size-3.5 shrink-0 text-muted-foreground" }),
6099
+ /* @__PURE__ */ jsx(
6100
+ Command$1.Input,
6101
+ {
6102
+ "data-slot": "command-input",
6103
+ placeholder: SEARCH_PLACEHOLDER[menuMode],
6104
+ className: "min-w-0 flex-1 bg-transparent text-[13.5px] text-foreground outline-hidden placeholder:text-muted-foreground",
6105
+ ...controlledSearch ? { value: searchQuery, onValueChange: onSearchChange } : {}
6106
+ }
6107
+ ),
6108
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 whitespace-nowrap text-[11px] text-muted-foreground", children: SEARCH_HINT[menuMode] })
6109
+ ] }),
6110
+ /* @__PURE__ */ jsx("div", { className: "h-px w-full bg-foreground/[0.07]" }),
6111
+ skillsUnattached ? /* @__PURE__ */ jsx(SkillsEmptyState, {}) : /* @__PURE__ */ jsxs(CommandList, { className: "p-2", children: [
6112
+ !(skillsLoading && showSkills) && /* @__PURE__ */ jsx(CommandEmpty, { className: "px-3 py-8 text-center text-sm text-muted-foreground", children: menuMode === "skills" ? "No skills match your search." : menuMode === "scheduled" ? "No scheduled tasks found." : "No commands found." }),
6113
+ showSkills && skillsLoading && adapterCommands.length === 0 && [0, 1, 2].map((i) => /* @__PURE__ */ jsxs(
6114
+ "div",
6115
+ {
6116
+ className: "grid grid-cols-[120px_1fr] items-baseline gap-3 px-3 py-[9px]",
6117
+ "aria-hidden": "true",
6118
+ children: [
6119
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-20" }),
6120
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-full max-w-[16rem]" })
6121
+ ]
6122
+ },
6123
+ `skill-skeleton-${i}`
6124
+ )),
6125
+ menuMode === "scheduled" && scheduledExamples.map((cmd) => /* @__PURE__ */ jsx(
6126
+ MenuRow,
6127
+ {
6128
+ cmd,
6129
+ onSelect: onCommandSelect
6130
+ },
6131
+ cmd.value
6132
+ )),
6133
+ showCommands && builtinCommands.map((cmd) => /* @__PURE__ */ jsx(
6134
+ MenuRow,
6135
+ {
6136
+ cmd,
6137
+ onSelect: onCommandSelect
6138
+ },
6139
+ cmd.value
6140
+ )),
6141
+ showSkills && adapterCommands.map((cmd) => /* @__PURE__ */ jsx(
6142
+ MenuRow,
6143
+ {
6144
+ cmd,
6145
+ keywords: cmd.isExpert ? [cmd.description, "expert"] : void 0,
6146
+ badge: cmd.isExpert ? "expert" : void 0,
6147
+ onSelect: onCommandSelect
6148
+ },
6149
+ cmd.value
6150
+ ))
6151
+ ] })
6152
+ ] })
6153
+ }
6154
+ );
6155
+ }
6156
+ function MenuRow({
6157
+ cmd,
6158
+ keywords,
6159
+ badge,
6160
+ onSelect
6161
+ }) {
6162
+ return /* @__PURE__ */ jsxs(
6163
+ CommandItem,
6164
+ {
6165
+ value: cmd.value,
6166
+ keywords: keywords ?? [cmd.description],
6167
+ onSelect: () => onSelect(cmd.value),
6168
+ className: ROW_CLASS,
6169
+ children: [
6170
+ /* @__PURE__ */ jsxs(
6171
+ "span",
6172
+ {
6173
+ className: "inline-flex min-w-0 max-w-full items-center gap-1.5",
6174
+ title: cmd.label,
6175
+ children: [
6176
+ /* @__PURE__ */ jsx("span", { className: "truncate font-mono text-[13px] font-medium text-amber-500", children: cmd.label }),
6177
+ badge && /* @__PURE__ */ jsx(
6178
+ "span",
6179
+ {
6180
+ className: "shrink-0 rounded-sm bg-amber-500/10 px-1 text-[9px] font-semibold uppercase tracking-wider text-amber-500",
6181
+ "aria-label": "Expert specialist",
6182
+ children: badge
6183
+ }
6184
+ )
6185
+ ]
6186
+ }
6187
+ ),
6188
+ /* @__PURE__ */ jsx(
6189
+ "span",
6190
+ {
6191
+ className: "min-w-0 truncate text-[12.5px] text-muted-foreground",
6192
+ title: cmd.description,
6193
+ children: cmd.description
6194
+ }
6195
+ )
6196
+ ]
6197
+ }
6198
+ );
6199
+ }
6200
+ function SkillsEmptyState() {
6201
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2.5 px-6 py-[30px] text-center", children: [
6202
+ /* @__PURE__ */ jsx(
6203
+ "span",
6204
+ {
6205
+ className: "text-2xl leading-none text-muted-foreground/70",
6206
+ "aria-hidden": "true",
6207
+ children: "\u2726"
6208
+ }
6209
+ ),
6210
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: "No skills attached" }),
6211
+ /* @__PURE__ */ jsxs("p", { className: "text-[12.5px] text-muted-foreground", children: [
6212
+ "Add them in",
6213
+ " ",
6214
+ /* @__PURE__ */ jsx("span", { className: "text-amber-500", children: "Configure \u2192 Skills & Tools" })
6215
+ ] })
6216
+ ] });
6217
+ }
6075
6218
  function ChatComposer(props) {
6076
6219
  return /* @__PURE__ */ jsx(PromptInputProvider, { children: /* @__PURE__ */ jsx(ChatComposerInner, { ...props }) });
6077
6220
  }
@@ -6102,6 +6245,26 @@ function formatBytes2(n) {
6102
6245
  }
6103
6246
  return `${n} B`;
6104
6247
  }
6248
+ function ComposerMenuButton({
6249
+ icon: Icon,
6250
+ label,
6251
+ onClick
6252
+ }) {
6253
+ return /* @__PURE__ */ jsxs(
6254
+ Button,
6255
+ {
6256
+ type: "button",
6257
+ variant: "secondary",
6258
+ size: "sm",
6259
+ className: "rounded-sm -uppercase font-display bg-white dark:bg-accent border-2 border-accent cursor-pointer",
6260
+ onClick,
6261
+ children: [
6262
+ /* @__PURE__ */ jsx(Icon, {}),
6263
+ label
6264
+ ]
6265
+ }
6266
+ );
6267
+ }
6105
6268
  function AttachmentPreviewStrip() {
6106
6269
  const attachments = useProviderAttachments();
6107
6270
  if (attachments.files.length === 0) return null;
@@ -6306,6 +6469,11 @@ function ChatComposerInner({
6306
6469
  textarea.setSelectionRange(end, end);
6307
6470
  });
6308
6471
  }, []);
6472
+ const openMenu = useCallback((mode) => {
6473
+ setMenuMode(mode);
6474
+ setMenuDismissed(false);
6475
+ setButtonMenuOpen(true);
6476
+ }, []);
6309
6477
  const handleCommandSelect = useCallback(
6310
6478
  (commandValue) => {
6311
6479
  textInput.setInput(`${commandValue} `);
@@ -6397,58 +6565,28 @@ function ChatComposerInner({
6397
6565
  children: [
6398
6566
  /* @__PURE__ */ jsx(AttachmentPreviewStrip, {}),
6399
6567
  viewMode === "expert" && !disabled && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2 px-1 pb-2", children: [
6400
- /* @__PURE__ */ jsxs(
6401
- Button,
6568
+ /* @__PURE__ */ jsx(
6569
+ ComposerMenuButton,
6402
6570
  {
6403
- type: "button",
6404
- variant: "secondary",
6405
- size: "sm",
6406
- className: "rounded-sm -uppercase font-display bg-white dark:bg-accent border-2 border-accent cursor-pointer",
6407
- onClick: () => {
6408
- setMenuMode("commands");
6409
- setMenuDismissed(false);
6410
- setButtonMenuOpen(true);
6411
- },
6412
- children: [
6413
- /* @__PURE__ */ jsx(TerminalIcon, {}),
6414
- "Commands"
6415
- ]
6571
+ icon: TerminalIcon,
6572
+ label: "Commands",
6573
+ onClick: () => openMenu("commands")
6416
6574
  }
6417
6575
  ),
6418
- /* @__PURE__ */ jsxs(
6419
- Button,
6576
+ /* @__PURE__ */ jsx(
6577
+ ComposerMenuButton,
6420
6578
  {
6421
- type: "button",
6422
- variant: "secondary",
6423
- size: "sm",
6424
- className: "rounded-sm -uppercase font-display bg-white dark:bg-accent border-2 border-accent cursor-pointer",
6425
- onClick: () => {
6426
- setMenuMode("skills");
6427
- setMenuDismissed(false);
6428
- setButtonMenuOpen(true);
6429
- },
6430
- children: [
6431
- /* @__PURE__ */ jsx(SparklesIcon, {}),
6432
- "Skills"
6433
- ]
6579
+ icon: SparklesIcon,
6580
+ label: "Skills",
6581
+ onClick: () => openMenu("skills")
6434
6582
  }
6435
6583
  ),
6436
- loopsEnabled && /* @__PURE__ */ jsxs(
6437
- Button,
6584
+ loopsEnabled && /* @__PURE__ */ jsx(
6585
+ ComposerMenuButton,
6438
6586
  {
6439
- type: "button",
6440
- variant: "secondary",
6441
- size: "sm",
6442
- className: "rounded-sm -uppercase font-display bg-white dark:bg-accent border-2 border-accent cursor-pointer",
6443
- onClick: () => {
6444
- setMenuMode("scheduled");
6445
- setMenuDismissed(false);
6446
- setButtonMenuOpen(true);
6447
- },
6448
- children: [
6449
- /* @__PURE__ */ jsx(ClockIcon, {}),
6450
- "Scheduled Tasks"
6451
- ]
6587
+ icon: ClockIcon,
6588
+ label: "Scheduled Tasks",
6589
+ onClick: () => openMenu("scheduled")
6452
6590
  }
6453
6591
  )
6454
6592
  ] }),
@@ -6645,135 +6783,17 @@ function ChatComposerInner({
6645
6783
  }
6646
6784
  ) }),
6647
6785
  /* @__PURE__ */ jsx(
6648
- PopoverContent,
6786
+ ComposerCommandMenu,
6649
6787
  {
6650
- side: "top",
6651
- align: "start",
6652
- className: "overflow-hidden rounded-xl p-0",
6653
- style: { width: "var(--radix-popover-trigger-width)" },
6654
- onCloseAutoFocus: (e) => e.preventDefault(),
6655
- onEscapeKeyDown: () => {
6656
- focusTextareaAtEnd();
6657
- },
6658
- children: /* @__PURE__ */ jsxs(Command, { children: [
6659
- menuMode === "skills" ? /* @__PURE__ */ jsx(CommandInput, { placeholder: "Search skills..." }) : menuMode === "scheduled" ? /* @__PURE__ */ jsx(CommandInput, { placeholder: "Search scheduled tasks..." }) : /* @__PURE__ */ jsx(
6660
- CommandInput,
6661
- {
6662
- placeholder: "Type a command or search...",
6663
- value: searchQuery,
6664
- onValueChange: handleSearchChange
6665
- }
6666
- ),
6667
- /* @__PURE__ */ jsxs(CommandList, { children: [
6668
- !(skillsLoading && (menuMode === "skills" || menuMode === "all")) && /* @__PURE__ */ jsx(CommandEmpty, { children: menuMode === "skills" ? "No skills found." : menuMode === "scheduled" ? "No scheduled tasks found." : "No commands found." }),
6669
- (menuMode === "skills" || menuMode === "all") && skillsLoading && adapterCommands.length === 0 && [0, 1, 2].map((i) => /* @__PURE__ */ jsxs(
6670
- "div",
6671
- {
6672
- className: "grid grid-cols-[12rem_1fr] items-baseline gap-3 px-2 py-2",
6673
- "aria-hidden": "true",
6674
- children: [
6675
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-28" }),
6676
- /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-full max-w-[16rem]" })
6677
- ]
6678
- },
6679
- `skill-skeleton-${i}`
6680
- )),
6681
- menuMode === "scheduled" && scheduledExamples.map((cmd) => /* @__PURE__ */ jsxs(
6682
- CommandItem,
6683
- {
6684
- value: cmd.value,
6685
- keywords: [cmd.description],
6686
- onSelect: () => handleCommandSelect(cmd.value),
6687
- className: "grid grid-cols-[14rem_1fr] items-baseline gap-3 [&_svg]:hidden",
6688
- children: [
6689
- /* @__PURE__ */ jsx(
6690
- "span",
6691
- {
6692
- className: "font-mono font-semibold text-foreground truncate",
6693
- title: cmd.label,
6694
- children: cmd.label
6695
- }
6696
- ),
6697
- /* @__PURE__ */ jsx(
6698
- "span",
6699
- {
6700
- className: "min-w-0 truncate text-sm text-muted-foreground",
6701
- title: cmd.description,
6702
- children: cmd.description
6703
- }
6704
- )
6705
- ]
6706
- },
6707
- cmd.value
6708
- )),
6709
- (menuMode === "commands" || menuMode === "all") && builtinCommands.map((cmd) => /* @__PURE__ */ jsxs(
6710
- CommandItem,
6711
- {
6712
- value: cmd.value,
6713
- keywords: [cmd.description],
6714
- onSelect: () => handleCommandSelect(cmd.value),
6715
- className: "grid grid-cols-[12rem_1fr] items-baseline gap-3 [&_svg]:hidden",
6716
- children: [
6717
- /* @__PURE__ */ jsx(
6718
- "span",
6719
- {
6720
- className: "font-mono font-semibold text-foreground truncate",
6721
- title: cmd.label,
6722
- children: cmd.label
6723
- }
6724
- ),
6725
- /* @__PURE__ */ jsx(
6726
- "span",
6727
- {
6728
- className: "min-w-0 truncate text-sm text-muted-foreground",
6729
- title: cmd.description,
6730
- children: cmd.description
6731
- }
6732
- )
6733
- ]
6734
- },
6735
- cmd.value
6736
- )),
6737
- (menuMode === "skills" || menuMode === "all") && adapterCommands.map((cmd) => /* @__PURE__ */ jsxs(
6738
- CommandItem,
6739
- {
6740
- value: cmd.value,
6741
- keywords: cmd.isExpert ? [cmd.description, "expert"] : [cmd.description],
6742
- onSelect: () => handleCommandSelect(cmd.value),
6743
- className: "grid grid-cols-[12rem_1fr] items-baseline gap-3 [&_svg]:hidden",
6744
- children: [
6745
- /* @__PURE__ */ jsxs(
6746
- "span",
6747
- {
6748
- className: "inline-flex items-center gap-1.5 min-w-0 max-w-full",
6749
- title: cmd.label,
6750
- children: [
6751
- /* @__PURE__ */ jsx("span", { className: "font-mono font-semibold text-foreground truncate", children: cmd.label }),
6752
- cmd.isExpert && /* @__PURE__ */ jsx(
6753
- "span",
6754
- {
6755
- className: "shrink-0 rounded-sm bg-primary/10 px-1 text-[9px] font-semibold uppercase tracking-wider text-primary",
6756
- "aria-label": "Expert specialist",
6757
- children: "expert"
6758
- }
6759
- )
6760
- ]
6761
- }
6762
- ),
6763
- /* @__PURE__ */ jsx(
6764
- "span",
6765
- {
6766
- className: "min-w-0 truncate text-sm text-muted-foreground",
6767
- title: cmd.description,
6768
- children: cmd.description
6769
- }
6770
- )
6771
- ]
6772
- },
6773
- cmd.value
6774
- ))
6775
- ] })
6776
- ] })
6788
+ menuMode,
6789
+ searchQuery,
6790
+ onSearchChange: handleSearchChange,
6791
+ skillsLoading,
6792
+ builtinCommands,
6793
+ adapterCommands,
6794
+ scheduledExamples,
6795
+ onCommandSelect: handleCommandSelect,
6796
+ onEscapeDismiss: focusTextareaAtEnd
6777
6797
  }
6778
6798
  )
6779
6799
  ]
@@ -16082,10 +16102,20 @@ function fallbackSessionTitle(entry) {
16082
16102
  if (entry.runKind === "scheduled") return "Scheduled run";
16083
16103
  return "New session";
16084
16104
  }
16105
+ function rowStateClass(isActive, isInActiveGroup) {
16106
+ if (isActive) {
16107
+ return "bg-faint/30 dark:bg-[#1e2840] text-foreground border-l-primary";
16108
+ }
16109
+ if (isInActiveGroup) {
16110
+ return "bg-line/70 dark:bg-line/60 text-foreground/80 hover:bg-input hover:text-foreground border-l-transparent";
16111
+ }
16112
+ return "bg-transparent text-foreground/80 hover:bg-input hover:text-foreground border-l-transparent";
16113
+ }
16085
16114
  function TreeNodeRow({
16086
16115
  entry,
16087
16116
  depth,
16088
16117
  activeSessionId,
16118
+ activeGroupRootId,
16089
16119
  canStop,
16090
16120
  canDelete,
16091
16121
  onSelect,
@@ -16097,11 +16127,15 @@ function TreeNodeRow({
16097
16127
  const isActive = entry.id === activeSessionId;
16098
16128
  const isRunning = entry.status === "active";
16099
16129
  const isChildSession = entry.parentId != null;
16130
+ const isInActiveGroup = activeGroupRootId !== null && (entry.id === activeGroupRootId || entry.parentId === activeGroupRootId);
16100
16131
  const title = entry.title ?? fallbackSessionTitle(entry);
16101
16132
  const subtitle = [
16102
16133
  formatRunKind(entry.runKind),
16103
16134
  formatSessionTime(entry.updatedAt)
16104
16135
  ].filter(Boolean).join(" \xB7 ");
16136
+ useEffect(() => {
16137
+ if (hasChildren) setExpanded(isInActiveGroup);
16138
+ }, [isInActiveGroup, hasChildren]);
16105
16139
  return /* @__PURE__ */ jsxs(Fragment, { children: [
16106
16140
  /* @__PURE__ */ jsxs(
16107
16141
  "div",
@@ -16115,7 +16149,7 @@ function TreeNodeRow({
16115
16149
  className: cn(
16116
16150
  "group flex items-center gap-2 w-full py-2 pr-2 text-left cursor-pointer transition-colors border-l-2",
16117
16151
  "min-h-11 md:min-h-0",
16118
- isActive ? "bg-line text-foreground border-l-primary" : "bg-transparent text-foreground/80 hover:bg-input hover:text-foreground border-l-transparent"
16152
+ rowStateClass(isActive, isInActiveGroup)
16119
16153
  ),
16120
16154
  style: { paddingLeft: `${depth * 12 + 12}px` },
16121
16155
  children: [
@@ -16174,6 +16208,7 @@ function TreeNodeRow({
16174
16208
  entry: child,
16175
16209
  depth: depth + 1,
16176
16210
  activeSessionId,
16211
+ activeGroupRootId,
16177
16212
  canStop,
16178
16213
  canDelete,
16179
16214
  onSelect,
@@ -16290,6 +16325,21 @@ function SessionTreePanel({
16290
16325
  return () => clearInterval(id);
16291
16326
  }, [refetch, runningCount]);
16292
16327
  const roots = useMemo(() => buildTree(nodes), [nodes]);
16328
+ const activeGroupRootId = useMemo(() => {
16329
+ if (!activeSessionId) return null;
16330
+ const parentOf = /* @__PURE__ */ new Map();
16331
+ for (const n of nodes) parentOf.set(n.id, n.parentId ?? null);
16332
+ const visited = /* @__PURE__ */ new Set();
16333
+ let current = activeSessionId;
16334
+ let parent = parentOf.get(current);
16335
+ while (parent != null) {
16336
+ if (visited.has(parent)) break;
16337
+ visited.add(current);
16338
+ current = parent;
16339
+ parent = parentOf.get(current);
16340
+ }
16341
+ return parentOf.has(current) ? current : null;
16342
+ }, [activeSessionId, nodes]);
16293
16343
  const handleSelect = useCallback(
16294
16344
  (id) => {
16295
16345
  onSessionSelect?.(id);
@@ -16353,6 +16403,7 @@ function SessionTreePanel({
16353
16403
  entry,
16354
16404
  depth: 0,
16355
16405
  activeSessionId: activeSessionId ?? "",
16406
+ activeGroupRootId,
16356
16407
  canStop: Boolean(adapter.stopSession),
16357
16408
  canDelete: Boolean(adapter.deleteSession),
16358
16409
  onSelect: handleSelect,