agentic-qe 1.8.3 → 1.9.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 (290) hide show
  1. package/.claude/skills/agentic-jujutsu/SKILL.md +645 -0
  2. package/.claude/skills/cicd-pipeline-qe-orchestrator/README.md +2 -2
  3. package/.claude/skills/cicd-pipeline-qe-orchestrator/SKILL.md +6 -6
  4. package/CHANGELOG.md +595 -0
  5. package/README.md +117 -16
  6. package/config/constitution.schema.json +423 -0
  7. package/config/otel-collector.yaml +234 -0
  8. package/dist/App.d.ts +5 -0
  9. package/dist/App.d.ts.map +1 -0
  10. package/dist/App.js +15 -0
  11. package/dist/App.js.map +1 -0
  12. package/dist/cli/commands/constitution.d.ts +34 -0
  13. package/dist/cli/commands/constitution.d.ts.map +1 -0
  14. package/dist/cli/commands/constitution.js +679 -0
  15. package/dist/cli/commands/constitution.js.map +1 -0
  16. package/dist/cli/commands/init-claude-md-template.js +3 -3
  17. package/dist/cli/commands/init.d.ts +8 -75
  18. package/dist/cli/commands/init.d.ts.map +1 -1
  19. package/dist/cli/commands/init.js +22 -2292
  20. package/dist/cli/commands/init.js.map +1 -1
  21. package/dist/cli/commands/telemetry.d.ts +36 -0
  22. package/dist/cli/commands/telemetry.d.ts.map +1 -0
  23. package/dist/cli/commands/telemetry.js +364 -0
  24. package/dist/cli/commands/telemetry.js.map +1 -0
  25. package/dist/cli/index.js +66 -0
  26. package/dist/cli/index.js.map +1 -1
  27. package/dist/cli/init/agents.d.ts +22 -0
  28. package/dist/cli/init/agents.d.ts.map +1 -0
  29. package/dist/cli/init/agents.js +522 -0
  30. package/dist/cli/init/agents.js.map +1 -0
  31. package/dist/cli/init/bash-wrapper.d.ts +14 -0
  32. package/dist/cli/init/bash-wrapper.d.ts.map +1 -0
  33. package/dist/cli/init/bash-wrapper.js +47 -0
  34. package/dist/cli/init/bash-wrapper.js.map +1 -0
  35. package/dist/cli/init/claude-config.d.ts +24 -0
  36. package/dist/cli/init/claude-config.d.ts.map +1 -0
  37. package/dist/cli/init/claude-config.js +275 -0
  38. package/dist/cli/init/claude-config.js.map +1 -0
  39. package/dist/cli/init/claude-md.d.ts +19 -0
  40. package/dist/cli/init/claude-md.d.ts.map +1 -0
  41. package/dist/cli/init/claude-md.js +153 -0
  42. package/dist/cli/init/claude-md.js.map +1 -0
  43. package/dist/cli/init/commands.d.ts +6 -0
  44. package/dist/cli/init/commands.d.ts.map +1 -0
  45. package/dist/cli/init/commands.js +83 -0
  46. package/dist/cli/init/commands.js.map +1 -0
  47. package/dist/cli/init/database-init.d.ts +15 -0
  48. package/dist/cli/init/database-init.d.ts.map +1 -0
  49. package/dist/cli/init/database-init.js +203 -0
  50. package/dist/cli/init/database-init.js.map +1 -0
  51. package/dist/cli/init/directory-structure.d.ts +14 -0
  52. package/dist/cli/init/directory-structure.d.ts.map +1 -0
  53. package/dist/cli/init/directory-structure.js +107 -0
  54. package/dist/cli/init/directory-structure.js.map +1 -0
  55. package/dist/cli/init/documentation.d.ts +14 -0
  56. package/dist/cli/init/documentation.d.ts.map +1 -0
  57. package/dist/cli/init/documentation.js +195 -0
  58. package/dist/cli/init/documentation.js.map +1 -0
  59. package/dist/cli/init/fleet-config.d.ts +34 -0
  60. package/dist/cli/init/fleet-config.d.ts.map +1 -0
  61. package/dist/cli/init/fleet-config.js +269 -0
  62. package/dist/cli/init/fleet-config.js.map +1 -0
  63. package/dist/cli/init/helpers.d.ts +6 -0
  64. package/dist/cli/init/helpers.d.ts.map +1 -0
  65. package/dist/cli/init/helpers.js +94 -0
  66. package/dist/cli/init/helpers.js.map +1 -0
  67. package/dist/cli/init/index.d.ts +32 -0
  68. package/dist/cli/init/index.d.ts.map +1 -0
  69. package/dist/cli/init/index.js +294 -0
  70. package/dist/cli/init/index.js.map +1 -0
  71. package/dist/cli/init/skills.d.ts +6 -0
  72. package/dist/cli/init/skills.d.ts.map +1 -0
  73. package/dist/cli/init/skills.js +138 -0
  74. package/dist/cli/init/skills.js.map +1 -0
  75. package/dist/cli/init/utils/file-utils.d.ts +74 -0
  76. package/dist/cli/init/utils/file-utils.d.ts.map +1 -0
  77. package/dist/cli/init/utils/file-utils.js +187 -0
  78. package/dist/cli/init/utils/file-utils.js.map +1 -0
  79. package/dist/cli/init/utils/index.d.ts +18 -0
  80. package/dist/cli/init/utils/index.d.ts.map +1 -0
  81. package/dist/cli/init/utils/index.js +48 -0
  82. package/dist/cli/init/utils/index.js.map +1 -0
  83. package/dist/cli/init/utils/log-utils.d.ts +47 -0
  84. package/dist/cli/init/utils/log-utils.d.ts.map +1 -0
  85. package/dist/cli/init/utils/log-utils.js +68 -0
  86. package/dist/cli/init/utils/log-utils.js.map +1 -0
  87. package/dist/cli/init/utils/path-utils.d.ts +91 -0
  88. package/dist/cli/init/utils/path-utils.d.ts.map +1 -0
  89. package/dist/cli/init/utils/path-utils.js +208 -0
  90. package/dist/cli/init/utils/path-utils.js.map +1 -0
  91. package/dist/cli/init/utils/validation-utils.d.ts +44 -0
  92. package/dist/cli/init/utils/validation-utils.d.ts.map +1 -0
  93. package/dist/cli/init/utils/validation-utils.js +68 -0
  94. package/dist/cli/init/utils/validation-utils.js.map +1 -0
  95. package/dist/cli/init/utils.d.ts +183 -0
  96. package/dist/cli/init/utils.d.ts.map +1 -0
  97. package/dist/cli/init/utils.js +354 -0
  98. package/dist/cli/init/utils.js.map +1 -0
  99. package/dist/components/Dashboard/Dashboard.d.ts +4 -0
  100. package/dist/components/Dashboard/Dashboard.d.ts.map +1 -0
  101. package/dist/components/Dashboard/Dashboard.js +148 -0
  102. package/dist/components/Dashboard/Dashboard.js.map +1 -0
  103. package/dist/components/Dashboard/DashboardHeader.d.ts +4 -0
  104. package/dist/components/Dashboard/DashboardHeader.d.ts.map +1 -0
  105. package/dist/components/Dashboard/DashboardHeader.js +138 -0
  106. package/dist/components/Dashboard/DashboardHeader.js.map +1 -0
  107. package/dist/constitution/evaluators/ast-evaluator.d.ts +42 -0
  108. package/dist/constitution/evaluators/ast-evaluator.d.ts.map +1 -0
  109. package/dist/constitution/evaluators/ast-evaluator.js +303 -0
  110. package/dist/constitution/evaluators/ast-evaluator.js.map +1 -0
  111. package/dist/constitution/evaluators/base.d.ts +144 -0
  112. package/dist/constitution/evaluators/base.d.ts.map +1 -0
  113. package/dist/constitution/evaluators/base.js +144 -0
  114. package/dist/constitution/evaluators/base.js.map +1 -0
  115. package/dist/constitution/evaluators/index.d.ts +19 -0
  116. package/dist/constitution/evaluators/index.d.ts.map +1 -0
  117. package/dist/constitution/evaluators/index.js +56 -0
  118. package/dist/constitution/evaluators/index.js.map +1 -0
  119. package/dist/constitution/evaluators/metric-evaluator.d.ts +59 -0
  120. package/dist/constitution/evaluators/metric-evaluator.d.ts.map +1 -0
  121. package/dist/constitution/evaluators/metric-evaluator.js +195 -0
  122. package/dist/constitution/evaluators/metric-evaluator.js.map +1 -0
  123. package/dist/constitution/evaluators/pattern-evaluator.d.ts +66 -0
  124. package/dist/constitution/evaluators/pattern-evaluator.d.ts.map +1 -0
  125. package/dist/constitution/evaluators/pattern-evaluator.js +221 -0
  126. package/dist/constitution/evaluators/pattern-evaluator.js.map +1 -0
  127. package/dist/constitution/evaluators/semantic-evaluator.d.ts +68 -0
  128. package/dist/constitution/evaluators/semantic-evaluator.d.ts.map +1 -0
  129. package/dist/constitution/evaluators/semantic-evaluator.js +250 -0
  130. package/dist/constitution/evaluators/semantic-evaluator.js.map +1 -0
  131. package/dist/constitution/index.d.ts +105 -0
  132. package/dist/constitution/index.d.ts.map +1 -0
  133. package/dist/constitution/index.js +207 -0
  134. package/dist/constitution/index.js.map +1 -0
  135. package/dist/constitution/loader.d.ts +141 -0
  136. package/dist/constitution/loader.d.ts.map +1 -0
  137. package/dist/constitution/loader.js +515 -0
  138. package/dist/constitution/loader.js.map +1 -0
  139. package/dist/constitution/schema.d.ts +409 -0
  140. package/dist/constitution/schema.d.ts.map +1 -0
  141. package/dist/constitution/schema.js +71 -0
  142. package/dist/constitution/schema.js.map +1 -0
  143. package/dist/contexts/DashboardContext.d.ts +41 -0
  144. package/dist/contexts/DashboardContext.d.ts.map +1 -0
  145. package/dist/contexts/DashboardContext.js +187 -0
  146. package/dist/contexts/DashboardContext.js.map +1 -0
  147. package/dist/core/memory/MemoryManagerFactory.d.ts +77 -0
  148. package/dist/core/memory/MemoryManagerFactory.d.ts.map +1 -0
  149. package/dist/core/memory/MemoryManagerFactory.js +270 -0
  150. package/dist/core/memory/MemoryManagerFactory.js.map +1 -0
  151. package/dist/core/memory/SwarmMemoryManager.d.ts +58 -0
  152. package/dist/core/memory/SwarmMemoryManager.d.ts.map +1 -1
  153. package/dist/core/memory/SwarmMemoryManager.js +375 -131
  154. package/dist/core/memory/SwarmMemoryManager.js.map +1 -1
  155. package/dist/core/memory/index.d.ts +1 -0
  156. package/dist/core/memory/index.d.ts.map +1 -1
  157. package/dist/core/memory/index.js +12 -1
  158. package/dist/core/memory/index.js.map +1 -1
  159. package/dist/hooks/useKeyboardShortcuts.d.ts +12 -0
  160. package/dist/hooks/useKeyboardShortcuts.d.ts.map +1 -0
  161. package/dist/hooks/useKeyboardShortcuts.js +69 -0
  162. package/dist/hooks/useKeyboardShortcuts.js.map +1 -0
  163. package/dist/mcp/handlers/memory/memory-backup.js +6 -6
  164. package/dist/mcp/handlers/memory/memory-backup.js.map +1 -1
  165. package/dist/mcp/handlers/phase2/Phase2Tools.d.ts.map +1 -1
  166. package/dist/mcp/handlers/phase2/Phase2Tools.js +4 -2
  167. package/dist/mcp/handlers/phase2/Phase2Tools.js.map +1 -1
  168. package/dist/mcp/server.d.ts.map +1 -1
  169. package/dist/mcp/server.js +4 -38
  170. package/dist/mcp/server.js.map +1 -1
  171. package/dist/mcp/services/AgentRegistry.d.ts.map +1 -1
  172. package/dist/mcp/services/AgentRegistry.js +4 -4
  173. package/dist/mcp/services/AgentRegistry.js.map +1 -1
  174. package/dist/persistence/event-store.d.ts +162 -0
  175. package/dist/persistence/event-store.d.ts.map +1 -0
  176. package/dist/persistence/event-store.js +315 -0
  177. package/dist/persistence/event-store.js.map +1 -0
  178. package/dist/persistence/index.d.ts +145 -0
  179. package/dist/persistence/index.d.ts.map +1 -0
  180. package/dist/persistence/index.js +227 -0
  181. package/dist/persistence/index.js.map +1 -0
  182. package/dist/persistence/metrics-aggregator.d.ts +187 -0
  183. package/dist/persistence/metrics-aggregator.d.ts.map +1 -0
  184. package/dist/persistence/metrics-aggregator.js +495 -0
  185. package/dist/persistence/metrics-aggregator.js.map +1 -0
  186. package/dist/persistence/reasoning-store.d.ts +178 -0
  187. package/dist/persistence/reasoning-store.d.ts.map +1 -0
  188. package/dist/persistence/reasoning-store.js +440 -0
  189. package/dist/persistence/reasoning-store.js.map +1 -0
  190. package/dist/persistence/schema.d.ts +181 -0
  191. package/dist/persistence/schema.d.ts.map +1 -0
  192. package/dist/persistence/schema.js +186 -0
  193. package/dist/persistence/schema.js.map +1 -0
  194. package/dist/telemetry/bootstrap.d.ts +67 -0
  195. package/dist/telemetry/bootstrap.d.ts.map +1 -0
  196. package/dist/telemetry/bootstrap.js +320 -0
  197. package/dist/telemetry/bootstrap.js.map +1 -0
  198. package/dist/telemetry/index.d.ts +16 -0
  199. package/dist/telemetry/index.d.ts.map +1 -0
  200. package/dist/telemetry/index.js +84 -0
  201. package/dist/telemetry/index.js.map +1 -0
  202. package/dist/telemetry/instrumentation/agent.d.ts +158 -0
  203. package/dist/telemetry/instrumentation/agent.d.ts.map +1 -0
  204. package/dist/telemetry/instrumentation/agent.js +372 -0
  205. package/dist/telemetry/instrumentation/agent.js.map +1 -0
  206. package/dist/telemetry/instrumentation/index.d.ts +24 -0
  207. package/dist/telemetry/instrumentation/index.d.ts.map +1 -0
  208. package/dist/telemetry/instrumentation/index.js +54 -0
  209. package/dist/telemetry/instrumentation/index.js.map +1 -0
  210. package/dist/telemetry/instrumentation/memory.d.ts +313 -0
  211. package/dist/telemetry/instrumentation/memory.d.ts.map +1 -0
  212. package/dist/telemetry/instrumentation/memory.js +552 -0
  213. package/dist/telemetry/instrumentation/memory.js.map +1 -0
  214. package/dist/telemetry/instrumentation/task.d.ts +146 -0
  215. package/dist/telemetry/instrumentation/task.d.ts.map +1 -0
  216. package/dist/telemetry/instrumentation/task.js +305 -0
  217. package/dist/telemetry/instrumentation/task.js.map +1 -0
  218. package/dist/telemetry/metrics/agent-metrics.d.ts +109 -0
  219. package/dist/telemetry/metrics/agent-metrics.d.ts.map +1 -0
  220. package/dist/telemetry/metrics/agent-metrics.js +213 -0
  221. package/dist/telemetry/metrics/agent-metrics.js.map +1 -0
  222. package/dist/telemetry/metrics/collectors/cost.d.ts +246 -0
  223. package/dist/telemetry/metrics/collectors/cost.d.ts.map +1 -0
  224. package/dist/telemetry/metrics/collectors/cost.js +526 -0
  225. package/dist/telemetry/metrics/collectors/cost.js.map +1 -0
  226. package/dist/telemetry/metrics/collectors/pricing-config.d.ts +87 -0
  227. package/dist/telemetry/metrics/collectors/pricing-config.d.ts.map +1 -0
  228. package/dist/telemetry/metrics/collectors/pricing-config.js +207 -0
  229. package/dist/telemetry/metrics/collectors/pricing-config.js.map +1 -0
  230. package/dist/telemetry/metrics/index.d.ts +54 -0
  231. package/dist/telemetry/metrics/index.d.ts.map +1 -0
  232. package/dist/telemetry/metrics/index.js +116 -0
  233. package/dist/telemetry/metrics/index.js.map +1 -0
  234. package/dist/telemetry/metrics/quality-metrics.d.ts +171 -0
  235. package/dist/telemetry/metrics/quality-metrics.d.ts.map +1 -0
  236. package/dist/telemetry/metrics/quality-metrics.js +259 -0
  237. package/dist/telemetry/metrics/quality-metrics.js.map +1 -0
  238. package/dist/telemetry/metrics/system-metrics.d.ts +129 -0
  239. package/dist/telemetry/metrics/system-metrics.d.ts.map +1 -0
  240. package/dist/telemetry/metrics/system-metrics.js +380 -0
  241. package/dist/telemetry/metrics/system-metrics.js.map +1 -0
  242. package/dist/telemetry/types.d.ts +195 -0
  243. package/dist/telemetry/types.d.ts.map +1 -0
  244. package/dist/telemetry/types.js +90 -0
  245. package/dist/telemetry/types.js.map +1 -0
  246. package/dist/visualization/api/RestEndpoints.d.ts +136 -0
  247. package/dist/visualization/api/RestEndpoints.d.ts.map +1 -0
  248. package/dist/visualization/api/RestEndpoints.js +428 -0
  249. package/dist/visualization/api/RestEndpoints.js.map +1 -0
  250. package/dist/visualization/api/WebSocketServer.d.ts +165 -0
  251. package/dist/visualization/api/WebSocketServer.d.ts.map +1 -0
  252. package/dist/visualization/api/WebSocketServer.js +518 -0
  253. package/dist/visualization/api/WebSocketServer.js.map +1 -0
  254. package/dist/visualization/core/DataTransformer.d.ts +89 -0
  255. package/dist/visualization/core/DataTransformer.d.ts.map +1 -0
  256. package/dist/visualization/core/DataTransformer.js +478 -0
  257. package/dist/visualization/core/DataTransformer.js.map +1 -0
  258. package/dist/visualization/index.d.ts +92 -0
  259. package/dist/visualization/index.d.ts.map +1 -0
  260. package/dist/visualization/index.js +121 -0
  261. package/dist/visualization/index.js.map +1 -0
  262. package/dist/visualization/types.d.ts +148 -0
  263. package/dist/visualization/types.d.ts.map +1 -0
  264. package/dist/visualization/types.js +7 -0
  265. package/dist/visualization/types.js.map +1 -0
  266. package/dist/voting/consensus.d.ts +87 -0
  267. package/dist/voting/consensus.d.ts.map +1 -0
  268. package/dist/voting/consensus.js +568 -0
  269. package/dist/voting/consensus.js.map +1 -0
  270. package/dist/voting/index.d.ts +12 -0
  271. package/dist/voting/index.d.ts.map +1 -0
  272. package/dist/voting/index.js +36 -0
  273. package/dist/voting/index.js.map +1 -0
  274. package/dist/voting/orchestrator.d.ts +65 -0
  275. package/dist/voting/orchestrator.d.ts.map +1 -0
  276. package/dist/voting/orchestrator.js +306 -0
  277. package/dist/voting/orchestrator.js.map +1 -0
  278. package/dist/voting/panel-assembly.d.ts +54 -0
  279. package/dist/voting/panel-assembly.d.ts.map +1 -0
  280. package/dist/voting/panel-assembly.js +192 -0
  281. package/dist/voting/panel-assembly.js.map +1 -0
  282. package/dist/voting/protocol.d.ts +119 -0
  283. package/dist/voting/protocol.d.ts.map +1 -0
  284. package/dist/voting/protocol.js +18 -0
  285. package/dist/voting/protocol.js.map +1 -0
  286. package/dist/voting/types.d.ts +125 -0
  287. package/dist/voting/types.d.ts.map +1 -0
  288. package/dist/voting/types.js +7 -0
  289. package/dist/voting/types.js.map +1 -0
  290. package/package.json +43 -2
