@herdctl/web 0.0.1 → 0.1.1

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 (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +146 -0
  3. package/dist/client/assets/index-Cyochp2F.css +1 -0
  4. package/dist/client/assets/index-mp9jz5eD.js +373 -0
  5. package/dist/client/favicon.ico +0 -0
  6. package/dist/client/favicon.svg +1 -0
  7. package/dist/client/herdctl-logo.svg +29 -0
  8. package/dist/client/index.html +21 -0
  9. package/dist/server/__tests__/routes.test.d.ts +8 -0
  10. package/dist/server/__tests__/routes.test.d.ts.map +1 -0
  11. package/dist/server/__tests__/routes.test.js +535 -0
  12. package/dist/server/__tests__/routes.test.js.map +1 -0
  13. package/dist/server/__tests__/ws-handler.test.d.ts +7 -0
  14. package/dist/server/__tests__/ws-handler.test.d.ts.map +1 -0
  15. package/dist/server/__tests__/ws-handler.test.js +380 -0
  16. package/dist/server/__tests__/ws-handler.test.js.map +1 -0
  17. package/dist/server/chat/index.d.ts +5 -0
  18. package/dist/server/chat/index.d.ts.map +1 -0
  19. package/dist/server/chat/index.js +5 -0
  20. package/dist/server/chat/index.js.map +1 -0
  21. package/dist/server/chat/web-chat-manager.d.ts +158 -0
  22. package/dist/server/chat/web-chat-manager.d.ts.map +1 -0
  23. package/dist/server/chat/web-chat-manager.js +437 -0
  24. package/dist/server/chat/web-chat-manager.js.map +1 -0
  25. package/dist/server/index.d.ts +144 -0
  26. package/dist/server/index.d.ts.map +1 -0
  27. package/dist/server/index.js +341 -0
  28. package/dist/server/index.js.map +1 -0
  29. package/dist/server/routes/agents.d.ts +15 -0
  30. package/dist/server/routes/agents.d.ts.map +1 -0
  31. package/dist/server/routes/agents.js +66 -0
  32. package/dist/server/routes/agents.js.map +1 -0
  33. package/dist/server/routes/chat.d.ts +18 -0
  34. package/dist/server/routes/chat.d.ts.map +1 -0
  35. package/dist/server/routes/chat.js +191 -0
  36. package/dist/server/routes/chat.js.map +1 -0
  37. package/dist/server/routes/fleet.d.ts +15 -0
  38. package/dist/server/routes/fleet.d.ts.map +1 -0
  39. package/dist/server/routes/fleet.js +36 -0
  40. package/dist/server/routes/fleet.js.map +1 -0
  41. package/dist/server/routes/jobs.d.ts +17 -0
  42. package/dist/server/routes/jobs.d.ts.map +1 -0
  43. package/dist/server/routes/jobs.js +188 -0
  44. package/dist/server/routes/jobs.js.map +1 -0
  45. package/dist/server/routes/schedules.d.ts +16 -0
  46. package/dist/server/routes/schedules.d.ts.map +1 -0
  47. package/dist/server/routes/schedules.js +126 -0
  48. package/dist/server/routes/schedules.js.map +1 -0
  49. package/dist/server/ws/fleet-bridge.d.ts +80 -0
  50. package/dist/server/ws/fleet-bridge.d.ts.map +1 -0
  51. package/dist/server/ws/fleet-bridge.js +184 -0
  52. package/dist/server/ws/fleet-bridge.js.map +1 -0
  53. package/dist/server/ws/handler.d.ts +93 -0
  54. package/dist/server/ws/handler.d.ts.map +1 -0
  55. package/dist/server/ws/handler.js +270 -0
  56. package/dist/server/ws/handler.js.map +1 -0
  57. package/dist/server/ws/index.d.ts +8 -0
  58. package/dist/server/ws/index.d.ts.map +1 -0
  59. package/dist/server/ws/index.js +8 -0
  60. package/dist/server/ws/index.js.map +1 -0
  61. package/dist/server/ws/types.d.ts +215 -0
  62. package/dist/server/ws/types.d.ts.map +1 -0
  63. package/dist/server/ws/types.js +67 -0
  64. package/dist/server/ws/types.js.map +1 -0
  65. package/package.json +77 -1
@@ -0,0 +1,380 @@
1
+ /**
2
+ * WebSocket handler and type guard tests for @herdctl/web
3
+ *
4
+ * Tests the WebSocket message type guards and handler behavior.
5
+ */
6
+ import { describe, it, expect, vi, beforeEach } from "vitest";
7
+ import { isClientMessage, isChatSendMessage, isAgentStartedPayload, isAgentStoppedPayload } from "../ws/types.js";
8
+ import { WebSocketHandler } from "../ws/handler.js";
9
+ // =============================================================================
10
+ // Type Guard Tests
11
+ // =============================================================================
12
+ describe("isClientMessage", () => {
13
+ it("accepts a valid subscribe message", () => {
14
+ expect(isClientMessage({ type: "subscribe", payload: { agentName: "coder" } })).toBe(true);
15
+ });
16
+ it("accepts a valid unsubscribe message", () => {
17
+ expect(isClientMessage({ type: "unsubscribe", payload: { agentName: "coder" } })).toBe(true);
18
+ });
19
+ it("accepts a valid ping message", () => {
20
+ expect(isClientMessage({ type: "ping" })).toBe(true);
21
+ });
22
+ it("accepts a valid chat:send message", () => {
23
+ expect(isClientMessage({
24
+ type: "chat:send",
25
+ payload: {
26
+ agentName: "coder",
27
+ sessionId: "session-1",
28
+ message: "Hello",
29
+ },
30
+ })).toBe(true);
31
+ });
32
+ it("rejects null", () => {
33
+ expect(isClientMessage(null)).toBe(false);
34
+ });
35
+ it("rejects non-objects", () => {
36
+ expect(isClientMessage("string")).toBe(false);
37
+ expect(isClientMessage(42)).toBe(false);
38
+ expect(isClientMessage(undefined)).toBe(false);
39
+ });
40
+ it("rejects object without type", () => {
41
+ expect(isClientMessage({ payload: { agentName: "coder" } })).toBe(false);
42
+ });
43
+ it("rejects unknown type", () => {
44
+ expect(isClientMessage({ type: "unknown" })).toBe(false);
45
+ });
46
+ it("rejects subscribe without agentName", () => {
47
+ expect(isClientMessage({ type: "subscribe", payload: {} })).toBe(false);
48
+ expect(isClientMessage({ type: "subscribe", payload: null })).toBe(false);
49
+ expect(isClientMessage({ type: "subscribe" })).toBe(false);
50
+ });
51
+ it("rejects unsubscribe without agentName", () => {
52
+ expect(isClientMessage({ type: "unsubscribe", payload: {} })).toBe(false);
53
+ });
54
+ });
55
+ describe("isChatSendMessage", () => {
56
+ it("accepts valid chat:send message", () => {
57
+ expect(isChatSendMessage({
58
+ type: "chat:send",
59
+ payload: {
60
+ agentName: "coder",
61
+ sessionId: "session-1",
62
+ message: "Hello",
63
+ },
64
+ })).toBe(true);
65
+ });
66
+ it("rejects missing payload fields", () => {
67
+ expect(isChatSendMessage({
68
+ type: "chat:send",
69
+ payload: { agentName: "coder", sessionId: "session-1" },
70
+ })).toBe(false);
71
+ });
72
+ it("rejects wrong type", () => {
73
+ expect(isChatSendMessage({
74
+ type: "ping",
75
+ payload: {
76
+ agentName: "coder",
77
+ sessionId: "session-1",
78
+ message: "Hello",
79
+ },
80
+ })).toBe(false);
81
+ });
82
+ it("rejects null payload", () => {
83
+ expect(isChatSendMessage({ type: "chat:send", payload: null })).toBe(false);
84
+ });
85
+ it("rejects non-object", () => {
86
+ expect(isChatSendMessage(null)).toBe(false);
87
+ expect(isChatSendMessage("string")).toBe(false);
88
+ });
89
+ });
90
+ describe("isAgentStartedPayload", () => {
91
+ it("returns true for started payload", () => {
92
+ expect(isAgentStartedPayload({
93
+ agent: { name: "coder", status: "running" },
94
+ })).toBe(true);
95
+ });
96
+ it("returns false for stopped payload", () => {
97
+ expect(isAgentStartedPayload({
98
+ agentName: "coder",
99
+ reason: "completed",
100
+ })).toBe(false);
101
+ });
102
+ });
103
+ describe("isAgentStoppedPayload", () => {
104
+ it("returns true for stopped payload", () => {
105
+ expect(isAgentStoppedPayload({
106
+ agentName: "coder",
107
+ reason: "completed",
108
+ })).toBe(true);
109
+ });
110
+ it("returns false for started payload", () => {
111
+ expect(isAgentStoppedPayload({
112
+ agent: { name: "coder", status: "running" },
113
+ })).toBe(false);
114
+ });
115
+ });
116
+ // =============================================================================
117
+ // WebSocketHandler Tests
118
+ // =============================================================================
119
+ describe("WebSocketHandler", () => {
120
+ let mockFleetManager;
121
+ beforeEach(() => {
122
+ mockFleetManager = {
123
+ getFleetStatus: vi.fn().mockResolvedValue({
124
+ state: "running",
125
+ counts: { totalAgents: 1 },
126
+ }),
127
+ on: vi.fn(),
128
+ off: vi.fn(),
129
+ };
130
+ });
131
+ it("can be instantiated", () => {
132
+ const handler = new WebSocketHandler(mockFleetManager);
133
+ expect(handler).toBeDefined();
134
+ expect(handler.getConnectedCount()).toBe(0);
135
+ });
136
+ it("reports zero subscribers for unknown agent", () => {
137
+ const handler = new WebSocketHandler(mockFleetManager);
138
+ expect(handler.getSubscriberCount("nonexistent")).toBe(0);
139
+ });
140
+ it("broadcasts to no clients when none connected", () => {
141
+ const handler = new WebSocketHandler(mockFleetManager);
142
+ // Should not throw when broadcasting to empty set
143
+ handler.broadcast({ type: "pong" });
144
+ });
145
+ it("broadcastToSubscribers does not throw with no clients", () => {
146
+ const handler = new WebSocketHandler(mockFleetManager);
147
+ // Should not throw when no one is subscribed
148
+ handler.broadcastToSubscribers("coder", { type: "pong" });
149
+ });
150
+ it("closeAll works on empty handler", () => {
151
+ const handler = new WebSocketHandler(mockFleetManager);
152
+ // Should not throw
153
+ handler.closeAll();
154
+ expect(handler.getConnectedCount()).toBe(0);
155
+ });
156
+ describe("handleConnection", () => {
157
+ it("tracks connected clients", async () => {
158
+ const handler = new WebSocketHandler(mockFleetManager);
159
+ const mockSocket = {
160
+ on: vi.fn(),
161
+ readyState: 1,
162
+ OPEN: 1,
163
+ send: vi.fn(),
164
+ close: vi.fn(),
165
+ };
166
+ await handler.handleConnection(mockSocket);
167
+ expect(handler.getConnectedCount()).toBe(1);
168
+ expect(mockSocket.on).toHaveBeenCalledWith("message", expect.any(Function));
169
+ expect(mockSocket.on).toHaveBeenCalledWith("close", expect.any(Function));
170
+ expect(mockSocket.on).toHaveBeenCalledWith("error", expect.any(Function));
171
+ });
172
+ it("sends initial fleet status on connection", async () => {
173
+ const handler = new WebSocketHandler(mockFleetManager);
174
+ const mockSocket = {
175
+ on: vi.fn(),
176
+ readyState: 1,
177
+ OPEN: 1,
178
+ send: vi.fn(),
179
+ close: vi.fn(),
180
+ };
181
+ await handler.handleConnection(mockSocket);
182
+ expect(mockFleetManager.getFleetStatus).toHaveBeenCalled();
183
+ expect(mockSocket.send).toHaveBeenCalledWith(expect.stringContaining('"type":"fleet:status"'));
184
+ });
185
+ it("handles disconnect", async () => {
186
+ const handler = new WebSocketHandler(mockFleetManager);
187
+ let closeHandler;
188
+ const mockSocket = {
189
+ on: vi.fn((event, cb) => {
190
+ if (event === "close")
191
+ closeHandler = cb;
192
+ }),
193
+ readyState: 1,
194
+ OPEN: 1,
195
+ send: vi.fn(),
196
+ close: vi.fn(),
197
+ };
198
+ await handler.handleConnection(mockSocket);
199
+ expect(handler.getConnectedCount()).toBe(1);
200
+ // Simulate disconnect
201
+ closeHandler();
202
+ expect(handler.getConnectedCount()).toBe(0);
203
+ });
204
+ it("handles subscribe and unsubscribe messages", async () => {
205
+ const handler = new WebSocketHandler(mockFleetManager);
206
+ let messageHandler;
207
+ const mockSocket = {
208
+ on: vi.fn((event, cb) => {
209
+ if (event === "message")
210
+ messageHandler = cb;
211
+ }),
212
+ readyState: 1,
213
+ OPEN: 1,
214
+ send: vi.fn(),
215
+ close: vi.fn(),
216
+ };
217
+ await handler.handleConnection(mockSocket);
218
+ // Subscribe to an agent
219
+ const subscribeMsg = JSON.stringify({
220
+ type: "subscribe",
221
+ payload: { agentName: "coder" },
222
+ });
223
+ messageHandler(Buffer.from(subscribeMsg));
224
+ expect(handler.getSubscriberCount("coder")).toBe(1);
225
+ // Unsubscribe from the agent
226
+ const unsubscribeMsg = JSON.stringify({
227
+ type: "unsubscribe",
228
+ payload: { agentName: "coder" },
229
+ });
230
+ messageHandler(Buffer.from(unsubscribeMsg));
231
+ expect(handler.getSubscriberCount("coder")).toBe(0);
232
+ });
233
+ it("responds to ping with pong", async () => {
234
+ const handler = new WebSocketHandler(mockFleetManager);
235
+ let messageHandler;
236
+ const mockSocket = {
237
+ on: vi.fn((event, cb) => {
238
+ if (event === "message")
239
+ messageHandler = cb;
240
+ }),
241
+ readyState: 1,
242
+ OPEN: 1,
243
+ send: vi.fn(),
244
+ close: vi.fn(),
245
+ };
246
+ await handler.handleConnection(mockSocket);
247
+ // Clear the initial fleet:status send
248
+ mockSocket.send.mockClear();
249
+ const pingMsg = JSON.stringify({ type: "ping" });
250
+ messageHandler(Buffer.from(pingMsg));
251
+ expect(mockSocket.send).toHaveBeenCalledWith(JSON.stringify({ type: "pong" }));
252
+ });
253
+ it("ignores invalid JSON messages", async () => {
254
+ const handler = new WebSocketHandler(mockFleetManager);
255
+ let messageHandler;
256
+ const mockSocket = {
257
+ on: vi.fn((event, cb) => {
258
+ if (event === "message")
259
+ messageHandler = cb;
260
+ }),
261
+ readyState: 1,
262
+ OPEN: 1,
263
+ send: vi.fn(),
264
+ close: vi.fn(),
265
+ };
266
+ await handler.handleConnection(mockSocket);
267
+ mockSocket.send.mockClear();
268
+ // Should not throw on invalid JSON
269
+ messageHandler(Buffer.from("not valid json"));
270
+ expect(mockSocket.send).not.toHaveBeenCalled();
271
+ });
272
+ it("ignores unknown message types", async () => {
273
+ const handler = new WebSocketHandler(mockFleetManager);
274
+ let messageHandler;
275
+ const mockSocket = {
276
+ on: vi.fn((event, cb) => {
277
+ if (event === "message")
278
+ messageHandler = cb;
279
+ }),
280
+ readyState: 1,
281
+ OPEN: 1,
282
+ send: vi.fn(),
283
+ close: vi.fn(),
284
+ };
285
+ await handler.handleConnection(mockSocket);
286
+ mockSocket.send.mockClear();
287
+ // Should not throw on unknown type (it's just filtered out)
288
+ messageHandler(Buffer.from(JSON.stringify({ type: "unknown" })));
289
+ expect(mockSocket.send).not.toHaveBeenCalled();
290
+ });
291
+ });
292
+ describe("broadcast", () => {
293
+ it("sends message to all connected clients", async () => {
294
+ const handler = new WebSocketHandler(mockFleetManager);
295
+ const socket1 = {
296
+ on: vi.fn(),
297
+ readyState: 1,
298
+ OPEN: 1,
299
+ send: vi.fn(),
300
+ close: vi.fn(),
301
+ };
302
+ const socket2 = {
303
+ on: vi.fn(),
304
+ readyState: 1,
305
+ OPEN: 1,
306
+ send: vi.fn(),
307
+ close: vi.fn(),
308
+ };
309
+ await handler.handleConnection(socket1);
310
+ await handler.handleConnection(socket2);
311
+ expect(handler.getConnectedCount()).toBe(2);
312
+ socket1.send.mockClear();
313
+ socket2.send.mockClear();
314
+ handler.broadcast({ type: "pong" });
315
+ expect(socket1.send).toHaveBeenCalledWith(JSON.stringify({ type: "pong" }));
316
+ expect(socket2.send).toHaveBeenCalledWith(JSON.stringify({ type: "pong" }));
317
+ });
318
+ });
319
+ describe("broadcastToSubscribers", () => {
320
+ it("sends message only to subscribed clients", async () => {
321
+ const handler = new WebSocketHandler(mockFleetManager);
322
+ let messageHandler1;
323
+ const socket1 = {
324
+ on: vi.fn((event, cb) => {
325
+ if (event === "message")
326
+ messageHandler1 = cb;
327
+ }),
328
+ readyState: 1,
329
+ OPEN: 1,
330
+ send: vi.fn(),
331
+ close: vi.fn(),
332
+ };
333
+ const socket2 = {
334
+ on: vi.fn(),
335
+ readyState: 1,
336
+ OPEN: 1,
337
+ send: vi.fn(),
338
+ close: vi.fn(),
339
+ };
340
+ await handler.handleConnection(socket1);
341
+ await handler.handleConnection(socket2);
342
+ // Subscribe socket1 to "coder"
343
+ messageHandler1(Buffer.from(JSON.stringify({ type: "subscribe", payload: { agentName: "coder" } })));
344
+ socket1.send.mockClear();
345
+ socket2.send.mockClear();
346
+ handler.broadcastToSubscribers("coder", { type: "pong" });
347
+ // socket1 subscribed, should receive
348
+ expect(socket1.send).toHaveBeenCalledWith(JSON.stringify({ type: "pong" }));
349
+ // socket2 not subscribed, should not receive
350
+ expect(socket2.send).not.toHaveBeenCalled();
351
+ });
352
+ });
353
+ describe("closeAll", () => {
354
+ it("closes all connected clients", async () => {
355
+ const handler = new WebSocketHandler(mockFleetManager);
356
+ const socket1 = {
357
+ on: vi.fn(),
358
+ readyState: 1,
359
+ OPEN: 1,
360
+ send: vi.fn(),
361
+ close: vi.fn(),
362
+ };
363
+ const socket2 = {
364
+ on: vi.fn(),
365
+ readyState: 1,
366
+ OPEN: 1,
367
+ send: vi.fn(),
368
+ close: vi.fn(),
369
+ };
370
+ await handler.handleConnection(socket1);
371
+ await handler.handleConnection(socket2);
372
+ expect(handler.getConnectedCount()).toBe(2);
373
+ handler.closeAll();
374
+ expect(socket1.close).toHaveBeenCalledWith(1000, "Server shutting down");
375
+ expect(socket2.close).toHaveBeenCalledWith(1000, "Server shutting down");
376
+ expect(handler.getConnectedCount()).toBe(0);
377
+ });
378
+ });
379
+ });
380
+ //# sourceMappingURL=ws-handler.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-handler.test.js","sourceRoot":"","sources":["../../../src/server/__tests__/ws-handler.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Chat module exports for @herdctl/web
3
+ */
4
+ export { WebChatManager, type WebChatSession, type WebChatSessionDetails, type ChatMessage, type SendMessageResult, type OnChunkCallback, } from "./web-chat-manager.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/chat/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,eAAe,GACrB,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Chat module exports for @herdctl/web
3
+ */
4
+ export { WebChatManager, } from "./web-chat-manager.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/chat/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,cAAc,GAMf,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Web Chat Manager for @herdctl/web
3
+ *
4
+ * Manages chat sessions for the web platform using @herdctl/chat infrastructure.
5
+ * Each web session maps to a unique conversation thread with an agent.
6
+ */
7
+ import { type FleetManager, type WebConfig } from "@herdctl/core";
8
+ /**
9
+ * Information about a web chat session
10
+ */
11
+ export interface WebChatSession {
12
+ /** Unique session identifier */
13
+ sessionId: string;
14
+ /** Agent this session is for */
15
+ agentName: string;
16
+ /** ISO timestamp when the session was created */
17
+ createdAt: string;
18
+ /** ISO timestamp of the last message */
19
+ lastMessageAt: string;
20
+ /** Number of messages in this session */
21
+ messageCount: number;
22
+ /** Preview of the last message */
23
+ preview?: string;
24
+ }
25
+ /**
26
+ * A single chat message
27
+ */
28
+ export interface ChatMessage {
29
+ /** Role of the sender */
30
+ role: "user" | "assistant";
31
+ /** Message content */
32
+ content: string;
33
+ /** ISO timestamp of the message */
34
+ timestamp: string;
35
+ }
36
+ /**
37
+ * Session details with full message history
38
+ */
39
+ export interface WebChatSessionDetails extends WebChatSession {
40
+ /** All messages in this session */
41
+ messages: ChatMessage[];
42
+ }
43
+ /**
44
+ * Result of sending a message
45
+ */
46
+ export interface SendMessageResult {
47
+ /** Job ID for tracking the execution */
48
+ jobId: string;
49
+ /** Whether the message was queued successfully */
50
+ success: boolean;
51
+ /** Error message if failed */
52
+ error?: string;
53
+ }
54
+ /**
55
+ * Callback for receiving streaming chunks
56
+ */
57
+ export type OnChunkCallback = (chunk: string) => void | Promise<void>;
58
+ /**
59
+ * WebChatManager manages chat sessions for the web platform
60
+ *
61
+ * Uses ChatSessionManager from @herdctl/chat for per-agent session management.
62
+ * Message history is stored in JSON files at `.herdctl/web/chat-history/<agent>/<session>.json`
63
+ */
64
+ export declare class WebChatManager {
65
+ private fleetManager;
66
+ private stateDir;
67
+ private sessionExpiryHours;
68
+ private initialized;
69
+ /** Per-agent session managers */
70
+ private sessionManagers;
71
+ /** In-memory session metadata cache (agentName -> sessionId -> metadata) */
72
+ private sessionMetadata;
73
+ /**
74
+ * Initialize the WebChatManager
75
+ *
76
+ * @param fleetManager - FleetManager instance for triggering jobs
77
+ * @param stateDir - State directory (e.g., ".herdctl")
78
+ * @param config - Web configuration from fleet config
79
+ */
80
+ initialize(fleetManager: FleetManager, stateDir: string, config: WebConfig): Promise<void>;
81
+ /**
82
+ * Create a new chat session for an agent
83
+ *
84
+ * @param agentName - Name of the agent
85
+ * @returns Session info with sessionId and createdAt
86
+ */
87
+ createSession(agentName: string): Promise<WebChatSession>;
88
+ /**
89
+ * List all sessions for an agent
90
+ *
91
+ * @param agentName - Name of the agent
92
+ * @returns Array of session summaries
93
+ */
94
+ listSessions(agentName: string): Promise<WebChatSession[]>;
95
+ /**
96
+ * Get session details with message history
97
+ *
98
+ * @param agentName - Name of the agent
99
+ * @param sessionId - Session ID
100
+ * @returns Session details with messages, or null if not found
101
+ */
102
+ getSession(agentName: string, sessionId: string): Promise<WebChatSessionDetails | null>;
103
+ /**
104
+ * Delete a session
105
+ *
106
+ * @param agentName - Name of the agent
107
+ * @param sessionId - Session ID
108
+ * @returns true if deleted, false if not found
109
+ */
110
+ deleteSession(agentName: string, sessionId: string): Promise<boolean>;
111
+ /**
112
+ * Send a message and trigger agent execution
113
+ *
114
+ * @param agentName - Name of the agent
115
+ * @param sessionId - Session ID
116
+ * @param message - User message text
117
+ * @param onChunk - Callback for streaming response chunks
118
+ * @returns Result with jobId
119
+ */
120
+ sendMessage(agentName: string, sessionId: string, message: string, onChunk: OnChunkCallback): Promise<SendMessageResult>;
121
+ /**
122
+ * Ensure the manager is initialized
123
+ */
124
+ private ensureInitialized;
125
+ /**
126
+ * Create a session manager for an agent
127
+ */
128
+ private createSessionManagerForAgent;
129
+ /**
130
+ * Get the chat history directory path
131
+ */
132
+ private getChatHistoryDir;
133
+ /**
134
+ * Get the message history file path for a session
135
+ */
136
+ private getMessageHistoryPath;
137
+ /**
138
+ * Ensure chat history directories exist
139
+ */
140
+ private ensureChatHistoryDir;
141
+ /**
142
+ * Load message history from disk
143
+ */
144
+ private loadMessageHistory;
145
+ /**
146
+ * Save message history to disk
147
+ */
148
+ private saveMessageHistory;
149
+ /**
150
+ * Delete message history file
151
+ */
152
+ private deleteMessageHistory;
153
+ /**
154
+ * Load sessions from disk into metadata cache
155
+ */
156
+ private loadSessionsFromDisk;
157
+ }
158
+ //# sourceMappingURL=web-chat-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-chat-manager.d.ts","sourceRoot":"","sources":["../../../src/server/chat/web-chat-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,SAAS,EAEf,MAAM,eAAe,CAAC;AAavB;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,yBAAyB;IACzB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,cAAc;IAC3D,mCAAmC;IACnC,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,OAAO,EAAE,OAAO,CAAC;IACjB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAMtE;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,kBAAkB,CAAc;IACxC,OAAO,CAAC,WAAW,CAAkB;IAErC,iCAAiC;IACjC,OAAO,CAAC,eAAe,CAA8C;IAErE,4EAA4E;IAC5E,OAAO,CAAC,eAAe,CAAuD;IAE9E;;;;;;OAMG;IACG,UAAU,CACd,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC,IAAI,CAAC;IA6BhB;;;;;OAKG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA0C/D;;;;;OAKG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAoBhE;;;;;;OAMG;IACG,UAAU,CACd,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAsBxC;;;;;;OAMG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAyB3E;;;;;;;;OAQG;IACG,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,iBAAiB,CAAC;IAsH7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;OAEG;YACW,4BAA4B;IA0B1C;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAI7B;;OAEG;YACW,oBAAoB;IAKlC;;OAEG;YACW,kBAAkB;IAwBhC;;OAEG;YACW,kBAAkB;IAoBhC;;OAEG;YACW,oBAAoB;IAoBlC;;OAEG;YACW,oBAAoB;CA4DnC"}