@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.
- package/LICENSE +21 -0
- package/README.md +146 -0
- package/dist/client/assets/index-Cyochp2F.css +1 -0
- package/dist/client/assets/index-mp9jz5eD.js +373 -0
- package/dist/client/favicon.ico +0 -0
- package/dist/client/favicon.svg +1 -0
- package/dist/client/herdctl-logo.svg +29 -0
- package/dist/client/index.html +21 -0
- package/dist/server/__tests__/routes.test.d.ts +8 -0
- package/dist/server/__tests__/routes.test.d.ts.map +1 -0
- package/dist/server/__tests__/routes.test.js +535 -0
- package/dist/server/__tests__/routes.test.js.map +1 -0
- package/dist/server/__tests__/ws-handler.test.d.ts +7 -0
- package/dist/server/__tests__/ws-handler.test.d.ts.map +1 -0
- package/dist/server/__tests__/ws-handler.test.js +380 -0
- package/dist/server/__tests__/ws-handler.test.js.map +1 -0
- package/dist/server/chat/index.d.ts +5 -0
- package/dist/server/chat/index.d.ts.map +1 -0
- package/dist/server/chat/index.js +5 -0
- package/dist/server/chat/index.js.map +1 -0
- package/dist/server/chat/web-chat-manager.d.ts +158 -0
- package/dist/server/chat/web-chat-manager.d.ts.map +1 -0
- package/dist/server/chat/web-chat-manager.js +437 -0
- package/dist/server/chat/web-chat-manager.js.map +1 -0
- package/dist/server/index.d.ts +144 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +341 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/routes/agents.d.ts +15 -0
- package/dist/server/routes/agents.d.ts.map +1 -0
- package/dist/server/routes/agents.js +66 -0
- package/dist/server/routes/agents.js.map +1 -0
- package/dist/server/routes/chat.d.ts +18 -0
- package/dist/server/routes/chat.d.ts.map +1 -0
- package/dist/server/routes/chat.js +191 -0
- package/dist/server/routes/chat.js.map +1 -0
- package/dist/server/routes/fleet.d.ts +15 -0
- package/dist/server/routes/fleet.d.ts.map +1 -0
- package/dist/server/routes/fleet.js +36 -0
- package/dist/server/routes/fleet.js.map +1 -0
- package/dist/server/routes/jobs.d.ts +17 -0
- package/dist/server/routes/jobs.d.ts.map +1 -0
- package/dist/server/routes/jobs.js +188 -0
- package/dist/server/routes/jobs.js.map +1 -0
- package/dist/server/routes/schedules.d.ts +16 -0
- package/dist/server/routes/schedules.d.ts.map +1 -0
- package/dist/server/routes/schedules.js +126 -0
- package/dist/server/routes/schedules.js.map +1 -0
- package/dist/server/ws/fleet-bridge.d.ts +80 -0
- package/dist/server/ws/fleet-bridge.d.ts.map +1 -0
- package/dist/server/ws/fleet-bridge.js +184 -0
- package/dist/server/ws/fleet-bridge.js.map +1 -0
- package/dist/server/ws/handler.d.ts +93 -0
- package/dist/server/ws/handler.d.ts.map +1 -0
- package/dist/server/ws/handler.js +270 -0
- package/dist/server/ws/handler.js.map +1 -0
- package/dist/server/ws/index.d.ts +8 -0
- package/dist/server/ws/index.d.ts.map +1 -0
- package/dist/server/ws/index.js +8 -0
- package/dist/server/ws/index.js.map +1 -0
- package/dist/server/ws/types.d.ts +215 -0
- package/dist/server/ws/types.d.ts.map +1 -0
- package/dist/server/ws/types.js +67 -0
- package/dist/server/ws/types.js.map +1 -0
- package/package.json +77 -1
|
@@ -0,0 +1,437 @@
|
|
|
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 { randomUUID } from "node:crypto";
|
|
8
|
+
import { mkdir, readFile, writeFile, unlink } from "node:fs/promises";
|
|
9
|
+
import { join, dirname } from "node:path";
|
|
10
|
+
import { createLogger, } from "@herdctl/core";
|
|
11
|
+
import { ChatSessionManager, extractMessageContent, } from "@herdctl/chat";
|
|
12
|
+
const logger = createLogger("web:chat");
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// WebChatManager Implementation
|
|
15
|
+
// =============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* WebChatManager manages chat sessions for the web platform
|
|
18
|
+
*
|
|
19
|
+
* Uses ChatSessionManager from @herdctl/chat for per-agent session management.
|
|
20
|
+
* Message history is stored in JSON files at `.herdctl/web/chat-history/<agent>/<session>.json`
|
|
21
|
+
*/
|
|
22
|
+
export class WebChatManager {
|
|
23
|
+
fleetManager = null;
|
|
24
|
+
stateDir = null;
|
|
25
|
+
sessionExpiryHours = 24;
|
|
26
|
+
initialized = false;
|
|
27
|
+
/** Per-agent session managers */
|
|
28
|
+
sessionManagers = new Map();
|
|
29
|
+
/** In-memory session metadata cache (agentName -> sessionId -> metadata) */
|
|
30
|
+
sessionMetadata = new Map();
|
|
31
|
+
/**
|
|
32
|
+
* Initialize the WebChatManager
|
|
33
|
+
*
|
|
34
|
+
* @param fleetManager - FleetManager instance for triggering jobs
|
|
35
|
+
* @param stateDir - State directory (e.g., ".herdctl")
|
|
36
|
+
* @param config - Web configuration from fleet config
|
|
37
|
+
*/
|
|
38
|
+
async initialize(fleetManager, stateDir, config) {
|
|
39
|
+
if (this.initialized) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
this.fleetManager = fleetManager;
|
|
43
|
+
this.stateDir = stateDir;
|
|
44
|
+
this.sessionExpiryHours = config.session_expiry_hours ?? 24;
|
|
45
|
+
// Get fleet config to find all agents
|
|
46
|
+
const fleetConfig = await fleetManager.getConfig();
|
|
47
|
+
if (!fleetConfig) {
|
|
48
|
+
logger.warn("No fleet config available, chat manager initialized without agents");
|
|
49
|
+
this.initialized = true;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Create session managers for each agent
|
|
53
|
+
for (const agent of fleetConfig.agents) {
|
|
54
|
+
await this.createSessionManagerForAgent(agent.name);
|
|
55
|
+
}
|
|
56
|
+
// Ensure chat history directories exist
|
|
57
|
+
await this.ensureChatHistoryDir();
|
|
58
|
+
this.initialized = true;
|
|
59
|
+
logger.info(`Web chat manager initialized with ${this.sessionManagers.size} agent(s)`);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create a new chat session for an agent
|
|
63
|
+
*
|
|
64
|
+
* @param agentName - Name of the agent
|
|
65
|
+
* @returns Session info with sessionId and createdAt
|
|
66
|
+
*/
|
|
67
|
+
async createSession(agentName) {
|
|
68
|
+
this.ensureInitialized();
|
|
69
|
+
// Ensure we have a session manager for this agent
|
|
70
|
+
let sessionManager = this.sessionManagers.get(agentName);
|
|
71
|
+
if (!sessionManager) {
|
|
72
|
+
sessionManager = await this.createSessionManagerForAgent(agentName);
|
|
73
|
+
}
|
|
74
|
+
// Generate a unique session UUID for the web session
|
|
75
|
+
const sessionId = randomUUID();
|
|
76
|
+
const now = new Date().toISOString();
|
|
77
|
+
// Create session metadata
|
|
78
|
+
const session = {
|
|
79
|
+
sessionId,
|
|
80
|
+
agentName,
|
|
81
|
+
createdAt: now,
|
|
82
|
+
lastMessageAt: now,
|
|
83
|
+
messageCount: 0,
|
|
84
|
+
};
|
|
85
|
+
// Store in metadata cache
|
|
86
|
+
let agentSessions = this.sessionMetadata.get(agentName);
|
|
87
|
+
if (!agentSessions) {
|
|
88
|
+
agentSessions = new Map();
|
|
89
|
+
this.sessionMetadata.set(agentName, agentSessions);
|
|
90
|
+
}
|
|
91
|
+
agentSessions.set(sessionId, session);
|
|
92
|
+
// Initialize empty message history file
|
|
93
|
+
await this.saveMessageHistory(agentName, sessionId, []);
|
|
94
|
+
// Register in ChatSessionManager using sessionId as the channelId
|
|
95
|
+
// (For web, each session is its own "channel")
|
|
96
|
+
await sessionManager.setSession(sessionId, sessionId);
|
|
97
|
+
logger.info(`Created web chat session`, { agentName, sessionId });
|
|
98
|
+
return session;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* List all sessions for an agent
|
|
102
|
+
*
|
|
103
|
+
* @param agentName - Name of the agent
|
|
104
|
+
* @returns Array of session summaries
|
|
105
|
+
*/
|
|
106
|
+
async listSessions(agentName) {
|
|
107
|
+
this.ensureInitialized();
|
|
108
|
+
// Load sessions from disk if not in cache
|
|
109
|
+
await this.loadSessionsFromDisk(agentName);
|
|
110
|
+
const agentSessions = this.sessionMetadata.get(agentName);
|
|
111
|
+
if (!agentSessions) {
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
114
|
+
// Return sessions sorted by lastMessageAt (most recent first)
|
|
115
|
+
const sessions = Array.from(agentSessions.values());
|
|
116
|
+
sessions.sort((a, b) => new Date(b.lastMessageAt).getTime() - new Date(a.lastMessageAt).getTime());
|
|
117
|
+
return sessions;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get session details with message history
|
|
121
|
+
*
|
|
122
|
+
* @param agentName - Name of the agent
|
|
123
|
+
* @param sessionId - Session ID
|
|
124
|
+
* @returns Session details with messages, or null if not found
|
|
125
|
+
*/
|
|
126
|
+
async getSession(agentName, sessionId) {
|
|
127
|
+
this.ensureInitialized();
|
|
128
|
+
// Load sessions from disk if not in cache
|
|
129
|
+
await this.loadSessionsFromDisk(agentName);
|
|
130
|
+
const agentSessions = this.sessionMetadata.get(agentName);
|
|
131
|
+
const session = agentSessions?.get(sessionId);
|
|
132
|
+
if (!session) {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
// Load message history
|
|
136
|
+
const messages = await this.loadMessageHistory(agentName, sessionId);
|
|
137
|
+
return {
|
|
138
|
+
...session,
|
|
139
|
+
messages,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Delete a session
|
|
144
|
+
*
|
|
145
|
+
* @param agentName - Name of the agent
|
|
146
|
+
* @param sessionId - Session ID
|
|
147
|
+
* @returns true if deleted, false if not found
|
|
148
|
+
*/
|
|
149
|
+
async deleteSession(agentName, sessionId) {
|
|
150
|
+
this.ensureInitialized();
|
|
151
|
+
const agentSessions = this.sessionMetadata.get(agentName);
|
|
152
|
+
if (!agentSessions?.has(sessionId)) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
// Remove from metadata cache
|
|
156
|
+
agentSessions.delete(sessionId);
|
|
157
|
+
// Delete message history file
|
|
158
|
+
await this.deleteMessageHistory(agentName, sessionId);
|
|
159
|
+
// Clear from ChatSessionManager
|
|
160
|
+
const sessionManager = this.sessionManagers.get(agentName);
|
|
161
|
+
if (sessionManager) {
|
|
162
|
+
await sessionManager.clearSession(sessionId);
|
|
163
|
+
}
|
|
164
|
+
logger.info(`Deleted web chat session`, { agentName, sessionId });
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Send a message and trigger agent execution
|
|
169
|
+
*
|
|
170
|
+
* @param agentName - Name of the agent
|
|
171
|
+
* @param sessionId - Session ID
|
|
172
|
+
* @param message - User message text
|
|
173
|
+
* @param onChunk - Callback for streaming response chunks
|
|
174
|
+
* @returns Result with jobId
|
|
175
|
+
*/
|
|
176
|
+
async sendMessage(agentName, sessionId, message, onChunk) {
|
|
177
|
+
this.ensureInitialized();
|
|
178
|
+
if (!this.fleetManager) {
|
|
179
|
+
return {
|
|
180
|
+
jobId: "",
|
|
181
|
+
success: false,
|
|
182
|
+
error: "Fleet manager not available",
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
// Load sessions from disk if not in cache
|
|
186
|
+
await this.loadSessionsFromDisk(agentName);
|
|
187
|
+
const agentSessions = this.sessionMetadata.get(agentName);
|
|
188
|
+
const session = agentSessions?.get(sessionId);
|
|
189
|
+
if (!session) {
|
|
190
|
+
return {
|
|
191
|
+
jobId: "",
|
|
192
|
+
success: false,
|
|
193
|
+
error: `Session not found: ${sessionId}`,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
// Get existing SDK session ID for conversation continuity
|
|
197
|
+
const sessionManager = this.sessionManagers.get(agentName);
|
|
198
|
+
let existingSdkSessionId;
|
|
199
|
+
if (sessionManager) {
|
|
200
|
+
const existingSession = await sessionManager.getSession(sessionId);
|
|
201
|
+
if (existingSession && existingSession.sessionId !== sessionId) {
|
|
202
|
+
// The session manager stores the SDK session ID, not our web session ID
|
|
203
|
+
existingSdkSessionId = existingSession.sessionId;
|
|
204
|
+
logger.debug(`Resuming SDK session`, { agentName, sessionId, sdkSessionId: existingSdkSessionId });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Load message history and add user message
|
|
208
|
+
const messages = await this.loadMessageHistory(agentName, sessionId);
|
|
209
|
+
const userMessage = {
|
|
210
|
+
role: "user",
|
|
211
|
+
content: message,
|
|
212
|
+
timestamp: new Date().toISOString(),
|
|
213
|
+
};
|
|
214
|
+
messages.push(userMessage);
|
|
215
|
+
await this.saveMessageHistory(agentName, sessionId, messages);
|
|
216
|
+
// Update session metadata
|
|
217
|
+
session.lastMessageAt = userMessage.timestamp;
|
|
218
|
+
session.messageCount = messages.length;
|
|
219
|
+
session.preview = message.substring(0, 100);
|
|
220
|
+
// Accumulate assistant response
|
|
221
|
+
let assistantContent = "";
|
|
222
|
+
try {
|
|
223
|
+
// Trigger job via FleetManager
|
|
224
|
+
const result = await this.fleetManager.trigger(agentName, undefined, {
|
|
225
|
+
triggerType: "web",
|
|
226
|
+
prompt: message,
|
|
227
|
+
resume: existingSdkSessionId,
|
|
228
|
+
onMessage: async (sdkMessage) => {
|
|
229
|
+
// Extract text content from assistant messages
|
|
230
|
+
if (sdkMessage.type === "assistant") {
|
|
231
|
+
const content = extractMessageContent(sdkMessage);
|
|
232
|
+
if (content) {
|
|
233
|
+
assistantContent += content;
|
|
234
|
+
// Send chunk to client
|
|
235
|
+
await onChunk(content);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
// Store assistant message if we got any content
|
|
241
|
+
if (assistantContent) {
|
|
242
|
+
const assistantMessage = {
|
|
243
|
+
role: "assistant",
|
|
244
|
+
content: assistantContent,
|
|
245
|
+
timestamp: new Date().toISOString(),
|
|
246
|
+
};
|
|
247
|
+
messages.push(assistantMessage);
|
|
248
|
+
await this.saveMessageHistory(agentName, sessionId, messages);
|
|
249
|
+
// Update session metadata
|
|
250
|
+
session.lastMessageAt = assistantMessage.timestamp;
|
|
251
|
+
session.messageCount = messages.length;
|
|
252
|
+
session.preview = assistantContent.substring(0, 100);
|
|
253
|
+
}
|
|
254
|
+
// Store SDK session ID for future conversation continuity
|
|
255
|
+
if (sessionManager && result.sessionId && result.success) {
|
|
256
|
+
await sessionManager.setSession(sessionId, result.sessionId);
|
|
257
|
+
logger.debug(`Stored SDK session`, { agentName, sessionId, sdkSessionId: result.sessionId });
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
jobId: result.jobId,
|
|
261
|
+
success: result.success,
|
|
262
|
+
error: result.error?.message,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
267
|
+
logger.error(`Failed to send message`, { agentName, sessionId, error: errorMessage });
|
|
268
|
+
return {
|
|
269
|
+
jobId: "",
|
|
270
|
+
success: false,
|
|
271
|
+
error: errorMessage,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// ===========================================================================
|
|
276
|
+
// Private Helpers
|
|
277
|
+
// ===========================================================================
|
|
278
|
+
/**
|
|
279
|
+
* Ensure the manager is initialized
|
|
280
|
+
*/
|
|
281
|
+
ensureInitialized() {
|
|
282
|
+
if (!this.initialized) {
|
|
283
|
+
throw new Error("WebChatManager not initialized. Call initialize() first.");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Create a session manager for an agent
|
|
288
|
+
*/
|
|
289
|
+
async createSessionManagerForAgent(agentName) {
|
|
290
|
+
const chatLogger = {
|
|
291
|
+
debug: (msg, data) => logger.debug(`[${agentName}] ${msg}${data ? ` ${JSON.stringify(data)}` : ""}`),
|
|
292
|
+
info: (msg, data) => logger.info(`[${agentName}] ${msg}${data ? ` ${JSON.stringify(data)}` : ""}`),
|
|
293
|
+
warn: (msg, data) => logger.warn(`[${agentName}] ${msg}${data ? ` ${JSON.stringify(data)}` : ""}`),
|
|
294
|
+
error: (msg, data) => logger.error(`[${agentName}] ${msg}${data ? ` ${JSON.stringify(data)}` : ""}`),
|
|
295
|
+
};
|
|
296
|
+
const sessionManager = new ChatSessionManager({
|
|
297
|
+
platform: "web",
|
|
298
|
+
agentName,
|
|
299
|
+
stateDir: this.stateDir,
|
|
300
|
+
sessionExpiryHours: this.sessionExpiryHours,
|
|
301
|
+
logger: chatLogger,
|
|
302
|
+
});
|
|
303
|
+
this.sessionManagers.set(agentName, sessionManager);
|
|
304
|
+
logger.debug(`Created session manager for agent`, { agentName });
|
|
305
|
+
return sessionManager;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Get the chat history directory path
|
|
309
|
+
*/
|
|
310
|
+
getChatHistoryDir(agentName) {
|
|
311
|
+
return join(this.stateDir, "web", "chat-history", agentName);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Get the message history file path for a session
|
|
315
|
+
*/
|
|
316
|
+
getMessageHistoryPath(agentName, sessionId) {
|
|
317
|
+
return join(this.getChatHistoryDir(agentName), `${sessionId}.json`);
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Ensure chat history directories exist
|
|
321
|
+
*/
|
|
322
|
+
async ensureChatHistoryDir() {
|
|
323
|
+
const baseDir = join(this.stateDir, "web", "chat-history");
|
|
324
|
+
await mkdir(baseDir, { recursive: true });
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Load message history from disk
|
|
328
|
+
*/
|
|
329
|
+
async loadMessageHistory(agentName, sessionId) {
|
|
330
|
+
const filePath = this.getMessageHistoryPath(agentName, sessionId);
|
|
331
|
+
try {
|
|
332
|
+
const content = await readFile(filePath, "utf-8");
|
|
333
|
+
const data = JSON.parse(content);
|
|
334
|
+
return data.messages ?? [];
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
const code = error.code;
|
|
338
|
+
if (code === "ENOENT") {
|
|
339
|
+
return [];
|
|
340
|
+
}
|
|
341
|
+
logger.warn(`Failed to load message history`, {
|
|
342
|
+
agentName,
|
|
343
|
+
sessionId,
|
|
344
|
+
error: error.message,
|
|
345
|
+
});
|
|
346
|
+
return [];
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Save message history to disk
|
|
351
|
+
*/
|
|
352
|
+
async saveMessageHistory(agentName, sessionId, messages) {
|
|
353
|
+
const filePath = this.getMessageHistoryPath(agentName, sessionId);
|
|
354
|
+
const dir = dirname(filePath);
|
|
355
|
+
await mkdir(dir, { recursive: true });
|
|
356
|
+
const data = {
|
|
357
|
+
sessionId,
|
|
358
|
+
agentName,
|
|
359
|
+
messages,
|
|
360
|
+
updatedAt: new Date().toISOString(),
|
|
361
|
+
};
|
|
362
|
+
await writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Delete message history file
|
|
366
|
+
*/
|
|
367
|
+
async deleteMessageHistory(agentName, sessionId) {
|
|
368
|
+
const filePath = this.getMessageHistoryPath(agentName, sessionId);
|
|
369
|
+
try {
|
|
370
|
+
await unlink(filePath);
|
|
371
|
+
}
|
|
372
|
+
catch (error) {
|
|
373
|
+
const code = error.code;
|
|
374
|
+
if (code !== "ENOENT") {
|
|
375
|
+
logger.warn(`Failed to delete message history`, {
|
|
376
|
+
agentName,
|
|
377
|
+
sessionId,
|
|
378
|
+
error: error.message,
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Load sessions from disk into metadata cache
|
|
385
|
+
*/
|
|
386
|
+
async loadSessionsFromDisk(agentName) {
|
|
387
|
+
// Skip if already loaded
|
|
388
|
+
if (this.sessionMetadata.has(agentName)) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
const dir = this.getChatHistoryDir(agentName);
|
|
392
|
+
const agentSessions = new Map();
|
|
393
|
+
try {
|
|
394
|
+
const { readdir } = await import("node:fs/promises");
|
|
395
|
+
const files = await readdir(dir);
|
|
396
|
+
for (const file of files) {
|
|
397
|
+
if (!file.endsWith(".json"))
|
|
398
|
+
continue;
|
|
399
|
+
const sessionId = file.slice(0, -5); // Remove .json
|
|
400
|
+
const filePath = join(dir, file);
|
|
401
|
+
try {
|
|
402
|
+
const content = await readFile(filePath, "utf-8");
|
|
403
|
+
const data = JSON.parse(content);
|
|
404
|
+
const messages = data.messages ?? [];
|
|
405
|
+
const lastMessage = messages[messages.length - 1];
|
|
406
|
+
const firstMessage = messages[0];
|
|
407
|
+
agentSessions.set(sessionId, {
|
|
408
|
+
sessionId,
|
|
409
|
+
agentName,
|
|
410
|
+
createdAt: firstMessage?.timestamp ?? data.updatedAt,
|
|
411
|
+
lastMessageAt: lastMessage?.timestamp ?? data.updatedAt,
|
|
412
|
+
messageCount: messages.length,
|
|
413
|
+
preview: lastMessage?.content?.substring(0, 100),
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
catch (error) {
|
|
417
|
+
logger.warn(`Failed to load session file`, {
|
|
418
|
+
agentName,
|
|
419
|
+
sessionId,
|
|
420
|
+
error: error.message,
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
const code = error.code;
|
|
427
|
+
if (code !== "ENOENT") {
|
|
428
|
+
logger.warn(`Failed to read chat history directory`, {
|
|
429
|
+
agentName,
|
|
430
|
+
error: error.message,
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
this.sessionMetadata.set(agentName, agentSessions);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
//# sourceMappingURL=web-chat-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-chat-manager.js","sourceRoot":"","sources":["../../../src/server/chat/web-chat-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web server factory and WebManager for @herdctl/web
|
|
3
|
+
*
|
|
4
|
+
* Creates a Fastify server that serves the React SPA and provides
|
|
5
|
+
* REST API endpoints and WebSocket connections for fleet management.
|
|
6
|
+
*/
|
|
7
|
+
import { type FastifyInstance } from "fastify";
|
|
8
|
+
import { type FleetManager, type FleetManagerContext, type IChatManager, type ChatManagerConnectorState } from "@herdctl/core";
|
|
9
|
+
import { WebSocketHandler, FleetBridge } from "./ws/index.js";
|
|
10
|
+
import { WebChatManager } from "./chat/index.js";
|
|
11
|
+
/**
|
|
12
|
+
* Configuration for the web server
|
|
13
|
+
*/
|
|
14
|
+
export interface WebServerConfig {
|
|
15
|
+
/** Port to listen on */
|
|
16
|
+
port: number;
|
|
17
|
+
/** Host to bind to */
|
|
18
|
+
host: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Result of createWebServer containing server and related components
|
|
22
|
+
*/
|
|
23
|
+
export interface WebServerResult {
|
|
24
|
+
/** The Fastify server instance */
|
|
25
|
+
server: FastifyInstance;
|
|
26
|
+
/** WebSocket handler for managing client connections */
|
|
27
|
+
wsHandler: WebSocketHandler;
|
|
28
|
+
/** Fleet bridge for event broadcasting */
|
|
29
|
+
fleetBridge: FleetBridge;
|
|
30
|
+
/** Web chat manager for handling chat sessions */
|
|
31
|
+
chatManager: WebChatManager;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Configuration for the web server (extended with state directory)
|
|
35
|
+
*/
|
|
36
|
+
export interface WebServerConfigExtended extends WebServerConfig {
|
|
37
|
+
/** State directory for persistence (e.g., ".herdctl") */
|
|
38
|
+
stateDir?: string;
|
|
39
|
+
/** Session expiry in hours for chat sessions */
|
|
40
|
+
sessionExpiryHours?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Creates a Fastify web server instance with WebSocket support
|
|
44
|
+
*
|
|
45
|
+
* The server is returned but NOT started - the caller controls the lifecycle.
|
|
46
|
+
* The returned FleetBridge should be started after the server starts listening,
|
|
47
|
+
* and stopped before the server closes.
|
|
48
|
+
*
|
|
49
|
+
* @param fleetManager - FleetManager instance for API calls and event subscription
|
|
50
|
+
* @param config - Server configuration
|
|
51
|
+
* @returns WebServerResult containing server, wsHandler, fleetBridge, and chatManager
|
|
52
|
+
*/
|
|
53
|
+
export declare function createWebServer(fleetManager: FleetManager, config: WebServerConfigExtended): Promise<WebServerResult>;
|
|
54
|
+
/**
|
|
55
|
+
* State object for WebManager
|
|
56
|
+
*/
|
|
57
|
+
export interface WebManagerState {
|
|
58
|
+
/** Whether the manager has been initialized */
|
|
59
|
+
initialized: boolean;
|
|
60
|
+
/** Whether the server is currently running */
|
|
61
|
+
running: boolean;
|
|
62
|
+
/** Host the server is bound to */
|
|
63
|
+
host: string | null;
|
|
64
|
+
/** Port the server is listening on */
|
|
65
|
+
port: number | null;
|
|
66
|
+
/** Number of connected WebSocket clients */
|
|
67
|
+
connectedClients: number;
|
|
68
|
+
/** ISO timestamp when the server started */
|
|
69
|
+
startedAt: string | null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* WebManager manages the web dashboard server lifecycle
|
|
73
|
+
*
|
|
74
|
+
* Implements IChatManager interface for integration with FleetManager.
|
|
75
|
+
* Unlike Discord/Slack managers which have per-agent connectors,
|
|
76
|
+
* WebManager provides a single dashboard that serves all agents.
|
|
77
|
+
*/
|
|
78
|
+
export declare class WebManager implements IChatManager {
|
|
79
|
+
private ctx;
|
|
80
|
+
private server;
|
|
81
|
+
private wsHandler;
|
|
82
|
+
private fleetBridge;
|
|
83
|
+
private initialized;
|
|
84
|
+
private connectorState;
|
|
85
|
+
constructor(ctx: FleetManagerContext);
|
|
86
|
+
/**
|
|
87
|
+
* Initialize the web manager
|
|
88
|
+
*
|
|
89
|
+
* Creates the Fastify server with WebSocket support and REST API routes.
|
|
90
|
+
* Does not start listening - that happens in start().
|
|
91
|
+
*/
|
|
92
|
+
initialize(): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Start the web server
|
|
95
|
+
*
|
|
96
|
+
* Starts listening on the configured host:port and begins
|
|
97
|
+
* broadcasting FleetManager events to WebSocket clients.
|
|
98
|
+
*/
|
|
99
|
+
start(): Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* Stop the web server
|
|
102
|
+
*
|
|
103
|
+
* Gracefully shuts down the Fastify server and stops event broadcasting.
|
|
104
|
+
*/
|
|
105
|
+
stop(): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Check if the manager is initialized
|
|
108
|
+
*/
|
|
109
|
+
isInitialized(): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Get the connector names managed by this manager
|
|
112
|
+
*
|
|
113
|
+
* Unlike Discord/Slack which have per-agent connectors,
|
|
114
|
+
* the web dashboard returns ["web"] to indicate it manages
|
|
115
|
+
* the single web interface.
|
|
116
|
+
*/
|
|
117
|
+
getConnectorNames(): string[];
|
|
118
|
+
/**
|
|
119
|
+
* Get the count of connected WebSocket clients
|
|
120
|
+
*/
|
|
121
|
+
getConnectedCount(): number;
|
|
122
|
+
/**
|
|
123
|
+
* Check if a specific agent is accessible via the web dashboard
|
|
124
|
+
*
|
|
125
|
+
* All agents are accessible via the web dashboard, so this always returns true.
|
|
126
|
+
*/
|
|
127
|
+
hasAgent(_agentName: string): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Get the connector state for a specific agent
|
|
130
|
+
*
|
|
131
|
+
* Since the web dashboard doesn't have per-agent connectors,
|
|
132
|
+
* this returns the overall web server state for any agent.
|
|
133
|
+
*/
|
|
134
|
+
getState(_agentName: string): ChatManagerConnectorState | undefined;
|
|
135
|
+
/**
|
|
136
|
+
* Get the internal web manager state
|
|
137
|
+
*
|
|
138
|
+
* This provides additional state information beyond the IChatManager interface.
|
|
139
|
+
*/
|
|
140
|
+
getWebState(): WebManagerState;
|
|
141
|
+
}
|
|
142
|
+
export { WebSocketHandler, FleetBridge, type WebSocketClient, type ClientMessage, type ServerMessage, type SubscribeMessage, type UnsubscribeMessage, type PingMessage, type FleetStatusMessage, type AgentUpdatedMessage, type JobCreatedMessage, type JobOutputMessage, type JobCompletedMessage, type JobFailedMessage, type JobCancelledMessage, type ScheduleTriggeredMessage, type PongMessage, type ChatSendMessage, type ChatResponseMessage, type ChatCompleteMessage, type ChatErrorMessage, isClientMessage, isChatSendMessage, isAgentStartedPayload, isAgentStoppedPayload, } from "./ws/index.js";
|
|
143
|
+
export { WebChatManager, type WebChatSession, type WebChatSessionDetails, type ChatMessage, type SendMessageResult, type OnChunkCallback, } from "./chat/index.js";
|
|
144
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAgB,EAAE,KAAK,eAAe,EAA0C,MAAM,SAAS,CAAC;AAOhG,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,yBAAyB,EAC/B,MAAM,eAAe,CAAC;AAOvB,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAQjD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,MAAM,EAAE,eAAe,CAAC;IACxB,wDAAwD;IACxD,SAAS,EAAE,gBAAgB,CAAC;IAC5B,0CAA0C;IAC1C,WAAW,EAAE,WAAW,CAAC;IACzB,kDAAkD;IAClD,WAAW,EAAE,cAAc,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,uBAAwB,SAAQ,eAAe;IAC9D,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,eAAe,CAAC,CA6G1B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,WAAW,EAAE,OAAO,CAAC;IACrB,8CAA8C;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,kCAAkC;IAClC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,sCAAsC;IACtC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,4CAA4C;IAC5C,gBAAgB,EAAE,MAAM,CAAC;IACzB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,qBAAa,UAAW,YAAW,YAAY;IAC7C,OAAO,CAAC,GAAG,CAAsB;IACjC,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,cAAc,CAYpB;gBAEU,GAAG,EAAE,mBAAmB;IAIpC;;;;;OAKG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA4CjC;;;;;OAKG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA+C5B;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB3B;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;;;;;OAMG;IACH,iBAAiB,IAAI,MAAM,EAAE;IAI7B;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAIrC;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,yBAAyB,GAAG,SAAS;IAWnE;;;;OAIG;IACH,WAAW,IAAI,eAAe;CAa/B;AAGD,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,eAAe,GACrB,MAAM,iBAAiB,CAAC"}
|