@invergent/agent-chat-react 1.10.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -209,11 +209,23 @@ interface AgentChatMissionTask {
209
209
  createdAt: string | null;
210
210
  completedAt: string | null;
211
211
  }
212
+ type AgentChatMissionWorkerKind = "task" | "worker" | "delegation";
212
213
  interface AgentChatMissionWorker {
213
- taskId: string;
214
+ /**
215
+ * Which delegation primitive produced this child:
216
+ *
217
+ * - "task" — `spawn_task` (durable Task row, retried by dispatcher)
218
+ * - "worker" — `spawn_worker` (async one-shot, durable session)
219
+ * - "delegation" — `delegate_task` (sync fork-join, ephemeral session)
220
+ *
221
+ * `taskId` / `taskStatus` are non-null only for `kind === "task"` —
222
+ * the other two primitives don't create Task rows.
223
+ */
224
+ kind: AgentChatMissionWorkerKind;
225
+ taskId: string | null;
214
226
  workerSessionId: string;
215
227
  agentDefName: string | null;
216
- taskStatus: string;
228
+ taskStatus: string | null;
217
229
  sessionStatus: string;
218
230
  latestEventId: number | null;
219
231
  latestEventKind: string | null;
package/dist/index.d.ts CHANGED
@@ -209,11 +209,23 @@ interface AgentChatMissionTask {
209
209
  createdAt: string | null;
210
210
  completedAt: string | null;
211
211
  }
212
+ type AgentChatMissionWorkerKind = "task" | "worker" | "delegation";
212
213
  interface AgentChatMissionWorker {
213
- taskId: string;
214
+ /**
215
+ * Which delegation primitive produced this child:
216
+ *
217
+ * - "task" — `spawn_task` (durable Task row, retried by dispatcher)
218
+ * - "worker" — `spawn_worker` (async one-shot, durable session)
219
+ * - "delegation" — `delegate_task` (sync fork-join, ephemeral session)
220
+ *
221
+ * `taskId` / `taskStatus` are non-null only for `kind === "task"` —
222
+ * the other two primitives don't create Task rows.
223
+ */
224
+ kind: AgentChatMissionWorkerKind;
225
+ taskId: string | null;
214
226
  workerSessionId: string;
215
227
  agentDefName: string | null;
216
- taskStatus: string;
228
+ taskStatus: string | null;
217
229
  sessionStatus: string;
218
230
  latestEventId: number | null;
219
231
  latestEventKind: string | null;
package/dist/index.js CHANGED
@@ -44,13 +44,13 @@ var buttonVariants = cva(
44
44
  link: "text-primary underline underline-offset-4 hover:underline"
45
45
  },
46
46
  size: {
47
- default: "h-10 gap-1.5 px-6 has-data-[icon=inline-end]:pr-4 has-data-[icon=inline-start]:pl-4",
47
+ default: "h-11 md:h-10 gap-1.5 px-6 has-data-[icon=inline-end]:pr-4 has-data-[icon=inline-start]:pl-4",
48
48
  xs: "h-7 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3",
49
- sm: "h-9 gap-1 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
49
+ sm: "h-11 md:h-9 gap-1 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
50
50
  lg: "h-11 gap-1.5 px-8 has-data-[icon=inline-end]:pr-5 has-data-[icon=inline-start]:pl-5",
51
- icon: "size-10",
51
+ icon: "size-11 md:size-10",
52
52
  "icon-xs": "size-7 [&_svg:not([class*='size-'])]:size-3",
53
- "icon-sm": "size-9",
53
+ "icon-sm": "size-11 md:size-9",
54
54
  "icon-lg": "size-11"
55
55
  }
56
56
  },
@@ -483,7 +483,7 @@ function BrowserPane({ sessionId, state, adapter }) {
483
483
  DialogContent,
484
484
  {
485
485
  "aria-describedby": void 0,
486
- className: "flex h-screen w-screen max-w-none flex-col gap-0 overflow-hidden rounded-none border-0 bg-background p-0 shadow-none ring-0 sm:max-w-none",
486
+ className: "flex h-dvh w-screen max-w-none flex-col gap-0 overflow-hidden rounded-none border-0 bg-background p-0 shadow-none ring-0 sm:max-w-none",
487
487
  children: [
488
488
  /* @__PURE__ */ jsxs(DialogHeader, { className: "h-10 shrink-0 flex-row items-center gap-2 border-b border-line bg-card px-4 py-0", children: [
489
489
  /* @__PURE__ */ jsx(ZapIcon, { className: "size-3.5 text-muted-foreground", "aria-hidden": "true" }),
@@ -3478,7 +3478,7 @@ function Input({ className, type, ...props }) {
3478
3478
  type,
3479
3479
  "data-slot": "input",
3480
3480
  className: cn(
3481
- "h-10 w-full min-w-0 border border-transparent border-b-input bg-transparent px-0 py-1 text-base transition-[color,border-color] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-b-ring disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-b-destructive md:text-sm dark:aria-invalid:border-b-destructive/50",
3481
+ "h-11 md:h-10 w-full min-w-0 border border-transparent border-b-input bg-transparent px-0 py-1 text-base transition-[color,border-color] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-b-ring disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-b-destructive md:text-sm dark:aria-invalid:border-b-destructive/50",
3482
3482
  className
3483
3483
  ),
3484
3484
  ...props
@@ -4308,7 +4308,7 @@ function InputGroup({ className, ...props }) {
4308
4308
  "data-slot": "input-group",
4309
4309
  role: "group",
4310
4310
  className: cn(
4311
- "group/input-group relative flex h-10 w-full min-w-0 items-center rounded-none border border-transparent border-b-input bg-transparent transition-[color,border-color] outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-data-[align=block-end]:rounded-none has-data-[align=block-start]:rounded-none has-[[data-slot=input-group-control]:focus-visible]:border-b-ring has-[[data-slot][aria-invalid=true]]:border-b-destructive has-[textarea]:rounded-none has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:has-[[data-slot][aria-invalid=true]]:border-b-destructive/50 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3",
4311
+ "group/input-group relative flex h-11 md:h-10 w-full min-w-0 items-center rounded-none border border-transparent border-b-input bg-transparent transition-[color,border-color] outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-data-[align=block-end]:rounded-none has-data-[align=block-start]:rounded-none has-[[data-slot=input-group-control]:focus-visible]:border-b-ring has-[[data-slot][aria-invalid=true]]:border-b-destructive has-[textarea]:rounded-none has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:has-[[data-slot][aria-invalid=true]]:border-b-destructive/50 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3",
4312
4312
  className
4313
4313
  ),
4314
4314
  ...props
@@ -7322,7 +7322,7 @@ function ChatThread({
7322
7322
  ] }) }),
7323
7323
  /* @__PURE__ */ jsx(ConversationScrollButton, {})
7324
7324
  ] }),
7325
- /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-4xl px-6 pb-5 pt-3", children: [
7325
+ /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-4xl px-3 sm:px-6 pb-3 sm:pb-5 pt-3", children: [
7326
7326
  retryIndicator && /* @__PURE__ */ jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsx(RetryBanner, { indicator: retryIndicator }) }),
7327
7327
  disabled && disabledReason ? /* @__PURE__ */ jsx(
7328
7328
  "div",
@@ -7978,7 +7978,7 @@ function RenderEntries({
7978
7978
  /* @__PURE__ */ jsx("span", { className: "size-4 shrink-0" }),
7979
7979
  /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: entry.name }),
7980
7980
  entry.size != null && /* @__PURE__ */ jsx("span", { className: "ml-1 shrink-0 text-xs text-muted-foreground/60", children: formatFileSize(entry.size) }),
7981
- /* @__PURE__ */ jsxs("div", { className: "ml-1 flex shrink-0 items-center gap-0 opacity-0 transition-opacity group-hover:opacity-100", children: [
7981
+ /* @__PURE__ */ 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: [
7982
7982
  /* @__PURE__ */ jsx(
7983
7983
  "a",
7984
7984
  {
@@ -9503,6 +9503,9 @@ function parseGoalDefinition(content) {
9503
9503
  const rubric = match ? args.slice(match.index + match[0].length).trim() : "";
9504
9504
  return rubric ? { description, rubric } : { description };
9505
9505
  }
9506
+ var RIGHT_STACK_STYLE = {
9507
+ ["--right-stack-w"]: "440px"
9508
+ };
9506
9509
  function AgentChat({
9507
9510
  adapter,
9508
9511
  agentId,
@@ -9514,6 +9517,7 @@ function AgentChat({
9514
9517
  onComposerError
9515
9518
  }) {
9516
9519
  const [workspacePath, setWorkspacePath] = useState(null);
9520
+ const [mobileView, setMobileView] = useState("chat");
9517
9521
  const runtime = useAgentChatRuntime({
9518
9522
  adapter,
9519
9523
  agentId,
@@ -9531,10 +9535,12 @@ function AgentChat({
9531
9535
  const handleFileSelect = useCallback(
9532
9536
  (path) => {
9533
9537
  setWorkspacePath(path);
9538
+ setMobileView("workspace");
9534
9539
  onFileSelect?.(path);
9535
9540
  },
9536
9541
  [onFileSelect]
9537
9542
  );
9543
+ const showMobileToggle = Boolean(sessionId);
9538
9544
  return /* @__PURE__ */ jsx(
9539
9545
  AgentChatAdapterProvider,
9540
9546
  {
@@ -9547,15 +9553,56 @@ function AgentChat({
9547
9553
  "section",
9548
9554
  {
9549
9555
  "data-testid": "agent-chat-layout",
9550
- className: hasBrowserPanel ? "relative min-h-0 flex-1 overflow-hidden bg-background text-sm text-foreground" : "flex min-h-0 flex-1 overflow-hidden bg-background text-sm text-foreground",
9551
- style: { direction: "ltr" },
9556
+ "data-mobile-view": mobileView,
9557
+ className: cn(
9558
+ // Phone: flex column, tab toggle on top, then either chat or
9559
+ // right stack visible based on `data-mobile-view`.
9560
+ "flex min-h-0 flex-1 flex-col overflow-hidden bg-background text-sm text-foreground",
9561
+ // md+: restore desktop two-pane layout.
9562
+ hasBrowserPanel ? "md:relative md:flex-row" : "md:flex-row"
9563
+ ),
9564
+ style: { direction: "ltr", ...RIGHT_STACK_STYLE },
9552
9565
  children: [
9566
+ showMobileToggle && /* @__PURE__ */ jsxs("div", { className: "md:hidden flex shrink-0 border-b border-line bg-card", children: [
9567
+ /* @__PURE__ */ jsx(
9568
+ "button",
9569
+ {
9570
+ type: "button",
9571
+ onClick: () => setMobileView("chat"),
9572
+ "aria-pressed": mobileView === "chat",
9573
+ className: cn(
9574
+ "flex-1 px-4 py-3 text-sm font-medium border-b-2 -mb-px transition-colors",
9575
+ mobileView === "chat" ? "border-primary text-foreground" : "border-transparent text-subtle hover:text-foreground"
9576
+ ),
9577
+ children: "Chat"
9578
+ }
9579
+ ),
9580
+ /* @__PURE__ */ jsx(
9581
+ "button",
9582
+ {
9583
+ type: "button",
9584
+ onClick: () => setMobileView("workspace"),
9585
+ "aria-pressed": mobileView === "workspace",
9586
+ className: cn(
9587
+ "flex-1 px-4 py-3 text-sm font-medium border-b-2 -mb-px transition-colors",
9588
+ mobileView === "workspace" ? "border-primary text-foreground" : "border-transparent text-subtle hover:text-foreground"
9589
+ ),
9590
+ children: "Workspace"
9591
+ }
9592
+ )
9593
+ ] }),
9553
9594
  /* @__PURE__ */ jsx(
9554
9595
  "div",
9555
9596
  {
9556
9597
  "data-testid": "chat-panel",
9557
- className: hasBrowserPanel ? "absolute inset-y-0 left-0 flex min-h-0 min-w-0 flex-col overflow-hidden" : "flex min-w-0 flex-1 flex-col overflow-hidden",
9558
- style: hasBrowserPanel ? { right: 440 } : void 0,
9598
+ "data-mobile-view": mobileView,
9599
+ className: cn(
9600
+ // Phone: full width column, hidden when workspace tab active.
9601
+ "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden",
9602
+ showMobileToggle && "data-[mobile-view=workspace]:hidden md:flex!",
9603
+ // md+: restore desktop positioning.
9604
+ hasBrowserPanel ? "md:absolute md:inset-y-0 md:left-0 md:right-(--right-stack-w,440px) md:flex" : "md:relative md:flex-1"
9605
+ ),
9559
9606
  children: /* @__PURE__ */ jsx(
9560
9607
  ChatThread,
9561
9608
  {
@@ -9580,8 +9627,16 @@ function AgentChat({
9580
9627
  "div",
9581
9628
  {
9582
9629
  "data-testid": "right-stack",
9583
- className: hasBrowserPanel ? "absolute inset-y-0 flex min-h-0 flex-col overflow-hidden" : "flex min-h-0 shrink-0 flex-col",
9584
- style: hasBrowserPanel ? { right: 0, width: 440 } : void 0,
9630
+ "data-mobile-view": mobileView,
9631
+ className: cn(
9632
+ // Phone: full width column, hidden when chat tab active.
9633
+ "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden",
9634
+ showMobileToggle && "data-[mobile-view=chat]:hidden md:flex!",
9635
+ // md+: restore desktop positioning. With browser panel the
9636
+ // right stack is absolutely positioned at the configured
9637
+ // width; without it the stack flows in the row.
9638
+ hasBrowserPanel ? "md:absolute md:inset-y-0 md:right-0 md:w-(--right-stack-w,440px) md:flex-none" : "md:relative md:shrink-0 md:flex-none md:w-(--right-stack-w,440px)"
9639
+ ),
9585
9640
  children: [
9586
9641
  hasBrowserPanel && /* @__PURE__ */ jsx(
9587
9642
  "div",
@@ -10415,6 +10470,16 @@ function truncate2(s, max) {
10415
10470
  return `${s.slice(0, max - 1)}\u2026`;
10416
10471
  }
10417
10472
  var DEFAULT_POLL_INTERVAL_MS = 5e3;
10473
+ var MISSION_WORKER_KIND_BADGE_CLASS = {
10474
+ task: "border-primary/40 bg-primary/10 text-primary uppercase tracking-wide text-[10px]",
10475
+ worker: "border-foreground/30 bg-foreground/5 text-foreground/80 uppercase tracking-wide text-[10px]",
10476
+ delegation: "border-foreground/20 bg-foreground/[0.03] text-foreground/60 uppercase tracking-wide text-[10px]"
10477
+ };
10478
+ var MISSION_WORKER_KIND_TOOLTIP = {
10479
+ task: "Durable Task row created by spawn_task. Retried by the dispatcher; survives across coordinator wakes.",
10480
+ worker: "Async one-shot session spawned by spawn_worker. Durable session, no retry/DAG.",
10481
+ delegation: "Sync fork-join child spawned by delegate_task. Coordinator's wake blocked until it finished."
10482
+ };
10418
10483
  var INITIAL_STATE = {
10419
10484
  mission: null,
10420
10485
  tasks: [],
@@ -10501,7 +10566,11 @@ function MissionDashboard({
10501
10566
  [state.tasks]
10502
10567
  );
10503
10568
  const runningWorkerCount = useMemo(
10504
- () => state.workers.filter((w) => w.taskStatus === "running").length,
10569
+ // "running" means the child is still consuming compute right now.
10570
+ // For task-backed children that's ``taskStatus === "running"``; for
10571
+ // spawn_worker / delegate_task direct children the Task row doesn't
10572
+ // exist, so fall back to the session-level signal.
10573
+ () => state.workers.filter((w) => w.kind === "task" ? w.taskStatus === "running" : w.sessionStatus === "active").length,
10505
10574
  [state.workers]
10506
10575
  );
10507
10576
  if (state.loading && !state.mission) {
@@ -10564,16 +10633,16 @@ function MissionDashboard({
10564
10633
  }
10565
10634
  };
10566
10635
  const statusVariant = mission.status === "satisfied" ? "default" : mission.status === "failed" || mission.status === "cancelled" ? "destructive" : "secondary";
10567
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6 p-6 max-w-6xl mx-auto", children: [
10636
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 p-4 sm:gap-6 sm:p-6", children: [
10568
10637
  /* @__PURE__ */ jsxs(Card, { children: [
10569
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
10570
- /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
10638
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-stretch gap-4 sm:flex-row sm:items-start sm:justify-between", children: [
10639
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1 min-w-0 flex-1", children: [
10571
10640
  /* @__PURE__ */ jsx(CardTitle, { className: "wrap-break-word -uppercase text-sm", children: mission.description }),
10572
10641
  /* @__PURE__ */ jsxs(CardDescription, { className: "wrap-break-word text-foreground/70", children: [
10573
10642
  "Rubric: ",
10574
10643
  mission.rubric
10575
10644
  ] }),
10576
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 pt-2 text-xs text-foreground/70", children: [
10645
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 pt-2 text-xs text-foreground/70", children: [
10577
10646
  /* @__PURE__ */ jsx(Badge, { variant: statusVariant, className: "font-mono text-foreground", children: mission.status }),
10578
10647
  /* @__PURE__ */ jsxs("span", { className: "font-mono text-primary", children: [
10579
10648
  "Iteration ",
@@ -10588,7 +10657,7 @@ function MissionDashboard({
10588
10657
  ] }) : null
10589
10658
  ] })
10590
10659
  ] }),
10591
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: ACTIVE_MISSION_STATUSES.has(mission.status) ? /* @__PURE__ */ jsxs(Fragment, { children: [
10660
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2 shrink-0", children: ACTIVE_MISSION_STATUSES.has(mission.status) ? /* @__PURE__ */ jsxs(Fragment, { children: [
10592
10661
  mission.status === "active" ? /* @__PURE__ */ jsxs(
10593
10662
  Button,
10594
10663
  {
@@ -10708,11 +10777,20 @@ function MissionDashboard({
10708
10777
  return /* @__PURE__ */ jsxs(
10709
10778
  "li",
10710
10779
  {
10711
- className: "flex items-start justify-between gap-3 rounded border border-border/40 px-3 py-2 text-sm",
10780
+ className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between rounded border border-border/40 px-3 py-2 text-sm",
10712
10781
  children: [
10713
10782
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
10714
10783
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10715
- /* @__PURE__ */ jsx(Badge, { className: "text-foreground/70", children: w.taskStatus }),
10784
+ /* @__PURE__ */ jsx(
10785
+ Badge,
10786
+ {
10787
+ variant: "outline",
10788
+ className: MISSION_WORKER_KIND_BADGE_CLASS[w.kind],
10789
+ title: MISSION_WORKER_KIND_TOOLTIP[w.kind],
10790
+ children: w.kind
10791
+ }
10792
+ ),
10793
+ /* @__PURE__ */ jsx(Badge, { className: "text-foreground/70", children: w.kind === "task" ? w.taskStatus ?? "\u2014" : w.sessionStatus }),
10716
10794
  w.agentDefName ? /* @__PURE__ */ jsx("span", { className: "text-xs text-foreground/70", children: w.agentDefName }) : null
10717
10795
  ] }),
10718
10796
  /* @__PURE__ */ jsx("div", { className: "text-sm wrap-break-word", children: deriveMissionWorkerActivityLabel(w) }),
@@ -10866,7 +10944,8 @@ function MissionRow({
10866
10944
  "div",
10867
10945
  {
10868
10946
  className: cn(
10869
- "group flex min-w-0 items-start gap-2 border-l-2 border-l-transparent px-3 py-2 text-sm transition-colors cursor-pointer hover:border-l-primary hover:bg-input"
10947
+ "group flex min-w-0 items-start gap-2 border-l-2 border-l-transparent px-3 py-2 text-sm transition-colors cursor-pointer hover:border-l-primary hover:bg-input",
10948
+ "min-h-11 md:min-h-0"
10870
10949
  ),
10871
10950
  onClick: openMission,
10872
10951
  onKeyDown: handleRowKeyDown,
@@ -10893,7 +10972,7 @@ function MissionRow({
10893
10972
  "button",
10894
10973
  {
10895
10974
  type: "button",
10896
- className: "rounded p-1 text-faint opacity-70 transition-all hover:bg-line hover:text-foreground disabled:pointer-events-none disabled:opacity-40 group-hover:opacity-100",
10975
+ className: "rounded p-2 md:p-1 text-faint opacity-100 md:opacity-70 transition-all hover:bg-line hover:text-foreground disabled:pointer-events-none disabled:opacity-40 md:group-hover:opacity-100",
10897
10976
  onClick: (e) => {
10898
10977
  stopActionClick(e);
10899
10978
  onPause(mission.id);
@@ -10908,7 +10987,7 @@ function MissionRow({
10908
10987
  "button",
10909
10988
  {
10910
10989
  type: "button",
10911
- className: "rounded p-1 text-faint opacity-70 transition-all hover:bg-line hover:text-foreground disabled:pointer-events-none disabled:opacity-40 group-hover:opacity-100",
10990
+ className: "rounded p-2 md:p-1 text-faint opacity-100 md:opacity-70 transition-all hover:bg-line hover:text-foreground disabled:pointer-events-none disabled:opacity-40 md:group-hover:opacity-100",
10912
10991
  onClick: (e) => {
10913
10992
  stopActionClick(e);
10914
10993
  onResume(mission.id);
@@ -10923,7 +11002,7 @@ function MissionRow({
10923
11002
  "button",
10924
11003
  {
10925
11004
  type: "button",
10926
- className: "rounded p-1 text-faint opacity-70 transition-all hover:bg-destructive/10 hover:text-destructive disabled:pointer-events-none disabled:opacity-40 group-hover:opacity-100",
11005
+ className: "rounded p-2 md:p-1 text-faint opacity-100 md:opacity-70 transition-all hover:bg-destructive/10 hover:text-destructive disabled:pointer-events-none disabled:opacity-40 md:group-hover:opacity-100",
10927
11006
  onClick: (e) => {
10928
11007
  stopActionClick(e);
10929
11008
  onCancel(mission.id);
@@ -11200,6 +11279,7 @@ function ScheduledWorkRow({
11200
11279
  {
11201
11280
  className: cn(
11202
11281
  "group flex min-w-0 items-start gap-2 border-l-2 border-l-transparent px-3 py-2 text-sm transition-colors hover:border-l-primary hover:bg-input",
11282
+ "min-h-11 md:min-h-0",
11203
11283
  lastSessionId && "cursor-pointer"
11204
11284
  ),
11205
11285
  onClick: openLastRun,
@@ -11226,7 +11306,7 @@ function ScheduledWorkRow({
11226
11306
  "button",
11227
11307
  {
11228
11308
  type: "button",
11229
- className: "rounded p-1 text-faint opacity-70 transition-all hover:bg-line hover:text-foreground disabled:pointer-events-none disabled:opacity-40 group-hover:opacity-100",
11309
+ className: "rounded p-2 md:p-1 text-faint opacity-100 md:opacity-70 transition-all hover:bg-line hover:text-foreground disabled:pointer-events-none disabled:opacity-40 md:group-hover:opacity-100",
11230
11310
  onClick: (e) => {
11231
11311
  stopActionClick(e);
11232
11312
  onRunNow(item.id);
@@ -11241,7 +11321,7 @@ function ScheduledWorkRow({
11241
11321
  "button",
11242
11322
  {
11243
11323
  type: "button",
11244
- className: "rounded p-1 text-faint opacity-70 transition-all hover:bg-destructive/10 hover:text-destructive disabled:pointer-events-none disabled:opacity-40 group-hover:opacity-100",
11324
+ className: "rounded p-2 md:p-1 text-faint opacity-100 md:opacity-70 transition-all hover:bg-destructive/10 hover:text-destructive disabled:pointer-events-none disabled:opacity-40 md:group-hover:opacity-100",
11245
11325
  onClick: (e) => {
11246
11326
  stopActionClick(e);
11247
11327
  onCancel(item.id);
@@ -11547,6 +11627,7 @@ function TreeNodeRow({
11547
11627
  },
11548
11628
  className: cn(
11549
11629
  "group flex items-center gap-2 w-full py-2 pr-2 text-left cursor-pointer transition-colors border-l-2",
11630
+ "min-h-11 md:min-h-0",
11550
11631
  isActive ? "bg-line text-foreground border-l-primary" : "bg-transparent text-subtle hover:bg-input hover:text-foreground border-l-transparent"
11551
11632
  ),
11552
11633
  style: { paddingLeft: `${depth * 12 + 12}px` },
@@ -11555,7 +11636,7 @@ function TreeNodeRow({
11555
11636
  "button",
11556
11637
  {
11557
11638
  type: "button",
11558
- className: "p-0.5 rounded hover:bg-line shrink-0",
11639
+ className: "p-2 md:p-0.5 rounded hover:bg-line shrink-0",
11559
11640
  onClick: (e) => {
11560
11641
  e.stopPropagation();
11561
11642
  setExpanded(!expanded);
@@ -11573,7 +11654,7 @@ function TreeNodeRow({
11573
11654
  "button",
11574
11655
  {
11575
11656
  type: "button",
11576
- className: "p-1 rounded opacity-0 group-hover:opacity-100 hover:bg-destructive/10 hover:text-destructive transition-all",
11657
+ className: "p-2 md:p-1 rounded opacity-100 md:opacity-0 md:group-hover:opacity-100 hover:bg-destructive/10 hover:text-destructive transition-all",
11577
11658
  onClick: (e) => {
11578
11659
  e.stopPropagation();
11579
11660
  onStop(entry.id);
@@ -11588,8 +11669,8 @@ function TreeNodeRow({
11588
11669
  {
11589
11670
  type: "button",
11590
11671
  className: cn(
11591
- "p-1 rounded hover:bg-destructive/10 hover:text-destructive disabled:pointer-events-none transition-all",
11592
- deletingSessionId === entry.id ? "opacity-100" : "opacity-0 group-hover:opacity-100 focus-visible:opacity-100"
11672
+ "p-2 md:p-1 rounded hover:bg-destructive/10 hover:text-destructive disabled:pointer-events-none transition-all",
11673
+ deletingSessionId === entry.id ? "opacity-100" : "opacity-100 md:opacity-0 md:group-hover:opacity-100 md:focus-visible:opacity-100"
11593
11674
  ),
11594
11675
  onClick: (e) => {
11595
11676
  e.stopPropagation();