@truefoundry/trueforge-ui 0.3.0-rc.2 → 0.3.0-rc.4

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.
Files changed (107) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +18 -10
  3. package/dist/{AgentCodeSnippets-637HQUXD.js → AgentCodeSnippets-U6KQWVBJ.js} +38 -23
  4. package/dist/AgentCodeSnippets-U6KQWVBJ.js.map +1 -0
  5. package/dist/AgentMetricChart-3D6FUFO6.js +15 -0
  6. package/dist/{AgentOverview-3FJ5EE6N.js → AgentOverview-RLJ6HZCN.js} +7 -7
  7. package/dist/{AgentSessionEventTimeline-VELWUYPR.js → AgentSessionEventTimeline-CDXRRUZQ.js} +8 -8
  8. package/dist/{AgentSessionEventTimeline-VELWUYPR.js.map → AgentSessionEventTimeline-CDXRRUZQ.js.map} +1 -1
  9. package/dist/{AgentSessionEventTimelineChart-CUKETHWM.js → AgentSessionEventTimelineChart-S2WX6ZEA.js} +12 -12
  10. package/dist/AgentSessionEventTimelineChart-S2WX6ZEA.js.map +1 -0
  11. package/dist/{AgentSessions-T7MOGOTZ.js → AgentSessions-UI3L7XY2.js} +72 -24
  12. package/dist/AgentSessions-UI3L7XY2.js.map +1 -0
  13. package/dist/{ConnectorSettings-ESZ2RSRG.js → ConnectorSettings-OIGAC2HU.js} +156 -116
  14. package/dist/ConnectorSettings-OIGAC2HU.js.map +1 -0
  15. package/dist/{DockLayout-NLFNU6F2.js → DockLayout-J5BRKMJZ.js} +10 -10
  16. package/dist/{DrawerLayout-PR3SMKA6.js → DrawerLayout-65YHGHIF.js} +13 -11
  17. package/dist/DrawerLayout-65YHGHIF.js.map +1 -0
  18. package/dist/{ModelSettings-LYW64IRR.js → ModelSettings-VP6WCMGT.js} +10 -10
  19. package/dist/{ModelSettings-LYW64IRR.js.map → ModelSettings-VP6WCMGT.js.map} +1 -1
  20. package/dist/OpenUiFenceBlock-UTDCTNTM.js +9 -0
  21. package/dist/{SandboxSettings-DF64LHYI.js → SandboxSettings-GTZT7LD6.js} +9 -9
  22. package/dist/SchedulesPage-ARWU7BZF.js +15 -0
  23. package/dist/{SettingsBuilder-LSXK2VN4.js → SettingsBuilder-A4BPYIFZ.js} +8 -8
  24. package/dist/{ShellRouteSync-B22IAV2W.js → ShellRouteSync-SSLGM35F.js} +157 -22
  25. package/dist/ShellRouteSync-SSLGM35F.js.map +1 -0
  26. package/dist/{SidebarLayout-XW6LXB7R.js → SidebarLayout-MFDOGAVJ.js} +74 -53
  27. package/dist/SidebarLayout-MFDOGAVJ.js.map +1 -0
  28. package/dist/{SkillSettings-64VXUO6J.js → SkillSettings-WQPUQ5TE.js} +18 -13
  29. package/dist/SkillSettings-WQPUQ5TE.js.map +1 -0
  30. package/dist/{TrueForgeUIWithRouter-3TSLV22Q.js → TrueForgeUIWithRouter-5CDICMCE.js} +9 -9
  31. package/dist/{WidgetLayout-Q5P7PYSJ.js → WidgetLayout-HE7E4UL5.js} +10 -10
  32. package/dist/{chunk-SQGT43Z3.js → chunk-2BDTG544.js} +21 -4
  33. package/dist/chunk-2BDTG544.js.map +1 -0
  34. package/dist/{chunk-YQO2NMJ3.js → chunk-2OKGEU6X.js} +4425 -2982
  35. package/dist/chunk-2OKGEU6X.js.map +1 -0
  36. package/dist/{chunk-FQK2XVVE.js → chunk-6CFZHEYH.js} +225 -72
  37. package/dist/chunk-6CFZHEYH.js.map +1 -0
  38. package/dist/{chunk-QC42MLAK.js → chunk-7AAO4UDQ.js} +4 -3
  39. package/dist/chunk-7AAO4UDQ.js.map +1 -0
  40. package/dist/chunk-E4GVP6PM.js +195 -0
  41. package/dist/chunk-E4GVP6PM.js.map +1 -0
  42. package/dist/{chunk-LGRHHFHN.js → chunk-F7ZAQIRE.js} +166 -45
  43. package/dist/chunk-F7ZAQIRE.js.map +1 -0
  44. package/dist/{chunk-VJ7BZGAF.js → chunk-GTTMLDCI.js} +2 -2
  45. package/dist/{chunk-5I2COQNL.js → chunk-IOPHQEUY.js} +13 -11
  46. package/dist/chunk-IOPHQEUY.js.map +1 -0
  47. package/dist/{chunk-G2TUAD65.js → chunk-KCYBMKQL.js} +235 -108
  48. package/dist/chunk-KCYBMKQL.js.map +1 -0
  49. package/dist/{chunk-H6WTY5PM.js → chunk-MAA7U4RF.js} +17 -227
  50. package/dist/chunk-MAA7U4RF.js.map +1 -0
  51. package/dist/{chunk-GXYAOAK5.js → chunk-MJULWIPI.js} +224 -162
  52. package/dist/chunk-MJULWIPI.js.map +1 -0
  53. package/dist/chunk-P7J2ABEP.js +587 -0
  54. package/dist/chunk-P7J2ABEP.js.map +1 -0
  55. package/dist/{chunk-VUMGMGKZ.js → chunk-TGKQRK3S.js} +52 -8
  56. package/dist/chunk-TGKQRK3S.js.map +1 -0
  57. package/dist/{chunk-I3AL54MA.js → chunk-VXKNS7FH.js} +28 -24
  58. package/dist/chunk-VXKNS7FH.js.map +1 -0
  59. package/dist/chunk-XO3FYN2W.js +517 -0
  60. package/dist/chunk-XO3FYN2W.js.map +1 -0
  61. package/dist/{createTrueFoundryServer-CmZnBh_l.d.ts → createTrueFoundryServer-B_FYhSdn.d.ts} +8 -5
  62. package/dist/index.d.ts +300 -89
  63. package/dist/index.js +65 -488
  64. package/dist/index.js.map +1 -1
  65. package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +44 -13
  66. package/dist/plugins/trueforge-agent-server-adapter/index.js +73 -37
  67. package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
  68. package/dist/styles.css +1 -1
  69. package/package.json +3 -3
  70. package/dist/AgentCodeSnippets-637HQUXD.js.map +0 -1
  71. package/dist/AgentMetricChart-4FYECRIN.js +0 -15
  72. package/dist/AgentSessionEventTimelineChart-CUKETHWM.js.map +0 -1
  73. package/dist/AgentSessions-T7MOGOTZ.js.map +0 -1
  74. package/dist/ConnectorSettings-ESZ2RSRG.js.map +0 -1
  75. package/dist/DrawerLayout-PR3SMKA6.js.map +0 -1
  76. package/dist/OpenUiFenceBlock-JEPNPJ7U.js +0 -9
  77. package/dist/SchedulesPage-WQU4H25F.js +0 -15
  78. package/dist/ShellRouteSync-B22IAV2W.js.map +0 -1
  79. package/dist/SidebarLayout-XW6LXB7R.js.map +0 -1
  80. package/dist/SkillSettings-64VXUO6J.js.map +0 -1
  81. package/dist/chunk-5I2COQNL.js.map +0 -1
  82. package/dist/chunk-BWHOZFIV.js +0 -587
  83. package/dist/chunk-BWHOZFIV.js.map +0 -1
  84. package/dist/chunk-FQK2XVVE.js.map +0 -1
  85. package/dist/chunk-G2TUAD65.js.map +0 -1
  86. package/dist/chunk-GXYAOAK5.js.map +0 -1
  87. package/dist/chunk-H6WTY5PM.js.map +0 -1
  88. package/dist/chunk-I3AL54MA.js.map +0 -1
  89. package/dist/chunk-LGRHHFHN.js.map +0 -1
  90. package/dist/chunk-NHHSZB5N.js +0 -74
  91. package/dist/chunk-NHHSZB5N.js.map +0 -1
  92. package/dist/chunk-QC42MLAK.js.map +0 -1
  93. package/dist/chunk-SFZNIO6U.js +0 -18
  94. package/dist/chunk-SFZNIO6U.js.map +0 -1
  95. package/dist/chunk-SQGT43Z3.js.map +0 -1
  96. package/dist/chunk-VUMGMGKZ.js.map +0 -1
  97. package/dist/chunk-YQO2NMJ3.js.map +0 -1
  98. /package/dist/{AgentMetricChart-4FYECRIN.js.map → AgentMetricChart-3D6FUFO6.js.map} +0 -0
  99. /package/dist/{AgentOverview-3FJ5EE6N.js.map → AgentOverview-RLJ6HZCN.js.map} +0 -0
  100. /package/dist/{DockLayout-NLFNU6F2.js.map → DockLayout-J5BRKMJZ.js.map} +0 -0
  101. /package/dist/{OpenUiFenceBlock-JEPNPJ7U.js.map → OpenUiFenceBlock-UTDCTNTM.js.map} +0 -0
  102. /package/dist/{SandboxSettings-DF64LHYI.js.map → SandboxSettings-GTZT7LD6.js.map} +0 -0
  103. /package/dist/{SchedulesPage-WQU4H25F.js.map → SchedulesPage-ARWU7BZF.js.map} +0 -0
  104. /package/dist/{SettingsBuilder-LSXK2VN4.js.map → SettingsBuilder-A4BPYIFZ.js.map} +0 -0
  105. /package/dist/{TrueForgeUIWithRouter-3TSLV22Q.js.map → TrueForgeUIWithRouter-5CDICMCE.js.map} +0 -0
  106. /package/dist/{WidgetLayout-Q5P7PYSJ.js.map → WidgetLayout-HE7E4UL5.js.map} +0 -0
  107. /package/dist/{chunk-VJ7BZGAF.js.map → chunk-GTTMLDCI.js.map} +0 -0
