@herdctl/web 0.0.1 → 0.1.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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/dist/client/assets/index-Cyochp2F.css +1 -0
  3. package/dist/client/assets/index-mp9jz5eD.js +373 -0
  4. package/dist/client/favicon.ico +0 -0
  5. package/dist/client/favicon.svg +1 -0
  6. package/dist/client/herdctl-logo.svg +29 -0
  7. package/dist/client/index.html +21 -0
  8. package/dist/server/__tests__/routes.test.d.ts +8 -0
  9. package/dist/server/__tests__/routes.test.d.ts.map +1 -0
  10. package/dist/server/__tests__/routes.test.js +535 -0
  11. package/dist/server/__tests__/routes.test.js.map +1 -0
  12. package/dist/server/__tests__/ws-handler.test.d.ts +7 -0
  13. package/dist/server/__tests__/ws-handler.test.d.ts.map +1 -0
  14. package/dist/server/__tests__/ws-handler.test.js +380 -0
  15. package/dist/server/__tests__/ws-handler.test.js.map +1 -0
  16. package/dist/server/chat/index.d.ts +5 -0
  17. package/dist/server/chat/index.d.ts.map +1 -0
  18. package/dist/server/chat/index.js +5 -0
  19. package/dist/server/chat/index.js.map +1 -0
  20. package/dist/server/chat/web-chat-manager.d.ts +158 -0
  21. package/dist/server/chat/web-chat-manager.d.ts.map +1 -0
  22. package/dist/server/chat/web-chat-manager.js +437 -0
  23. package/dist/server/chat/web-chat-manager.js.map +1 -0
  24. package/dist/server/index.d.ts +144 -0
  25. package/dist/server/index.d.ts.map +1 -0
  26. package/dist/server/index.js +341 -0
  27. package/dist/server/index.js.map +1 -0
  28. package/dist/server/routes/agents.d.ts +15 -0
  29. package/dist/server/routes/agents.d.ts.map +1 -0
  30. package/dist/server/routes/agents.js +66 -0
  31. package/dist/server/routes/agents.js.map +1 -0
  32. package/dist/server/routes/chat.d.ts +18 -0
  33. package/dist/server/routes/chat.d.ts.map +1 -0
  34. package/dist/server/routes/chat.js +191 -0
  35. package/dist/server/routes/chat.js.map +1 -0
  36. package/dist/server/routes/fleet.d.ts +15 -0
  37. package/dist/server/routes/fleet.d.ts.map +1 -0
  38. package/dist/server/routes/fleet.js +36 -0
  39. package/dist/server/routes/fleet.js.map +1 -0
  40. package/dist/server/routes/jobs.d.ts +17 -0
  41. package/dist/server/routes/jobs.d.ts.map +1 -0
  42. package/dist/server/routes/jobs.js +188 -0
  43. package/dist/server/routes/jobs.js.map +1 -0
  44. package/dist/server/routes/schedules.d.ts +16 -0
  45. package/dist/server/routes/schedules.d.ts.map +1 -0
  46. package/dist/server/routes/schedules.js +126 -0
  47. package/dist/server/routes/schedules.js.map +1 -0
  48. package/dist/server/ws/fleet-bridge.d.ts +80 -0
  49. package/dist/server/ws/fleet-bridge.d.ts.map +1 -0
  50. package/dist/server/ws/fleet-bridge.js +184 -0
  51. package/dist/server/ws/fleet-bridge.js.map +1 -0
  52. package/dist/server/ws/handler.d.ts +93 -0
  53. package/dist/server/ws/handler.d.ts.map +1 -0
  54. package/dist/server/ws/handler.js +270 -0
  55. package/dist/server/ws/handler.js.map +1 -0
  56. package/dist/server/ws/index.d.ts +8 -0
  57. package/dist/server/ws/index.d.ts.map +1 -0
  58. package/dist/server/ws/index.js +8 -0
  59. package/dist/server/ws/index.js.map +1 -0
  60. package/dist/server/ws/types.d.ts +215 -0
  61. package/dist/server/ws/types.d.ts.map +1 -0
  62. package/dist/server/ws/types.js +67 -0
  63. package/dist/server/ws/types.js.map +1 -0
  64. package/package.json +77 -1
