@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.
@@ -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 (currentTab === "browse") return "menu";
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
+
@@ -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>
@@ -353,4 +353,4 @@ const createAuthProfiles = () => {
353
353
  };
354
354
  };
355
355
 
356
- module.exports = { createAuthProfiles };
356
+ module.exports = { createAuthProfiles, getEnvVarForApiKeyProvider };