@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,184 @@
1
+ /**
2
+ * Fleet Bridge - Connects FleetManager events to WebSocket broadcasts
3
+ *
4
+ * This module subscribes to FleetManager events and broadcasts them to
5
+ * connected WebSocket clients. It handles event filtering so that high-volume
6
+ * events like job:output are only sent to subscribed clients.
7
+ */
8
+ import { createLogger, } from "@herdctl/core";
9
+ const logger = createLogger("web:ws");
10
+ /**
11
+ * FleetBridge connects FleetManager events to WebSocket clients
12
+ */
13
+ export class FleetBridge {
14
+ fleetManager;
15
+ wsHandler;
16
+ isStarted = false;
17
+ // Store bound handlers so we can remove them later
18
+ handlers = {
19
+ agentStarted: this.onAgentStarted.bind(this),
20
+ agentStopped: this.onAgentStopped.bind(this),
21
+ jobCreated: this.onJobCreated.bind(this),
22
+ jobOutput: this.onJobOutput.bind(this),
23
+ jobCompleted: this.onJobCompleted.bind(this),
24
+ jobFailed: this.onJobFailed.bind(this),
25
+ jobCancelled: this.onJobCancelled.bind(this),
26
+ scheduleTriggered: this.onScheduleTriggered.bind(this),
27
+ };
28
+ constructor(fleetManager, wsHandler) {
29
+ this.fleetManager = fleetManager;
30
+ this.wsHandler = wsHandler;
31
+ }
32
+ /**
33
+ * Start listening to FleetManager events and broadcasting to WebSocket clients
34
+ */
35
+ start() {
36
+ if (this.isStarted) {
37
+ logger.debug("FleetBridge already started");
38
+ return;
39
+ }
40
+ logger.debug("Starting FleetBridge event listeners");
41
+ // Subscribe to FleetManager events
42
+ this.fleetManager.on("agent:started", this.handlers.agentStarted);
43
+ this.fleetManager.on("agent:stopped", this.handlers.agentStopped);
44
+ this.fleetManager.on("job:created", this.handlers.jobCreated);
45
+ this.fleetManager.on("job:output", this.handlers.jobOutput);
46
+ this.fleetManager.on("job:completed", this.handlers.jobCompleted);
47
+ this.fleetManager.on("job:failed", this.handlers.jobFailed);
48
+ this.fleetManager.on("job:cancelled", this.handlers.jobCancelled);
49
+ this.fleetManager.on("schedule:triggered", this.handlers.scheduleTriggered);
50
+ this.isStarted = true;
51
+ logger.info("FleetBridge started - broadcasting events to WebSocket clients");
52
+ }
53
+ /**
54
+ * Stop listening to FleetManager events
55
+ */
56
+ stop() {
57
+ if (!this.isStarted) {
58
+ logger.debug("FleetBridge not started");
59
+ return;
60
+ }
61
+ logger.debug("Stopping FleetBridge event listeners");
62
+ // Unsubscribe from FleetManager events
63
+ this.fleetManager.off("agent:started", this.handlers.agentStarted);
64
+ this.fleetManager.off("agent:stopped", this.handlers.agentStopped);
65
+ this.fleetManager.off("job:created", this.handlers.jobCreated);
66
+ this.fleetManager.off("job:output", this.handlers.jobOutput);
67
+ this.fleetManager.off("job:completed", this.handlers.jobCompleted);
68
+ this.fleetManager.off("job:failed", this.handlers.jobFailed);
69
+ this.fleetManager.off("job:cancelled", this.handlers.jobCancelled);
70
+ this.fleetManager.off("schedule:triggered", this.handlers.scheduleTriggered);
71
+ this.isStarted = false;
72
+ logger.info("FleetBridge stopped");
73
+ }
74
+ /**
75
+ * Check if the bridge is currently running
76
+ */
77
+ isRunning() {
78
+ return this.isStarted;
79
+ }
80
+ // ==========================================================================
81
+ // Event Handlers
82
+ // ==========================================================================
83
+ /**
84
+ * Handle agent:started event
85
+ *
86
+ * Broadcast to ALL clients (low volume event)
87
+ */
88
+ onAgentStarted(payload) {
89
+ logger.debug(`Broadcasting agent:started for ${payload.agent.name}`);
90
+ this.wsHandler.broadcast({
91
+ type: "agent:updated",
92
+ payload,
93
+ });
94
+ }
95
+ /**
96
+ * Handle agent:stopped event
97
+ *
98
+ * Broadcast to ALL clients (low volume event)
99
+ */
100
+ onAgentStopped(payload) {
101
+ logger.debug(`Broadcasting agent:stopped for ${payload.agentName}`);
102
+ this.wsHandler.broadcast({
103
+ type: "agent:updated",
104
+ payload,
105
+ });
106
+ }
107
+ /**
108
+ * Handle job:created event
109
+ *
110
+ * Broadcast to ALL clients (low volume event)
111
+ */
112
+ onJobCreated(payload) {
113
+ logger.debug(`Broadcasting job:created for job ${payload.job.id} (agent: ${payload.agentName})`);
114
+ this.wsHandler.broadcast({
115
+ type: "job:created",
116
+ payload,
117
+ });
118
+ }
119
+ /**
120
+ * Handle job:output event
121
+ *
122
+ * Broadcast ONLY to clients subscribed to this agent (high volume event)
123
+ */
124
+ onJobOutput(payload) {
125
+ // Only log at debug level since this can be very high volume
126
+ const subscriberCount = this.wsHandler.getSubscriberCount(payload.agentName);
127
+ if (subscriberCount > 0) {
128
+ logger.debug(`Broadcasting job:output for job ${payload.jobId} to ${subscriberCount} subscribers`);
129
+ this.wsHandler.broadcastToSubscribers(payload.agentName, {
130
+ type: "job:output",
131
+ payload,
132
+ });
133
+ }
134
+ }
135
+ /**
136
+ * Handle job:completed event
137
+ *
138
+ * Broadcast to ALL clients (low volume event)
139
+ */
140
+ onJobCompleted(payload) {
141
+ logger.debug(`Broadcasting job:completed for job ${payload.job.id} (agent: ${payload.agentName})`);
142
+ this.wsHandler.broadcast({
143
+ type: "job:completed",
144
+ payload,
145
+ });
146
+ }
147
+ /**
148
+ * Handle job:failed event
149
+ *
150
+ * Broadcast to ALL clients (low volume event)
151
+ */
152
+ onJobFailed(payload) {
153
+ logger.debug(`Broadcasting job:failed for job ${payload.job.id} (agent: ${payload.agentName})`);
154
+ this.wsHandler.broadcast({
155
+ type: "job:failed",
156
+ payload,
157
+ });
158
+ }
159
+ /**
160
+ * Handle job:cancelled event
161
+ *
162
+ * Broadcast to ALL clients (low volume event)
163
+ */
164
+ onJobCancelled(payload) {
165
+ logger.debug(`Broadcasting job:cancelled for job ${payload.job.id} (agent: ${payload.agentName})`);
166
+ this.wsHandler.broadcast({
167
+ type: "job:cancelled",
168
+ payload,
169
+ });
170
+ }
171
+ /**
172
+ * Handle schedule:triggered event
173
+ *
174
+ * Broadcast to ALL clients (low volume event)
175
+ */
176
+ onScheduleTriggered(payload) {
177
+ logger.debug(`Broadcasting schedule:triggered for ${payload.agentName}/${payload.scheduleName}`);
178
+ this.wsHandler.broadcast({
179
+ type: "schedule:triggered",
180
+ payload,
181
+ });
182
+ }
183
+ }
184
+ //# sourceMappingURL=fleet-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fleet-bridge.js","sourceRoot":"","sources":["../../../src/server/ws/fleet-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,GAUb,MAAM,eAAe,CAAC;AAGvB,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;AAEtC;;GAEG;AACH,MAAM,OAAO,WAAW;IACd,YAAY,CAAe;IAC3B,SAAS,CAAmB;IAC5B,SAAS,GAAG,KAAK,CAAC;IAE1B,mDAAmD;IAC3C,QAAQ,GAAG;QACjB,YAAY,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5C,YAAY,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5C,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;QACxC,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QACtC,YAAY,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5C,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QACtC,YAAY,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5C,iBAAiB,EAAE,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;KACvD,CAAC;IAEF,YAAY,YAA0B,EAAE,SAA2B;QACjE,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YAC5C,OAAO;QACT,CAAC;QAED,MAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAErD,mCAAmC;QACnC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAClE,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAClE,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC9D,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC5D,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAClE,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC5D,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAClE,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,oBAAoB,EAAE,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;QAE5E,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;IAChF,CAAC;IAED;;OAEG;IACH,IAAI;QACF,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;YACxC,OAAO;QACT,CAAC;QAED,MAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAErD,uCAAuC;QACvC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QACnE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QACnE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC/D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC7D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QACnE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC7D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QACnE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;QAE7E,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,6EAA6E;IAC7E,iBAAiB;IACjB,6EAA6E;IAE7E;;;;OAIG;IACK,cAAc,CAAC,OAA4B;QACjD,MAAM,CAAC,KAAK,CAAC,kCAAkC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;YACvB,IAAI,EAAE,eAAe;YACrB,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACK,cAAc,CAAC,OAA4B;QACjD,MAAM,CAAC,KAAK,CAAC,kCAAkC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;YACvB,IAAI,EAAE,eAAe;YACrB,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACK,YAAY,CAAC,OAA0B;QAC7C,MAAM,CAAC,KAAK,CAAC,oCAAoC,OAAO,CAAC,GAAG,CAAC,EAAE,YAAY,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;QACjG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;YACvB,IAAI,EAAE,aAAa;YACnB,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACK,WAAW,CAAC,OAAyB;QAC3C,6DAA6D;QAC7D,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC7E,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,KAAK,CAAC,mCAAmC,OAAO,CAAC,KAAK,OAAO,eAAe,cAAc,CAAC,CAAC;YACnG,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC,OAAO,CAAC,SAAS,EAAE;gBACvD,IAAI,EAAE,YAAY;gBAClB,OAAO;aACR,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,cAAc,CAAC,OAA4B;QACjD,MAAM,CAAC,KAAK,CAAC,sCAAsC,OAAO,CAAC,GAAG,CAAC,EAAE,YAAY,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;QACnG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;YACvB,IAAI,EAAE,eAAe;YACrB,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACK,WAAW,CAAC,OAAyB;QAC3C,MAAM,CAAC,KAAK,CAAC,mCAAmC,OAAO,CAAC,GAAG,CAAC,EAAE,YAAY,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;QAChG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;YACvB,IAAI,EAAE,YAAY;YAClB,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACK,cAAc,CAAC,OAA4B;QACjD,MAAM,CAAC,KAAK,CAAC,sCAAsC,OAAO,CAAC,GAAG,CAAC,EAAE,YAAY,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;QACnG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;YACvB,IAAI,EAAE,eAAe;YACrB,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACK,mBAAmB,CAAC,OAAiC;QAC3D,MAAM,CAAC,KAAK,CAAC,uCAAuC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QACjG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;YACvB,IAAI,EAAE,oBAAoB;YAC1B,OAAO;SACR,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * WebSocket connection handler for @herdctl/web
3
+ *
4
+ * Manages connected WebSocket clients, handles incoming messages,
5
+ * and provides broadcast functions for the fleet bridge.
6
+ */
7
+ import type { WebSocket } from "ws";
8
+ import { type FleetManager } from "@herdctl/core";
9
+ import { type ServerMessage } from "./types.js";
10
+ import type { WebChatManager } from "../chat/index.js";
11
+ /**
12
+ * Represents a connected WebSocket client with its subscriptions
13
+ */
14
+ export interface WebSocketClient {
15
+ /** The WebSocket connection */
16
+ socket: WebSocket;
17
+ /** Set of agent names this client is subscribed to for output events */
18
+ subscriptions: Set<string>;
19
+ /** Unique client ID for logging */
20
+ clientId: string;
21
+ }
22
+ /**
23
+ * WebSocket handler manages all connected clients and message routing
24
+ */
25
+ export declare class WebSocketHandler {
26
+ /** All connected clients */
27
+ private clients;
28
+ /** Counter for generating unique client IDs */
29
+ private clientIdCounter;
30
+ /** FleetManager for getting initial status */
31
+ private fleetManager;
32
+ /** WebChatManager for handling chat messages */
33
+ private chatManager;
34
+ constructor(fleetManager: FleetManager);
35
+ /**
36
+ * Set the chat manager for handling chat messages
37
+ *
38
+ * @param chatManager - WebChatManager instance
39
+ */
40
+ setChatManager(chatManager: WebChatManager): void;
41
+ /**
42
+ * Handle a new WebSocket connection
43
+ *
44
+ * @param socket - The WebSocket connection
45
+ */
46
+ handleConnection(socket: WebSocket): Promise<void>;
47
+ /**
48
+ * Handle an incoming message from a client
49
+ */
50
+ private handleMessage;
51
+ /**
52
+ * Process a validated client message
53
+ */
54
+ private processClientMessage;
55
+ /**
56
+ * Handle a chat:send message from a client
57
+ */
58
+ private handleChatSend;
59
+ /**
60
+ * Handle client disconnect
61
+ */
62
+ private handleDisconnect;
63
+ /**
64
+ * Send a message to a specific client
65
+ */
66
+ private sendToClient;
67
+ /**
68
+ * Broadcast a message to ALL connected clients
69
+ *
70
+ * Use this for low-volume events like job:created, job:completed, etc.
71
+ */
72
+ broadcast(message: ServerMessage): void;
73
+ /**
74
+ * Broadcast a message only to clients subscribed to a specific agent
75
+ *
76
+ * Use this for high-volume events like job:output to avoid overwhelming
77
+ * clients that aren't viewing that agent.
78
+ */
79
+ broadcastToSubscribers(agentName: string, message: ServerMessage): void;
80
+ /**
81
+ * Get the number of connected clients
82
+ */
83
+ getConnectedCount(): number;
84
+ /**
85
+ * Get the number of clients subscribed to a specific agent
86
+ */
87
+ getSubscriberCount(agentName: string): number;
88
+ /**
89
+ * Close all connections (for shutdown)
90
+ */
91
+ closeAll(): void;
92
+ }
93
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/server/ws/handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAW,MAAM,IAAI,CAAC;AAC7C,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAIL,KAAK,aAAa,EAEnB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIvD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,+BAA+B;IAC/B,MAAM,EAAE,SAAS,CAAC;IAClB,wEAAwE;IACxE,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,4BAA4B;IAC5B,OAAO,CAAC,OAAO,CAAmC;IAClD,+CAA+C;IAC/C,OAAO,CAAC,eAAe,CAAK;IAC5B,8CAA8C;IAC9C,OAAO,CAAC,YAAY,CAAe;IACnC,gDAAgD;IAChD,OAAO,CAAC,WAAW,CAA+B;gBAEtC,YAAY,EAAE,YAAY;IAItC;;;;OAIG;IACH,cAAc,CAAC,WAAW,EAAE,cAAc,GAAG,IAAI;IAIjD;;;;OAIG;IACG,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCxD;;OAEG;IACH,OAAO,CAAC,aAAa;IA0BrB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA8B5B;;OAEG;YACW,cAAc;IA4E5B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAKxB;;OAEG;IACH,OAAO,CAAC,YAAY;IAUpB;;;;OAIG;IACH,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAMvC;;;;;OAKG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI;IAQvE;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAU7C;;OAEG;IACH,QAAQ,IAAI,IAAI;CAUjB"}
@@ -0,0 +1,270 @@
1
+ /**
2
+ * WebSocket connection handler for @herdctl/web
3
+ *
4
+ * Manages connected WebSocket clients, handles incoming messages,
5
+ * and provides broadcast functions for the fleet bridge.
6
+ */
7
+ import { createLogger } from "@herdctl/core";
8
+ import { isClientMessage, } from "./types.js";
9
+ const logger = createLogger("web:ws");
10
+ /**
11
+ * WebSocket handler manages all connected clients and message routing
12
+ */
13
+ export class WebSocketHandler {
14
+ /** All connected clients */
15
+ clients = new Set();
16
+ /** Counter for generating unique client IDs */
17
+ clientIdCounter = 0;
18
+ /** FleetManager for getting initial status */
19
+ fleetManager;
20
+ /** WebChatManager for handling chat messages */
21
+ chatManager = null;
22
+ constructor(fleetManager) {
23
+ this.fleetManager = fleetManager;
24
+ }
25
+ /**
26
+ * Set the chat manager for handling chat messages
27
+ *
28
+ * @param chatManager - WebChatManager instance
29
+ */
30
+ setChatManager(chatManager) {
31
+ this.chatManager = chatManager;
32
+ }
33
+ /**
34
+ * Handle a new WebSocket connection
35
+ *
36
+ * @param socket - The WebSocket connection
37
+ */
38
+ async handleConnection(socket) {
39
+ const clientId = `client-${++this.clientIdCounter}`;
40
+ const client = {
41
+ socket,
42
+ subscriptions: new Set(),
43
+ clientId,
44
+ };
45
+ this.clients.add(client);
46
+ logger.info(`WebSocket client connected: ${clientId} (total: ${this.clients.size})`);
47
+ // Send initial fleet status snapshot
48
+ try {
49
+ const status = await this.fleetManager.getFleetStatus();
50
+ this.sendToClient(client, { type: "fleet:status", payload: status });
51
+ }
52
+ catch (error) {
53
+ logger.warn(`Failed to send initial fleet status to ${clientId}: ${error.message}`);
54
+ }
55
+ // Handle incoming messages
56
+ socket.on("message", (data) => {
57
+ this.handleMessage(client, data);
58
+ });
59
+ // Handle disconnect
60
+ socket.on("close", () => {
61
+ this.handleDisconnect(client);
62
+ });
63
+ // Handle errors
64
+ socket.on("error", (error) => {
65
+ logger.warn(`WebSocket error for ${clientId}: ${error.message}`);
66
+ });
67
+ }
68
+ /**
69
+ * Handle an incoming message from a client
70
+ */
71
+ handleMessage(client, data) {
72
+ try {
73
+ // Parse the message
74
+ let message;
75
+ if (typeof data === "string") {
76
+ message = JSON.parse(data);
77
+ }
78
+ else if (Buffer.isBuffer(data)) {
79
+ message = JSON.parse(data.toString("utf-8"));
80
+ }
81
+ else {
82
+ logger.debug(`Received non-string/buffer message from ${client.clientId}`);
83
+ return;
84
+ }
85
+ // Validate the message
86
+ if (!isClientMessage(message)) {
87
+ logger.debug(`Invalid message from ${client.clientId}: ${JSON.stringify(message)}`);
88
+ return;
89
+ }
90
+ // Handle based on message type
91
+ this.processClientMessage(client, message);
92
+ }
93
+ catch (error) {
94
+ logger.debug(`Failed to parse message from ${client.clientId}: ${error.message}`);
95
+ }
96
+ }
97
+ /**
98
+ * Process a validated client message
99
+ */
100
+ processClientMessage(client, message) {
101
+ switch (message.type) {
102
+ case "subscribe": {
103
+ const { agentName } = message.payload;
104
+ client.subscriptions.add(agentName);
105
+ logger.debug(`${client.clientId} subscribed to agent: ${agentName}`);
106
+ break;
107
+ }
108
+ case "unsubscribe": {
109
+ const { agentName } = message.payload;
110
+ client.subscriptions.delete(agentName);
111
+ logger.debug(`${client.clientId} unsubscribed from agent: ${agentName}`);
112
+ break;
113
+ }
114
+ case "ping": {
115
+ this.sendToClient(client, { type: "pong" });
116
+ break;
117
+ }
118
+ case "chat:send": {
119
+ this.handleChatSend(client, message).catch((error) => {
120
+ logger.error(`Error handling chat:send: ${error.message}`);
121
+ });
122
+ break;
123
+ }
124
+ }
125
+ }
126
+ /**
127
+ * Handle a chat:send message from a client
128
+ */
129
+ async handleChatSend(client, message) {
130
+ const { agentName, sessionId, message: userMessage } = message.payload;
131
+ if (!this.chatManager) {
132
+ this.sendToClient(client, {
133
+ type: "chat:error",
134
+ payload: {
135
+ agentName,
136
+ sessionId,
137
+ error: "Chat manager not available",
138
+ },
139
+ });
140
+ return;
141
+ }
142
+ logger.debug(`${client.clientId} sending chat message`, { agentName, sessionId });
143
+ let jobId = "";
144
+ try {
145
+ const result = await this.chatManager.sendMessage(agentName, sessionId, userMessage, async (chunk) => {
146
+ // Stream chunks back to the client
147
+ this.sendToClient(client, {
148
+ type: "chat:response",
149
+ payload: {
150
+ agentName,
151
+ sessionId,
152
+ jobId,
153
+ chunk,
154
+ },
155
+ });
156
+ });
157
+ jobId = result.jobId;
158
+ if (result.success) {
159
+ // Send completion message
160
+ this.sendToClient(client, {
161
+ type: "chat:complete",
162
+ payload: {
163
+ agentName,
164
+ sessionId,
165
+ jobId: result.jobId,
166
+ },
167
+ });
168
+ }
169
+ else {
170
+ // Send error message
171
+ this.sendToClient(client, {
172
+ type: "chat:error",
173
+ payload: {
174
+ agentName,
175
+ sessionId,
176
+ error: result.error ?? "Unknown error",
177
+ },
178
+ });
179
+ }
180
+ }
181
+ catch (error) {
182
+ const errorMessage = error instanceof Error ? error.message : String(error);
183
+ logger.error(`Chat send failed`, { agentName, sessionId, error: errorMessage });
184
+ this.sendToClient(client, {
185
+ type: "chat:error",
186
+ payload: {
187
+ agentName,
188
+ sessionId,
189
+ error: errorMessage,
190
+ },
191
+ });
192
+ }
193
+ }
194
+ /**
195
+ * Handle client disconnect
196
+ */
197
+ handleDisconnect(client) {
198
+ this.clients.delete(client);
199
+ logger.info(`WebSocket client disconnected: ${client.clientId} (remaining: ${this.clients.size})`);
200
+ }
201
+ /**
202
+ * Send a message to a specific client
203
+ */
204
+ sendToClient(client, message) {
205
+ if (client.socket.readyState === client.socket.OPEN) {
206
+ try {
207
+ client.socket.send(JSON.stringify(message));
208
+ }
209
+ catch (error) {
210
+ logger.warn(`Failed to send message to ${client.clientId}: ${error.message}`);
211
+ }
212
+ }
213
+ }
214
+ /**
215
+ * Broadcast a message to ALL connected clients
216
+ *
217
+ * Use this for low-volume events like job:created, job:completed, etc.
218
+ */
219
+ broadcast(message) {
220
+ for (const client of this.clients) {
221
+ this.sendToClient(client, message);
222
+ }
223
+ }
224
+ /**
225
+ * Broadcast a message only to clients subscribed to a specific agent
226
+ *
227
+ * Use this for high-volume events like job:output to avoid overwhelming
228
+ * clients that aren't viewing that agent.
229
+ */
230
+ broadcastToSubscribers(agentName, message) {
231
+ for (const client of this.clients) {
232
+ if (client.subscriptions.has(agentName)) {
233
+ this.sendToClient(client, message);
234
+ }
235
+ }
236
+ }
237
+ /**
238
+ * Get the number of connected clients
239
+ */
240
+ getConnectedCount() {
241
+ return this.clients.size;
242
+ }
243
+ /**
244
+ * Get the number of clients subscribed to a specific agent
245
+ */
246
+ getSubscriberCount(agentName) {
247
+ let count = 0;
248
+ for (const client of this.clients) {
249
+ if (client.subscriptions.has(agentName)) {
250
+ count++;
251
+ }
252
+ }
253
+ return count;
254
+ }
255
+ /**
256
+ * Close all connections (for shutdown)
257
+ */
258
+ closeAll() {
259
+ for (const client of this.clients) {
260
+ try {
261
+ client.socket.close(1000, "Server shutting down");
262
+ }
263
+ catch {
264
+ // Ignore errors during shutdown
265
+ }
266
+ }
267
+ this.clients.clear();
268
+ }
269
+ }
270
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/server/ws/handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAqB,MAAM,eAAe,CAAC;AAChE,OAAO,EACL,eAAe,GAKhB,MAAM,YAAY,CAAC;AAGpB,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;AActC;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAC3B,4BAA4B;IACpB,OAAO,GAAyB,IAAI,GAAG,EAAE,CAAC;IAClD,+CAA+C;IACvC,eAAe,GAAG,CAAC,CAAC;IAC5B,8CAA8C;IACtC,YAAY,CAAe;IACnC,gDAAgD;IACxC,WAAW,GAA0B,IAAI,CAAC;IAElD,YAAY,YAA0B;QACpC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,cAAc,CAAC,WAA2B;QACxC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,gBAAgB,CAAC,MAAiB;QACtC,MAAM,QAAQ,GAAG,UAAU,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC;QACpD,MAAM,MAAM,GAAoB;YAC9B,MAAM;YACN,aAAa,EAAE,IAAI,GAAG,EAAE;YACxB,QAAQ;SACT,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,+BAA+B,QAAQ,YAAY,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC;QAErF,qCAAqC;QACrC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC;YACxD,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACvE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,0CAA0C,QAAQ,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QACjG,CAAC;QAED,2BAA2B;QAC3B,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAa,EAAE,EAAE;YACrC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,oBAAoB;QACpB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACtB,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QAEH,gBAAgB;QAChB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE;YAClC,MAAM,CAAC,IAAI,CAAC,uBAAuB,QAAQ,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,MAAuB,EAAE,IAAa;QAC1D,IAAI,CAAC;YACH,oBAAoB;YACpB,IAAI,OAAgB,CAAC;YACrB,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7B,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC;iBAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YAC/C,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,KAAK,CAAC,2CAA2C,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC3E,OAAO;YACT,CAAC;YAED,uBAAuB;YACvB,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9B,MAAM,CAAC,KAAK,CAAC,wBAAwB,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBACpF,OAAO;YACT,CAAC;YAED,+BAA+B;YAC/B,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,gCAAgC,MAAM,CAAC,QAAQ,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;IAED;;OAEG;IACK,oBAAoB,CAAC,MAAuB,EAAE,OAAsB;QAC1E,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;gBACtC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBACpC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,QAAQ,yBAAyB,SAAS,EAAE,CAAC,CAAC;gBACrE,MAAM;YACR,CAAC;YAED,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;gBACtC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBACvC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,QAAQ,6BAA6B,SAAS,EAAE,CAAC,CAAC;gBACzE,MAAM;YACR,CAAC;YAED,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC5C,MAAM;YACR,CAAC;YAED,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;oBACnD,MAAM,CAAC,KAAK,CAAC,6BAA8B,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;gBACxE,CAAC,CAAC,CAAC;gBACH,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,cAAc,CAAC,MAAuB,EAAE,OAAwB;QAC5E,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;QAEvE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;gBACxB,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE;oBACP,SAAS;oBACT,SAAS;oBACT,KAAK,EAAE,4BAA4B;iBACpC;aACF,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,QAAQ,uBAAuB,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;QAElF,IAAI,KAAK,GAAG,EAAE,CAAC;QAEf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,CAC/C,SAAS,EACT,SAAS,EACT,WAAW,EACX,KAAK,EAAE,KAAK,EAAE,EAAE;gBACd,mCAAmC;gBACnC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;oBACxB,IAAI,EAAE,eAAe;oBACrB,OAAO,EAAE;wBACP,SAAS;wBACT,SAAS;wBACT,KAAK;wBACL,KAAK;qBACN;iBACF,CAAC,CAAC;YACL,CAAC,CACF,CAAC;YAEF,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;YAErB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,0BAA0B;gBAC1B,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;oBACxB,IAAI,EAAE,eAAe;oBACrB,OAAO,EAAE;wBACP,SAAS;wBACT,SAAS;wBACT,KAAK,EAAE,MAAM,CAAC,KAAK;qBACpB;iBACF,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,qBAAqB;gBACrB,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;oBACxB,IAAI,EAAE,YAAY;oBAClB,OAAO,EAAE;wBACP,SAAS;wBACT,SAAS;wBACT,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,eAAe;qBACvC;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5E,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;YAEhF,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;gBACxB,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE;oBACP,SAAS;oBACT,SAAS;oBACT,KAAK,EAAE,YAAY;iBACpB;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,MAAuB;QAC9C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,kCAAkC,MAAM,CAAC,QAAQ,gBAAgB,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC;IACrG,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,MAAuB,EAAE,OAAsB;QAClE,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACpD,IAAI,CAAC;gBACH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;YAC9C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,6BAA6B,MAAM,CAAC,QAAQ,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3F,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,OAAsB;QAC9B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,sBAAsB,CAAC,SAAiB,EAAE,OAAsB;QAC9D,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACxC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,iBAAiB;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,kBAAkB,CAAC,SAAiB;QAClC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACxC,KAAK,EAAE,CAAC;YACV,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;YACpD,CAAC;YAAC,MAAM,CAAC;gBACP,gCAAgC;YAClC,CAAC;QACH,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * WebSocket module exports for @herdctl/web
3
+ */
4
+ export * from "./types.js";
5
+ export { isChatSendMessage } from "./types.js";
6
+ export { WebSocketHandler, type WebSocketClient } from "./handler.js";
7
+ export { FleetBridge } from "./fleet-bridge.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/ws/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * WebSocket module exports for @herdctl/web
3
+ */
4
+ export * from "./types.js";
5
+ export { isChatSendMessage } from "./types.js";
6
+ export { WebSocketHandler } from "./handler.js";
7
+ export { FleetBridge } from "./fleet-bridge.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/ws/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAwB,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}