@@ -1,42 +1,57 @@
1
1
  "use client";
2
2
  import {
3
3
  buildSessionResumeHref
4
- } from "./chunk-SQGT43Z3.js";
4
+ } from "./chunk-2BDTG544.js";
5
5
  import {
6
6
  useOptionalResolvedRoutes
7
7
  } from "./chunk-Y6S4OVVQ.js";
8
- import {
9
- drainListPages
10
- } from "./chunk-SFZNIO6U.js";
11
8
  import {
12
9
  sessionIsCreateAgent
13
10
  } from "./chunk-RDXBMTP5.js";
14
11
  import {
15
12
  EmptyScreen,
16
13
  Skeleton,
14
+ useResourcePermissions,
17
15
  useSessionShareSearch,
18
16
  useSlot
19
- } from "./chunk-YQO2NMJ3.js";
20
- import "./chunk-NHHSZB5N.js";
17
+ } from "./chunk-2OKGEU6X.js";
18
+ import "./chunk-E4GVP6PM.js";
21
19
  import {
22
20
  Icon
23
- } from "./chunk-H6WTY5PM.js";
21
+ } from "./chunk-MAA7U4RF.js";
24
22
  import {
25
23
  sessionTimeRangeFromCreatedAt,
26
24
  useAgentSessionsServer,
27
25
  useOptionalShellMode,
28
26
  useServer
29
- } from "./chunk-FQK2XVVE.js";
27
+ } from "./chunk-6CFZHEYH.js";
30
28
  import "./chunk-M6MHLVSO.js";