@@ -0,0 +1,215 @@
1
+ /**
2
+ * WebSocket protocol types for @herdctl/web
3
+ *
4
+ * Defines the message types exchanged between the WebSocket server and clients.
5
+ * The server broadcasts FleetManager events to connected clients, and clients
6
+ * can subscribe to specific agents for high-volume output events.
7
+ */
8
+ import type { FleetStatus, AgentStartedPayload, AgentStoppedPayload, JobCreatedPayload, JobOutputPayload, JobCompletedPayload, JobFailedPayload, JobCancelledPayload, ScheduleTriggeredPayload } from "@herdctl/core";
9
+ /**
10
+ * Subscribe to an agent's output events
11
+ *
12
+ * The server will only forward `job:output` events for the specified agent
13
+ * to this client. This is used for the live output streaming feature to avoid
14
+ * overwhelming clients with output from agents they're not viewing.
15
+ */
16
+ export interface SubscribeMessage {
17
+ type: "subscribe";
18
+ payload: {
19
+ /** Name of the agent to subscribe to */
20
+ agentName: string;
21
+ };
22
+ }
23
+ /**
24
+ * Unsubscribe from an agent's output events
25
+ *
26
+ * Stop receiving `job:output` events for the specified agent.
27
+ */
28
+ export interface UnsubscribeMessage {
29
+ type: "unsubscribe";
30
+ payload: {
31
+ /** Name of the agent to unsubscribe from */
32
+ agentName: string;
33
+ };
34
+ }
35
+ /**
36
+ * Ping message for keepalive
37
+ *
38
+ * The client sends this periodically to keep the connection alive.
39
+ * The server responds with a `pong` message.
40
+ */
41
+ export interface PingMessage {
42
+ type: "ping";
43
+ }
44
+ /**
45
+ * Chat send message
46
+ *
47
+ * Client sends this to send a message to an agent in a chat session.
48
+ * The response streams back via `chat:response` messages.
49
+ */
50
+ export interface ChatSendMessage {
51
+ type: "chat:send";
52
+ payload: {
53
+ /** Name of the agent to chat with */
54
+ agentName: string;
55
+ /** Session ID for the chat conversation */
56
+ sessionId: string;
57
+ /** User message content */
58
+ message: string;
59
+ };
60
+ }
61
+ /**
62
+ * Union type of all messages that clients can send to the server
63
+ */
64
+ export type ClientMessage = SubscribeMessage | UnsubscribeMessage | PingMessage | ChatSendMessage;
65
+ /**
66
+ * Full fleet status snapshot
67
+ *
68
+ * Sent to a client immediately upon connection, and can be requested
69
+ * by the client at any time to resync state.
70
+ */
71
+ export interface FleetStatusMessage {
72
+ type: "fleet:status";
73
+ payload: FleetStatus;
74
+ }
75
+ /**
76
+ * Agent started or stopped event
77
+ *
78
+ * Broadcasts when an agent's lifecycle state changes.
79
+ */
80
+ export interface AgentUpdatedMessage {
81
+ type: "agent:updated";
82
+ payload: AgentStartedPayload | AgentStoppedPayload;
83
+ }
84
+ /**
85
+ * Job created event
86
+ *
87
+ * Broadcast to all clients when a new job is created.
88
+ */
89
+ export interface JobCreatedMessage {
90
+ type: "job:created";
91
+ payload: JobCreatedPayload;
92
+ }
93
+ /**
94
+ * Job output event
95
+ *
96
+ * Sent only to clients that have subscribed to the relevant agent.
97
+ * This is the high-volume event used for live output streaming.
98
+ */
99
+ export interface JobOutputMessage {
100
+ type: "job:output";
101
+ payload: JobOutputPayload;
102
+ }
103
+ /**
104
+ * Job completed event
105
+ *
106
+ * Broadcast to all clients when a job completes successfully.
107
+ */
108
+ export interface JobCompletedMessage {
109
+ type: "job:completed";
110
+ payload: JobCompletedPayload;
111
+ }
112
+ /**
113
+ * Job failed event
114
+ *
115
+ * Broadcast to all clients when a job fails.
116
+ */
117
+ export interface JobFailedMessage {
118
+ type: "job:failed";
119
+ payload: JobFailedPayload;
120
+ }
121
+ /**
122
+ * Job cancelled event
123
+ *
124
+ * Broadcast to all clients when a job is cancelled.
125
+ */
126
+ export interface JobCancelledMessage {
127
+ type: "job:cancelled";
128
+ payload: JobCancelledPayload;
129
+ }
130
+ /**
131
+ * Schedule triggered event
132
+ *
133
+ * Broadcast to all clients when a schedule triggers an agent run.
134
+ */
135
+ export interface ScheduleTriggeredMessage {
136
+ type: "schedule:triggered";
137
+ payload: ScheduleTriggeredPayload;
138
+ }
139
+ /**
140
+ * Pong response to ping keepalive
141
+ */
142
+ export interface PongMessage {
143
+ type: "pong";
144
+ }
145
+ /**
146
+ * Chat response chunk
147
+ *
148
+ * Server sends this as streaming response chunks during chat.
149
+ */
150
+ export interface ChatResponseMessage {
151
+ type: "chat:response";
152
+ payload: {
153
+ /** Name of the agent */
154
+ agentName: string;
155
+ /** Session ID for the chat conversation */
156
+ sessionId: string;
157
+ /** Job ID for tracking the execution */
158
+ jobId: string;
159
+ /** Response chunk content */
160
+ chunk: string;
161
+ };
162
+ }
163
+ /**
164
+ * Chat complete message
165
+ *
166
+ * Server sends this when chat response is complete.
167
+ */
168
+ export interface ChatCompleteMessage {
169
+ type: "chat:complete";
170
+ payload: {
171
+ /** Name of the agent */
172
+ agentName: string;
173
+ /** Session ID for the chat conversation */
174
+ sessionId: string;
175
+ /** Job ID for tracking the execution */
176
+ jobId: string;
177
+ };
178
+ }
179
+ /**
180
+ * Chat error message
181
+ *
182
+ * Server sends this when a chat error occurs.
183
+ */
184
+ export interface ChatErrorMessage {
185
+ type: "chat:error";
186
+ payload: {
187
+ /** Name of the agent */
188
+ agentName: string;
189
+ /** Session ID for the chat conversation */
190
+ sessionId: string;
191
+ /** Error message */
192
+ error: string;
193
+ };
194
+ }
195
+ /**
196
+ * Union type of all messages that the server can send to clients
197
+ */
198
+ export type ServerMessage = FleetStatusMessage | AgentUpdatedMessage | JobCreatedMessage | JobOutputMessage | JobCompletedMessage | JobFailedMessage | JobCancelledMessage | ScheduleTriggeredMessage | PongMessage | ChatResponseMessage | ChatCompleteMessage | ChatErrorMessage;
199
+ /**
200
+ * Check if a message is a valid ClientMessage
201
+ */
202
+ export declare function isClientMessage(data: unknown): data is ClientMessage;
203
+ /**
204
+ * Check if a message is a valid ChatSendMessage
205
+ */
206
+ export declare function isChatSendMessage(data: unknown): data is ChatSendMessage;
207
+ /**
208
+ * Type guard to check if a payload is AgentStartedPayload
209
+ */
210
+ export declare function isAgentStartedPayload(payload: AgentStartedPayload | AgentStoppedPayload): payload is AgentStartedPayload;
211
+ /**
212
+ * Type guard to check if a payload is AgentStoppedPayload
213
+ */
214
+ export declare function isAgentStoppedPayload(payload: AgentStartedPayload | AgentStoppedPayload): payload is AgentStoppedPayload;
215
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/server/ws/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EACzB,MAAM,eAAe,CAAC;AAMvB;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE;QACP,wCAAwC;QACxC,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE;QACP,4CAA4C;QAC5C,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE;QACP,qCAAqC;QACrC,SAAS,EAAE,MAAM,CAAC;QAClB,2CAA2C;QAC3C,SAAS,EAAE,MAAM,CAAC;QAClB,2BAA2B;QAC3B,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,gBAAgB,GAAG,kBAAkB,GAAG,WAAW,GAAG,eAAe,CAAC;AAMlG;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,WAAW,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,CAAC;CACpD;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,OAAO,EAAE,wBAAwB,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE;QACP,wBAAwB;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,2CAA2C;QAC3C,SAAS,EAAE,MAAM,CAAC;QAClB,wCAAwC;QACxC,KAAK,EAAE,MAAM,CAAC;QACd,6BAA6B;QAC7B,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE;QACP,wBAAwB;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,2CAA2C;QAC3C,SAAS,EAAE,MAAM,CAAC;QAClB,wCAAwC;QACxC,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE;QACP,wBAAwB;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,2CAA2C;QAC3C,SAAS,EAAE,MAAM,CAAC;QAClB,oBAAoB;QACpB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,kBAAkB,GAClB,mBAAmB,GACnB,iBAAiB,GACjB,gBAAgB,GAChB,mBAAmB,GACnB,gBAAgB,GAChB,mBAAmB,GACnB,wBAAwB,GACxB,WAAW,GACX,mBAAmB,GACnB,mBAAmB,GACnB,gBAAgB,CAAC;AAMrB;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,aAAa,CA0BpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,eAAe,CAqBxE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,GACjD,OAAO,IAAI,mBAAmB,CAEhC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,GACjD,OAAO,IAAI,mBAAmB,CAEhC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * WebSocket protocol types for @herdctl/web
3
+ *
4
+ * Defines the message types exchanged between the WebSocket server and clients.
5
+ * The server broadcasts FleetManager events to connected clients, and clients
6
+ * can subscribe to specific agents for high-volume output events.
7
+ */
8
+ // =============================================================================
9
+ // Type Guards
10
+ // =============================================================================
11
+ /**
12
+ * Check if a message is a valid ClientMessage
13
+ */
14
+ export function isClientMessage(data) {
15
+ if (typeof data !== "object" || data === null) {
16
+ return false;
17
+ }
18
+ const msg = data;
19
+ if (typeof msg.type !== "string") {
20
+ return false;
21
+ }
22
+ switch (msg.type) {
23
+ case "subscribe":
24
+ case "unsubscribe":
25
+ return (typeof msg.payload === "object" &&
26
+ msg.payload !== null &&
27
+ typeof msg.payload.agentName === "string");
28
+ case "ping":
29
+ return true;
30
+ case "chat:send":
31
+ return isChatSendMessage(msg);
32
+ default:
33
+ return false;
34
+ }
35
+ }
36
+ /**
37
+ * Check if a message is a valid ChatSendMessage
38
+ */
39
+ export function isChatSendMessage(data) {
40
+ if (typeof data !== "object" || data === null) {
41
+ return false;
42
+ }
43
+ const msg = data;
44
+ if (msg.type !== "chat:send") {
45
+ return false;
46
+ }
47
+ const payload = msg.payload;
48
+ if (typeof payload !== "object" || payload === null) {
49
+ return false;
50
+ }
51
+ return (typeof payload.agentName === "string" &&
52
+ typeof payload.sessionId === "string" &&
53
+ typeof payload.message === "string");
54
+ }
55
+ /**
56
+ * Type guard to check if a payload is AgentStartedPayload
57
+ */
58
+ export function isAgentStartedPayload(payload) {
59
+ return "agent" in payload;
60
+ }
61
+ /**
62
+ * Type guard to check if a payload is AgentStoppedPayload
63
+ */
64
+ export function isAgentStoppedPayload(payload) {
65
+ return "agentName" in payload && !("agent" in payload);
66
+ }
67
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/server/ws/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkPH,gFAAgF;AAChF,cAAc;AACd,gFAAgF;AAEhF;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,IAAa;IAC3C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,GAAG,GAAG,IAA+B,CAAC;IAE5C,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,WAAW,CAAC;QACjB,KAAK,aAAa;YAChB,OAAO,CACL,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;gBAC/B,GAAG,CAAC,OAAO,KAAK,IAAI;gBACpB,OAAQ,GAAG,CAAC,OAAmC,CAAC,SAAS,KAAK,QAAQ,CACvE,CAAC;QACJ,KAAK,MAAM;YACT,OAAO,IAAI,CAAC;QACd,KAAK,WAAW;YACd,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAChC;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAa;IAC7C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,GAAG,GAAG,IAA+B,CAAC;IAE5C,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,OAAqD,CAAC;IAC1E,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACpD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CACL,OAAO,OAAO,CAAC,SAAS,KAAK,QAAQ;QACrC,OAAO,OAAO,CAAC,SAAS,KAAK,QAAQ;QACrC,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CACpC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAkD;IAElD,OAAO,OAAO,IAAI,OAAO,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAkD;IAElD,OAAO,WAAW,IAAI,OAAO,IAAI,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC;AACzD,CAAC"}
package/package.json CHANGED
@@ -1 +1,77 @@
1
- {"name":"@herdctl/web","version":"0.0.1","description":"Web dashboard for herdctl fleet management","license":"MIT","publishConfig":{"access":"public"}}
1
+ {
2
+ "name": "@herdctl/web",
3
+ "version": "0.1.0",
4
+ "description": "Web dashboard for herdctl fleet management",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/server/index.js",
8
+ "types": "./dist/server/index.d.ts",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "dependencies": {
13
+ "@dicebear/bottts": "^9.3.1",
14
+ "@dicebear/core": "^9.3.1",
15
+ "@fastify/cors": "^10.0.3",
16
+ "@fastify/static": "^8.2.0",
17
+ "@fastify/websocket": "^11.0.3",
18
+ "fastify": "^5.2.2",
19
+ "lucide-react": "^0.475.0",
20
+ "react": "^19.0.0",
21
+ "react-dom": "^19.0.0",
22
+ "react-markdown": "^10.1.0",
23
+ "react-resizable-panels": "^2.1.7",
24
+ "react-router": "^7.2.0",
25
+ "remark-gfm": "^4.0.1",
26
+ "zustand": "^5.0.3",
27
+ "@herdctl/chat": "0.2.2",
28
+ "@herdctl/core": "5.2.0"
29
+ },
30
+ "devDependencies": {
31
+ "@tailwindcss/vite": "^4.1.18",
32
+ "@testing-library/jest-dom": "^6.6.3",
33
+ "@testing-library/react": "^16.2.0",
34
+ "@types/react": "^19.0.10",
35
+ "@types/react-dom": "^19.0.4",
36
+ "@types/ws": "^8.5.10",
37
+ "@vitejs/plugin-react": "^4.3.4",
38
+ "@vitest/coverage-v8": "^4.0.17",
39
+ "concurrently": "^9.1.2",
40
+ "jsdom": "^26.0.0",
41
+ "tailwindcss": "^4.0.9",
42
+ "typescript": "^5",
43
+ "vite": "^6.2.0",
44
+ "vitest": "^4.0.17"
45
+ },
46
+ "homepage": "https://herdctl.dev",
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "https://github.com/edspencer/herdctl"
50
+ },
51
+ "keywords": [
52
+ "claude",
53
+ "agent",
54
+ "fleet",
55
+ "orchestration",
56
+ "dashboard",
57
+ "web",
58
+ "anthropic"
59
+ ],
60
+ "engines": {
61
+ "node": ">=18"
62
+ },
63
+ "publishConfig": {
64
+ "access": "public",
65
+ "provenance": true
66
+ },
67
+ "scripts": {
68
+ "build": "npm run build:client && npm run build:server",
69
+ "build:client": "vite build",
70
+ "build:server": "tsc -p tsconfig.json",
71
+ "dev": "concurrently \"npm run dev:client\" \"npm run dev:server\"",
72
+ "dev:client": "vite",
73
+ "dev:server": "tsc -p tsconfig.json --watch",
74
+ "typecheck": "tsc --noEmit -p tsconfig.json",
75
+ "test": "vitest run --coverage --passWithNoTests"
76
+ }
77
+ }