@@ -0,0 +1,165 @@
1
+ /**
2
+ * @fileoverview WebSocket server for real-time event streaming
3
+ * @module visualization/api/WebSocketServer
4
+ */
5
+ import { EventEmitter } from 'events';
6
+ import { EventStore } from '../../persistence/event-store';
7
+ import { ReasoningStore } from '../../persistence/reasoning-store';
8
+ import { RealtimeEventMessage, SubscriptionOptions } from '../types';
9
+ import * as http from 'http';
10
+ /**
11
+ * WebSocket server configuration
12
+ */
13
+ export interface WebSocketServerConfig {
14
+ /** HTTP server to attach to */
15
+ server?: http.Server;
16
+ /** Port to listen on (if no server provided) */
17
+ port?: number;
18
+ /** Heartbeat interval in milliseconds */
19
+ heartbeatInterval?: number;
20
+ /** Client timeout in milliseconds */
21
+ clientTimeout?: number;
22
+ /** Maximum backlog size per client */
23
+ maxBacklogSize?: number;
24
+ /** Enable message compression */
25
+ compression?: boolean;
26
+ }
27
+ /**
28
+ * WebSocket server for real-time visualization event streaming
29
+ *
30
+ * Features:
31
+ * - Real-time event streaming with <500ms latency
32
+ * - Client subscription management with filtering
33
+ * - Backpressure handling for high-throughput scenarios
34
+ * - Automatic heartbeat and connection management
35
+ * - Message types: event, reasoning, metrics, heartbeat
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const wsServer = new WebSocketServer(eventStore, reasoningStore, {
40
+ * port: 8080,
41
+ * heartbeatInterval: 30000,
42
+ * maxBacklogSize: 1000
43
+ * });
44
+ *
45
+ * await wsServer.start();
46
+ *
47
+ * // Broadcast event to subscribed clients
48
+ * wsServer.broadcastEvent({
49
+ * type: 'event',
50
+ * timestamp: new Date().toISOString(),
51
+ * data: { agent_id: 'test-gen', event_type: 'test_generated' }
52
+ * });
53
+ * ```
54
+ */
55
+ export declare class WebSocketServer extends EventEmitter {
56
+ private clients;
57
+ private eventStore;
58
+ private reasoningStore;
59
+ private transformer;
60
+ private config;
61
+ private heartbeatTimer?;
62
+ private isRunning;
63
+ private messageQueue;
64
+ private wss?;
65
+ private httpServer?;
66
+ /**
67
+ * Default configuration
68
+ */
69
+ private static readonly DEFAULT_CONFIG;
70
+ constructor(eventStore: EventStore, reasoningStore: ReasoningStore, config?: WebSocketServerConfig);
71
+ /**
72
+ * Start the WebSocket server
73
+ */
74
+ start(): Promise<void>;
75
+ /**
76
+ * Stop the WebSocket server
77
+ */
78
+ stop(): Promise<void>;
79
+ /**
80
+ * Handle new WebSocket connection
81
+ */
82
+ private handleConnection;
83
+ /**
84
+ * Send initial data to newly connected client
85
+ */
86
+ private sendInitialData;
87
+ /**
88
+ * Handle incoming message from client
89
+ */
90
+ private handleMessage;
91
+ /**
92
+ * Handle client disconnection
93
+ */
94
+ private handleDisconnect;
95
+ /**
96
+ * Handle client error
97
+ */
98
+ private handleError;
99
+ /**
100
+ * Handle pong response (heartbeat)
101
+ */
102
+ private handlePong;
103
+ /**
104
+ * Disconnect a client
105
+ */
106
+ private disconnectClient;
107
+ /**
108
+ * Update client subscription
109
+ */
110
+ private updateSubscription;
111
+ /**
112
+ * Remove client subscription
113
+ */
114
+ private removeSubscription;
115
+ /**
116
+ * Broadcast event to all subscribed clients
117
+ * @param message - Event message to broadcast
118
+ */
119
+ broadcastEvent(message: RealtimeEventMessage): void;
120
+ /**
121
+ * Send message to specific client with backpressure handling
122
+ */
123
+ private sendMessage;
124
+ /**
125
+ * Flush message queue for a client
126
+ */
127
+ private flushMessageQueue;
128
+ /**
129
+ * Check if message should be sent to client based on subscriptions
130
+ */
131
+ private shouldSendToClient;
132
+ /**
133
+ * Start heartbeat timer
134
+ */
135
+ private startHeartbeat;
136
+ /**
137
+ * Stop heartbeat timer
138
+ */
139
+ private stopHeartbeat;
140
+ /**
141
+ * Generate unique client ID
142
+ */
143
+ private generateClientId;
144
+ /**
145
+ * Parse subscription options from URL query parameters
146
+ */
147
+ private parseSubscriptionOptions;
148
+ /**
149
+ * Get server statistics
150
+ */
151
+ getStatistics(): {
152
+ isRunning: boolean;
153
+ connectedClients: number;
154
+ totalMessagesSent: number;
155
+ averageQueueSize: number;
156
+ };
157
+ /**
158
+ * Get connected clients
159
+ */
160
+ getConnectedClients(): Array<{
161
+ id: string;
162
+ subscriptions: SubscriptionOptions;
163
+ }>;
164
+ }
165
+ //# sourceMappingURL=WebSocketServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketServer.d.ts","sourceRoot":"","sources":["../../../src/visualization/api/WebSocketServer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEnE,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACrE,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAa7B;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,+BAA+B;IAC/B,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC;IACrB,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qCAAqC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sCAAsC;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iCAAiC;IACjC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,YAAY,CAAsC;IAC1D,OAAO,CAAC,GAAG,CAAC,CAAW;IACvB,OAAO,CAAC,UAAU,CAAC,CAAc;IAEjC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAOpC;gBAGA,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,cAAc,EAC9B,MAAM,GAAE,qBAA0B;IAYpC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqD5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqC3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAuCxB;;OAEG;IACH,OAAO,CAAC,eAAe;IAmCvB;;OAEG;IACH,OAAO,CAAC,aAAa;IAoBrB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;OAEG;IACH,OAAO,CAAC,WAAW;IAKnB;;OAEG;IACH,OAAO,CAAC,UAAU;IAOlB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAQ1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAQ1B;;;OAGG;IACH,cAAc,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAkBnD;;OAEG;IACH,OAAO,CAAC,WAAW;IAmBnB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA8BzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA8B1B;;OAEG;IACH,OAAO,CAAC,cAAc;IAiCtB;;OAEG;IACH,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAchC;;OAEG;IACH,aAAa,IAAI;QACf,SAAS,EAAE,OAAO,CAAC;QACnB,gBAAgB,EAAE,MAAM,CAAC;QACzB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,gBAAgB,EAAE,MAAM,CAAC;KAC1B;IAcD;;OAEG;IACH,mBAAmB,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,mBAAmB,CAAA;KAAE,CAAC;CAMjF"}
@@ -0,0 +1,518 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview WebSocket server for real-time event streaming
4
+ * @module visualization/api/WebSocketServer
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.WebSocketServer = void 0;
41
+ const events_1 = require("events");
42
+ const DataTransformer_1 = require("../core/DataTransformer");
43
+ const http = __importStar(require("http"));
44
+ const ws_1 = require("ws");
45
+ /**
46
+ * WebSocket server for real-time visualization event streaming
47
+ *
48
+ * Features:
49
+ * - Real-time event streaming with <500ms latency
50
+ * - Client subscription management with filtering
51
+ * - Backpressure handling for high-throughput scenarios
52
+ * - Automatic heartbeat and connection management
53
+ * - Message types: event, reasoning, metrics, heartbeat
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * const wsServer = new WebSocketServer(eventStore, reasoningStore, {
58
+ * port: 8080,
59
+ * heartbeatInterval: 30000,
60
+ * maxBacklogSize: 1000
61
+ * });
62
+ *
63
+ * await wsServer.start();
64
+ *
65
+ * // Broadcast event to subscribed clients
66
+ * wsServer.broadcastEvent({
67
+ * type: 'event',
68
+ * timestamp: new Date().toISOString(),
69
+ * data: { agent_id: 'test-gen', event_type: 'test_generated' }
70
+ * });
71
+ * ```
72
+ */
73
+ class WebSocketServer extends events_1.EventEmitter {
74
+ constructor(eventStore, reasoningStore, config = {}) {
75
+ super();
76
+ this.eventStore = eventStore;
77
+ this.reasoningStore = reasoningStore;
78
+ this.transformer = new DataTransformer_1.DataTransformer(eventStore, reasoningStore);
79
+ this.config = { ...WebSocketServer.DEFAULT_CONFIG, ...config };
80
+ this.clients = new Map();
81
+ this.messageQueue = new Map();
82
+ this.isRunning = false;
83
+ }
84
+ /**
85
+ * Start the WebSocket server
86
+ */
87
+ async start() {
88
+ if (this.isRunning) {
89
+ throw new Error('WebSocket server is already running');
90
+ }
91
+ return new Promise((resolve, reject) => {
92
+ try {
93
+ // Create HTTP server if not provided
94
+ this.httpServer = this.config.server || http.createServer();
95
+ // Create WebSocket server
96
+ this.wss = new ws_1.WebSocketServer({
97
+ server: this.httpServer,
98
+ perMessageDeflate: this.config.compression,
99
+ });
100
+ // Handle WebSocket connections
101
+ this.wss.on('connection', (socket, req) => {
102
+ this.handleConnection(socket, req);
103
+ });
104
+ // Handle WebSocket server errors
105
+ this.wss.on('error', (error) => {
106
+ this.emit('error', { error: error.message, source: 'wss' });
107
+ });
108
+ // Start HTTP server if we created it
109
+ if (!this.config.server) {
110
+ this.httpServer.listen(this.config.port, () => {
111
+ console.log(`WebSocket server listening on port ${this.config.port}`);
112
+ this.startHeartbeat();
113
+ this.isRunning = true;
114
+ this.emit('started', { port: this.config.port });
115
+ resolve();
116
+ });
117
+ this.httpServer.on('error', (error) => {
118
+ this.emit('error', { error: error.message, source: 'http' });
119
+ reject(error);
120
+ });
121
+ }
122
+ else {
123
+ // Server already listening, just start heartbeat
124
+ this.startHeartbeat();
125
+ this.isRunning = true;
126
+ this.emit('started', { port: this.config.port });
127
+ resolve();
128
+ }
129
+ }
130
+ catch (error) {
131
+ reject(error);
132
+ }
133
+ });
134
+ }
135
+ /**
136
+ * Stop the WebSocket server
137
+ */
138
+ async stop() {
139
+ if (!this.isRunning) {
140
+ return;
141
+ }
142
+ this.stopHeartbeat();
143
+ // Close all client connections
144
+ for (const client of this.clients.values()) {
145
+ this.disconnectClient(client.id, 'Server shutting down');
146
+ }
147
+ // Close WebSocket server
148
+ return new Promise((resolve) => {
149
+ if (this.wss) {
150
+ this.wss.close(() => {
151
+ // Close HTTP server if we created it
152
+ if (this.httpServer && !this.config.server) {
153
+ this.httpServer.close(() => {
154
+ this.isRunning = false;
155
+ this.emit('stopped');
156
+ resolve();
157
+ });
158
+ }
159
+ else {
160
+ this.isRunning = false;
161
+ this.emit('stopped');
162
+ resolve();
163
+ }
164
+ });
165
+ }
166
+ else {
167
+ this.isRunning = false;
168
+ this.emit('stopped');
169
+ resolve();
170
+ }
171
+ });
172
+ }
173
+ /**
174
+ * Handle new WebSocket connection
175
+ */
176
+ handleConnection(socket, request) {
177
+ const clientId = this.generateClientId();
178
+ const client = {
179
+ id: clientId,
180
+ socket,
181
+ subscriptions: this.parseSubscriptionOptions(request.url),
182
+ lastHeartbeat: Date.now(),
183
+ };
184
+ this.clients.set(clientId, client);
185
+ this.messageQueue.set(clientId, []);
186
+ // Setup WebSocket event handlers
187
+ socket.on('message', (data) => {
188
+ try {
189
+ this.handleMessage(clientId, data);
190
+ }
191
+ catch (error) {
192
+ this.emit('error', { clientId, error, source: 'message_handler' });
193
+ }
194
+ });
195
+ socket.on('close', () => {
196
+ this.handleDisconnect(clientId);
197
+ });
198
+ socket.on('error', (error) => {
199
+ this.handleError(clientId, error);
200
+ });
201
+ socket.on('pong', () => {
202
+ this.handlePong(clientId);
203
+ });
204
+ this.emit('client_connected', { clientId, subscriptions: client.subscriptions });
205
+ // Send initial data based on subscriptions
206
+ this.sendInitialData(client);
207
+ }
208
+ /**
209
+ * Send initial data to newly connected client
210
+ */
211
+ sendInitialData(client) {
212
+ const { session_id, agent_id, since } = client.subscriptions;
213
+ // Send recent events
214
+ if (session_id) {
215
+ const events = this.eventStore.getEventsBySession(session_id);
216
+ const filteredEvents = since
217
+ ? events.filter(e => e.timestamp >= since)
218
+ : events.slice(-50); // Last 50 events
219
+ for (const event of filteredEvents) {
220
+ this.sendMessage(client.id, {
221
+ type: 'event',
222
+ timestamp: event.timestamp,
223
+ data: event,
224
+ });
225
+ }
226
+ }
227
+ // Send reasoning chains
228
+ if (session_id) {
229
+ const chains = this.reasoningStore.getChainsBySession(session_id, { limit: 10 });
230
+ for (const chain of chains) {
231
+ const tree = this.transformer.buildReasoningTree(chain.id);
232
+ if (tree) {
233
+ this.sendMessage(client.id, {
234
+ type: 'reasoning',
235
+ timestamp: chain.created_at,
236
+ data: tree,
237
+ });
238
+ }
239
+ }
240
+ }
241
+ }
242
+ /**
243
+ * Handle incoming message from client
244
+ */
245
+ handleMessage(clientId, data) {
246
+ try {
247
+ const message = JSON.parse(data.toString());
248
+ if (message.type === 'subscribe') {
249
+ this.updateSubscription(clientId, message.options);
250
+ }
251
+ else if (message.type === 'unsubscribe') {
252
+ this.removeSubscription(clientId);
253
+ }
254
+ else if (message.type === 'ping') {
255
+ this.sendMessage(clientId, {
256
+ type: 'heartbeat',
257
+ timestamp: new Date().toISOString(),
258
+ data: { status: 'pong' },
259
+ });
260
+ }
261
+ }
262
+ catch (error) {
263
+ this.emit('error', { clientId, error });
264
+ }
265
+ }
266
+ /**
267
+ * Handle client disconnection
268
+ */
269
+ handleDisconnect(clientId) {
270
+ this.disconnectClient(clientId, 'Client disconnected');
271
+ }
272
+ /**
273
+ * Handle client error
274
+ */
275
+ handleError(clientId, error) {
276
+ this.emit('error', { clientId, error });
277
+ this.disconnectClient(clientId, `Error: ${error.message}`);
278
+ }
279
+ /**
280
+ * Handle pong response (heartbeat)
281
+ */
282
+ handlePong(clientId) {
283
+ const client = this.clients.get(clientId);
284
+ if (client) {
285
+ client.lastHeartbeat = Date.now();
286
+ }
287
+ }
288
+ /**
289
+ * Disconnect a client
290
+ */
291
+ disconnectClient(clientId, reason) {
292
+ const client = this.clients.get(clientId);
293
+ if (!client)
294
+ return;
295
+ try {
296
+ // Close the WebSocket connection
297
+ if (client.socket.readyState === ws_1.WebSocket.OPEN || client.socket.readyState === ws_1.WebSocket.CONNECTING) {
298
+ client.socket.close(1000, reason);
299
+ }
300
+ }
301
+ catch (error) {
302
+ this.emit('error', { clientId, error, source: 'disconnect' });
303
+ }
304
+ this.clients.delete(clientId);
305
+ this.messageQueue.delete(clientId);
306
+ this.emit('client_disconnected', { clientId, reason });
307
+ }
308
+ /**
309
+ * Update client subscription
310
+ */
311
+ updateSubscription(clientId, options) {
312
+ const client = this.clients.get(clientId);
313
+ if (!client)
314
+ return;
315
+ client.subscriptions = { ...client.subscriptions, ...options };
316
+ this.emit('subscription_updated', { clientId, subscriptions: client.subscriptions });
317
+ }
318
+ /**
319
+ * Remove client subscription
320
+ */
321
+ removeSubscription(clientId) {
322
+ const client = this.clients.get(clientId);
323
+ if (!client)
324
+ return;
325
+ client.subscriptions = {};
326
+ this.emit('subscription_removed', { clientId });
327
+ }
328
+ /**
329
+ * Broadcast event to all subscribed clients
330
+ * @param message - Event message to broadcast
331
+ */
332
+ broadcastEvent(message) {
333
+ const startTime = Date.now();
334
+ for (const client of this.clients.values()) {
335
+ if (this.shouldSendToClient(client, message)) {
336
+ this.sendMessage(client.id, message);
337
+ }
338
+ }
339
+ const latency = Date.now() - startTime;
340
+ this.emit('broadcast_complete', { latency, clientCount: this.clients.size });
341
+ // Emit warning if latency exceeds 500ms threshold
342
+ if (latency > 500) {
343
+ this.emit('latency_warning', { latency, threshold: 500 });
344
+ }
345
+ }
346
+ /**
347
+ * Send message to specific client with backpressure handling
348
+ */
349
+ sendMessage(clientId, message) {
350
+ const client = this.clients.get(clientId);
351
+ if (!client)
352
+ return;
353
+ const queue = this.messageQueue.get(clientId);
354
+ // Check backlog size
355
+ if (queue.length >= this.config.maxBacklogSize) {
356
+ // Drop oldest message (FIFO)
357
+ queue.shift();
358
+ this.emit('backpressure', { clientId, queueSize: queue.length });
359
+ }
360
+ queue.push(message);
361
+ // Attempt to flush queue
362
+ this.flushMessageQueue(clientId);
363
+ }
364
+ /**
365
+ * Flush message queue for a client
366
+ */
367
+ flushMessageQueue(clientId) {
368
+ const client = this.clients.get(clientId);
369
+ const queue = this.messageQueue.get(clientId);
370
+ if (!client || !queue)
371
+ return;
372
+ while (queue.length > 0) {
373
+ const message = queue[0];
374
+ // Check if socket is open
375
+ if (client.socket.readyState !== ws_1.WebSocket.OPEN) {
376
+ break;
377
+ }
378
+ // Check for backpressure (buffered data)
379
+ if (client.socket.bufferedAmount > 0) {
380
+ // Socket buffer is full, wait for next flush
381
+ break;
382
+ }
383
+ // Send message
384
+ try {
385
+ client.socket.send(JSON.stringify(message));
386
+ queue.shift();
387
+ }
388
+ catch (error) {
389
+ this.emit('send_error', { clientId, error });
390
+ break;
391
+ }
392
+ }
393
+ }
394
+ /**
395
+ * Check if message should be sent to client based on subscriptions
396
+ */
397
+ shouldSendToClient(client, message) {
398
+ const { session_id, agent_id, event_types, since } = client.subscriptions;
399
+ // Check timestamp filter
400
+ if (since && message.timestamp < since) {
401
+ return false;
402
+ }
403
+ // Check event-specific filters
404
+ if (message.type === 'event') {
405
+ const eventData = message.data;
406
+ if (session_id && eventData.session_id !== session_id) {
407
+ return false;
408
+ }
409
+ if (agent_id && eventData.agent_id !== agent_id) {
410
+ return false;
411
+ }
412
+ if (event_types && eventData.event_type && !event_types.includes(eventData.event_type)) {
413
+ return false;
414
+ }
415
+ }
416
+ return true;
417
+ }
418
+ /**
419
+ * Start heartbeat timer
420
+ */
421
+ startHeartbeat() {
422
+ this.heartbeatTimer = setInterval(() => {
423
+ const now = Date.now();
424
+ for (const client of this.clients.values()) {
425
+ // Check for timeout
426
+ if (now - client.lastHeartbeat > this.config.clientTimeout) {
427
+ this.disconnectClient(client.id, 'Heartbeat timeout');
428
+ continue;
429
+ }
430
+ // Send WebSocket ping frame
431
+ try {
432
+ if (client.socket.readyState === ws_1.WebSocket.OPEN) {
433
+ client.socket.ping();
434
+ }
435
+ }
436
+ catch (error) {
437
+ this.emit('error', { clientId: client.id, error, source: 'ping' });
438
+ }
439
+ // Send heartbeat message
440
+ this.sendMessage(client.id, {
441
+ type: 'heartbeat',
442
+ timestamp: new Date().toISOString(),
443
+ data: {
444
+ connected_clients: this.clients.size,
445
+ uptime_ms: now - (client.lastHeartbeat - this.config.heartbeatInterval),
446
+ },
447
+ });
448
+ }
449
+ }, this.config.heartbeatInterval);
450
+ }
451
+ /**
452
+ * Stop heartbeat timer
453
+ */
454
+ stopHeartbeat() {
455
+ if (this.heartbeatTimer) {
456
+ clearInterval(this.heartbeatTimer);
457
+ this.heartbeatTimer = undefined;
458
+ }
459
+ }
460
+ /**
461
+ * Generate unique client ID
462
+ */
463
+ generateClientId() {
464
+ return `client-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
465
+ }
466
+ /**
467
+ * Parse subscription options from URL query parameters
468
+ */
469
+ parseSubscriptionOptions(url) {
470
+ if (!url)
471
+ return {};
472
+ const urlObj = new URL(url, 'http://localhost');
473
+ const params = urlObj.searchParams;
474
+ return {
475
+ session_id: params.get('session_id') || undefined,
476
+ agent_id: params.get('agent_id') || undefined,
477
+ event_types: params.get('event_types')?.split(','),
478
+ since: params.get('since') || undefined,
479
+ };
480
+ }
481
+ /**
482
+ * Get server statistics
483
+ */
484
+ getStatistics() {
485
+ let totalQueueSize = 0;
486
+ for (const queue of this.messageQueue.values()) {
487
+ totalQueueSize += queue.length;
488
+ }
489
+ return {
490
+ isRunning: this.isRunning,
491
+ connectedClients: this.clients.size,
492
+ totalMessagesSent: 0, // Would track in real implementation
493
+ averageQueueSize: this.clients.size > 0 ? totalQueueSize / this.clients.size : 0,
494
+ };
495
+ }
496
+ /**
497
+ * Get connected clients
498
+ */
499
+ getConnectedClients() {
500
+ return Array.from(this.clients.values()).map(client => ({
501
+ id: client.id,
502
+ subscriptions: client.subscriptions,
503
+ }));
504
+ }
505
+ }
506
+ exports.WebSocketServer = WebSocketServer;
507
+ /**
508
+ * Default configuration
509
+ */
510
+ WebSocketServer.DEFAULT_CONFIG = {
511
+ server: undefined,
512
+ port: 8080,
513
+ heartbeatInterval: 30000, // 30 seconds
514
+ clientTimeout: 60000, // 60 seconds
515
+ maxBacklogSize: 1000,
516
+ compression: true,
517
+ };
518
+ //# sourceMappingURL=WebSocketServer.js.map