31
- import "./chunk-VJ7BZGAF.js";
29
+ import "./chunk-GTTMLDCI.js";
32
30
  import {
33
31
  cn
34
- } from "./chunk-BWHOZFIV.js";
32
+ } from "./chunk-P7J2ABEP.js";
35
33
 
36
34
  // src/atoms/agent-details/AgentSessions.tsx
37
35
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
38
36
  import { Group, Panel, Separator } from "react-resizable-panels";
37
+
38
+ // src/utils/drainListPages.ts
39
+ async function drainListPages({
40
+ fetchPage
41
+ }) {
42
+ const items = [];
43
+ let pageToken;
44
+ do {
45
+ const page = await fetchPage(pageToken);
46
+ items.push(...page.data);
47
+ pageToken = page.nextPageToken;
48
+ } while (pageToken != null && pageToken.length > 0);
49
+ return items;
50
+ }
51
+
52
+ // src/atoms/agent-details/AgentSessions.tsx
39
53
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
54
+ var LOAD_MORE_ROOT_MARGIN = "96px";
40
55
  function sessionTitle(entry) {
41
56
  const title = entry.title?.trim();
42
57
  return title != null && title.length > 0 ? title : "Untitled session";
@@ -47,12 +62,20 @@ function entryIsMutable(entry) {
47
62
  }
48
63
  return entry.agentName == null;
49
64
  }
65
+ function entrySourceType(entry) {
66
+ return "sourceType" in entry && Reflect.get(entry, "sourceType") === "schedule" ? "schedule" : void 0;
67
+ }
50
68
  function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
51
69
  const sessionsServer = useAgentSessionsServer();
52
70
  const chatServer = useServer();
53
71
  const shell = useOptionalShellMode();
54
72
  const routes = useOptionalResolvedRoutes();
55
73
  const { sessionId: selectedSessionId, updateShareSearch } = useSessionShareSearch();
74
+ const { allows } = useResourcePermissions({
75
+ resourceType: "session",
76
+ resourceIds: selectedSessionId == null ? [] : [selectedSessionId]
77
+ });
78
+ const canResume = allows(selectedSessionId, "MANAGE");
56
79
  const AgentSessionListRow = useSlot("AgentSessionListRow");
57
80
  const AgentSessionDetailHeader = useSlot("AgentSessionDetailHeader");
58
81
  const AgentSessionTimelineContainer = useSlot("AgentSessionTimelineContainer");
@@ -60,8 +83,12 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
60
83
  const [nextPageToken, setNextPageToken] = useState();
61
84
  const [listLoading, setListLoading] = useState(true);
62
85
  const [listLoadingMore, setListLoadingMore] = useState(false);
