@invergent/agent-chat-react 1.4.10 → 1.4.11

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
@@ -22,6 +22,7 @@ var Ansi = require('ansi-to-react');
22
22
  var tokenlens = require('tokenlens');
23
23
  var cmdk = require('cmdk');
24
24
  var nanoid = require('nanoid');
25
+ var dateFns = require('date-fns');
25
26
 
26
27
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
27
28
 
@@ -7927,17 +7928,10 @@ function mergeTreeNodes(groups) {
7927
7928
  }
7928
7929
  return Array.from(byId.values());
7929
7930
  }
7930
- function statusColor(status) {
7931
- switch (status) {
7932
- case "active":
7933
- return "default";
7934
- case "completed":
7935
- return "secondary";
7936
- case "failed":
7937
- return "destructive";
7938
- default:
7939
- return "outline";
7940
- }
7931
+ function formatSessionTime(value) {
7932
+ const date = new Date(value);
7933
+ if (Number.isNaN(date.getTime())) return "";
7934
+ return dateFns.formatDistanceToNow(date, { addSuffix: true });
7941
7935
  }
7942
7936
  function TreeNodeRow({
7943
7937
  entry,
@@ -7954,6 +7948,11 @@ function TreeNodeRow({
7954
7948
  const hasChildren = entry.children.length > 0;
7955
7949
  const isActive = entry.id === activeSessionId;
7956
7950
  const isRunning = entry.status === "active";
7951
+ const title = entry.title ?? "New session";
7952
+ const subtitle = [
7953
+ entry.model ?? "default",
7954
+ formatSessionTime(entry.updatedAt)
7955
+ ].filter(Boolean).join(" \xB7 ");
7957
7956
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7958
7957
  /* @__PURE__ */ jsxRuntime.jsxs(
7959
7958
  "div",
@@ -7965,16 +7964,16 @@ function TreeNodeRow({
7965
7964
  if (e.key === "Enter" || e.key === " ") onSelect(entry.id);
7966
7965
  },
7967
7966
  className: cn(
7968
- "group flex items-center gap-1.5 py-1.5 pr-1 rounded cursor-pointer text-sm transition-colors",
7969
- isActive ? "bg-line text-foreground" : "hover:bg-input text-subtle hover:text-foreground"
7967
+ "group flex items-center gap-2 w-full py-2 pr-2 text-left cursor-pointer transition-colors border-l-2",
7968
+ isActive ? "bg-line text-foreground border-l-primary" : "bg-transparent text-subtle hover:bg-input hover:text-foreground border-l-transparent"
7970
7969
  ),
7971
- style: { paddingLeft: `${depth * 12 + 4}px` },
7970
+ style: { paddingLeft: `${depth * 12 + 12}px` },
7972
7971
  children: [
7973
7972
  hasChildren ? /* @__PURE__ */ jsxRuntime.jsx(
7974
7973
  "button",
7975
7974
  {
7976
7975
  type: "button",
7977
- className: "p-0.5 rounded hover:bg-line",
7976
+ className: "p-0.5 rounded hover:bg-line shrink-0",
7978
7977
  onClick: (e) => {
7979
7978
  e.stopPropagation();
7980
7979
  setExpanded(!expanded);
@@ -7984,17 +7983,9 @@ function TreeNodeRow({
7984
7983
  children: expanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, { className: "w-3.5 h-3.5" })
7985
7984
  }
7986
7985
  ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-4 h-4 shrink-0" }),
7987
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 flex items-center gap-1.5", children: [
7988
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: entry.title ?? "session" }),
7989
- entry.agentType && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "outline", className: "h-4 px-1.5 text-[10px]", children: entry.agentType }),
7990
- /* @__PURE__ */ jsxRuntime.jsx(
7991
- Badge,
7992
- {
7993
- variant: statusColor(entry.status),
7994
- className: "h-4 px-1.5 text-[10px]",
7995
- children: entry.status
7996
- }
7997
- )
7986
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
7987
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm truncate", children: title }),
7988
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-faint truncate", children: subtitle })
7998
7989
  ] }),
7999
7990
  isRunning && canStop && /* @__PURE__ */ jsxRuntime.jsx(
8000
7991
  "button",
@@ -8066,6 +8057,7 @@ function SessionTreePanel({
8066
8057
  const mounted = react.useRef(true);
8067
8058
  const requestId = react.useRef(0);
8068
8059
  const lastFingerprint = react.useRef("");
8060
+ const resetContext = react.useRef(null);
8069
8061
  const refetch = react.useCallback(
8070
8062
  async (opts) => {
8071
8063
  const canLoadSessionList = Boolean(agentId && adapter.listSessions);
@@ -8120,12 +8112,17 @@ function SessionTreePanel({
8120
8112
  };
8121
8113
  }, []);
8122
8114
  react.useEffect(() => {
8123
- setNodes([]);
8115
+ const previous = resetContext.current;
8116
+ const shouldReset = !previous || previous.adapter !== adapter || previous.agentId !== agentId || previous.sessionListLimit !== sessionListLimit;
8117
+ resetContext.current = { adapter, agentId, sessionListLimit };
8118
+ if (shouldReset) {
8119
+ setNodes([]);
8120
+ setHasEverLoaded(false);
8121
+ lastFingerprint.current = "";
8122
+ }
8124
8123
  setError(null);
8125
- setHasEverLoaded(false);
8126
- lastFingerprint.current = "";
8127
8124
  void refetch();
8128
- }, [refetch, sessionId]);
8125
+ }, [adapter, agentId, refetch, sessionListLimit]);
8129
8126
  const runningCount = react.useMemo(
8130
8127
  () => nodes.filter((n) => n.status === "active").length,
8131
8128
  [nodes]
@@ -8177,12 +8174,23 @@ function SessionTreePanel({
8177
8174
  const topLevel = hideRoot ? roots.flatMap((r) => r.children) : roots;
8178
8175
  if (topLevel.length === 0) return null;
8179
8176
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-line", children: [
8180
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 px-3 py-2 text-xs font-semibold uppercase tracking-wide text-faint", children: [
8177
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 px-3 py-2 text-xs font-semibold uppercase tracking-wide", children: [
8181
8178
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UsersIcon, { className: "w-3.5 h-3.5" }),
8182
8179
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: title }),
8183
8180
  runningCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", className: "h-4 px-1.5 text-[10px] ml-auto", children: runningCount })
8184
8181
  ] }),
8185
- loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 text-xs text-faint", children: "Loading..." }),
8182
+ loading && /* @__PURE__ */ jsxRuntime.jsx(
8183
+ "div",
8184
+ {
8185
+ className: "px-3 py-2",
8186
+ role: "status",
8187
+ "aria-label": "Loading sessions",
8188
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
8189
+ /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-3.5 w-28" }),
8190
+ /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-3 w-20" })
8191
+ ] })
8192
+ }
8193
+ ),
8186
8194
  error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 text-xs text-destructive", children: error }),
8187
8195
  !error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-1 pb-2", children: topLevel.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(
8188
8196
  TreeNodeRow,