@chrysb/alphaclaw 0.8.2 → 0.8.3-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/lib/public/css/chat.css +426 -0
- package/lib/public/css/explorer.css +101 -0
- package/lib/public/dist/app.bundle.js +2307 -2115
- package/lib/public/js/app.js +34 -0
- package/lib/public/js/components/nodes-tab/connected-nodes/index.js +16 -14
- package/lib/public/js/components/routes/chat-route.js +1094 -0
- package/lib/public/js/components/routes/index.js +1 -0
- package/lib/public/js/components/sidebar.js +52 -0
- package/lib/public/js/hooks/use-browse-navigation.js +13 -2
- package/lib/public/js/lib/app-navigation.js +1 -0
- package/lib/public/js/lib/storage-keys.js +3 -0
- package/lib/public/setup.html +1 -0
- package/lib/server/auth-profiles.js +1 -1
- package/lib/server/chat-ws.js +835 -0
- package/lib/server/onboarding/validation.js +15 -10
- package/lib/server/watchdog-terminal-ws.js +14 -1
- package/lib/server.js +36 -0
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { AgentsRoute } from "./agents-route.js";
|
|
2
2
|
export { BrowseRoute } from "./browse-route.js";
|
|
3
|
+
export { ChatRoute } from "./chat-route.js";
|
|
3
4
|
export { CronRoute } from "./cron-route.js";
|
|
4
5
|
export { DoctorRoute } from "./doctor-route.js";
|
|
5
6
|
export { EnvarsRoute } from "./envars-route.js";
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
BarChartLineIcon,
|
|
8
8
|
Brain2LineIcon,
|
|
9
9
|
BracesLineIcon,
|
|
10
|
+
ChatVoiceLineIcon,
|
|
10
11
|
ComputerLineIcon,
|
|
11
12
|
EyeLineIcon,
|
|
12
13
|
FolderLineIcon,
|
|
@@ -93,6 +94,10 @@ export const AppSidebar = ({
|
|
|
93
94
|
selectedAgentId = "",
|
|
94
95
|
onSelectAgent = () => {},
|
|
95
96
|
onAddAgent = () => {},
|
|
97
|
+
chatSessions = [],
|
|
98
|
+
selectedChatSessionKey = "",
|
|
99
|
+
onSelectChatSession = () => {},
|
|
100
|
+
onStartChat = () => {},
|
|
96
101
|
}) => {
|
|
97
102
|
const browseLayoutRef = useRef(null);
|
|
98
103
|
const browseBottomPanelRef = useRef(null);
|
|
@@ -208,6 +213,14 @@ export const AppSidebar = ({
|
|
|
208
213
|
>
|
|
209
214
|
<${FolderLineIcon} className="sidebar-tab-icon" />
|
|
210
215
|
</button>
|
|
216
|
+
<button
|
|
217
|
+
class=${`sidebar-tab ${sidebarTab === "chat" ? "active" : ""}`}
|
|
218
|
+
aria-label="Chat tab"
|
|
219
|
+
title="Chat"
|
|
220
|
+
onclick=${() => onSelectSidebarTab("chat")}
|
|
221
|
+
>
|
|
222
|
+
<${ChatVoiceLineIcon} className="sidebar-tab-icon" />
|
|
223
|
+
</button>
|
|
211
224
|
</div>
|
|
212
225
|
<div
|
|
213
226
|
style=${{
|
|
@@ -283,6 +296,45 @@ export const AppSidebar = ({
|
|
|
283
296
|
: null}
|
|
284
297
|
</div>
|
|
285
298
|
</div>
|
|
299
|
+
<div
|
|
300
|
+
style=${{
|
|
301
|
+
display: sidebarTab === "chat" ? "flex" : "none",
|
|
302
|
+
flexDirection: "column",
|
|
303
|
+
flex: "1 1 auto",
|
|
304
|
+
minHeight: 0,
|
|
305
|
+
}}
|
|
306
|
+
>
|
|
307
|
+
<div class="sidebar-chat-header">
|
|
308
|
+
<div class="sidebar-label sidebar-chat-label">Sessions</div>
|
|
309
|
+
<button
|
|
310
|
+
type="button"
|
|
311
|
+
class="sidebar-chat-new-button"
|
|
312
|
+
onclick=${onStartChat}
|
|
313
|
+
title="New chat"
|
|
314
|
+
aria-label="New chat"
|
|
315
|
+
>
|
|
316
|
+
<${AddLineIcon} className="sidebar-chat-new-icon" />
|
|
317
|
+
</button>
|
|
318
|
+
</div>
|
|
319
|
+
<div class="sidebar-chat-sessions-list">
|
|
320
|
+
${chatSessions.length === 0
|
|
321
|
+
? html`<div class="sidebar-chat-empty">No sessions found</div>`
|
|
322
|
+
: chatSessions.map(
|
|
323
|
+
(sessionRow) => html`
|
|
324
|
+
<button
|
|
325
|
+
key=${sessionRow.key}
|
|
326
|
+
class=${`sidebar-chat-session-item ${selectedChatSessionKey === sessionRow.key ? "active" : ""}`}
|
|
327
|
+
onclick=${() => onSelectChatSession(sessionRow.key)}
|
|
328
|
+
title=${sessionRow.label || sessionRow.key}
|
|
329
|
+
>
|
|
330
|
+
<span class="sidebar-chat-session-name"
|
|
331
|
+
>${sessionRow.label || sessionRow.key}</span
|
|
332
|
+
>
|
|
333
|
+
</button>
|
|
334
|
+
`,
|
|
335
|
+
)}
|
|
336
|
+
</div>
|
|
337
|
+
</div>
|
|
286
338
|
<div
|
|
287
339
|
style=${{
|
|
288
340
|
display: sidebarTab === "browse" ? "flex" : "none",
|
|
@@ -13,6 +13,7 @@ export const useBrowseNavigation = ({
|
|
|
13
13
|
} = {}) => {
|
|
14
14
|
const [sidebarTab, setSidebarTab] = useState(() => {
|
|
15
15
|
if (location.startsWith("/browse")) return "browse";
|
|
16
|
+
if (location.startsWith("/chat")) return "chat";
|
|
16
17
|
return "menu";
|
|
17
18
|
});
|
|
18
19
|
const [lastBrowsePath, setLastBrowsePath] = useState(() => {
|
|
@@ -28,7 +29,8 @@ export const useBrowseNavigation = ({
|
|
|
28
29
|
typeof storedRoute === "string" &&
|
|
29
30
|
storedRoute.startsWith("/") &&
|
|
30
31
|
!storedRoute.startsWith("/browse") &&
|
|
31
|
-
!storedRoute.startsWith("/agents")
|
|
32
|
+
!storedRoute.startsWith("/agents") &&
|
|
33
|
+
!storedRoute.startsWith("/chat")
|
|
32
34
|
) {
|
|
33
35
|
return storedRoute;
|
|
34
36
|
}
|
|
@@ -57,7 +59,8 @@ export const useBrowseNavigation = ({
|
|
|
57
59
|
useEffect(() => {
|
|
58
60
|
setSidebarTab((currentTab) => {
|
|
59
61
|
if (location.startsWith("/browse")) return "browse";
|
|
60
|
-
if (
|
|
62
|
+
if (location.startsWith("/chat")) return "chat";
|
|
63
|
+
if (currentTab === "browse" || currentTab === "chat") return "menu";
|
|
61
64
|
return currentTab;
|
|
62
65
|
});
|
|
63
66
|
}, [location]);
|
|
@@ -79,6 +82,7 @@ export const useBrowseNavigation = ({
|
|
|
79
82
|
|
|
80
83
|
useEffect(() => {
|
|
81
84
|
if (location.startsWith("/browse")) return;
|
|
85
|
+
if (location.startsWith("/chat")) return;
|
|
82
86
|
if (location.startsWith("/telegram")) return;
|
|
83
87
|
setLastMenuRoute((currentRoute) =>
|
|
84
88
|
currentRoute === location ? currentRoute : location,
|
|
@@ -150,10 +154,17 @@ export const useBrowseNavigation = ({
|
|
|
150
154
|
setLocation(lastMenuRoute || `/${kDefaultUiTab}`);
|
|
151
155
|
return;
|
|
152
156
|
}
|
|
157
|
+
if (nextTab === "menu" && location.startsWith("/chat")) {
|
|
158
|
+
setLocation(lastMenuRoute || `/${kDefaultUiTab}`);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
153
161
|
if (nextTab === "browse" && !location.startsWith("/browse")) {
|
|
154
162
|
setLocation(buildBrowseRoute(lastBrowsePath));
|
|
155
163
|
return;
|
|
156
164
|
}
|
|
165
|
+
if (nextTab === "chat" && !location.startsWith("/chat")) {
|
|
166
|
+
setLocation("/chat");
|
|
167
|
+
}
|
|
157
168
|
}, [lastBrowsePath, lastMenuRoute, location, setLocation]);
|
|
158
169
|
|
|
159
170
|
const handleSelectNavItem = useCallback((itemId) => {
|
|
@@ -30,6 +30,7 @@ export const kNavSections = [
|
|
|
30
30
|
export const getSelectedNavId = ({ isBrowseRoute = false, location = "" } = {}) => {
|
|
31
31
|
if (isBrowseRoute) return "browse";
|
|
32
32
|
if (location.startsWith("/telegram")) return "";
|
|
33
|
+
if (location.startsWith("/chat")) return "";
|
|
33
34
|
if (location.startsWith("/models")) return "models";
|
|
34
35
|
if (location.startsWith("/agents")) return "agents";
|
|
35
36
|
if (location.startsWith("/providers")) return "models";
|
|
@@ -27,3 +27,6 @@ export const kTelegramWorkspaceCacheKey = "alphaclaw.telegram.workspaceCache";
|
|
|
27
27
|
export const kAgentSessionsCacheKey = "alphaclaw.agent.sessionsCache";
|
|
28
28
|
export const kAgentLastSessionKey = "alphaclaw.agent.lastSessionKey";
|
|
29
29
|
|
|
30
|
+
// --- Chat ---
|
|
31
|
+
export const kChatSessionDraftsStorageKey = "alphaclaw.chat.sessionDrafts";
|
|
32
|
+
|
package/lib/public/setup.html
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
<link rel="stylesheet" href="./css/shell.css" />
|
|
15
15
|
<link rel="stylesheet" href="./css/explorer.css" />
|
|
16
16
|
<link rel="stylesheet" href="./css/agents.css" />
|
|
17
|
+
<link rel="stylesheet" href="./css/chat.css" />
|
|
17
18
|
<link rel="stylesheet" href="./css/cron.css" />
|
|
18
19
|
</head>
|
|
19
20
|
<body>
|