86
+ const [listLoadMoreFailed, setListLoadMoreFailed] = useState(false);
63
87
  const [listFailed, setListFailed] = useState(false);
64
88
  const listRequestIdRef = useRef(0);
89
+ const loadMoreInflightRef = useRef(false);
90
+ const [listEl, setListEl] = useState(null);
91
+ const [sentinelEl, setSentinelEl] = useState(null);
65
92
  const [detailEvents, setDetailEvents] = useState();
66
93
  const [detailSession, setDetailSession] = useState();
67
94
  const [detailLoading, setDetailLoading] = useState(false);
@@ -79,8 +106,11 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
79
106
  useEffect(() => {
80
107
  const requestId = ++listRequestIdRef.current;
81
108
  let cancelled = false;
109
+ loadMoreInflightRef.current = false;
110
+ setNextPageToken(void 0);
82
111
  setListLoading(true);
83
112
  setListLoadingMore(false);
113
+ setListLoadMoreFailed(false);
84
114
  setListFailed(false);
85
115
  void sessionsServer.listSessions(listRequest).then((page) => {
86
116
  if (cancelled || listRequestIdRef.current !== requestId) return;
@@ -99,19 +129,36 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
99
129
  };
100
130
  }, [listRequest, sessionsServer]);
101
131
  const loadMore = useCallback(async () => {
102
- if (nextPageToken == null || listLoadingMore) return;
132
+ if (listLoading || nextPageToken == null || loadMoreInflightRef.current) return;
103
133
  const requestId = listRequestIdRef.current;
134
+ loadMoreInflightRef.current = true;
104
135
  setListLoadingMore(true);
136
+ setListLoadMoreFailed(false);
105
137
  try {
106
138
  const page = await sessionsServer.listSessions({ ...listRequest, pageToken: nextPageToken });
107
139
  if (listRequestIdRef.current !== requestId) return;
108
140
  setEntries((current) => [...current, ...page.data]);
109
141
  setNextPageToken(page.nextPageToken);
110
142
  } catch {
143
+ if (listRequestIdRef.current === requestId) setListLoadMoreFailed(true);
111
144
  } finally {
112
- if (listRequestIdRef.current === requestId) setListLoadingMore(false);
145
+ if (listRequestIdRef.current === requestId) {
146
+ loadMoreInflightRef.current = false;
147
+ setListLoadingMore(false);
148
+ }
113
149
  }
114
- }, [listLoadingMore, listRequest, nextPageToken, sessionsServer]);
150
+ }, [listLoading, listRequest, nextPageToken, sessionsServer]);
151
+ useEffect(() => {
152
+ if (listLoading || nextPageToken == null || listEl == null || sentinelEl == null) return;
153
+ const observer = new IntersectionObserver(
154
+ (observed) => {
155
+ if (observed.some((entry) => entry.isIntersecting)) void loadMore();
156
+ },
157
+ { root: listEl, rootMargin: LOAD_MORE_ROOT_MARGIN }
158
+ );
159
+ observer.observe(sentinelEl);
160
+ return () => observer.disconnect();
161
+ }, [entries.length, listEl, listLoading, loadMore, nextPageToken, sentinelEl]);
115
162
  useEffect(() => {
116
163
  if (selectedSessionId == null || selectedSessionId.length === 0) {
117
164
  setDetailEvents(void 0);
@@ -165,7 +212,7 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
165
212
  const resumeLabel = resumeIsCreateAgent ? "Resume Agent building" : "Resume Chat";
166
213
  const resumeHref = selectedSessionId != null && routes != null ? buildSessionResumeHref({ sessionId: selectedSessionId, routes }) : null;
167
214
  const handleResume = () => {
168
- if (selectedSessionId == null || shell == null) return;
215
+ if (!canResume || selectedSessionId == null || shell == null) return;
169
216
  const agentName = detailSession?.agentName ?? selectedEntry?.agentName;
170
217
  shell.openHistorySession({
171
218
  sessionId: selectedSessionId,
@@ -193,30 +240,30 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
193
240
  className: "h-full min-h-0 w-full",
194
241
  resizeTargetMinimumSize: { coarse: 24, fine: 11 },
195
242
  children: [
196
- /* @__PURE__ */ jsx(Panel, { id: "agent-sessions-list", defaultSize: "35%", minSize: "20%", maxSize: "50%", children: /* @__PURE__ */ jsxs("aside", { className: "flex h-full min-h-0 w-full flex-col bg-sidebar-bg", children: [
197
- /* @__PURE__ */ jsx("div", { className: "scrollbar-none min-h-0 flex-1 overflow-y-auto", children: listLoading ? /* @__PURE__ */ jsx("div", { className: "space-y-2 p-3", role: "status", "aria-label": "Loading sessions", children: ["a", "b", "c"].map((key) => /* @__PURE__ */ jsx(Skeleton, { className: "h-16 rounded-md" }, key)) }) : listFailed ? /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-xs text-text-secondary", children: "Sessions could not be loaded." }) : entries.map((entry) => /* @__PURE__ */ jsx(
243
+ /* @__PURE__ */ jsx(Panel, { id: "agent-sessions-list", defaultSize: "35%", minSize: "20%", maxSize: "50%", children: /* @__PURE__ */ jsx("aside", { className: "flex h-full min-h-0 w-full flex-col bg-sidebar-bg", children: /* @__PURE__ */ jsxs("div", { ref: setListEl, className: "scrollbar-none min-h-0 flex-1 overflow-y-auto", children: [
244
+ listLoading ? /* @__PURE__ */ jsx("div", { className: "space-y-2 p-3", role: "status", "aria-label": "Loading sessions", children: ["a", "b", "c"].map((key) => /* @__PURE__ */ jsx(Skeleton, { className: "h-16 rounded-md" }, key)) }) : listFailed ? /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-xs text-text-secondary", children: "Sessions could not be loaded." }) : entries.map((entry) => /* @__PURE__ */ jsx(
198
245
  AgentSessionListRow,
199
246
  {
200
247
  title: sessionTitle(entry),
201
248
  agentName: entry.agentName ?? void 0,
249
+ sourceType: entrySourceType(entry),
202
250
  lastActivityAt: entry.lastActivityAt,
203
251
  metrics: entry.metrics,
204
252
  active: entry.id === selectedSessionId,
205
253
  onSelect: () => selectSession(entry)
206
254
  },
207
255
  entry.id
208
- )) }),
209
- nextPageToken != null && !listLoading ? /* @__PURE__ */ jsx("div", { className: "shrink-0 border-t border-border p-3", children: /* @__PURE__ */ jsx(
256
+ )),
257
+ nextPageToken != null && !listLoading && !listFailed ? /* @__PURE__ */ jsx("div", { ref: setSentinelEl, className: "px-3 py-2", children: listLoadingMore ? /* @__PURE__ */ jsx(Skeleton, { className: "h-16 rounded-md", role: "status", "aria-label": "Loading more sessions" }) : listLoadMoreFailed ? /* @__PURE__ */ jsx(
210
258
  "button",
211
259
  {
212
260
  type: "button",
213
- disabled: listLoadingMore,
261
+ className: "h-8 w-full rounded-md border border-border text-xs font-medium text-text-primary hover:bg-ghost-button-hover",
214
262
  onClick: () => void loadMore(),
215
- className: "h-8 w-full rounded-md border border-border text-xs font-medium text-text-primary hover:bg-ghost-button-hover disabled:opacity-60",
216
- children: listLoadingMore ? "Loading\u2026" : "Load more"
263
+ children: "Retry loading sessions"
217
264
  }
218
- ) }) : null
219
- ] }) }),
265
+ ) : null }) : null
266
+ ] }) }) }),
220
267
  /* @__PURE__ */ jsxs(
221
268
  Separator,
222
269
  {
@@ -253,6 +300,7 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
253
300
  createdAt: detailSession?.createdAt ?? selectedEntry?.createdAt,
254
301
  view: shareView,
255
302
  onClose: clearSelectedSession,
303
+ canResume,
256
304
  ...resumeProps
257
305
  }
258
306
  ),
@@ -272,4 +320,4 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
272
320
  export {
273
321
  AgentSessions
274
322
  };
275
- //# sourceMappingURL=AgentSessions-T7MOGOTZ.js.map
323
+ //# sourceMappingURL=AgentSessions-UI3L7XY2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/atoms/agent-details/AgentSessions.tsx","../src/utils/drainListPages.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useRef, useState, type ComponentType } from 'react';\nimport { Group, Panel, Separator } from 'react-resizable-panels';\n\nimport { useResourcePermissions } from '../../hooks/useResourcePermissions.js';\nimport { useSessionShareSearch } from '../../hooks/useSessionShareSearch.js';\nimport { Icon } from '../../icons/Icon.js';\nimport { buildSessionResumeHref } from '../../routing/paths.js';\nimport { useOptionalResolvedRoutes } from '../../routing/ResolvedRoutesContext.js';\nimport { useAgentSessionsServer, useServer } from '../../server/ServerContext.js';\nimport { useOptionalShellMode } from '../../server/ShellModeContext.js';\nimport type { Session, SessionEventItem, SessionListEntry } from '../../server/types.js';\nimport { useSlot } from '../../theme/SlotsProvider.js';\nimport { drainListPages } from '../../utils/drainListPages.js';\nimport { sessionTimeRangeFromCreatedAt } from '../../utils/sessionShareUrl.js';\nimport { EmptyScreen } from '../EmptyScreen.js';\nimport { cn } from '../lib/cn.js';\nimport { sessionIsCreateAgent } from '../lib/sessionCreateAgent.js';\nimport { Skeleton } from '../primitives/Skeleton.js';\nimport type { AgentSessionsProps } from './types.js';\n\nconst LOAD_MORE_ROOT_MARGIN = '96px';\n\nfunction sessionTitle(entry: Pick<SessionListEntry, 'title'>): string {\n const title = entry.title?.trim();\n return title != null && title.length > 0 ? title : 'Untitled session';\n}\n\nfunction entryIsMutable(entry: SessionListEntry): boolean {\n if ('isMutable' in entry && typeof Reflect.get(entry, 'isMutable') === 'boolean') {\n return Reflect.get(entry, 'isMutable') === true;\n }\n return entry.agentName == null;\n}\n\nfunction entrySourceType(entry: SessionListEntry): 'schedule' | undefined {\n return 'sourceType' in entry && Reflect.get(entry, 'sourceType') === 'schedule' ? 'schedule' : undefined;\n}\n\nexport function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }: AgentSessionsProps) {\n const sessionsServer = useAgentSessionsServer();\n const chatServer = useServer();\n const shell = useOptionalShellMode();\n const routes = useOptionalResolvedRoutes();\n const { sessionId: selectedSessionId, updateShareSearch } = useSessionShareSearch();\n const { allows } = useResourcePermissions({\n resourceType: 'session',\n resourceIds: selectedSessionId == null ? [] : [selectedSessionId],\n });\n const canResume = allows(selectedSessionId, 'MANAGE');\n\n const AgentSessionListRow = useSlot('AgentSessionListRow');\n const AgentSessionDetailHeader = useSlot('AgentSessionDetailHeader');\n const AgentSessionTimelineContainer = useSlot('AgentSessionTimelineContainer');\n\n const [entries, setEntries] = useState<SessionListEntry[]>([]);\n const [nextPageToken, setNextPageToken] = useState<string | undefined>();\n const [listLoading, setListLoading] = useState(true);\n const [listLoadingMore, setListLoadingMore] = useState(false);\n const [listLoadMoreFailed, setListLoadMoreFailed] = useState(false);\n const [listFailed, setListFailed] = useState(false);\n const listRequestIdRef = useRef(0);\n const loadMoreInflightRef = useRef(false);\n const [listEl, setListEl] = useState<HTMLDivElement | null>(null);\n const [sentinelEl, setSentinelEl] = useState<HTMLDivElement | null>(null);\n const [detailEvents, setDetailEvents] = useState<SessionEventItem[]>();\n const [detailSession, setDetailSession] = useState<Session>();\n const [detailLoading, setDetailLoading] = useState(false);\n const [detailFailed, setDetailFailed] = useState(false);\n\n const listRequest = useMemo(\n () => ({\n order: 'desc' as const,\n limit: 20,\n ...(agentId == null || agentId.length === 0 ? {} : { agentId }),\n ...(startTimestamp == null ? {} : { startTimestamp }),\n ...(endTimestamp == null ? {} : { endTimestamp }),\n }),\n [agentId, endTimestamp, startTimestamp],\n );\n\n useEffect(() => {\n const requestId = ++listRequestIdRef.current;\n let cancelled = false;\n loadMoreInflightRef.current = false;\n setNextPageToken(undefined);\n setListLoading(true);\n setListLoadingMore(false);\n setListLoadMoreFailed(false);\n setListFailed(false);\n void sessionsServer\n .listSessions(listRequest)\n .then(page => {\n if (cancelled || listRequestIdRef.current !== requestId) return;\n setEntries(page.data);\n setNextPageToken(page.nextPageToken);\n })\n .catch(() => {\n if (cancelled || listRequestIdRef.current !== requestId) return;\n setEntries([]);\n setNextPageToken(undefined);\n setListFailed(true);\n })\n .finally(() => {\n if (!cancelled && listRequestIdRef.current === requestId) setListLoading(false);\n });\n\n return () => {\n cancelled = true;\n };\n }, [listRequest, sessionsServer]);\n\n const loadMore = useCallback(async () => {\n // A ref, not `listLoadingMore`: the observer can fire twice before a re-render.\n if (listLoading || nextPageToken == null || loadMoreInflightRef.current) return;\n const requestId = listRequestIdRef.current;\n loadMoreInflightRef.current = true;\n setListLoadingMore(true);\n setListLoadMoreFailed(false);\n try {\n const page = await sessionsServer.listSessions({ ...listRequest, pageToken: nextPageToken });\n if (listRequestIdRef.current !== requestId) return;\n setEntries(current => [...current, ...page.data]);\n setNextPageToken(page.nextPageToken);\n } catch {\n if (listRequestIdRef.current === requestId) setListLoadMoreFailed(true);\n } finally {\n if (listRequestIdRef.current === requestId) {\n loadMoreInflightRef.current = false;\n setListLoadingMore(false);\n }\n }\n }, [listLoading, listRequest, nextPageToken, sessionsServer]);\n\n // `entries.length` re-arms the observer: an already-intersecting sentinel emits no new entry.\n useEffect(() => {\n if (listLoading || nextPageToken == null || listEl == null || sentinelEl == null) return;\n\n const observer = new IntersectionObserver(\n observed => {\n if (observed.some(entry => entry.isIntersecting)) void loadMore();\n },\n { root: listEl, rootMargin: LOAD_MORE_ROOT_MARGIN },\n );\n observer.observe(sentinelEl);\n return () => observer.disconnect();\n }, [entries.length, listEl, listLoading, loadMore, nextPageToken, sentinelEl]);\n\n useEffect(() => {\n if (selectedSessionId == null || selectedSessionId.length === 0) {\n setDetailEvents(undefined);\n setDetailSession(undefined);\n setDetailFailed(false);\n setDetailLoading(false);\n return;\n }\n\n let cancelled = false;\n setDetailLoading(true);\n setDetailFailed(false);\n setDetailEvents(undefined);\n setDetailSession(undefined);\n\n void Promise.all([\n drainListPages({\n fetchPage: pageToken =>\n sessionsServer.listSessionEvents({\n sessionId: selectedSessionId,\n limit: 100,\n ...(pageToken == null ? {} : { pageToken }),\n }),\n }),\n chatServer.getSession({ sessionId: selectedSessionId }).catch(() => undefined),\n ])\n .then(([itemsNewestFirst, session]) => {\n if (cancelled) return;\n setDetailEvents([...itemsNewestFirst].reverse());\n setDetailSession(session);\n })\n .catch(() => {\n if (!cancelled) setDetailFailed(true);\n })\n .finally(() => {\n if (!cancelled) setDetailLoading(false);\n });\n\n return () => {\n cancelled = true;\n };\n }, [chatServer, selectedSessionId, sessionsServer]);\n\n const selectSession = (entry: SessionListEntry) => {\n const pinned = shareView === 'sessions' ? sessionTimeRangeFromCreatedAt(entry.createdAt) : null;\n updateShareSearch({\n sessionId: entry.id,\n ...(shareView === 'sessions'\n ? { view: 'sessions', ...(pinned == null ? {} : { timeRange: pinned }) }\n : { agentId: agentId ?? null, tab: 'sessions', view: null, timeRange: null }),\n });\n };\n\n const clearSelectedSession = () => {\n if (selectedSessionId == null) return;\n updateShareSearch({ sessionId: null });\n };\n\n const selectedEntry = entries.find(entry => entry.id === selectedSessionId);\n const selectedTitle =\n detailSession != null\n ? sessionTitle(detailSession)\n : selectedEntry != null\n ? sessionTitle(selectedEntry)\n : (selectedSessionId ?? 'Untitled session');\n\n const resumeIsCreateAgent =\n detailSession != null\n ? sessionIsCreateAgent(detailSession)\n : selectedEntry != null\n ? sessionIsCreateAgent(selectedEntry)\n : false;\n const resumeIsMutable =\n detailSession != null ? detailSession.isMutable : selectedEntry != null ? entryIsMutable(selectedEntry) : true;\n const resumeLabel = resumeIsCreateAgent ? 'Resume Agent building' : 'Resume Chat';\n const resumeHref =\n selectedSessionId != null && routes != null\n ? buildSessionResumeHref({ sessionId: selectedSessionId, routes })\n : null;\n\n const handleResume = () => {\n if (!canResume || selectedSessionId == null || shell == null) return;\n const agentName = detailSession?.agentName ?? selectedEntry?.agentName;\n shell.openHistorySession({\n sessionId: selectedSessionId,\n isMutable: resumeIsMutable,\n isCreateAgent: resumeIsCreateAgent,\n ...(agentName != null && agentName.length > 0 ? { agentName } : {}),\n });\n };\n\n const resumeProps =\n resumeHref != null ? { resumeHref, resumeLabel } : shell != null ? { onResume: handleResume, resumeLabel } : {};\n\n // Full empty only when nothing is selected — keep the detail pane for deep-linked sessionIds\n // (filters/time range can empty the list while share state still points at a session).\n if (\n !listLoading &&\n !listFailed &&\n entries.length === 0 &&\n (selectedSessionId == null || selectedSessionId.length === 0)\n ) {\n return (\n <EmptyScreen\n title=\"No Sessions Found\"\n description=\"There are no sessions available at the moment.\"\n className=\"bg-primary-bg\"\n />\n );\n }\n\n return (\n <Group\n id=\"agent-sessions-split\"\n orientation=\"horizontal\"\n className=\"h-full min-h-0 w-full\"\n resizeTargetMinimumSize={{ coarse: 24, fine: 11 }}\n >\n <Panel id=\"agent-sessions-list\" defaultSize=\"35%\" minSize=\"20%\" maxSize=\"50%\">\n <aside className=\"flex h-full min-h-0 w-full flex-col bg-sidebar-bg\">\n <div ref={setListEl} className=\"scrollbar-none min-h-0 flex-1 overflow-y-auto\">\n {listLoading ? (\n <div className=\"space-y-2 p-3\" role=\"status\" aria-label=\"Loading sessions\">\n {['a', 'b', 'c'].map(key => (\n <Skeleton key={key} className=\"h-16 rounded-md\" />\n ))}\n </div>\n ) : listFailed ? (\n <p className=\"px-3 py-6 text-center text-xs text-text-secondary\">Sessions could not be loaded.</p>\n ) : (\n entries.map(entry => (\n <AgentSessionListRow\n key={entry.id}\n title={sessionTitle(entry)}\n agentName={entry.agentName ?? undefined}\n sourceType={entrySourceType(entry)}\n lastActivityAt={entry.lastActivityAt}\n metrics={entry.metrics}\n active={entry.id === selectedSessionId}\n onSelect={() => selectSession(entry)}\n />\n ))\n )}\n\n {nextPageToken != null && !listLoading && !listFailed ? (\n <div ref={setSentinelEl} className=\"px-3 py-2\">\n {listLoadingMore ? (\n <Skeleton className=\"h-16 rounded-md\" role=\"status\" aria-label=\"Loading more sessions\" />\n ) : listLoadMoreFailed ? (\n <button\n type=\"button\"\n className=\"h-8 w-full rounded-md border border-border text-xs font-medium text-text-primary hover:bg-ghost-button-hover\"\n onClick={() => void loadMore()}\n >\n Retry loading sessions\n </button>\n ) : null}\n </div>\n ) : null}\n </div>\n </aside>\n </Panel>\n\n <Separator\n id=\"agent-sessions-resizer\"\n aria-label=\"Resize session list\"\n className=\"group/resizer relative z-10 w-0 cursor-col-resize focus-visible:outline-none\"\n >\n <div aria-hidden className=\"absolute inset-y-0 -left-1.25 w-2.75\" />\n <div aria-hidden className=\"absolute inset-y-0 left-0 w-px bg-border transition-colors\" />\n <div\n aria-hidden\n className={cn(\n 'absolute top-1/2 left-0 z-10 flex h-4 w-2 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-xs shadow-sm transition-colors',\n 'bg-secondary-button-bg text-text-secondary',\n 'group-hover/resizer:bg-primary-button-bg group-hover/resizer:text-primary-button-text',\n 'group-active/resizer:bg-primary-button-bg group-active/resizer:text-primary-button-text',\n 'group-focus-visible/resizer:bg-primary-button-bg group-focus-visible/resizer:text-primary-button-text',\n )}\n >\n <Icon name=\"grip-vertical\" size={10} />\n </div>\n </Separator>\n\n <Panel id=\"agent-session-detail\" defaultSize=\"65%\" minSize=\"30%\">\n <section className=\"flex h-full min-w-0 flex-col bg-primary-bg\">\n {selectedSessionId == null ? (\n <div className=\"flex flex-1 items-center justify-center px-6 text-sm text-text-secondary\">\n Select a session to view details\n </div>\n ) : detailFailed ? (\n <div className=\"flex flex-1 items-center justify-center px-6 text-sm text-text-secondary\">\n Session details could not be loaded.\n </div>\n ) : (\n <>\n <AgentSessionDetailHeader\n title={selectedTitle}\n sessionId={selectedSessionId}\n agentId={agentId}\n createdAt={detailSession?.createdAt ?? selectedEntry?.createdAt}\n view={shareView}\n onClose={clearSelectedSession}\n canResume={canResume}\n {...resumeProps}\n />\n {detailLoading || detailEvents === undefined ? (\n <div className=\"flex flex-1 flex-col p-4\" role=\"status\" aria-label=\"Loading session details\">\n <Skeleton className=\"min-h-64 flex-1 rounded-lg\" />\n </div>\n ) : (\n <AgentSessionTimelineContainer\n sessionId={selectedSessionId}\n events={detailEvents}\n listMetrics={selectedEntry?.metrics}\n />\n )}\n </>\n )}\n </section>\n </Panel>\n </Group>\n );\n}\n\ndeclare module '../../theme/SlotsProvider.js' {\n interface AtomSlots {\n AgentSessions: ComponentType<AgentSessionsProps>;\n }\n}\n","import type { ListResult } from '../server/types.js';\n\n/** Drain token-paginated list endpoints until `nextPageToken` is exhausted. */\nexport async function drainListPages<T>({\n fetchPage,\n}: {\n fetchPage: (pageToken?: string) => Promise<ListResult<T>>;\n}): Promise<T[]> {\n const items: T[] = [];\n let pageToken: string | undefined;\n do {\n const page = await fetchPage(pageToken);\n items.push(...page.data);\n pageToken = page.nextPageToken;\n } while (pageToken != null && pageToken.length > 0);\n return items;\n}\n"],"mappings":"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","names":[]}