@invergent/agent-chat-react 1.10.0 → 2.0.0

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.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",
@@ -10564,16 +10619,16 @@ function MissionDashboard({
10564
10619
  }
10565
10620
  };
10566
10621
  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: [
10622
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 p-4 sm:gap-6 sm:p-6 max-w-6xl mx-auto", children: [
10568
10623
  /* @__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: [
10624
+ /* @__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: [
10625
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1 min-w-0 flex-1", children: [
10571
10626
  /* @__PURE__ */ jsx(CardTitle, { className: "wrap-break-word -uppercase text-sm", children: mission.description }),
10572
10627
  /* @__PURE__ */ jsxs(CardDescription, { className: "wrap-break-word text-foreground/70", children: [
10573
10628
  "Rubric: ",
10574
10629
  mission.rubric
10575
10630
  ] }),
10576
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 pt-2 text-xs text-foreground/70", children: [
10631
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 pt-2 text-xs text-foreground/70", children: [
10577
10632
  /* @__PURE__ */ jsx(Badge, { variant: statusVariant, className: "font-mono text-foreground", children: mission.status }),
10578
10633
  /* @__PURE__ */ jsxs("span", { className: "font-mono text-primary", children: [
10579
10634
  "Iteration ",
@@ -10588,7 +10643,7 @@ function MissionDashboard({
10588
10643
  ] }) : null
10589
10644
  ] })
10590
10645
  ] }),
10591
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: ACTIVE_MISSION_STATUSES.has(mission.status) ? /* @__PURE__ */ jsxs(Fragment, { children: [
10646
+ /* @__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
10647
  mission.status === "active" ? /* @__PURE__ */ jsxs(
10593
10648
  Button,
10594
10649
  {
@@ -10708,7 +10763,7 @@ function MissionDashboard({
10708
10763
  return /* @__PURE__ */ jsxs(
10709
10764
  "li",
10710
10765
  {
10711
- className: "flex items-start justify-between gap-3 rounded border border-border/40 px-3 py-2 text-sm",
10766
+ 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
10767
  children: [
10713
10768
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
10714
10769
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
@@ -10866,7 +10921,8 @@ function MissionRow({
10866
10921
  "div",
10867
10922
  {
10868
10923
  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"
10924
+ "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",
10925
+ "min-h-11 md:min-h-0"
10870
10926
  ),
10871
10927
  onClick: openMission,
10872
10928
  onKeyDown: handleRowKeyDown,
@@ -10893,7 +10949,7 @@ function MissionRow({
10893
10949
  "button",
10894
10950
  {
10895
10951
  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",
10952
+ 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
10953
  onClick: (e) => {
10898
10954
  stopActionClick(e);
10899
10955
  onPause(mission.id);
@@ -10908,7 +10964,7 @@ function MissionRow({
10908
10964
  "button",
10909
10965
  {
10910
10966
  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",
10967
+ 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
10968
  onClick: (e) => {
10913
10969
  stopActionClick(e);
10914
10970
  onResume(mission.id);
@@ -10923,7 +10979,7 @@ function MissionRow({
10923
10979
  "button",
10924
10980
  {
10925
10981
  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",
10982
+ 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
10983
  onClick: (e) => {
10928
10984
  stopActionClick(e);
10929
10985
  onCancel(mission.id);
@@ -11200,6 +11256,7 @@ function ScheduledWorkRow({
11200
11256
  {
11201
11257
  className: cn(
11202
11258
  "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",
11259
+ "min-h-11 md:min-h-0",
11203
11260
  lastSessionId && "cursor-pointer"
11204
11261
  ),
11205
11262
  onClick: openLastRun,
@@ -11226,7 +11283,7 @@ function ScheduledWorkRow({
11226
11283
  "button",
11227
11284
  {
11228
11285
  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",
11286
+ 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
11287
  onClick: (e) => {
11231
11288
  stopActionClick(e);
11232
11289
  onRunNow(item.id);
@@ -11241,7 +11298,7 @@ function ScheduledWorkRow({
11241
11298
  "button",
11242
11299
  {
11243
11300
  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",
11301
+ 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
11302
  onClick: (e) => {
11246
11303
  stopActionClick(e);
11247
11304
  onCancel(item.id);
@@ -11547,6 +11604,7 @@ function TreeNodeRow({
11547
11604
  },
11548
11605
  className: cn(
11549
11606
  "group flex items-center gap-2 w-full py-2 pr-2 text-left cursor-pointer transition-colors border-l-2",
11607
+ "min-h-11 md:min-h-0",
11550
11608
  isActive ? "bg-line text-foreground border-l-primary" : "bg-transparent text-subtle hover:bg-input hover:text-foreground border-l-transparent"
11551
11609
  ),
11552
11610
  style: { paddingLeft: `${depth * 12 + 12}px` },
@@ -11555,7 +11613,7 @@ function TreeNodeRow({
11555
11613
  "button",
11556
11614
  {
11557
11615
  type: "button",
11558
- className: "p-0.5 rounded hover:bg-line shrink-0",
11616
+ className: "p-2 md:p-0.5 rounded hover:bg-line shrink-0",
11559
11617
  onClick: (e) => {
11560
11618
  e.stopPropagation();
11561
11619
  setExpanded(!expanded);
@@ -11573,7 +11631,7 @@ function TreeNodeRow({
11573
11631
  "button",
11574
11632
  {
11575
11633
  type: "button",
11576
- className: "p-1 rounded opacity-0 group-hover:opacity-100 hover:bg-destructive/10 hover:text-destructive transition-all",
11634
+ 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
11635
  onClick: (e) => {
11578
11636
  e.stopPropagation();
11579
11637
  onStop(entry.id);
@@ -11588,8 +11646,8 @@ function TreeNodeRow({
11588
11646
  {
11589
11647
  type: "button",
11590
11648
  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"
11649
+ "p-2 md:p-1 rounded hover:bg-destructive/10 hover:text-destructive disabled:pointer-events-none transition-all",
11650
+ deletingSessionId === entry.id ? "opacity-100" : "opacity-100 md:opacity-0 md:group-hover:opacity-100 md:focus-visible:opacity-100"
11593
11651
  ),
11594
11652
  onClick: (e) => {
11595
11653
  e.stopPropagation();