@truefoundry/trueforge-ui 0.3.0-rc.0 → 0.3.0-rc.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/CHANGELOG.md +68 -0
- package/README.md +21 -6
- package/dist/AgentCodeSnippets-637HQUXD.js +74 -0
- package/dist/AgentCodeSnippets-637HQUXD.js.map +1 -0
- package/dist/AgentMetricChart-4FYECRIN.js +15 -0
- package/dist/AgentOverview-3FJ5EE6N.js +167 -0
- package/dist/AgentOverview-3FJ5EE6N.js.map +1 -0
- package/dist/AgentSessionEventTimeline-VELWUYPR.js +88 -0
- package/dist/AgentSessionEventTimeline-VELWUYPR.js.map +1 -0
- package/dist/AgentSessionEventTimelineChart-CUKETHWM.js +591 -0
- package/dist/AgentSessionEventTimelineChart-CUKETHWM.js.map +1 -0
- package/dist/AgentSessions-T7MOGOTZ.js +275 -0
- package/dist/AgentSessions-T7MOGOTZ.js.map +1 -0
- package/dist/{ConnectorSettings-FXQ5B7TN.js → ConnectorSettings-ESZ2RSRG.js} +19 -21
- package/dist/ConnectorSettings-ESZ2RSRG.js.map +1 -0
- package/dist/{DockLayout-LBNQJZNF.js → DockLayout-NLFNU6F2.js} +11 -10
- package/dist/{DockLayout-LBNQJZNF.js.map → DockLayout-NLFNU6F2.js.map} +1 -1
- package/dist/DrawerLayout-PR3SMKA6.js +184 -0
- package/dist/DrawerLayout-PR3SMKA6.js.map +1 -0
- package/dist/{ModelSettings-4L4LOQJA.js → ModelSettings-LYW64IRR.js} +20 -24
- package/dist/ModelSettings-LYW64IRR.js.map +1 -0
- package/dist/OpenUiFenceBlock-JEPNPJ7U.js +9 -0
- package/dist/OpenUiFenceBlock-JEPNPJ7U.js.map +1 -0
- package/dist/{SandboxSettings-Z4ZG6ZX4.js → SandboxSettings-DF64LHYI.js} +16 -18
- package/dist/SandboxSettings-DF64LHYI.js.map +1 -0
- package/dist/SchedulesPage-WQU4H25F.js +15 -0
- package/dist/SchedulesPage-WQU4H25F.js.map +1 -0
- package/dist/{SettingsBuilder-WF7ZWKQW.js → SettingsBuilder-LSXK2VN4.js} +26 -22
- package/dist/SettingsBuilder-LSXK2VN4.js.map +1 -0
- package/dist/ShellRouteSync-B22IAV2W.js +255 -0
- package/dist/ShellRouteSync-B22IAV2W.js.map +1 -0
- package/dist/SidebarLayout-XW6LXB7R.js +309 -0
- package/dist/SidebarLayout-XW6LXB7R.js.map +1 -0
- package/dist/{SkillSettings-3EPPC3IT.js → SkillSettings-64VXUO6J.js} +14 -15
- package/dist/SkillSettings-64VXUO6J.js.map +1 -0
- package/dist/{TrueForgeUIWithRouter-NZ4FGPE4.js → TrueForgeUIWithRouter-3TSLV22Q.js} +14 -10
- package/dist/{TrueForgeUIWithRouter-NZ4FGPE4.js.map → TrueForgeUIWithRouter-3TSLV22Q.js.map} +1 -1
- package/dist/{WidgetLayout-3QZ357FL.js → WidgetLayout-Q5P7PYSJ.js} +17 -13
- package/dist/WidgetLayout-Q5P7PYSJ.js.map +1 -0
- package/dist/chunk-5I2COQNL.js +119 -0
- package/dist/chunk-5I2COQNL.js.map +1 -0
- package/dist/chunk-BWHOZFIV.js +587 -0
- package/dist/chunk-BWHOZFIV.js.map +1 -0
- package/dist/chunk-DJUFS2BW.js +27 -0
- package/dist/chunk-DJUFS2BW.js.map +1 -0
- package/dist/chunk-FQK2XVVE.js +880 -0
- package/dist/chunk-FQK2XVVE.js.map +1 -0
- package/dist/chunk-G2TUAD65.js +555 -0
- package/dist/chunk-G2TUAD65.js.map +1 -0
- package/dist/chunk-GXYAOAK5.js +1357 -0
- package/dist/chunk-GXYAOAK5.js.map +1 -0
- package/dist/{chunk-FJ5RSSMA.js → chunk-H6WTY5PM.js} +196 -32
- package/dist/chunk-H6WTY5PM.js.map +1 -0
- package/dist/chunk-I3AL54MA.js +180 -0
- package/dist/chunk-I3AL54MA.js.map +1 -0
- package/dist/{chunk-WREC7D54.js → chunk-LGRHHFHN.js} +120 -32
- package/dist/chunk-LGRHHFHN.js.map +1 -0
- package/dist/chunk-NHHSZB5N.js +74 -0
- package/dist/chunk-NHHSZB5N.js.map +1 -0
- package/dist/{chunk-CFLVPV5M.js → chunk-QC42MLAK.js} +7 -2
- package/dist/chunk-QC42MLAK.js.map +1 -0
- package/dist/chunk-RDXBMTP5.js +32 -0
- package/dist/chunk-RDXBMTP5.js.map +1 -0
- package/dist/chunk-SFZNIO6U.js +18 -0
- package/dist/chunk-SFZNIO6U.js.map +1 -0
- package/dist/chunk-SQGT43Z3.js +200 -0
- package/dist/chunk-SQGT43Z3.js.map +1 -0
- package/dist/{chunk-B52K63AW.js → chunk-VJ7BZGAF.js} +2 -2
- package/dist/chunk-VUMGMGKZ.js +252 -0
- package/dist/chunk-VUMGMGKZ.js.map +1 -0
- package/dist/chunk-Y6S4OVVQ.js +16 -0
- package/dist/chunk-Y6S4OVVQ.js.map +1 -0
- package/dist/chunk-YQO2NMJ3.js +13341 -0
- package/dist/chunk-YQO2NMJ3.js.map +1 -0
- package/dist/{createTrueFoundryServer-B72bU-J7.d.ts → createTrueFoundryServer-CmZnBh_l.d.ts} +15 -4
- package/dist/index.d.ts +1024 -24
- package/dist/index.js +691 -67
- package/dist/index.js.map +1 -1
- package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +552 -8
- package/dist/plugins/trueforge-agent-server-adapter/index.js +504 -188
- package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +9 -8
- package/dist/ConnectorSettings-FXQ5B7TN.js.map +0 -1
- package/dist/DrawerLayout-Q6UK4VMI.js +0 -159
- package/dist/DrawerLayout-Q6UK4VMI.js.map +0 -1
- package/dist/ModelSettings-4L4LOQJA.js.map +0 -1
- package/dist/OpenUiFenceBlock-6UIIAVBX.js +0 -9
- package/dist/SandboxSettings-Z4ZG6ZX4.js.map +0 -1
- package/dist/SettingsBuilder-WF7ZWKQW.js.map +0 -1
- package/dist/ShellRouteSync-T4WLY57Q.js +0 -172
- package/dist/ShellRouteSync-T4WLY57Q.js.map +0 -1
- package/dist/SidebarLayout-3WZ3CVON.js +0 -256
- package/dist/SidebarLayout-3WZ3CVON.js.map +0 -1
- package/dist/SkillSettings-3EPPC3IT.js.map +0 -1
- package/dist/WidgetLayout-3QZ357FL.js.map +0 -1
- package/dist/chunk-36KOSC2J.js +0 -567
- package/dist/chunk-36KOSC2J.js.map +0 -1
- package/dist/chunk-3S6KHO7H.js +0 -2121
- package/dist/chunk-3S6KHO7H.js.map +0 -1
- package/dist/chunk-7L63OK3O.js +0 -91
- package/dist/chunk-7L63OK3O.js.map +0 -1
- package/dist/chunk-CFLVPV5M.js.map +0 -1
- package/dist/chunk-FJ5RSSMA.js.map +0 -1
- package/dist/chunk-OSV3HI5M.js +0 -6891
- package/dist/chunk-OSV3HI5M.js.map +0 -1
- package/dist/chunk-WQULF5AT.js +0 -460
- package/dist/chunk-WQULF5AT.js.map +0 -1
- package/dist/chunk-WREC7D54.js.map +0 -1
- package/dist/chunk-YIWUG6MC.js +0 -101
- package/dist/chunk-YIWUG6MC.js.map +0 -1
- package/dist/chunk-ZXOADNF3.js +0 -75
- package/dist/chunk-ZXOADNF3.js.map +0 -1
- /package/dist/{OpenUiFenceBlock-6UIIAVBX.js.map → AgentMetricChart-4FYECRIN.js.map} +0 -0
- /package/dist/{chunk-B52K63AW.js.map → chunk-VJ7BZGAF.js.map} +0 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
buildPath,
|
|
4
|
+
matchLocation,
|
|
5
|
+
placesEqual,
|
|
6
|
+
sanitizeSearchForPlace
|
|
7
|
+
} from "./chunk-SQGT43Z3.js";
|
|
8
|
+
import {
|
|
9
|
+
sessionIsCreateAgent
|
|
10
|
+
} from "./chunk-RDXBMTP5.js";
|
|
11
|
+
import "./chunk-NHHSZB5N.js";
|
|
12
|
+
import {
|
|
13
|
+
toEffectiveRoutes,
|
|
14
|
+
useOptionalAgentSessionsServer,
|
|
15
|
+
useOptionalCatalogServer,
|
|
16
|
+
useOptionalScheduleServer,
|
|
17
|
+
useOptionalServer,
|
|
18
|
+
useServerCapabilities,
|
|
19
|
+
useShellMode
|
|
20
|
+
} from "./chunk-FQK2XVVE.js";
|
|
21
|
+
|
|
22
|
+
// src/routing/ShellRouteSync.tsx
|
|
23
|
+
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
24
|
+
import { useLocation, useNavigate } from "react-router-dom";
|
|
25
|
+
|
|
26
|
+
// src/routing/derivePlace.ts
|
|
27
|
+
function deriveChatPlace(snapshot) {
|
|
28
|
+
const sessionId = snapshot.activeRemoteId ?? snapshot.pendingSessionId;
|
|
29
|
+
if (sessionId != null) return { type: "session", sessionId };
|
|
30
|
+
const { mode, agentConfigMode } = snapshot;
|
|
31
|
+
if (mode.status === "active" && !mode.isMutable && agentConfigMode !== "SingleAgent") {
|
|
32
|
+
const agentName = mode.agentName ?? mode.agentId;
|
|
33
|
+
if (agentName != null) return { type: "agent", agentName };
|
|
34
|
+
}
|
|
35
|
+
return { type: "root" };
|
|
36
|
+
}
|
|
37
|
+
function derivePlace(snapshot) {
|
|
38
|
+
if (snapshot.settingsOpen) return { type: "settings" };
|
|
39
|
+
if (snapshot.schedulesOpen) return { type: "schedules" };
|
|
40
|
+
if (snapshot.sessionsOpen) return { type: "sessionsBrowser" };
|
|
41
|
+
if (snapshot.libraryOpen && snapshot.libraryAgentId != null) {
|
|
42
|
+
return { type: "libraryAgent", agentId: snapshot.libraryAgentId };
|
|
43
|
+
}
|
|
44
|
+
if (snapshot.libraryOpen) return { type: "library" };
|
|
45
|
+
return deriveChatPlace(snapshot);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/routing/ShellRouteSync.tsx
|
|
49
|
+
function ShellRouteSync({
|
|
50
|
+
routes,
|
|
51
|
+
activeRemoteId,
|
|
52
|
+
initialSettingsOpen
|
|
53
|
+
}) {
|
|
54
|
+
const shell = useShellMode();
|
|
55
|
+
const server = useOptionalServer();
|
|
56
|
+
const catalog = useOptionalCatalogServer();
|
|
57
|
+
const sessions = useOptionalAgentSessionsServer();
|
|
58
|
+
const schedules = useOptionalScheduleServer();
|
|
59
|
+
const capabilities = useServerCapabilities();
|
|
60
|
+
const navigate = useNavigate();
|
|
61
|
+
const location = useLocation();
|
|
62
|
+
const effectiveRoutes = useMemo(
|
|
63
|
+
() => toEffectiveRoutes({ routes, catalog, capabilities, sessions, schedules }),
|
|
64
|
+
[routes, catalog, capabilities, sessions, schedules]
|
|
65
|
+
);
|
|
66
|
+
const settingsChromeEnabled = effectiveRoutes.settings != null;
|
|
67
|
+
const routeGatesKey = [
|
|
68
|
+
effectiveRoutes.settings,
|
|
69
|
+
effectiveRoutes.sessionsBrowser,
|
|
70
|
+
effectiveRoutes.libraryAgent,
|
|
71
|
+
effectiveRoutes.schedules
|
|
72
|
+
].join("\0");
|
|
73
|
+
const snapshot = {
|
|
74
|
+
settingsOpen: shell.settingsOpen,
|
|
75
|
+
libraryOpen: shell.libraryOpen,
|
|
76
|
+
sessionsOpen: shell.sessionsOpen,
|
|
77
|
+
libraryAgentId: shell.libraryAgentId,
|
|
78
|
+
schedulesOpen: shell.schedulesOpen,
|
|
79
|
+
pendingSessionId: shell.pendingSessionId,
|
|
80
|
+
activeRemoteId,
|
|
81
|
+
mode: shell.mode,
|
|
82
|
+
agentConfigMode: shell.agentConfigMode
|
|
83
|
+
};
|
|
84
|
+
const place = derivePlace(snapshot);
|
|
85
|
+
const placeKey = JSON.stringify(place);
|
|
86
|
+
const selfNavPathRef = useRef(null);
|
|
87
|
+
const prevPlaceRef = useRef(null);
|
|
88
|
+
const bootedRef = useRef(false);
|
|
89
|
+
const requestedSessionRef = useRef(null);
|
|
90
|
+
const shellSyncStartedRef = useRef(false);
|
|
91
|
+
const urlSyncStartedRef = useRef(false);
|
|
92
|
+
const openSession = useCallback(
|
|
93
|
+
(sessionId) => {
|
|
94
|
+
requestedSessionRef.current = sessionId;
|
|
95
|
+
if (server == null) {
|
|
96
|
+
shell.openHistorySession({ sessionId });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
void server.getSession({ sessionId }).then((session) => {
|
|
100
|
+
if (requestedSessionRef.current !== sessionId) return;
|
|
101
|
+
shell.openHistorySession({
|
|
102
|
+
sessionId,
|
|
103
|
+
isMutable: session.isMutable,
|
|
104
|
+
isCreateAgent: sessionIsCreateAgent(session),
|
|
105
|
+
...session.agentName != null ? { agentName: session.agentName } : {}
|
|
106
|
+
});
|
|
107
|
+
}).catch(() => {
|
|
108
|
+
if (requestedSessionRef.current !== sessionId) return;
|
|
109
|
+
shell.openHistorySession({ sessionId });
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
[server, shell]
|
|
113
|
+
);
|
|
114
|
+
const applyPlace = useCallback(
|
|
115
|
+
(target) => {
|
|
116
|
+
switch (target.type) {
|
|
117
|
+
case "settings":
|
|
118
|
+
shell.setSettingsOpen(true);
|
|
119
|
+
return;
|
|
120
|
+
case "library":
|
|
121
|
+
shell.setLibraryOpen(true);
|
|
122
|
+
return;
|
|
123
|
+
case "sessionsBrowser":
|
|
124
|
+
shell.setSessionsOpen(true);
|
|
125
|
+
return;
|
|
126
|
+
case "libraryAgent":
|
|
127
|
+
shell.openLibraryAgent(target.agentId);
|
|
128
|
+
return;
|
|
129
|
+
case "schedules":
|
|
130
|
+
shell.setSchedulesOpen(true);
|
|
131
|
+
return;
|
|
132
|
+
case "session":
|
|
133
|
+
shell.setLibraryOpen(false);
|
|
134
|
+
if (shell.pendingSessionId === target.sessionId || activeRemoteId === target.sessionId) return;
|
|
135
|
+
openSession(target.sessionId);
|
|
136
|
+
return;
|
|
137
|
+
case "agent":
|
|
138
|
+
shell.setLibraryOpen(false);
|
|
139
|
+
shell.selectLibraryAgent({ isMutable: false, agentName: target.agentName });
|
|
140
|
+
return;
|
|
141
|
+
case "root":
|
|
142
|
+
shell.setSettingsOpen(false);
|
|
143
|
+
shell.setLibraryOpen(false);
|
|
144
|
+
shell.setSchedulesOpen(false);
|
|
145
|
+
switch (shell.agentConfigMode) {
|
|
146
|
+
case "AgentLibrary":
|
|
147
|
+
shell.openLibraryHome();
|
|
148
|
+
return;
|
|
149
|
+
case "AgentComposer":
|
|
150
|
+
case "AgentLibraryWithComposer":
|
|
151
|
+
shell.openDraft();
|
|
152
|
+
return;
|
|
153
|
+
case "SingleAgent":
|
|
154
|
+
shell.clearChat();
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
[shell, activeRemoteId, openSession]
|
|
160
|
+
);
|
|
161
|
+
useEffect(() => {
|
|
162
|
+
if (bootedRef.current) return;
|
|
163
|
+
bootedRef.current = true;
|
|
164
|
+
const urlPlace = matchLocation({
|
|
165
|
+
pathname: location.pathname,
|
|
166
|
+
search: location.search,
|
|
167
|
+
routes: effectiveRoutes
|
|
168
|
+
}) ?? { type: "root" };
|
|
169
|
+
const settingsOnBoot = settingsChromeEnabled && (initialSettingsOpen || urlPlace.type === "settings");
|
|
170
|
+
if (urlPlace.type === "settings") {
|
|
171
|
+
if (settingsChromeEnabled) shell.setSettingsOpen(true);
|
|
172
|
+
} else if (urlPlace.type === "library") {
|
|
173
|
+
shell.setLibraryOpen(true);
|
|
174
|
+
} else if (urlPlace.type === "sessionsBrowser") {
|
|
175
|
+
shell.setSessionsOpen(true);
|
|
176
|
+
} else if (urlPlace.type === "libraryAgent") {
|
|
177
|
+
shell.openLibraryAgent(urlPlace.agentId);
|
|
178
|
+
} else if (urlPlace.type === "schedules") {
|
|
179
|
+
shell.setSchedulesOpen(true);
|
|
180
|
+
} else {
|
|
181
|
+
const chatPlace = deriveChatPlace(snapshot);
|
|
182
|
+
if (!placesEqual(chatPlace, urlPlace)) applyPlace(urlPlace);
|
|
183
|
+
if (settingsOnBoot) shell.setSettingsOpen(true);
|
|
184
|
+
}
|
|
185
|
+
const desiredPlace = settingsOnBoot ? { type: "settings" } : urlPlace;
|
|
186
|
+
const desiredPath = buildPath(desiredPlace, effectiveRoutes);
|
|
187
|
+
const desiredSearch = sanitizeSearchForPlace(desiredPlace, location.search);
|
|
188
|
+
prevPlaceRef.current = desiredPlace;
|
|
189
|
+
if (desiredPath != null && (desiredPath !== location.pathname || desiredSearch !== location.search)) {
|
|
190
|
+
selfNavPathRef.current = desiredPath !== location.pathname ? desiredPath : null;
|
|
191
|
+
navigate({ pathname: desiredPath, search: desiredSearch, hash: location.hash }, { replace: true });
|
|
192
|
+
}
|
|
193
|
+
}, []);
|
|
194
|
+
useEffect(() => {
|
|
195
|
+
if (!bootedRef.current) return;
|
|
196
|
+
if (!shellSyncStartedRef.current) {
|
|
197
|
+
shellSyncStartedRef.current = true;
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const target = buildPath(place, effectiveRoutes);
|
|
201
|
+
if (target == null) return;
|
|
202
|
+
const basename = effectiveRoutes.basename.endsWith("/") ? effectiveRoutes.basename.slice(0, -1) : effectiveRoutes.basename;
|
|
203
|
+
const browserPathname = `${basename}${location.pathname}` || "/";
|
|
204
|
+
const latestSearch = window.location.pathname === browserPathname ? window.location.search : location.search;
|
|
205
|
+
const targetSearch = sanitizeSearchForPlace(place, latestSearch);
|
|
206
|
+
const prev = prevPlaceRef.current;
|
|
207
|
+
prevPlaceRef.current = place;
|
|
208
|
+
if (target === location.pathname && targetSearch === location.search) return;
|
|
209
|
+
const replace = place.type === "session" && shell.pendingSessionId == null && prev != null && prev.type !== "session";
|
|
210
|
+
selfNavPathRef.current = target !== location.pathname ? target : null;
|
|
211
|
+
navigate({ pathname: target, search: targetSearch, hash: location.hash }, { replace });
|
|
212
|
+
}, [placeKey, routeGatesKey]);
|
|
213
|
+
useEffect(() => {
|
|
214
|
+
if (!bootedRef.current) return;
|
|
215
|
+
if (!urlSyncStartedRef.current) {
|
|
216
|
+
urlSyncStartedRef.current = true;
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (selfNavPathRef.current === location.pathname) {
|
|
220
|
+
selfNavPathRef.current = null;
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const urlPlace = matchLocation({
|
|
224
|
+
pathname: location.pathname,
|
|
225
|
+
search: location.search,
|
|
226
|
+
routes: effectiveRoutes
|
|
227
|
+
});
|
|
228
|
+
if (urlPlace == null) {
|
|
229
|
+
const rootPath = effectiveRoutes.root;
|
|
230
|
+
const rootSearch = sanitizeSearchForPlace({ type: "root" }, location.search);
|
|
231
|
+
selfNavPathRef.current = rootPath;
|
|
232
|
+
navigate({ pathname: rootPath, search: rootSearch, hash: location.hash }, { replace: true });
|
|
233
|
+
applyPlace({ type: "root" });
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (urlPlace.type !== "settings" && shell.settingsOpen) {
|
|
237
|
+
shell.setSettingsOpen(false);
|
|
238
|
+
}
|
|
239
|
+
if (urlPlace.type !== "library" && urlPlace.type !== "libraryAgent" && shell.libraryOpen) {
|
|
240
|
+
shell.setLibraryOpen(false);
|
|
241
|
+
}
|
|
242
|
+
if (urlPlace.type !== "sessionsBrowser" && shell.sessionsOpen) {
|
|
243
|
+
shell.setSessionsOpen(false);
|
|
244
|
+
}
|
|
245
|
+
if (urlPlace.type !== "schedules" && shell.schedulesOpen) {
|
|
246
|
+
shell.setSchedulesOpen(false);
|
|
247
|
+
}
|
|
248
|
+
applyPlace(urlPlace);
|
|
249
|
+
}, [location.pathname]);
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
export {
|
|
253
|
+
ShellRouteSync
|
|
254
|
+
};
|
|
255
|
+
//# sourceMappingURL=ShellRouteSync-B22IAV2W.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/routing/ShellRouteSync.tsx","../src/routing/derivePlace.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { useLocation, useNavigate } from 'react-router-dom';\n\nimport { sessionIsCreateAgent } from '../atoms/lib/sessionCreateAgent.js';\nimport {\n useOptionalAgentSessionsServer,\n useOptionalCatalogServer,\n useOptionalScheduleServer,\n useOptionalServer,\n useServerCapabilities,\n} from '../server/ServerContext.js';\nimport { useShellMode } from '../server/ShellModeContext.js';\nimport { toEffectiveRoutes } from '../server/serverChrome.js';\nimport { deriveChatPlace, derivePlace } from './derivePlace.js';\nimport { buildPath, matchLocation, placesEqual, sanitizeSearchForPlace } from './paths.js';\nimport type { ResolvedRoutes, RoutePlace, ShellSnapshot } from './types.js';\n\n/**\n * Single bidirectional bridge between shell state and the URL. Mounted under\n * `ShellModeProvider` but outside the keyed chat runtime so boot applies once.\n */\nexport function ShellRouteSync({\n routes,\n activeRemoteId,\n initialSettingsOpen,\n}: {\n routes: ResolvedRoutes;\n activeRemoteId: string | undefined;\n initialSettingsOpen: boolean;\n}) {\n const shell = useShellMode();\n const server = useOptionalServer();\n const catalog = useOptionalCatalogServer();\n const sessions = useOptionalAgentSessionsServer();\n const schedules = useOptionalScheduleServer();\n const capabilities = useServerCapabilities();\n const navigate = useNavigate();\n const location = useLocation();\n // Same gates as sidebar chrome: missing optional ports unregister their paths.\n const effectiveRoutes = useMemo(\n () => toEffectiveRoutes({ routes, catalog, capabilities, sessions, schedules }),\n [routes, catalog, capabilities, sessions, schedules],\n );\n const settingsChromeEnabled = effectiveRoutes.settings != null;\n // Gate identity only — avoid re-syncing when capabilities object identity churns\n // without changing which paths are registered (would clobber window share query).\n const routeGatesKey = [\n effectiveRoutes.settings,\n effectiveRoutes.sessionsBrowser,\n effectiveRoutes.libraryAgent,\n effectiveRoutes.schedules,\n ].join('\\0');\n\n const snapshot: ShellSnapshot = {\n settingsOpen: shell.settingsOpen,\n libraryOpen: shell.libraryOpen,\n sessionsOpen: shell.sessionsOpen,\n libraryAgentId: shell.libraryAgentId,\n schedulesOpen: shell.schedulesOpen,\n pendingSessionId: shell.pendingSessionId,\n activeRemoteId,\n mode: shell.mode,\n agentConfigMode: shell.agentConfigMode,\n };\n\n const place = derivePlace(snapshot);\n const placeKey = JSON.stringify(place);\n\n // Guards. `selfNavPathRef` marks a path we navigated to ourselves so the\n // URL->shell effect does not re-apply it. `prevPlaceRef` powers push/replace.\n const selfNavPathRef = useRef<string | null>(null);\n const prevPlaceRef = useRef<RoutePlace | null>(null);\n const bootedRef = useRef(false);\n // Latest session id the URL asked for, so slower lookups cannot bind over it.\n const requestedSessionRef = useRef<string | null>(null);\n // Boot owns the first URL; the ongoing effects skip their initial commit so\n // they do not fight boot with the stale first-render place.\n const shellSyncStartedRef = useRef(false);\n const urlSyncStartedRef = useRef(false);\n\n /**\n * A URL carries only the id, so ask the server whether it names a mutable\n * draft or an agent chat; guessing \"mutable\" opens an agent session as a\n * blank draft. `requestedSessionRef` drops replies a later place superseded.\n */\n const openSession = useCallback(\n (sessionId: string) => {\n requestedSessionRef.current = sessionId;\n if (server == null) {\n shell.openHistorySession({ sessionId });\n return;\n }\n void server\n .getSession({ sessionId })\n .then(session => {\n if (requestedSessionRef.current !== sessionId) return;\n shell.openHistorySession({\n sessionId,\n isMutable: session.isMutable,\n isCreateAgent: sessionIsCreateAgent(session),\n ...(session.agentName != null ? { agentName: session.agentName } : {}),\n });\n })\n .catch(() => {\n if (requestedSessionRef.current !== sessionId) return;\n // Unreachable session: bind by id alone rather than stranding the shell.\n shell.openHistorySession({ sessionId });\n });\n },\n [server, shell],\n );\n\n const applyPlace = useCallback(\n (target: RoutePlace) => {\n switch (target.type) {\n case 'settings':\n shell.setSettingsOpen(true);\n return;\n case 'library':\n shell.setLibraryOpen(true);\n return;\n case 'sessionsBrowser':\n shell.setSessionsOpen(true);\n return;\n case 'libraryAgent':\n shell.openLibraryAgent(target.agentId);\n return;\n case 'schedules':\n shell.setSchedulesOpen(true);\n return;\n case 'session':\n shell.setLibraryOpen(false);\n if (shell.pendingSessionId === target.sessionId || activeRemoteId === target.sessionId) return;\n openSession(target.sessionId);\n return;\n case 'agent':\n shell.setLibraryOpen(false);\n shell.selectLibraryAgent({ isMutable: false, agentName: target.agentName });\n return;\n case 'root':\n shell.setSettingsOpen(false);\n shell.setLibraryOpen(false);\n shell.setSchedulesOpen(false);\n switch (shell.agentConfigMode) {\n case 'AgentLibrary':\n shell.openLibraryHome();\n return;\n case 'AgentComposer':\n case 'AgentLibraryWithComposer':\n shell.openDraft();\n return;\n case 'SingleAgent':\n shell.clearChat();\n return;\n }\n }\n },\n [shell, activeRemoteId, openSession],\n );\n\n // Boot: URL wins, except an explicit `initialSettingsOpen` overlay. Boot is the\n // sole authority for the first commit and sets the final URL + `prevPlaceRef`.\n useEffect(() => {\n if (bootedRef.current) return;\n bootedRef.current = true;\n\n const urlPlace = matchLocation({\n pathname: location.pathname,\n search: location.search,\n routes: effectiveRoutes,\n }) ?? { type: 'root' };\n const settingsOnBoot = settingsChromeEnabled && (initialSettingsOpen || urlPlace.type === 'settings');\n\n if (urlPlace.type === 'settings') {\n if (settingsChromeEnabled) shell.setSettingsOpen(true);\n } else if (urlPlace.type === 'library') {\n shell.setLibraryOpen(true);\n } else if (urlPlace.type === 'sessionsBrowser') {\n shell.setSessionsOpen(true);\n } else if (urlPlace.type === 'libraryAgent') {\n shell.openLibraryAgent(urlPlace.agentId);\n } else if (urlPlace.type === 'schedules') {\n shell.setSchedulesOpen(true);\n } else {\n const chatPlace = deriveChatPlace(snapshot);\n if (!placesEqual(chatPlace, urlPlace)) applyPlace(urlPlace);\n if (settingsOnBoot) shell.setSettingsOpen(true);\n }\n\n const desiredPlace: RoutePlace = settingsOnBoot ? { type: 'settings' } : urlPlace;\n const desiredPath = buildPath(desiredPlace, effectiveRoutes);\n const desiredSearch = sanitizeSearchForPlace(desiredPlace, location.search);\n prevPlaceRef.current = desiredPlace;\n if (desiredPath != null && (desiredPath !== location.pathname || desiredSearch !== location.search)) {\n selfNavPathRef.current = desiredPath !== location.pathname ? desiredPath : null;\n navigate({ pathname: desiredPath, search: desiredSearch, hash: location.hash }, { replace: true });\n }\n // Boot runs once; snapshot is read imperatively here.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Shell -> URL: mirror the derived place. Skip the first commit (boot owns it).\n useEffect(() => {\n if (!bootedRef.current) return;\n if (!shellSyncStartedRef.current) {\n shellSyncStartedRef.current = true;\n return;\n }\n const target = buildPath(place, effectiveRoutes);\n if (target == null) return; // place has no configured URL (e.g. settings disabled)\n const basename = effectiveRoutes.basename.endsWith('/')\n ? effectiveRoutes.basename.slice(0, -1)\n : effectiveRoutes.basename;\n const browserPathname = `${basename}${location.pathname}` || '/';\n const latestSearch = window.location.pathname === browserPathname ? window.location.search : location.search;\n const targetSearch = sanitizeSearchForPlace(place, latestSearch);\n\n const prev = prevPlaceRef.current;\n prevPlaceRef.current = place;\n\n if (target === location.pathname && targetSearch === location.search) return;\n\n // Replace when a fresh chat just acquired its session id (same place, new id).\n const replace =\n place.type === 'session' && shell.pendingSessionId == null && prev != null && prev.type !== 'session';\n\n selfNavPathRef.current = target !== location.pathname ? target : null;\n // Query keys owned by other shell places are removed; host keys and hash survive.\n navigate({ pathname: target, search: targetSearch, hash: location.hash }, { replace });\n // location.pathname intentionally excluded: only react to shell-derived place changes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [placeKey, routeGatesKey]);\n\n // URL -> shell: apply on genuine location changes (Back/Forward, manual edits).\n useEffect(() => {\n if (!bootedRef.current) return;\n if (!urlSyncStartedRef.current) {\n urlSyncStartedRef.current = true;\n return;\n }\n if (selfNavPathRef.current === location.pathname) {\n selfNavPathRef.current = null;\n return;\n }\n const urlPlace = matchLocation({\n pathname: location.pathname,\n search: location.search,\n routes: effectiveRoutes,\n });\n if (urlPlace == null) {\n // Unknown path: normalize to root.\n const rootPath = effectiveRoutes.root;\n const rootSearch = sanitizeSearchForPlace({ type: 'root' }, location.search);\n selfNavPathRef.current = rootPath;\n navigate({ pathname: rootPath, search: rootSearch, hash: location.hash }, { replace: true });\n applyPlace({ type: 'root' });\n return;\n }\n if (urlPlace.type !== 'settings' && shell.settingsOpen) {\n // Leaving settings via Back to a chat place.\n shell.setSettingsOpen(false);\n }\n if (urlPlace.type !== 'library' && urlPlace.type !== 'libraryAgent' && shell.libraryOpen) {\n shell.setLibraryOpen(false);\n }\n if (urlPlace.type !== 'sessionsBrowser' && shell.sessionsOpen) {\n shell.setSessionsOpen(false);\n }\n if (urlPlace.type !== 'schedules' && shell.schedulesOpen) {\n // Leaving schedules via Back to a chat place.\n shell.setSchedulesOpen(false);\n }\n applyPlace(urlPlace);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [location.pathname]);\n\n return null;\n}\n","import type { RoutePlace, ShellSnapshot } from './types.js';\n\n/**\n * The chat place implied by shell state, ignoring settings, schedules,\n * sessions-browser, and library overlays.\n * SingleAgent canonicalizes to `root` so `/` and `/agents/{name}` alias.\n */\nexport function deriveChatPlace(snapshot: ShellSnapshot): RoutePlace {\n // The live thread wins: reusing a mutable shell switches thread without a\n // remount, leaving `pendingSessionId` on the session the shell last opened.\n // It only leads while a requested session has not reported its thread yet.\n const sessionId = snapshot.activeRemoteId ?? snapshot.pendingSessionId;\n if (sessionId != null) return { type: 'session', sessionId };\n\n const { mode, agentConfigMode } = snapshot;\n if (mode.status === 'active' && !mode.isMutable && agentConfigMode !== 'SingleAgent') {\n const agentName = mode.agentName ?? mode.agentId;\n if (agentName != null) return { type: 'agent', agentName };\n }\n return { type: 'root' };\n}\n\n/** Full place with overlay priority: settings, schedules, sessions, library, chat. */\nexport function derivePlace(snapshot: ShellSnapshot): RoutePlace {\n if (snapshot.settingsOpen) return { type: 'settings' };\n if (snapshot.schedulesOpen) return { type: 'schedules' };\n if (snapshot.sessionsOpen) return { type: 'sessionsBrowser' };\n if (snapshot.libraryOpen && snapshot.libraryAgentId != null) {\n return { type: 'libraryAgent', agentId: snapshot.libraryAgentId };\n }\n if (snapshot.libraryOpen) return { type: 'library' };\n return deriveChatPlace(snapshot);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
AgentConfigDrawerContainer,
|
|
4
|
+
NamedAgentHeaderLabel,
|
|
5
|
+
ShellActions
|
|
6
|
+
} from "./chunk-VUMGMGKZ.js";
|
|
7
|
+
import {
|
|
8
|
+
Thread
|
|
9
|
+
} from "./chunk-G2TUAD65.js";
|
|
10
|
+
import "./chunk-BSIPI3KV.js";
|
|
11
|
+
import {
|
|
12
|
+
resolveBrandChrome,
|
|
13
|
+
useChatHeaderContentVisible,
|
|
14
|
+
useIsMobile,
|
|
15
|
+
useSlot
|
|
16
|
+
} from "./chunk-YQO2NMJ3.js";
|
|
17
|
+
import "./chunk-NHHSZB5N.js";
|
|
18
|
+
import {
|
|
19
|
+
Icon,
|
|
20
|
+
PageHeader,
|
|
21
|
+
Spinner,
|
|
22
|
+
auiButtonClass,
|
|
23
|
+
sidebarRailButtonClassName
|
|
24
|
+
} from "./chunk-H6WTY5PM.js";
|
|
25
|
+
import {
|
|
26
|
+
shellIsCreateAgent,
|
|
27
|
+
useOptionalShellMode
|
|
28
|
+
} from "./chunk-FQK2XVVE.js";
|
|
29
|
+
import {
|
|
30
|
+
useAui
|
|
31
|
+
} from "./chunk-M6MHLVSO.js";
|
|
32
|
+
import "./chunk-VJ7BZGAF.js";
|
|
33
|
+
import {
|
|
34
|
+
cn,
|
|
35
|
+
useBrand
|
|
36
|
+
} from "./chunk-BWHOZFIV.js";
|
|
37
|
+
|
|
38
|
+
// src/layouts/SidebarLayout.tsx
|
|
39
|
+
import {
|
|
40
|
+
lazy,
|
|
41
|
+
Suspense,
|
|
42
|
+
useEffect,
|
|
43
|
+
useRef,
|
|
44
|
+
useState
|
|
45
|
+
} from "react";
|
|
46
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
47
|
+
var TruefoundrySettingsBuilder = lazy(() => import("./SettingsBuilder-LSXK2VN4.js"));
|
|
48
|
+
var SchedulesPage = lazy(
|
|
49
|
+
() => import("./SchedulesPage-WQU4H25F.js").then((m) => ({ default: m.SchedulesPage }))
|
|
50
|
+
);
|
|
51
|
+
var brandLogoClassName = "h-5 w-5 max-w-40 shrink-0 object-contain";
|
|
52
|
+
var railWidthClassName = "w-18";
|
|
53
|
+
var railActionButtonClassName = cn(sidebarRailButtonClassName, "text-sidebar-text");
|
|
54
|
+
var railSelectedClassName = "bg-primary-button-bg font-medium text-primary-button-text hover:bg-primary-button-hover hover:text-primary-button-text";
|
|
55
|
+
function SidebarNav() {
|
|
56
|
+
const aui = useAui();
|
|
57
|
+
const shell = useOptionalShellMode();
|
|
58
|
+
const AgentsLibraryButton = useSlot("AgentsLibraryButton");
|
|
59
|
+
const SessionsBrowserButton = useSlot("SessionsBrowserButton");
|
|
60
|
+
const SchedulesButton = useSlot("SchedulesButton");
|
|
61
|
+
const showNewActions = shell?.isNewChatEnabled !== false;
|
|
62
|
+
const overlayOpen = shell?.settingsOpen === true || shell?.libraryOpen === true || shell?.sessionsOpen === true || shell?.schedulesOpen === true;
|
|
63
|
+
const mode = shell?.mode;
|
|
64
|
+
const newChatSelected = !overlayOpen && mode?.status === "active" && mode.isMutable && !mode.isCreateAgent;
|
|
65
|
+
const newAgentSelected = !overlayOpen && mode != null && shellIsCreateAgent(mode);
|
|
66
|
+
const handleNewChat = () => {
|
|
67
|
+
shell?.setLibraryOpen(false);
|
|
68
|
+
shell?.setSessionsOpen(false);
|
|
69
|
+
if (shell?.isComposerEnabled) {
|
|
70
|
+
shell.openDraft();
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
shell?.setSettingsOpen(false);
|
|
74
|
+
shell?.setSchedulesOpen(false);
|
|
75
|
+
void Promise.resolve(aui.threads().switchToNewThread()).catch(() => void 0);
|
|
76
|
+
};
|
|
77
|
+
const handleNewAgent = () => {
|
|
78
|
+
shell?.setLibraryOpen(false);
|
|
79
|
+
shell?.setSessionsOpen(false);
|
|
80
|
+
if (shell?.isComposerEnabled) {
|
|
81
|
+
shell.openAgentBuilder();
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
return /* @__PURE__ */ jsxs("nav", { className: "flex min-h-0 flex-1 flex-col items-center gap-1 p-1", "aria-label": "Sidebar", children: [
|
|
85
|
+
showNewActions ? /* @__PURE__ */ jsxs(
|
|
86
|
+
"button",
|
|
87
|
+
{
|
|
88
|
+
type: "button",
|
|
89
|
+
"aria-label": "Start new chat",
|
|
90
|
+
title: "New chat",
|
|
91
|
+
"aria-current": newChatSelected ? "page" : void 0,
|
|
92
|
+
className: auiButtonClass({
|
|
93
|
+
variant: "ghost",
|
|
94
|
+
className: cn(railActionButtonClassName, newChatSelected && railSelectedClassName)
|
|
95
|
+
}),
|
|
96
|
+
onClick: handleNewChat,
|
|
97
|
+
children: [
|
|
98
|
+
/* @__PURE__ */ jsx(Icon, { name: "square-pen", size: 14 }),
|
|
99
|
+
/* @__PURE__ */ jsx("span", { className: "text-center", children: "New Chat" })
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
) : null,
|
|
103
|
+
showNewActions && shell?.isComposerEnabled ? /* @__PURE__ */ jsxs(
|
|
104
|
+
"button",
|
|
105
|
+
{
|
|
106
|
+
type: "button",
|
|
107
|
+
"aria-label": "Start new agent",
|
|
108
|
+
title: "New Agent",
|
|
109
|
+
"aria-current": newAgentSelected ? "page" : void 0,
|
|
110
|
+
className: auiButtonClass({
|
|
111
|
+
variant: "ghost",
|
|
112
|
+
className: cn(railActionButtonClassName, newAgentSelected && railSelectedClassName)
|
|
113
|
+
}),
|
|
114
|
+
onClick: handleNewAgent,
|
|
115
|
+
children: [
|
|
116
|
+
/* @__PURE__ */ jsx(Icon, { name: "agent-2", size: 14 }),
|
|
117
|
+
/* @__PURE__ */ jsx("span", { className: "text-center", children: "New Agent" })
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
) : null,
|
|
121
|
+
/* @__PURE__ */ jsx(AgentsLibraryButton, { compact: true }),
|
|
122
|
+
/* @__PURE__ */ jsx(SessionsBrowserButton, { compact: true }),
|
|
123
|
+
/* @__PURE__ */ jsx(SchedulesButton, { compact: true })
|
|
124
|
+
] });
|
|
125
|
+
}
|
|
126
|
+
function SidebarRail({
|
|
127
|
+
onNavigate,
|
|
128
|
+
className,
|
|
129
|
+
railRef,
|
|
130
|
+
...dialogProps
|
|
131
|
+
}) {
|
|
132
|
+
const brand = useBrand();
|
|
133
|
+
const chrome = resolveBrandChrome(brand);
|
|
134
|
+
const BrandLogo = useSlot("BrandLogo");
|
|
135
|
+
return /* @__PURE__ */ jsxs(
|
|
136
|
+
"aside",
|
|
137
|
+
{
|
|
138
|
+
ref: railRef,
|
|
139
|
+
className: cn(
|
|
140
|
+
railWidthClassName,
|
|
141
|
+
"flex min-h-0 shrink-0 flex-col border-r border-border bg-sidebar-bg",
|
|
142
|
+
className
|
|
143
|
+
),
|
|
144
|
+
onClick: (event) => {
|
|
145
|
+
if (onNavigate == null) return;
|
|
146
|
+
const target = event.target;
|
|
147
|
+
if (!(target instanceof Element)) return;
|
|
148
|
+
if (target.closest("button") != null) onNavigate();
|
|
149
|
+
},
|
|
150
|
+
...dialogProps,
|
|
151
|
+
children: [
|
|
152
|
+
/* @__PURE__ */ jsx("div", { className: "flex h-14 w-full shrink-0 items-center justify-center text-text-primary", children: /* @__PURE__ */ jsx(BrandLogo, { variant: chrome.collapsedVariant, className: brandLogoClassName }) }),
|
|
153
|
+
/* @__PURE__ */ jsx(SidebarNav, {}),
|
|
154
|
+
/* @__PURE__ */ jsx("footer", { className: "flex shrink-0 flex-col items-center border-border p-2", children: /* @__PURE__ */ jsx(ShellActions, { labeled: true, className: "flex-col" }) })
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
function SidebarLayout({ className }) {
|
|
160
|
+
const shell = useOptionalShellMode();
|
|
161
|
+
const isMobile = useIsMobile();
|
|
162
|
+
const AgentDetailsPage = useSlot("AgentDetailsPage");
|
|
163
|
+
const AgentsLibrary = useSlot("AgentsLibrary");
|
|
164
|
+
const SessionsPage = useSlot("SessionsPage");
|
|
165
|
+
const ClearChatButton = useSlot("ClearChatButton");
|
|
166
|
+
const SaveAgentButton = useSlot("SaveAgentButton");
|
|
167
|
+
const SelectAgentEmptyState = useSlot("SelectAgentEmptyState");
|
|
168
|
+
const [mobileNavOpen, setMobileNavOpen] = useState(false);
|
|
169
|
+
const menuBtnRef = useRef(null);
|
|
170
|
+
const dialogRef = useRef(null);
|
|
171
|
+
const mainRef = useRef(null);
|
|
172
|
+
const wasOpen = useRef(false);
|
|
173
|
+
const isIdle = shell?.mode.status === "idle";
|
|
174
|
+
const settingsOpen = shell?.settingsOpen === true;
|
|
175
|
+
const libraryOpen = shell?.libraryOpen === true;
|
|
176
|
+
const sessionsOpen = shell?.sessionsOpen === true;
|
|
177
|
+
const schedulesOpen = shell?.schedulesOpen === true;
|
|
178
|
+
const overlayOpen = settingsOpen || libraryOpen || sessionsOpen || schedulesOpen;
|
|
179
|
+
const showAgentConfig = shell != null && shellIsCreateAgent(shell.mode) && !overlayOpen && (!isMobile || shell.agentConfigOpen);
|
|
180
|
+
const hasChatHeaderContent = useChatHeaderContentVisible();
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
if (!mobileNavOpen) return;
|
|
183
|
+
const onKeyDown = (event) => {
|
|
184
|
+
if (event.key === "Escape") setMobileNavOpen(false);
|
|
185
|
+
};
|
|
186
|
+
window.addEventListener("keydown", onKeyDown);
|
|
187
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
188
|
+
}, [mobileNavOpen]);
|
|
189
|
+
useEffect(() => {
|
|
190
|
+
const main = mainRef.current;
|
|
191
|
+
if (mobileNavOpen) {
|
|
192
|
+
wasOpen.current = true;
|
|
193
|
+
if (main) main.inert = true;
|
|
194
|
+
dialogRef.current?.focus();
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (wasOpen.current) {
|
|
198
|
+
if (main) main.inert = false;
|
|
199
|
+
menuBtnRef.current?.focus();
|
|
200
|
+
wasOpen.current = false;
|
|
201
|
+
}
|
|
202
|
+
}, [mobileNavOpen]);
|
|
203
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative flex h-full min-h-0 w-full min-w-0", className), children: [
|
|
204
|
+
/* @__PURE__ */ jsx(SidebarRail, { className: "hidden md:flex" }),
|
|
205
|
+
showAgentConfig ? /* @__PURE__ */ jsx(
|
|
206
|
+
"aside",
|
|
207
|
+
{
|
|
208
|
+
role: "dialog",
|
|
209
|
+
"aria-label": "Agent Config",
|
|
210
|
+
className: "absolute inset-y-0 left-0 z-20 w-full max-w-sm border-r border-border shadow-xl md:static md:z-auto md:w-88 md:max-w-none md:shrink-0 md:shadow-none",
|
|
211
|
+
children: /* @__PURE__ */ jsx(AgentConfigDrawerContainer, { showClose: isMobile })
|
|
212
|
+
}
|
|
213
|
+
) : null,
|
|
214
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col bg-primary-bg", children: [
|
|
215
|
+
/* @__PURE__ */ jsx(
|
|
216
|
+
PageHeader,
|
|
217
|
+
{
|
|
218
|
+
className: cn(
|
|
219
|
+
"bg-topbar-bg",
|
|
220
|
+
// Desktop: hide when settings/idle or the thread header has nothing to show
|
|
221
|
+
// (empty untitled draft). Mobile still needs the menu button.
|
|
222
|
+
// Builder mode keeps New Agent and its actions beside the persistent config.
|
|
223
|
+
(overlayOpen || isIdle || !hasChatHeaderContent) && "md:hidden"
|
|
224
|
+
),
|
|
225
|
+
start: !overlayOpen ? /* @__PURE__ */ jsx(
|
|
226
|
+
"button",
|
|
227
|
+
{
|
|
228
|
+
ref: menuBtnRef,
|
|
229
|
+
type: "button",
|
|
230
|
+
"aria-label": "Navigation",
|
|
231
|
+
"aria-expanded": mobileNavOpen,
|
|
232
|
+
className: cn(auiButtonClass({ variant: "ghost", size: "icon" }), "md:hidden"),
|
|
233
|
+
onClick: () => setMobileNavOpen(true),
|
|
234
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "bars" })
|
|
235
|
+
}
|
|
236
|
+
) : null,
|
|
237
|
+
title: !overlayOpen ? /* @__PURE__ */ jsx(NamedAgentHeaderLabel, {}) : null,
|
|
238
|
+
end: !overlayOpen ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
239
|
+
/* @__PURE__ */ jsx(ClearChatButton, {}),
|
|
240
|
+
/* @__PURE__ */ jsx(SaveAgentButton, {})
|
|
241
|
+
] }) : null
|
|
242
|
+
}
|
|
243
|
+
),
|
|
244
|
+
/* @__PURE__ */ jsx("div", { ref: mainRef, className: "min-h-0 min-w-0 flex-1", children: settingsOpen ? /* @__PURE__ */ jsx(
|
|
245
|
+
Suspense,
|
|
246
|
+
{
|
|
247
|
+
fallback: /* @__PURE__ */ jsxs(
|
|
248
|
+
"div",
|
|
249
|
+
{
|
|
250
|
+
className: "flex h-full items-center justify-center",
|
|
251
|
+
role: "status",
|
|
252
|
+
"aria-live": "polite",
|
|
253
|
+
"aria-busy": "true",
|
|
254
|
+
children: [
|
|
255
|
+
/* @__PURE__ */ jsx(Spinner, { size: 28, className: "text-text-primary" }),
|
|
256
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
257
|
+
]
|
|
258
|
+
}
|
|
259
|
+
),
|
|
260
|
+
children: /* @__PURE__ */ jsx(TruefoundrySettingsBuilder, {})
|
|
261
|
+
}
|
|
262
|
+
) : sessionsOpen ? /* @__PURE__ */ jsx(SessionsPage, {}) : libraryOpen && shell?.libraryAgentId != null ? /* @__PURE__ */ jsx(AgentDetailsPage, { agentId: shell.libraryAgentId }, shell.libraryAgentId) : libraryOpen ? /* @__PURE__ */ jsx(AgentsLibrary, { onSelectAgent: () => setMobileNavOpen(false) }) : schedulesOpen ? /* @__PURE__ */ jsx(
|
|
263
|
+
Suspense,
|
|
264
|
+
{
|
|
265
|
+
fallback: /* @__PURE__ */ jsxs(
|
|
266
|
+
"div",
|
|
267
|
+
{
|
|
268
|
+
className: "flex h-full items-center justify-center",
|
|
269
|
+
role: "status",
|
|
270
|
+
"aria-live": "polite",
|
|
271
|
+
"aria-busy": "true",
|
|
272
|
+
children: [
|
|
273
|
+
/* @__PURE__ */ jsx(Spinner, { size: 28, className: "text-text-primary" }),
|
|
274
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
275
|
+
]
|
|
276
|
+
}
|
|
277
|
+
),
|
|
278
|
+
children: /* @__PURE__ */ jsx(SchedulesPage, {})
|
|
279
|
+
}
|
|
280
|
+
) : isIdle ? /* @__PURE__ */ jsx(SelectAgentEmptyState, {}) : /* @__PURE__ */ jsx(Thread, {}) })
|
|
281
|
+
] }),
|
|
282
|
+
mobileNavOpen ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
283
|
+
/* @__PURE__ */ jsx(
|
|
284
|
+
"button",
|
|
285
|
+
{
|
|
286
|
+
type: "button",
|
|
287
|
+
"aria-label": "Close navigation",
|
|
288
|
+
className: "absolute inset-0 z-[9] cursor-pointer bg-[var(--overlay)] md:hidden",
|
|
289
|
+
onClick: () => setMobileNavOpen(false)
|
|
290
|
+
}
|
|
291
|
+
),
|
|
292
|
+
/* @__PURE__ */ jsx(
|
|
293
|
+
SidebarRail,
|
|
294
|
+
{
|
|
295
|
+
railRef: dialogRef,
|
|
296
|
+
role: "dialog",
|
|
297
|
+
"aria-label": "Navigation",
|
|
298
|
+
tabIndex: -1,
|
|
299
|
+
onNavigate: () => setMobileNavOpen(false),
|
|
300
|
+
className: "absolute inset-y-0 left-0 z-10 shadow-lg outline-none md:hidden"
|
|
301
|
+
}
|
|
302
|
+
)
|
|
303
|
+
] }) : null
|
|
304
|
+
] });
|
|
305
|
+
}
|
|
306
|
+
export {
|
|
307
|
+
SidebarLayout
|
|
308
|
+
};
|
|
309
|
+
//# sourceMappingURL=SidebarLayout-XW6LXB7R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/layouts/SidebarLayout.tsx"],"sourcesContent":["'use client';\n\nimport {\n lazy,\n Suspense,\n useEffect,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type ReactNode,\n type Ref,\n} from 'react';\n\nimport { useAui } from '../assistant-ui.js';\nimport { auiButtonClass, sidebarRailButtonClassName } from '../atoms/lib/buttonClasses.js';\nimport { cn } from '../atoms/lib/cn.js';\nimport { useIsMobile } from '../atoms/lib/useIsMobile.js';\nimport { NamedAgentHeaderLabel } from '../atoms/NamedAgentHeaderLabel.js';\nimport { PageHeader } from '../atoms/PageHeader.js';\nimport { Spinner } from '../atoms/primitives/Spinner.js';\nimport { ShellActions } from '../atoms/ShellActions.js';\nimport { AgentConfigDrawerContainer } from '../containers/AgentConfigDrawerContainer.js';\nimport { Thread } from '../containers/Thread.js';\nimport { useChatHeaderContentVisible } from '../hooks/useChatChromeActionsVisible.js';\nimport { Icon } from '../icons/Icon.js';\nimport { shellIsCreateAgent, useOptionalShellMode } from '../server/ShellModeContext.js';\nimport { resolveBrandChrome } from '../theme/brand.js';\nimport { useSlot } from '../theme/SlotsProvider.js';\nimport { useBrand } from '../theme/ThemeProvider.js';\n\nconst TruefoundrySettingsBuilder = lazy(() => import('../containers/SettingsBuilder/index.js'));\nconst SchedulesPage = lazy(() =>\n import('../atoms/schedules/SchedulesPage.js').then(m => ({ default: m.SchedulesPage })),\n);\n\nconst brandLogoClassName = 'h-5 w-5 max-w-40 shrink-0 object-contain';\nconst railWidthClassName = 'w-18';\n\nconst railActionButtonClassName = cn(sidebarRailButtonClassName, 'text-sidebar-text');\n\nconst railSelectedClassName =\n 'bg-primary-button-bg font-medium text-primary-button-text hover:bg-primary-button-hover hover:text-primary-button-text';\n\nfunction SidebarNav(): ReactNode {\n const aui = useAui();\n const shell = useOptionalShellMode();\n const AgentsLibraryButton = useSlot('AgentsLibraryButton');\n const SessionsBrowserButton = useSlot('SessionsBrowserButton');\n const SchedulesButton = useSlot('SchedulesButton');\n const showNewActions = shell?.isNewChatEnabled !== false;\n const overlayOpen =\n shell?.settingsOpen === true ||\n shell?.libraryOpen === true ||\n shell?.sessionsOpen === true ||\n shell?.schedulesOpen === true;\n const mode = shell?.mode;\n const newChatSelected = !overlayOpen && mode?.status === 'active' && mode.isMutable && !mode.isCreateAgent;\n const newAgentSelected = !overlayOpen && mode != null && shellIsCreateAgent(mode);\n\n const handleNewChat = () => {\n shell?.setLibraryOpen(false);\n shell?.setSessionsOpen(false);\n if (shell?.isComposerEnabled) {\n shell.openDraft();\n return;\n }\n shell?.setSettingsOpen(false);\n shell?.setSchedulesOpen(false);\n void Promise.resolve(aui.threads().switchToNewThread()).catch(() => undefined);\n };\n\n const handleNewAgent = () => {\n shell?.setLibraryOpen(false);\n shell?.setSessionsOpen(false);\n if (shell?.isComposerEnabled) {\n shell.openAgentBuilder();\n }\n };\n\n return (\n <nav className=\"flex min-h-0 flex-1 flex-col items-center gap-1 p-1\" aria-label=\"Sidebar\">\n {showNewActions ? (\n <button\n type=\"button\"\n aria-label=\"Start new chat\"\n title=\"New chat\"\n aria-current={newChatSelected ? 'page' : undefined}\n className={auiButtonClass({\n variant: 'ghost',\n className: cn(railActionButtonClassName, newChatSelected && railSelectedClassName),\n })}\n onClick={handleNewChat}\n >\n <Icon name=\"square-pen\" size={14} />\n <span className=\"text-center\">New Chat</span>\n </button>\n ) : null}\n {showNewActions && shell?.isComposerEnabled ? (\n <button\n type=\"button\"\n aria-label=\"Start new agent\"\n title=\"New Agent\"\n aria-current={newAgentSelected ? 'page' : undefined}\n className={auiButtonClass({\n variant: 'ghost',\n className: cn(railActionButtonClassName, newAgentSelected && railSelectedClassName),\n })}\n onClick={handleNewAgent}\n >\n <Icon name=\"agent-2\" size={14} />\n <span className=\"text-center\">New Agent</span>\n </button>\n ) : null}\n <AgentsLibraryButton compact />\n <SessionsBrowserButton compact />\n <SchedulesButton compact />\n </nav>\n );\n}\n\n/** Shared desktop + mobile icon+label rail (brand, nav, footer actions). */\nfunction SidebarRail({\n onNavigate,\n className,\n railRef,\n ...dialogProps\n}: {\n onNavigate?: () => void;\n className?: string;\n railRef?: Ref<HTMLElement>;\n} & Omit<ComponentPropsWithoutRef<'aside'>, 'children' | 'className'>): ReactNode {\n const brand = useBrand();\n const chrome = resolveBrandChrome(brand);\n const BrandLogo = useSlot('BrandLogo');\n\n return (\n <aside\n ref={railRef}\n className={cn(\n railWidthClassName,\n 'flex min-h-0 shrink-0 flex-col border-r border-border bg-sidebar-bg',\n className,\n )}\n onClick={event => {\n if (onNavigate == null) return;\n const target = event.target;\n if (!(target instanceof Element)) return;\n if (target.closest('button') != null) onNavigate();\n }}\n {...dialogProps}\n >\n <div className=\"flex h-14 w-full shrink-0 items-center justify-center text-text-primary\">\n <BrandLogo variant={chrome.collapsedVariant} className={brandLogoClassName} />\n </div>\n <SidebarNav />\n <footer className=\"flex shrink-0 flex-col items-center border-border p-2\">\n <ShellActions labeled className=\"flex-col\" />\n </footer>\n </aside>\n );\n}\n\nexport function SidebarLayout({ className }: { className?: string }) {\n const shell = useOptionalShellMode();\n const isMobile = useIsMobile();\n const AgentDetailsPage = useSlot('AgentDetailsPage');\n const AgentsLibrary = useSlot('AgentsLibrary');\n const SessionsPage = useSlot('SessionsPage');\n const ClearChatButton = useSlot('ClearChatButton');\n const SaveAgentButton = useSlot('SaveAgentButton');\n const SelectAgentEmptyState = useSlot('SelectAgentEmptyState');\n const [mobileNavOpen, setMobileNavOpen] = useState(false);\n const menuBtnRef = useRef<HTMLButtonElement>(null);\n const dialogRef = useRef<HTMLElement>(null);\n const mainRef = useRef<HTMLDivElement>(null);\n const wasOpen = useRef(false);\n const isIdle = shell?.mode.status === 'idle';\n const settingsOpen = shell?.settingsOpen === true;\n const libraryOpen = shell?.libraryOpen === true;\n const sessionsOpen = shell?.sessionsOpen === true;\n const schedulesOpen = shell?.schedulesOpen === true;\n const overlayOpen = settingsOpen || libraryOpen || sessionsOpen || schedulesOpen;\n const showAgentConfig =\n shell != null && shellIsCreateAgent(shell.mode) && !overlayOpen && (!isMobile || shell.agentConfigOpen);\n const hasChatHeaderContent = useChatHeaderContentVisible();\n\n useEffect(() => {\n if (!mobileNavOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') setMobileNavOpen(false);\n };\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [mobileNavOpen]);\n\n useEffect(() => {\n const main = mainRef.current;\n if (mobileNavOpen) {\n wasOpen.current = true;\n if (main) main.inert = true;\n dialogRef.current?.focus();\n return;\n }\n if (wasOpen.current) {\n if (main) main.inert = false;\n menuBtnRef.current?.focus();\n wasOpen.current = false;\n }\n }, [mobileNavOpen]);\n\n return (\n <div className={cn('relative flex h-full min-h-0 w-full min-w-0', className)}>\n <SidebarRail className=\"hidden md:flex\" />\n\n {showAgentConfig ? (\n <aside\n role=\"dialog\"\n aria-label=\"Agent Config\"\n className=\"absolute inset-y-0 left-0 z-20 w-full max-w-sm border-r border-border shadow-xl md:static md:z-auto md:w-88 md:max-w-none md:shrink-0 md:shadow-none\"\n >\n <AgentConfigDrawerContainer showClose={isMobile} />\n </aside>\n ) : null}\n\n <div className=\"flex min-h-0 min-w-0 flex-1 flex-col bg-primary-bg\">\n {/* Desktop keeps shell chrome in the rail footer (always mounted, including\n when visually hidden on small screens so host action-slot state persists).\n Mobile reaches theme/settings via the nav drawer rail. */}\n <PageHeader\n className={cn(\n 'bg-topbar-bg',\n // Desktop: hide when settings/idle or the thread header has nothing to show\n // (empty untitled draft). Mobile still needs the menu button.\n // Builder mode keeps New Agent and its actions beside the persistent config.\n (overlayOpen || isIdle || !hasChatHeaderContent) && 'md:hidden',\n )}\n start={\n !overlayOpen ? (\n <button\n ref={menuBtnRef}\n type=\"button\"\n aria-label=\"Navigation\"\n aria-expanded={mobileNavOpen}\n className={cn(auiButtonClass({ variant: 'ghost', size: 'icon' }), 'md:hidden')}\n onClick={() => setMobileNavOpen(true)}\n >\n <Icon name=\"bars\" />\n </button>\n ) : null\n }\n title={!overlayOpen ? <NamedAgentHeaderLabel /> : null}\n end={\n !overlayOpen ? (\n <>\n <ClearChatButton />\n <SaveAgentButton />\n </>\n ) : null\n }\n />\n\n <div ref={mainRef} className=\"min-h-0 min-w-0 flex-1\">\n {settingsOpen ? (\n <Suspense\n fallback={\n <div\n className=\"flex h-full items-center justify-center\"\n role=\"status\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n >\n <Spinner size={28} className=\"text-text-primary\" />\n <span className=\"sr-only\">Loading</span>\n </div>\n }\n >\n <TruefoundrySettingsBuilder />\n </Suspense>\n ) : sessionsOpen ? (\n <SessionsPage />\n ) : libraryOpen && shell?.libraryAgentId != null ? (\n <AgentDetailsPage key={shell.libraryAgentId} agentId={shell.libraryAgentId} />\n ) : libraryOpen ? (\n <AgentsLibrary onSelectAgent={() => setMobileNavOpen(false)} />\n ) : schedulesOpen ? (\n <Suspense\n fallback={\n <div\n className=\"flex h-full items-center justify-center\"\n role=\"status\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n >\n <Spinner size={28} className=\"text-text-primary\" />\n <span className=\"sr-only\">Loading</span>\n </div>\n }\n >\n <SchedulesPage />\n </Suspense>\n ) : isIdle ? (\n <SelectAgentEmptyState />\n ) : (\n <Thread />\n )}\n </div>\n </div>\n\n {/* Mobile: same narrow rail as desktop */}\n {mobileNavOpen ? (\n <>\n <button\n type=\"button\"\n aria-label=\"Close navigation\"\n className=\"absolute inset-0 z-[9] cursor-pointer bg-[var(--overlay)] md:hidden\"\n onClick={() => setMobileNavOpen(false)}\n />\n <SidebarRail\n railRef={dialogRef}\n role=\"dialog\"\n aria-label=\"Navigation\"\n tabIndex={-1}\n onNavigate={() => setMobileNavOpen(false)}\n className=\"absolute inset-y-0 left-0 z-10 shadow-lg outline-none md:hidden\"\n />\n </>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|