@jagilber-org/index-server 1.19.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 (360) hide show
  1. package/CHANGELOG.md +1218 -0
  2. package/CODE_OF_CONDUCT.md +49 -0
  3. package/CONTRIBUTING.md +75 -0
  4. package/LICENSE +21 -0
  5. package/README.md +523 -0
  6. package/SECURITY.md +50 -0
  7. package/dist/config/configUtils.d.ts +11 -0
  8. package/dist/config/configUtils.js +87 -0
  9. package/dist/config/dashboardConfig.d.ts +45 -0
  10. package/dist/config/dashboardConfig.js +63 -0
  11. package/dist/config/defaultValues.d.ts +61 -0
  12. package/dist/config/defaultValues.js +70 -0
  13. package/dist/config/dirConstants.d.ts +17 -0
  14. package/dist/config/dirConstants.js +28 -0
  15. package/dist/config/featureConfig.d.ts +61 -0
  16. package/dist/config/featureConfig.js +121 -0
  17. package/dist/config/runtimeConfig.d.ts +145 -0
  18. package/dist/config/runtimeConfig.js +334 -0
  19. package/dist/config/serverConfig.d.ts +90 -0
  20. package/dist/config/serverConfig.js +164 -0
  21. package/dist/dashboard/analytics/AnalyticsEngine.d.ts +142 -0
  22. package/dist/dashboard/analytics/AnalyticsEngine.js +373 -0
  23. package/dist/dashboard/analytics/BusinessIntelligence.d.ts +187 -0
  24. package/dist/dashboard/analytics/BusinessIntelligence.js +594 -0
  25. package/dist/dashboard/client/admin.html +2150 -0
  26. package/dist/dashboard/client/chunks/mermaid-layout-elk.esm.min/chunk-SP2CHFBE.mjs +1 -0
  27. package/dist/dashboard/client/chunks/mermaid-layout-elk.esm.min/render-T6MDALS3.mjs +27 -0
  28. package/dist/dashboard/client/css/admin.css +1466 -0
  29. package/dist/dashboard/client/js/admin.boot.js +359 -0
  30. package/dist/dashboard/client/js/admin.config.js +196 -0
  31. package/dist/dashboard/client/js/admin.embeddings.js +425 -0
  32. package/dist/dashboard/client/js/admin.graph.js +583 -0
  33. package/dist/dashboard/client/js/admin.instances.js +120 -0
  34. package/dist/dashboard/client/js/admin.instructions.js +552 -0
  35. package/dist/dashboard/client/js/admin.logs.js +113 -0
  36. package/dist/dashboard/client/js/admin.maintenance.js +354 -0
  37. package/dist/dashboard/client/js/admin.messaging.js +635 -0
  38. package/dist/dashboard/client/js/admin.monitor.js +181 -0
  39. package/dist/dashboard/client/js/admin.overview.js +221 -0
  40. package/dist/dashboard/client/js/admin.performance.js +61 -0
  41. package/dist/dashboard/client/js/admin.sessions.js +293 -0
  42. package/dist/dashboard/client/js/admin.sqlite.js +366 -0
  43. package/dist/dashboard/client/js/admin.utils.js +49 -0
  44. package/dist/dashboard/client/js/chart.umd.js +14 -0
  45. package/dist/dashboard/client/js/elk.bundled.js +6696 -0
  46. package/dist/dashboard/client/js/marked.umd.js +74 -0
  47. package/dist/dashboard/client/js/mermaid.min.js +3022 -0
  48. package/dist/dashboard/client/mermaid-layout-elk.esm.min.mjs +1 -0
  49. package/dist/dashboard/export/DataExporter.d.ts +169 -0
  50. package/dist/dashboard/export/DataExporter.js +737 -0
  51. package/dist/dashboard/export/exporters/csvExporter.d.ts +11 -0
  52. package/dist/dashboard/export/exporters/csvExporter.js +46 -0
  53. package/dist/dashboard/export/exporters/exportTypes.d.ts +89 -0
  54. package/dist/dashboard/export/exporters/exportTypes.js +5 -0
  55. package/dist/dashboard/export/exporters/jsonExporter.d.ts +7 -0
  56. package/dist/dashboard/export/exporters/jsonExporter.js +22 -0
  57. package/dist/dashboard/export/exporters/xmlExporter.d.ts +17 -0
  58. package/dist/dashboard/export/exporters/xmlExporter.js +175 -0
  59. package/dist/dashboard/integration/APIIntegration.d.ts +41 -0
  60. package/dist/dashboard/integration/APIIntegration.js +95 -0
  61. package/dist/dashboard/security/SecurityMonitor.d.ts +167 -0
  62. package/dist/dashboard/security/SecurityMonitor.js +559 -0
  63. package/dist/dashboard/server/AdminPanel.d.ts +183 -0
  64. package/dist/dashboard/server/AdminPanel.js +792 -0
  65. package/dist/dashboard/server/AdminPanelConfig.d.ts +42 -0
  66. package/dist/dashboard/server/AdminPanelConfig.js +80 -0
  67. package/dist/dashboard/server/AdminPanelState.d.ts +47 -0
  68. package/dist/dashboard/server/AdminPanelState.js +214 -0
  69. package/dist/dashboard/server/ApiRoutes.d.ts +17 -0
  70. package/dist/dashboard/server/ApiRoutes.js +149 -0
  71. package/dist/dashboard/server/DashboardServer.d.ts +49 -0
  72. package/dist/dashboard/server/DashboardServer.js +159 -0
  73. package/dist/dashboard/server/FileMetricsStorage.d.ts +49 -0
  74. package/dist/dashboard/server/FileMetricsStorage.js +195 -0
  75. package/dist/dashboard/server/HttpTransport.d.ts +23 -0
  76. package/dist/dashboard/server/HttpTransport.js +116 -0
  77. package/dist/dashboard/server/InstanceManager.d.ts +53 -0
  78. package/dist/dashboard/server/InstanceManager.js +284 -0
  79. package/dist/dashboard/server/KnowledgeStore.d.ts +35 -0
  80. package/dist/dashboard/server/KnowledgeStore.js +105 -0
  81. package/dist/dashboard/server/LeaderElection.d.ts +81 -0
  82. package/dist/dashboard/server/LeaderElection.js +268 -0
  83. package/dist/dashboard/server/MetricsCollector.d.ts +200 -0
  84. package/dist/dashboard/server/MetricsCollector.js +803 -0
  85. package/dist/dashboard/server/SessionPersistenceManager.d.ts +88 -0
  86. package/dist/dashboard/server/SessionPersistenceManager.js +457 -0
  87. package/dist/dashboard/server/ThinClient.d.ts +64 -0
  88. package/dist/dashboard/server/ThinClient.js +237 -0
  89. package/dist/dashboard/server/WebSocketManager.d.ts +161 -0
  90. package/dist/dashboard/server/WebSocketManager.js +463 -0
  91. package/dist/dashboard/server/httpLifecycle.d.ts +17 -0
  92. package/dist/dashboard/server/httpLifecycle.js +35 -0
  93. package/dist/dashboard/server/legacyDashboardHtml.d.ts +9 -0
  94. package/dist/dashboard/server/legacyDashboardHtml.js +618 -0
  95. package/dist/dashboard/server/legacyDashboardStyles.d.ts +5 -0
  96. package/dist/dashboard/server/legacyDashboardStyles.js +490 -0
  97. package/dist/dashboard/server/metricsAggregation.d.ts +252 -0
  98. package/dist/dashboard/server/metricsAggregation.js +206 -0
  99. package/dist/dashboard/server/metricsSerializer.d.ts +25 -0
  100. package/dist/dashboard/server/metricsSerializer.js +195 -0
  101. package/dist/dashboard/server/routes/admin.routes.d.ts +16 -0
  102. package/dist/dashboard/server/routes/admin.routes.js +596 -0
  103. package/dist/dashboard/server/routes/alerts.routes.d.ts +7 -0
  104. package/dist/dashboard/server/routes/alerts.routes.js +93 -0
  105. package/dist/dashboard/server/routes/api.feedback.routes.d.ts +73 -0
  106. package/dist/dashboard/server/routes/api.feedback.routes.js +171 -0
  107. package/dist/dashboard/server/routes/api.instructions.routes.d.ts +101 -0
  108. package/dist/dashboard/server/routes/api.instructions.routes.js +213 -0
  109. package/dist/dashboard/server/routes/api.usage.routes.d.ts +57 -0
  110. package/dist/dashboard/server/routes/api.usage.routes.js +374 -0
  111. package/dist/dashboard/server/routes/embeddings.routes.d.ts +6 -0
  112. package/dist/dashboard/server/routes/embeddings.routes.js +246 -0
  113. package/dist/dashboard/server/routes/graph.routes.d.ts +6 -0
  114. package/dist/dashboard/server/routes/graph.routes.js +280 -0
  115. package/dist/dashboard/server/routes/index.d.ts +38 -0
  116. package/dist/dashboard/server/routes/index.js +194 -0
  117. package/dist/dashboard/server/routes/instances.routes.d.ts +6 -0
  118. package/dist/dashboard/server/routes/instances.routes.js +35 -0
  119. package/dist/dashboard/server/routes/instructions.routes.d.ts +8 -0
  120. package/dist/dashboard/server/routes/instructions.routes.js +336 -0
  121. package/dist/dashboard/server/routes/knowledge.routes.d.ts +6 -0
  122. package/dist/dashboard/server/routes/knowledge.routes.js +82 -0
  123. package/dist/dashboard/server/routes/logs.routes.d.ts +6 -0
  124. package/dist/dashboard/server/routes/logs.routes.js +164 -0
  125. package/dist/dashboard/server/routes/messaging.routes.d.ts +16 -0
  126. package/dist/dashboard/server/routes/messaging.routes.js +293 -0
  127. package/dist/dashboard/server/routes/metrics.routes.d.ts +10 -0
  128. package/dist/dashboard/server/routes/metrics.routes.js +346 -0
  129. package/dist/dashboard/server/routes/scripts.routes.d.ts +9 -0
  130. package/dist/dashboard/server/routes/scripts.routes.js +84 -0
  131. package/dist/dashboard/server/routes/sqlite.routes.d.ts +9 -0
  132. package/dist/dashboard/server/routes/sqlite.routes.js +569 -0
  133. package/dist/dashboard/server/routes/status.routes.d.ts +7 -0
  134. package/dist/dashboard/server/routes/status.routes.js +183 -0
  135. package/dist/dashboard/server/routes/synthetic.routes.d.ts +7 -0
  136. package/dist/dashboard/server/routes/synthetic.routes.js +195 -0
  137. package/dist/dashboard/server/routes/tools.routes.d.ts +6 -0
  138. package/dist/dashboard/server/routes/tools.routes.js +46 -0
  139. package/dist/dashboard/server/routes/usage.routes.d.ts +6 -0
  140. package/dist/dashboard/server/routes/usage.routes.js +25 -0
  141. package/dist/dashboard/server/wsInit.d.ts +16 -0
  142. package/dist/dashboard/server/wsInit.js +35 -0
  143. package/dist/externalClientLib.d.ts +1 -0
  144. package/dist/externalClientLib.js +2 -0
  145. package/dist/minimal/index.d.ts +1 -0
  146. package/dist/minimal/index.js +140 -0
  147. package/dist/models/SessionPersistence.d.ts +115 -0
  148. package/dist/models/SessionPersistence.js +66 -0
  149. package/dist/models/instruction.d.ts +45 -0
  150. package/dist/models/instruction.js +2 -0
  151. package/dist/perf/benchmark.d.ts +1 -0
  152. package/dist/perf/benchmark.js +50 -0
  153. package/dist/portableClientWrapper.d.ts +1 -0
  154. package/dist/portableClientWrapper.js +2 -0
  155. package/dist/schemas/index.d.ts +128 -0
  156. package/dist/schemas/index.js +371 -0
  157. package/dist/scripts/runPerformanceBaseline.d.ts +1 -0
  158. package/dist/scripts/runPerformanceBaseline.js +17 -0
  159. package/dist/server/handshakeManager.d.ts +25 -0
  160. package/dist/server/handshakeManager.js +472 -0
  161. package/dist/server/index-server.d.ts +56 -0
  162. package/dist/server/index-server.js +822 -0
  163. package/dist/server/registry.d.ts +44 -0
  164. package/dist/server/registry.js +236 -0
  165. package/dist/server/sdkServer.d.ts +8 -0
  166. package/dist/server/sdkServer.js +299 -0
  167. package/dist/server/shutdownGuard.d.ts +41 -0
  168. package/dist/server/shutdownGuard.js +52 -0
  169. package/dist/server/thin-client.d.ts +22 -0
  170. package/dist/server/thin-client.js +111 -0
  171. package/dist/server/transport.d.ts +41 -0
  172. package/dist/server/transport.js +312 -0
  173. package/dist/server/transportFactory.d.ts +21 -0
  174. package/dist/server/transportFactory.js +429 -0
  175. package/dist/services/atomicFs.d.ts +22 -0
  176. package/dist/services/atomicFs.js +103 -0
  177. package/dist/services/auditLog.d.ts +38 -0
  178. package/dist/services/auditLog.js +142 -0
  179. package/dist/services/autoBackup.d.ts +14 -0
  180. package/dist/services/autoBackup.js +171 -0
  181. package/dist/services/autoSplit.d.ts +32 -0
  182. package/dist/services/autoSplit.js +113 -0
  183. package/dist/services/backupZip.d.ts +25 -0
  184. package/dist/services/backupZip.js +110 -0
  185. package/dist/services/bootstrapGating.d.ts +123 -0
  186. package/dist/services/bootstrapGating.js +221 -0
  187. package/dist/services/canonical.d.ts +23 -0
  188. package/dist/services/canonical.js +65 -0
  189. package/dist/services/categoryRules.d.ts +7 -0
  190. package/dist/services/categoryRules.js +37 -0
  191. package/dist/services/classificationService.d.ts +42 -0
  192. package/dist/services/classificationService.js +168 -0
  193. package/dist/services/embeddingService.d.ts +62 -0
  194. package/dist/services/embeddingService.js +259 -0
  195. package/dist/services/errors.d.ts +22 -0
  196. package/dist/services/errors.js +31 -0
  197. package/dist/services/featureFlags.d.ts +25 -0
  198. package/dist/services/featureFlags.js +89 -0
  199. package/dist/services/features.d.ts +13 -0
  200. package/dist/services/features.js +35 -0
  201. package/dist/services/handlers/instructions.add.d.ts +1 -0
  202. package/dist/services/handlers/instructions.add.js +496 -0
  203. package/dist/services/handlers/instructions.groom.d.ts +1 -0
  204. package/dist/services/handlers/instructions.groom.js +523 -0
  205. package/dist/services/handlers/instructions.import.d.ts +1 -0
  206. package/dist/services/handlers/instructions.import.js +173 -0
  207. package/dist/services/handlers/instructions.patch.d.ts +1 -0
  208. package/dist/services/handlers/instructions.patch.js +167 -0
  209. package/dist/services/handlers/instructions.query.d.ts +163 -0
  210. package/dist/services/handlers/instructions.query.js +522 -0
  211. package/dist/services/handlers/instructions.reload.d.ts +1 -0
  212. package/dist/services/handlers/instructions.reload.js +13 -0
  213. package/dist/services/handlers/instructions.remove.d.ts +1 -0
  214. package/dist/services/handlers/instructions.remove.js +118 -0
  215. package/dist/services/handlers/instructions.shared.d.ts +31 -0
  216. package/dist/services/handlers/instructions.shared.js +124 -0
  217. package/dist/services/handlers.activation.d.ts +1 -0
  218. package/dist/services/handlers.activation.js +203 -0
  219. package/dist/services/handlers.bootstrap.d.ts +1 -0
  220. package/dist/services/handlers.bootstrap.js +38 -0
  221. package/dist/services/handlers.dashboardConfig.d.ts +34 -0
  222. package/dist/services/handlers.dashboardConfig.js +108 -0
  223. package/dist/services/handlers.diagnostics.d.ts +1 -0
  224. package/dist/services/handlers.diagnostics.js +64 -0
  225. package/dist/services/handlers.feedback.d.ts +15 -0
  226. package/dist/services/handlers.feedback.js +378 -0
  227. package/dist/services/handlers.gates.d.ts +1 -0
  228. package/dist/services/handlers.gates.js +46 -0
  229. package/dist/services/handlers.graph.d.ts +53 -0
  230. package/dist/services/handlers.graph.js +231 -0
  231. package/dist/services/handlers.help.d.ts +1 -0
  232. package/dist/services/handlers.help.js +119 -0
  233. package/dist/services/handlers.instructionSchema.d.ts +1 -0
  234. package/dist/services/handlers.instructionSchema.js +227 -0
  235. package/dist/services/handlers.instructions.d.ts +8 -0
  236. package/dist/services/handlers.instructions.js +14 -0
  237. package/dist/services/handlers.instructionsDiagnostics.d.ts +1 -0
  238. package/dist/services/handlers.instructionsDiagnostics.js +14 -0
  239. package/dist/services/handlers.integrity.d.ts +1 -0
  240. package/dist/services/handlers.integrity.js +35 -0
  241. package/dist/services/handlers.manifest.d.ts +1 -0
  242. package/dist/services/handlers.manifest.js +24 -0
  243. package/dist/services/handlers.messaging.d.ts +12 -0
  244. package/dist/services/handlers.messaging.js +203 -0
  245. package/dist/services/handlers.metrics.d.ts +1 -0
  246. package/dist/services/handlers.metrics.js +43 -0
  247. package/dist/services/handlers.promote.d.ts +1 -0
  248. package/dist/services/handlers.promote.js +306 -0
  249. package/dist/services/handlers.prompt.d.ts +1 -0
  250. package/dist/services/handlers.prompt.js +7 -0
  251. package/dist/services/handlers.search.d.ts +69 -0
  252. package/dist/services/handlers.search.js +645 -0
  253. package/dist/services/handlers.testPrimitive.d.ts +1 -0
  254. package/dist/services/handlers.testPrimitive.js +5 -0
  255. package/dist/services/handlers.trace.d.ts +1 -0
  256. package/dist/services/handlers.trace.js +31 -0
  257. package/dist/services/handlers.usage.d.ts +1 -0
  258. package/dist/services/handlers.usage.js +11 -0
  259. package/dist/services/hotScore.d.ts +137 -0
  260. package/dist/services/hotScore.js +244 -0
  261. package/dist/services/indexContext.d.ts +117 -0
  262. package/dist/services/indexContext.js +968 -0
  263. package/dist/services/indexLoader.d.ts +44 -0
  264. package/dist/services/indexLoader.js +921 -0
  265. package/dist/services/indexRepository.d.ts +32 -0
  266. package/dist/services/indexRepository.js +71 -0
  267. package/dist/services/indexingService.d.ts +1 -0
  268. package/dist/services/indexingService.js +2 -0
  269. package/dist/services/instructions.dispatcher.d.ts +1 -0
  270. package/dist/services/instructions.dispatcher.js +231 -0
  271. package/dist/services/logPrefix.d.ts +1 -0
  272. package/dist/services/logPrefix.js +30 -0
  273. package/dist/services/logger.d.ts +52 -0
  274. package/dist/services/logger.js +268 -0
  275. package/dist/services/manifestManager.d.ts +82 -0
  276. package/dist/services/manifestManager.js +200 -0
  277. package/dist/services/messaging/agentMailbox.d.ts +60 -0
  278. package/dist/services/messaging/agentMailbox.js +353 -0
  279. package/dist/services/messaging/messagingPersistence.d.ts +20 -0
  280. package/dist/services/messaging/messagingPersistence.js +111 -0
  281. package/dist/services/messaging/messagingTypes.d.ts +150 -0
  282. package/dist/services/messaging/messagingTypes.js +66 -0
  283. package/dist/services/ownershipService.d.ts +1 -0
  284. package/dist/services/ownershipService.js +38 -0
  285. package/dist/services/performanceBaseline.d.ts +19 -0
  286. package/dist/services/performanceBaseline.js +210 -0
  287. package/dist/services/preflight.d.ts +12 -0
  288. package/dist/services/preflight.js +79 -0
  289. package/dist/services/promptReviewService.d.ts +44 -0
  290. package/dist/services/promptReviewService.js +101 -0
  291. package/dist/services/responseEnvelope.d.ts +6 -0
  292. package/dist/services/responseEnvelope.js +25 -0
  293. package/dist/services/seedBootstrap.d.ts +34 -0
  294. package/dist/services/seedBootstrap.js +427 -0
  295. package/dist/services/storage/factory.d.ts +17 -0
  296. package/dist/services/storage/factory.js +35 -0
  297. package/dist/services/storage/hashUtils.d.ts +11 -0
  298. package/dist/services/storage/hashUtils.js +35 -0
  299. package/dist/services/storage/index.d.ts +12 -0
  300. package/dist/services/storage/index.js +18 -0
  301. package/dist/services/storage/jsonFileStore.d.ts +32 -0
  302. package/dist/services/storage/jsonFileStore.js +241 -0
  303. package/dist/services/storage/migrationEngine.d.ts +35 -0
  304. package/dist/services/storage/migrationEngine.js +93 -0
  305. package/dist/services/storage/sqliteMessageStore.d.ts +53 -0
  306. package/dist/services/storage/sqliteMessageStore.js +146 -0
  307. package/dist/services/storage/sqliteSchema.d.ts +12 -0
  308. package/dist/services/storage/sqliteSchema.js +122 -0
  309. package/dist/services/storage/sqliteStore.d.ts +41 -0
  310. package/dist/services/storage/sqliteStore.js +339 -0
  311. package/dist/services/storage/sqliteUsageStore.d.ts +35 -0
  312. package/dist/services/storage/sqliteUsageStore.js +94 -0
  313. package/dist/services/storage/types.d.ts +171 -0
  314. package/dist/services/storage/types.js +12 -0
  315. package/dist/services/toolHandlers.d.ts +23 -0
  316. package/dist/services/toolHandlers.js +50 -0
  317. package/dist/services/toolRegistry.d.ts +20 -0
  318. package/dist/services/toolRegistry.js +490 -0
  319. package/dist/services/toolRegistry.zod.d.ts +10 -0
  320. package/dist/services/toolRegistry.zod.js +323 -0
  321. package/dist/services/tracing.d.ts +26 -0
  322. package/dist/services/tracing.js +260 -0
  323. package/dist/services/usageBuckets.d.ts +161 -0
  324. package/dist/services/usageBuckets.js +364 -0
  325. package/dist/services/validationService.d.ts +38 -0
  326. package/dist/services/validationService.js +125 -0
  327. package/dist/utils/BufferRing.d.ts +203 -0
  328. package/dist/utils/BufferRing.js +551 -0
  329. package/dist/utils/BufferRingExamples.d.ts +55 -0
  330. package/dist/utils/BufferRingExamples.js +188 -0
  331. package/dist/utils/envUtils.d.ts +42 -0
  332. package/dist/utils/envUtils.js +80 -0
  333. package/dist/utils/memoryMonitor.d.ts +83 -0
  334. package/dist/utils/memoryMonitor.js +275 -0
  335. package/dist/versioning/schemaVersion.d.ts +6 -0
  336. package/dist/versioning/schemaVersion.js +93 -0
  337. package/package.json +134 -0
  338. package/schemas/README.md +13 -0
  339. package/schemas/feedback-entry.schema.json +27 -0
  340. package/schemas/graph-export-v2.schema.json +60 -0
  341. package/schemas/index-server.code-schema.json +38477 -0
  342. package/schemas/instruction.schema.json +262 -0
  343. package/schemas/json-schema/SessionPersistence-persisted-admin-session.schema.json +54 -0
  344. package/schemas/json-schema/SessionPersistence-persisted-session-history-entry.schema.json +51 -0
  345. package/schemas/json-schema/SessionPersistence-persisted-web-socket-connection.schema.json +54 -0
  346. package/schemas/json-schema/SessionPersistence-session-persistence-config.schema.json +110 -0
  347. package/schemas/json-schema/SessionPersistence-session-persistence-data.schema.json +229 -0
  348. package/schemas/json-schema/SessionPersistence-session-persistence-manifest.schema.json +109 -0
  349. package/schemas/json-schema/SessionPersistence-session-persistence-metadata.schema.json +55 -0
  350. package/schemas/json-schema/instruction-audience-scope.schema.json +14 -0
  351. package/schemas/json-schema/instruction-content-type.schema.json +17 -0
  352. package/schemas/json-schema/instruction-instruction-entry.schema.json +206 -0
  353. package/schemas/json-schema/instruction-requirement-level.schema.json +16 -0
  354. package/schemas/manifest.json +78 -0
  355. package/schemas/manifest.schema.json +33 -0
  356. package/schemas/usage-batch.schema.json +16 -0
  357. package/schemas/usage-buckets.schema.json +30 -0
  358. package/schemas/usage-event.schema.json +17 -0
  359. package/scripts/copy-dashboard-assets.mjs +170 -0
  360. package/scripts/setup-hooks.cjs +28 -0
@@ -0,0 +1,803 @@
1
+ "use strict";
2
+ /**
3
+ * MetricsCollector — coordinator class (Phase 1–4 Dashboard Foundation).
4
+ *
5
+ * Owns all mutable metrics state and delegates:
6
+ * - pure math to metricsAggregation.ts
7
+ * - output serialisation to metricsSerializer.ts
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.MetricsCollector = void 0;
14
+ exports.getMetricsCollector = getMetricsCollector;
15
+ exports.setMetricsCollector = setMetricsCollector;
16
+ const fs_1 = __importDefault(require("fs"));
17
+ const path_1 = __importDefault(require("path"));
18
+ const v8_1 = __importDefault(require("v8"));
19
+ const FileMetricsStorage_js_1 = require("./FileMetricsStorage.js");
20
+ const BufferRing_js_1 = require("../../utils/BufferRing.js");
21
+ const runtimeConfig_1 = require("../../config/runtimeConfig");
22
+ const metricsAggregation_js_1 = require("./metricsAggregation.js");
23
+ const metricsSerializer_js_1 = require("./metricsSerializer.js");
24
+ class MetricsCollector {
25
+ tools = new Map();
26
+ // Resource usage samples (CPU/Memory) for leak/trend analysis
27
+ resourceSamples;
28
+ lastCpuUsageSample = null;
29
+ lastCpuSampleTime = 0;
30
+ snapshots = []; // Keep small in-memory cache for real-time queries
31
+ connections = new Set();
32
+ disconnectedCount = 0;
33
+ totalSessionTime = 0;
34
+ sessionStartTimes = new Map();
35
+ startTime = Date.now();
36
+ options;
37
+ collectTimer;
38
+ lastCpuUsage;
39
+ // Phase 4: Advanced features
40
+ recentAlerts = [];
41
+ activeConnections = 0;
42
+ // Rolling timestamp buffer for recent tool calls (used for stable RPM calculation)
43
+ recentCallTimestamps = [];
44
+ static MAX_RECENT_CALLS = 10000; // cap to avoid unbounded growth
45
+ static MAX_MEMORY_SNAPSHOTS = 60; // Keep only 1 hour in memory
46
+ static MAX_TOOL_METRICS = 1000; // cap tool metrics to prevent memory leaks
47
+ // File storage for historical data (optional)
48
+ fileStorage = null;
49
+ useFileStorage;
50
+ // BufferRing-Enhanced Storage
51
+ historicalSnapshots;
52
+ toolCallEvents;
53
+ // Persistence throttling state for tool call events (defined explicitly to avoid dynamic props)
54
+ _lastToolPersist = 0;
55
+ _pendingToolPersist = 0;
56
+ performanceMetrics;
57
+ bufferConfig;
58
+ // Append/segment logging state (optional)
59
+ appendMode = false;
60
+ appendLogPath = null;
61
+ pendingAppendEvents = [];
62
+ lastAppendFlush = 0;
63
+ lastAppendCompact = 0;
64
+ appendChunkSize = 250;
65
+ appendFlushMs = 5000;
66
+ appendCompactMs = 5 * 60 * 1000; // 5 min default
67
+ constructor(options = {}) {
68
+ this.options = {
69
+ retentionMinutes: options.retentionMinutes ?? 60,
70
+ maxSnapshots: options.maxSnapshots ?? 720, // 12 hours at 1-minute intervals
71
+ collectInterval: options.collectInterval ?? 60000, // 1 minute
72
+ };
73
+ const metricsConfig = (0, runtimeConfig_1.getRuntimeConfig)().metrics;
74
+ // Initialize resource sampling buffer (default capacity ~1h at 5s interval = 720)
75
+ const resourceCapacity = Math.max(1, metricsConfig.resourceCapacity || 720);
76
+ this.resourceSamples = new BufferRing_js_1.BufferRing({
77
+ capacity: resourceCapacity,
78
+ overflowStrategy: BufferRing_js_1.OverflowStrategy.DROP_OLDEST,
79
+ autoPersist: false,
80
+ enableIntegrityCheck: false
81
+ });
82
+ try {
83
+ const intervalMs = Math.max(100, metricsConfig.sampleIntervalMs || 5000);
84
+ setInterval(() => this.sampleResources(), intervalMs).unref();
85
+ }
86
+ catch { /* ignore */ }
87
+ // Configure BufferRing settings
88
+ const metricsDir = metricsConfig.dir || path_1.default.join(process.cwd(), 'metrics');
89
+ this.bufferConfig = {
90
+ historicalSnapshots: {
91
+ capacity: this.options.maxSnapshots,
92
+ retentionMinutes: this.options.retentionMinutes * 12, // Keep 12x longer than original
93
+ persistenceFile: path_1.default.join(metricsDir, 'historical-snapshots.json')
94
+ },
95
+ toolCallEvents: {
96
+ capacity: 10000, // Store last 10k tool calls
97
+ retentionMinutes: this.options.retentionMinutes * 2, // 2 hours of tool calls
98
+ persistenceFile: path_1.default.join(metricsDir, 'tool-call-events.json')
99
+ },
100
+ performanceMetrics: {
101
+ capacity: 1440, // Store 24 hours worth of minute-by-minute metrics
102
+ persistenceFile: path_1.default.join(metricsDir, 'performance-metrics.json')
103
+ }
104
+ };
105
+ // Check if file storage should be enabled (accept "true", "1", "yes", "on")
106
+ this.useFileStorage = metricsConfig.fileStorage;
107
+ // Initialize BufferRing storage
108
+ this.historicalSnapshots = new BufferRing_js_1.BufferRing({
109
+ capacity: this.bufferConfig.historicalSnapshots.capacity,
110
+ overflowStrategy: BufferRing_js_1.OverflowStrategy.DROP_OLDEST,
111
+ persistPath: this.useFileStorage ? this.bufferConfig.historicalSnapshots.persistenceFile : undefined,
112
+ autoPersist: this.useFileStorage
113
+ });
114
+ this.toolCallEvents = new BufferRing_js_1.BufferRing({
115
+ capacity: this.bufferConfig.toolCallEvents.capacity,
116
+ overflowStrategy: BufferRing_js_1.OverflowStrategy.DROP_OLDEST,
117
+ persistPath: this.useFileStorage ? this.bufferConfig.toolCallEvents.persistenceFile : undefined,
118
+ autoPersist: false, // we'll manage chunked persistence manually for performance
119
+ suppressPersistLog: true
120
+ });
121
+ this.performanceMetrics = new BufferRing_js_1.BufferRing({
122
+ capacity: this.bufferConfig.performanceMetrics.capacity,
123
+ overflowStrategy: BufferRing_js_1.OverflowStrategy.DROP_OLDEST,
124
+ persistPath: this.useFileStorage ? this.bufferConfig.performanceMetrics.persistenceFile : undefined,
125
+ autoPersist: this.useFileStorage
126
+ });
127
+ // Configure optional append-only logging for tool call events (reduces large snapshot writes)
128
+ if (this.useFileStorage) {
129
+ this.appendMode = metricsConfig.toolcall.appendLogEnabled;
130
+ if (this.appendMode) {
131
+ this.appendLogPath = path_1.default.join(path_1.default.dirname(this.bufferConfig.toolCallEvents.persistenceFile), 'tool-call-events.ndjson');
132
+ this.appendChunkSize = Math.max(1, metricsConfig.toolcall.chunkSize || this.appendChunkSize);
133
+ this.appendFlushMs = Math.max(1, metricsConfig.toolcall.flushMs || this.appendFlushMs);
134
+ this.appendCompactMs = Math.max(1, metricsConfig.toolcall.compactMs || this.appendCompactMs);
135
+ try {
136
+ // Load any un-compacted append log tail (best-effort)
137
+ if (this.appendLogPath && fs_1.default.existsSync(this.appendLogPath)) {
138
+ const stat = fs_1.default.statSync(this.appendLogPath);
139
+ if (stat.size < 25 * 1024 * 1024) { // safety cap 25MB
140
+ const raw = fs_1.default.readFileSync(this.appendLogPath, 'utf8');
141
+ const lines = raw.split(/\r?\n/).filter(l => l.trim().length > 0);
142
+ for (const line of lines) {
143
+ try {
144
+ const evt = JSON.parse(line);
145
+ this.toolCallEvents.add(evt);
146
+ }
147
+ catch { /* ignore bad line */ }
148
+ }
149
+ }
150
+ else {
151
+ console.warn('tool-call-events.ndjson too large to preload (>25MB); will rely on last snapshot');
152
+ }
153
+ }
154
+ }
155
+ catch (err) {
156
+ console.warn('Failed to preload append log', err);
157
+ }
158
+ }
159
+ }
160
+ if (this.useFileStorage) {
161
+ // Initialize legacy file storage for backward compatibility
162
+ this.fileStorage = (0, FileMetricsStorage_js_1.getFileMetricsStorage)({
163
+ storageDir: metricsDir,
164
+ maxFiles: this.options.maxSnapshots,
165
+ retentionMinutes: this.options.retentionMinutes,
166
+ });
167
+ console.error('📊 MetricsCollector: BufferRing + File storage enabled');
168
+ }
169
+ else {
170
+ console.error('📊 MetricsCollector: BufferRing memory-only mode (set INDEX_SERVER_METRICS_FILE_STORAGE=1|true|yes|on for persistence)');
171
+ }
172
+ // Start periodic collection
173
+ this.startCollection();
174
+ }
175
+ /**
176
+ * Record a tool call event
177
+ */
178
+ recordToolCall(toolName, success, responseTimeMs, errorType, clientId) {
179
+ const now = Date.now();
180
+ if (!this.tools.has(toolName)) {
181
+ this.tools.set(toolName, {
182
+ callCount: 0,
183
+ successCount: 0,
184
+ errorCount: 0,
185
+ totalResponseTime: 0,
186
+ errorTypes: {},
187
+ });
188
+ }
189
+ const metrics = this.tools.get(toolName);
190
+ metrics.callCount++;
191
+ metrics.totalResponseTime += responseTimeMs;
192
+ metrics.lastCalled = now;
193
+ if (success) {
194
+ metrics.successCount++;
195
+ }
196
+ else {
197
+ metrics.errorCount++;
198
+ if (errorType) {
199
+ metrics.errorTypes[errorType] = (metrics.errorTypes[errorType] || 0) + 1;
200
+ }
201
+ }
202
+ // Store detailed tool call event in BufferRing
203
+ this.toolCallEvents.add({
204
+ timestamp: now,
205
+ toolName,
206
+ success,
207
+ responseTimeMs,
208
+ errorType,
209
+ clientId
210
+ });
211
+ if (this.useFileStorage) {
212
+ if (this.appendMode) {
213
+ this.pendingAppendEvents.push({ timestamp: now, toolName, success, responseTimeMs, errorType, clientId });
214
+ this.flushToolCallEvents(false); // schedule conditional flush
215
+ }
216
+ else {
217
+ // legacy snapshot batching (retain previous throttling fields)
218
+ this._pendingToolPersist++;
219
+ const dueTime = now - this._lastToolPersist > this.appendFlushMs;
220
+ if (this._pendingToolPersist >= this.appendChunkSize || dueTime) {
221
+ setTimeout(() => {
222
+ this.toolCallEvents.saveToDisk().catch(() => { });
223
+ this._lastToolPersist = Date.now();
224
+ this._pendingToolPersist = 0;
225
+ }, 0).unref?.();
226
+ }
227
+ }
228
+ }
229
+ // Track call timestamp for rolling RPM calculation (last 60s window)
230
+ this.recentCallTimestamps.push(now);
231
+ // Prune anything older than 5 minutes to constrain memory
232
+ const cutoff = now - 5 * 60 * 1000;
233
+ if (this.recentCallTimestamps.length > MetricsCollector.MAX_RECENT_CALLS || (this.recentCallTimestamps.length % 100) === 0) {
234
+ // Periodically prune (on every 100th push or when over cap)
235
+ let firstValidIdx = 0;
236
+ while (firstValidIdx < this.recentCallTimestamps.length && this.recentCallTimestamps[firstValidIdx] < cutoff)
237
+ firstValidIdx++;
238
+ if (firstValidIdx > 0)
239
+ this.recentCallTimestamps.splice(0, firstValidIdx);
240
+ // Hard cap safeguard
241
+ if (this.recentCallTimestamps.length > MetricsCollector.MAX_RECENT_CALLS) {
242
+ this.recentCallTimestamps.splice(0, this.recentCallTimestamps.length - MetricsCollector.MAX_RECENT_CALLS);
243
+ }
244
+ }
245
+ // Prevent unbounded tool metrics growth - cleanup old/unused tools after adding the new tool
246
+ if (this.tools.size > MetricsCollector.MAX_TOOL_METRICS) {
247
+ this.cleanupOldToolMetrics();
248
+ }
249
+ }
250
+ /** Flush tool call events (append or snapshot) */
251
+ flushToolCallEvents(force) {
252
+ if (!this.useFileStorage)
253
+ return;
254
+ const now = Date.now();
255
+ if (this.appendMode) {
256
+ const timeDue = (now - this.lastAppendFlush) >= this.appendFlushMs;
257
+ if (!force && this.pendingAppendEvents.length < this.appendChunkSize && !timeDue)
258
+ return;
259
+ if (!this.appendLogPath || this.pendingAppendEvents.length === 0)
260
+ return;
261
+ const toWrite = this.pendingAppendEvents.splice(0, this.pendingAppendEvents.length);
262
+ const lines = toWrite.map(e => JSON.stringify(e)).join('\n') + '\n';
263
+ fs_1.default.promises.appendFile(this.appendLogPath, lines).catch(() => { });
264
+ this.lastAppendFlush = now;
265
+ // Periodic compaction: write full snapshot & truncate log
266
+ if ((now - this.lastAppendCompact) >= this.appendCompactMs || force) {
267
+ this.toolCallEvents.saveToDisk().catch(() => { });
268
+ this.lastAppendCompact = now;
269
+ if (this.appendLogPath) {
270
+ fs_1.default.promises.writeFile(this.appendLogPath, '').catch(() => { }); // truncate
271
+ }
272
+ }
273
+ }
274
+ else {
275
+ // snapshot mode manual force
276
+ if (force) {
277
+ this.toolCallEvents.saveToDisk().catch(() => { });
278
+ this._lastToolPersist = now;
279
+ this._pendingToolPersist = 0;
280
+ }
281
+ }
282
+ }
283
+ /**
284
+ * Record client connection
285
+ */
286
+ recordConnection(clientId) {
287
+ this.connections.add(clientId);
288
+ this.sessionStartTimes.set(clientId, Date.now());
289
+ }
290
+ /**
291
+ * Record client disconnection
292
+ */
293
+ recordDisconnection(clientId) {
294
+ if (this.connections.has(clientId)) {
295
+ this.connections.delete(clientId);
296
+ this.disconnectedCount++;
297
+ const sessionStart = this.sessionStartTimes.get(clientId);
298
+ if (sessionStart) {
299
+ this.totalSessionTime += Date.now() - sessionStart;
300
+ this.sessionStartTimes.delete(clientId);
301
+ }
302
+ }
303
+ }
304
+ /**
305
+ * Get current metrics snapshot
306
+ */
307
+ getCurrentSnapshot() {
308
+ const now = Date.now();
309
+ const uptime = now - this.startTime;
310
+ // Calculate performance metrics
311
+ const totalCalls = Array.from(this.tools.values()).reduce((sum, tool) => sum + tool.callCount, 0);
312
+ const totalSuccesses = Array.from(this.tools.values()).reduce((sum, tool) => sum + tool.successCount, 0);
313
+ const totalErrors = Array.from(this.tools.values()).reduce((sum, tool) => sum + tool.errorCount, 0);
314
+ const totalResponseTime = Array.from(this.tools.values()).reduce((sum, tool) => sum + tool.totalResponseTime, 0);
315
+ // Stable rolling Requests Per Minute based on last 60s calls (not lifetime average)
316
+ const oneMinuteCutoff = now - 60 * 1000;
317
+ let recentCount = 0;
318
+ // Iterate from end backwards until we exit window (timestamps are append-only & ascending)
319
+ for (let i = this.recentCallTimestamps.length - 1; i >= 0; i--) {
320
+ const ts = this.recentCallTimestamps[i];
321
+ if (ts >= oneMinuteCutoff)
322
+ recentCount++;
323
+ else
324
+ break;
325
+ }
326
+ const requestsPerMinute = recentCount;
327
+ const successRate = totalCalls > 0 ? (totalSuccesses / totalCalls) * 100 : 100;
328
+ const avgResponseTime = totalCalls > 0 ? (totalResponseTime / totalCalls) : 0;
329
+ const errorRate = totalCalls > 0 ? (totalErrors / totalCalls) * 100 : 0;
330
+ // Calculate average session duration
331
+ const activeSessionTime = Array.from(this.sessionStartTimes.values())
332
+ .reduce((sum, startTime) => sum + (now - startTime), 0);
333
+ const totalSessions = this.disconnectedCount + this.connections.size;
334
+ const avgSessionDuration = totalSessions > 0
335
+ ? (this.totalSessionTime + activeSessionTime) / totalSessions
336
+ : 0;
337
+ // Get CPU usage (if available)
338
+ let cpuUsage;
339
+ try {
340
+ cpuUsage = process.cpuUsage(this.lastCpuUsage);
341
+ this.lastCpuUsage = process.cpuUsage();
342
+ }
343
+ catch {
344
+ // CPU usage not available on all platforms
345
+ }
346
+ const memUsage = process.memoryUsage();
347
+ let heapLimit;
348
+ try {
349
+ heapLimit = v8_1.default.getHeapStatistics().heap_size_limit;
350
+ }
351
+ catch { /* v8 not available */ }
352
+ return {
353
+ timestamp: now,
354
+ server: {
355
+ uptime,
356
+ version: this.getVersion(),
357
+ memoryUsage: { ...memUsage, ...(heapLimit ? { heapLimit } : {}) },
358
+ cpuUsage,
359
+ startTime: this.startTime,
360
+ },
361
+ tools: Object.fromEntries(this.tools.entries()),
362
+ connections: {
363
+ activeConnections: this.connections.size,
364
+ totalConnections: this.disconnectedCount + this.connections.size,
365
+ disconnectedConnections: this.disconnectedCount,
366
+ avgSessionDuration,
367
+ },
368
+ performance: {
369
+ requestsPerMinute,
370
+ successRate,
371
+ avgResponseTime,
372
+ errorRate,
373
+ },
374
+ };
375
+ }
376
+ /**
377
+ * Get historical snapshots (from memory for recent, or from files for historical)
378
+ */
379
+ getSnapshots(count) {
380
+ if (count) {
381
+ return this.snapshots.slice(-count);
382
+ }
383
+ return [...this.snapshots];
384
+ }
385
+ /**
386
+ * Get snapshots from file storage (for historical analysis)
387
+ */
388
+ async getHistoricalSnapshots(count = 720) {
389
+ if (!this.fileStorage) {
390
+ console.warn('File storage not enabled, returning memory snapshots only');
391
+ return this.getSnapshots(count);
392
+ }
393
+ try {
394
+ return await this.fileStorage.getRecentSnapshots(count);
395
+ }
396
+ catch (error) {
397
+ console.error('Failed to load historical snapshots:', error);
398
+ return [];
399
+ }
400
+ }
401
+ /**
402
+ * Get snapshots within a specific time range from files
403
+ */
404
+ async getSnapshotsInRange(startTime, endTime) {
405
+ if (!this.fileStorage) {
406
+ console.warn('File storage not enabled, filtering memory snapshots');
407
+ return this.snapshots.filter(s => s.timestamp >= startTime && s.timestamp <= endTime);
408
+ }
409
+ try {
410
+ return await this.fileStorage.getSnapshotsInRange(startTime, endTime);
411
+ }
412
+ catch (error) {
413
+ console.error('Failed to load snapshots in range:', error);
414
+ return [];
415
+ }
416
+ }
417
+ /**
418
+ * Get file storage statistics
419
+ */
420
+ async getStorageStats() {
421
+ if (!this.fileStorage) {
422
+ return {
423
+ fileCount: 0,
424
+ totalSizeKB: 0,
425
+ memorySnapshots: this.snapshots.length,
426
+ };
427
+ }
428
+ const fileStats = await this.fileStorage.getStorageStats();
429
+ return {
430
+ ...fileStats,
431
+ memorySnapshots: this.snapshots.length,
432
+ };
433
+ }
434
+ /**
435
+ * Get tool-specific metrics
436
+ */
437
+ getToolMetrics(toolName) {
438
+ if (toolName) {
439
+ return this.tools.get(toolName) || null;
440
+ }
441
+ return Object.fromEntries(this.tools.entries());
442
+ }
443
+ /**
444
+ * Clear all metrics data (memory and files)
445
+ */
446
+ async clearMetrics() {
447
+ // Clear in-memory data
448
+ this.tools.clear();
449
+ this.snapshots.length = 0;
450
+ this.connections.clear();
451
+ this.disconnectedCount = 0;
452
+ this.totalSessionTime = 0;
453
+ this.sessionStartTimes.clear();
454
+ this.startTime = Date.now();
455
+ this.recentCallTimestamps.length = 0;
456
+ // Clear file storage if enabled
457
+ if (this.fileStorage) {
458
+ try {
459
+ await this.fileStorage.clearAll();
460
+ }
461
+ catch (error) {
462
+ console.error('Failed to clear file storage:', error);
463
+ }
464
+ }
465
+ }
466
+ /**
467
+ * Clear only memory data (keep files)
468
+ */
469
+ clearMemoryMetrics() {
470
+ this.tools.clear();
471
+ this.snapshots.length = 0;
472
+ this.connections.clear();
473
+ this.disconnectedCount = 0;
474
+ this.totalSessionTime = 0;
475
+ this.sessionStartTimes.clear();
476
+ this.startTime = Date.now();
477
+ this.recentCallTimestamps.length = 0;
478
+ }
479
+ /**
480
+ * Stop metrics collection
481
+ */
482
+ stop() {
483
+ if (this.collectTimer) {
484
+ clearInterval(this.collectTimer);
485
+ this.collectTimer = undefined;
486
+ }
487
+ }
488
+ startCollection() {
489
+ // Take initial snapshot
490
+ this.takeSnapshot();
491
+ // Schedule periodic snapshots
492
+ this.collectTimer = setInterval(() => {
493
+ this.takeSnapshot();
494
+ }, this.options.collectInterval);
495
+ }
496
+ takeSnapshot() {
497
+ const snapshot = this.getCurrentSnapshot();
498
+ // Store enhanced snapshot in BufferRing with performance data
499
+ const timeSeriesEntry = {
500
+ timestamp: snapshot.timestamp,
501
+ snapshot,
502
+ performanceData: {
503
+ responseTimeMs: snapshot.performance.avgResponseTime,
504
+ requestCount: Array.from(this.tools.values()).reduce((sum, tool) => sum + tool.callCount, 0),
505
+ errorCount: Array.from(this.tools.values()).reduce((sum, tool) => sum + tool.errorCount, 0),
506
+ connectionCount: snapshot.connections.activeConnections
507
+ }
508
+ };
509
+ this.historicalSnapshots.add(timeSeriesEntry);
510
+ // Store performance metrics for charting
511
+ this.performanceMetrics.add({
512
+ timestamp: snapshot.timestamp,
513
+ responseTime: snapshot.performance.avgResponseTime,
514
+ throughput: snapshot.performance.requestsPerMinute,
515
+ errorRate: snapshot.performance.errorRate
516
+ });
517
+ // Store to file immediately (async, non-blocking) if file storage enabled
518
+ if (this.fileStorage) {
519
+ this.fileStorage.storeSnapshot(snapshot).catch(error => {
520
+ console.error('Failed to store metrics snapshot to file:', error);
521
+ });
522
+ }
523
+ // Keep limited snapshots in memory for real-time queries
524
+ this.snapshots.push(snapshot);
525
+ // Trim in-memory snapshots to prevent memory accumulation
526
+ const maxMemorySnapshots = this.useFileStorage
527
+ ? MetricsCollector.MAX_MEMORY_SNAPSHOTS
528
+ : this.options.maxSnapshots;
529
+ if (this.snapshots.length > maxMemorySnapshots) {
530
+ this.snapshots.splice(0, this.snapshots.length - maxMemorySnapshots);
531
+ }
532
+ // If not using file storage, apply original retention logic
533
+ if (!this.useFileStorage) {
534
+ const cutoff = Date.now() - (this.options.retentionMinutes * 60 * 1000);
535
+ const firstValidIndex = this.snapshots.findIndex(s => s.timestamp >= cutoff);
536
+ if (firstValidIndex > 0) {
537
+ this.snapshots.splice(0, firstValidIndex);
538
+ }
539
+ }
540
+ // Periodically cleanup tool metrics (every 10 snapshots, ~10 minutes)
541
+ if (this.snapshots.length % 10 === 0) {
542
+ this.cleanupOldToolMetrics();
543
+ }
544
+ }
545
+ getVersion() {
546
+ try {
547
+ const candidates = [
548
+ path_1.default.join(process.cwd(), 'package.json'),
549
+ path_1.default.join(__dirname, '..', '..', '..', 'package.json')
550
+ ];
551
+ for (const candidate of candidates) {
552
+ if (fs_1.default.existsSync(candidate)) {
553
+ const pkg = JSON.parse(fs_1.default.readFileSync(candidate, 'utf8'));
554
+ if (pkg?.version)
555
+ return pkg.version;
556
+ }
557
+ }
558
+ }
559
+ catch {
560
+ // Ignore errors
561
+ }
562
+ return '0.0.0';
563
+ }
564
+ // ====== Phase 3: Real-time Chart Data Methods ======
565
+ getRealtimeMetrics() {
566
+ return (0, metricsSerializer_js_1.buildRealtimeMetrics)(this.getCurrentSnapshot(), this.tools);
567
+ }
568
+ getToolUsageChartData(minutes = 60) {
569
+ return (0, metricsSerializer_js_1.buildToolUsageChartData)(this.snapshots, minutes);
570
+ }
571
+ getPerformanceChartData(minutes = 60) {
572
+ return (0, metricsSerializer_js_1.buildPerformanceChartData)(this.snapshots, minutes);
573
+ }
574
+ getTimeRangeMetrics(range) {
575
+ const rangeMinutes = { '1h': 60, '6h': 360, '24h': 1440, '7d': 10080, '30d': 43200 };
576
+ const cutoff = Date.now() - rangeMinutes[range] * 60_000;
577
+ return this.snapshots.filter(s => s.timestamp >= cutoff);
578
+ }
579
+ // ====== Phase 4: Advanced Real-time & Analytics Methods ======
580
+ getRealtimeStreamingData() {
581
+ const recentSnaps10 = this.snapshots.slice(-10);
582
+ const latency = recentSnaps10.length > 0
583
+ ? recentSnaps10.reduce((s, snap) => s + snap.performance.avgResponseTime, 0) / recentSnaps10.length
584
+ : 0;
585
+ return {
586
+ timestamp: Date.now(),
587
+ systemHealth: this.getSystemHealth(),
588
+ performanceMetrics: this.getDetailedPerformanceMetrics(),
589
+ recentActivity: (0, metricsSerializer_js_1.buildRecentActivity)(this.tools),
590
+ streamingStats: {
591
+ totalStreamingConnections: this.activeConnections,
592
+ dataTransferRate: this.connections.size * 0.1 + Math.random() * 0.5,
593
+ latency,
594
+ compressionRatio: 0.7,
595
+ },
596
+ };
597
+ }
598
+ getSystemHealth() {
599
+ const cpu = (0, metricsAggregation_js_1.estimateCPUUsage)(this.snapshots.slice(-5));
600
+ const memory = (0, metricsAggregation_js_1.estimateMemoryUsage)(this.connections.size, this.snapshots.length);
601
+ return {
602
+ cpuUsage: cpu,
603
+ memoryUsage: memory,
604
+ diskUsage: (0, metricsAggregation_js_1.estimateDiskUsage)(this.snapshots.length),
605
+ networkLatency: (0, metricsAggregation_js_1.getAverageResponseTime)(this.tools),
606
+ uptime: Date.now() - this.startTime,
607
+ lastHealthCheck: new Date(),
608
+ status: (0, metricsAggregation_js_1.getOverallHealthStatus)(cpu, memory, (0, metricsAggregation_js_1.getErrorRate)(this.tools)),
609
+ };
610
+ }
611
+ getDetailedPerformanceMetrics() {
612
+ const totalRequests = (0, metricsAggregation_js_1.getTotalRequests)(this.tools);
613
+ const avg = (0, metricsAggregation_js_1.getAverageResponseTime)(this.tools);
614
+ const rps = (0, metricsAggregation_js_1.calculateRequestsPerSecond)(this.snapshots);
615
+ return {
616
+ requestThroughput: rps * 60,
617
+ averageResponseTime: avg,
618
+ p95ResponseTime: (0, metricsAggregation_js_1.calculatePercentileFromAvg)(avg, 95),
619
+ p99ResponseTime: (0, metricsAggregation_js_1.calculatePercentileFromAvg)(avg, 99),
620
+ errorRate: (0, metricsAggregation_js_1.getErrorRate)(this.tools),
621
+ concurrentConnections: this.activeConnections,
622
+ totalRequests,
623
+ successfulRequests: totalRequests - (0, metricsAggregation_js_1.getTotalErrors)(this.tools),
624
+ requestsPerSecond: rps,
625
+ bytesTransferred: totalRequests * 1024 * 2,
626
+ };
627
+ }
628
+ getAdvancedAnalytics(timeRange = '1h') {
629
+ return (0, metricsSerializer_js_1.buildAdvancedAnalytics)(timeRange, this.snapshots, this.tools, (0, metricsAggregation_js_1.getErrorRate)(this.tools), (0, metricsAggregation_js_1.detectAnomalies)(this.snapshots.slice(-20)));
630
+ }
631
+ /**
632
+ * Generate real-time alert
633
+ */
634
+ generateRealTimeAlert(type, severity, message, value, threshold) {
635
+ const alert = {
636
+ id: `alert_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
637
+ type: type,
638
+ severity: severity,
639
+ message,
640
+ timestamp: new Date(),
641
+ resolved: false,
642
+ value,
643
+ threshold,
644
+ source: 'MetricsCollector',
645
+ category: (0, metricsAggregation_js_1.categorizeAlert)(type)
646
+ };
647
+ this.recentAlerts.unshift(alert);
648
+ if (this.recentAlerts.length > 100) {
649
+ this.recentAlerts = this.recentAlerts.slice(0, 100);
650
+ }
651
+ return alert;
652
+ }
653
+ /**
654
+ * Get active alerts
655
+ */
656
+ getActiveAlerts() {
657
+ return this.recentAlerts.filter(alert => !alert.resolved);
658
+ }
659
+ /**
660
+ * Resolve alert by ID
661
+ */
662
+ resolveAlert(alertId) {
663
+ const alert = this.recentAlerts.find(a => a.id === alertId);
664
+ if (alert) {
665
+ alert.resolved = true;
666
+ alert.resolvedAt = new Date();
667
+ return true;
668
+ }
669
+ return false;
670
+ }
671
+ // ===== Resource Sampling / Leak Detection =====
672
+ sampleResources() {
673
+ try {
674
+ const now = Date.now();
675
+ const mem = process.memoryUsage();
676
+ let cpuPercent = 0;
677
+ const curr = process.cpuUsage();
678
+ if (this.lastCpuUsageSample && this.lastCpuSampleTime) {
679
+ const userDiff = curr.user - this.lastCpuUsageSample.user; // microseconds
680
+ const systemDiff = curr.system - this.lastCpuUsageSample.system;
681
+ const elapsedMs = now - this.lastCpuSampleTime;
682
+ if (elapsedMs > 0) {
683
+ // total diff in microseconds / (elapsedMs * 1000) gives fraction of single core; *100 -> percent
684
+ cpuPercent = ((userDiff + systemDiff) / 1000) / elapsedMs * 100;
685
+ // Clamp 0-100 (single process perspective)
686
+ if (cpuPercent < 0)
687
+ cpuPercent = 0;
688
+ else if (cpuPercent > 100)
689
+ cpuPercent = 100;
690
+ }
691
+ }
692
+ this.lastCpuUsageSample = curr;
693
+ this.lastCpuSampleTime = now;
694
+ this.resourceSamples.add({ timestamp: now, cpuPercent, heapUsed: mem.heapUsed, rss: mem.rss });
695
+ }
696
+ catch { /* ignore sampling errors */ }
697
+ }
698
+ getResourceHistory(limit = 200) {
699
+ const all = this.resourceSamples.getAll();
700
+ const samples = limit > 0 ? all.slice(-limit) : all;
701
+ const trend = (0, metricsAggregation_js_1.calculateLinearSlopes)(samples);
702
+ return { samples, trend };
703
+ }
704
+ /** Remove stale / low-activity tool entries to prevent unbounded map growth. */
705
+ cleanupOldToolMetrics() {
706
+ const staleThreshold = Date.now() - 3_600_000; // 1 hour
707
+ const toRemove = (0, metricsAggregation_js_1.computeToolsToCleanup)(this.tools, MetricsCollector.MAX_TOOL_METRICS, staleThreshold);
708
+ let removedCount = 0;
709
+ for (const name of toRemove) {
710
+ if (this.tools.delete(name))
711
+ removedCount++;
712
+ }
713
+ if (removedCount > 0) {
714
+ console.log(`🧹 MetricsCollector: Cleaned up ${removedCount} stale tool metrics (${this.tools.size} remaining)`);
715
+ }
716
+ }
717
+ // ====== BufferRing-Enhanced Methods ======
718
+ /**
719
+ * Get historical metrics data for charting
720
+ */
721
+ getHistoricalMetrics(minutes = 60) {
722
+ const cutoff = Date.now() - (minutes * 60 * 1000);
723
+ return this.historicalSnapshots.filter(entry => entry.timestamp >= cutoff);
724
+ }
725
+ /**
726
+ * Get recent tool call events for analysis
727
+ */
728
+ getRecentToolCallEvents(minutes = 30) {
729
+ const cutoff = Date.now() - (minutes * 60 * 1000);
730
+ return this.toolCallEvents.filter(event => event.timestamp >= cutoff);
731
+ }
732
+ /**
733
+ * Get performance metrics time series for dashboard charts (BufferRing-enhanced)
734
+ */
735
+ getPerformanceTimeSeriesData(minutes = 60) {
736
+ return (0, metricsSerializer_js_1.buildPerformanceTimeSeriesData)(this.performanceMetrics.getAll(), minutes);
737
+ }
738
+ /**
739
+ * Get tool usage analytics from historical data
740
+ */
741
+ getToolUsageAnalytics(minutes = 60) {
742
+ return (0, metricsSerializer_js_1.buildToolUsageAnalytics)(this.toolCallEvents.getAll(), minutes);
743
+ }
744
+ /**
745
+ * Get BufferRing statistics for monitoring
746
+ */
747
+ getBufferRingStats() {
748
+ return {
749
+ historicalSnapshots: this.historicalSnapshots.getStats(),
750
+ toolCallEvents: this.toolCallEvents.getStats(),
751
+ performanceMetrics: this.performanceMetrics.getStats()
752
+ };
753
+ }
754
+ /**
755
+ * Export metrics data for backup/analysis
756
+ */
757
+ exportMetricsData(options = {}) {
758
+ const data = {
759
+ timestamp: Date.now(),
760
+ currentSnapshot: this.getCurrentSnapshot(),
761
+ bufferStats: this.getBufferRingStats()
762
+ };
763
+ const result = data;
764
+ if (options.includeHistorical !== false) {
765
+ result.historicalSnapshots = this.historicalSnapshots.getAll();
766
+ }
767
+ if (options.includeEvents !== false) {
768
+ result.toolCallEvents = this.toolCallEvents.getAll();
769
+ }
770
+ if (options.includePerformance !== false) {
771
+ result.performanceMetrics = this.performanceMetrics.getAll();
772
+ }
773
+ return result;
774
+ }
775
+ /**
776
+ * Clear all BufferRing data (for maintenance)
777
+ */
778
+ clearBufferedData() {
779
+ this.historicalSnapshots.clear();
780
+ this.toolCallEvents.clear();
781
+ this.performanceMetrics.clear();
782
+ console.error('📊 MetricsCollector: Cleared all BufferRing data');
783
+ }
784
+ }
785
+ exports.MetricsCollector = MetricsCollector;
786
+ // Global singleton instance
787
+ let globalCollector = null;
788
+ /**
789
+ * Get or create the global metrics collector instance
790
+ */
791
+ function getMetricsCollector() {
792
+ if (!globalCollector) {
793
+ globalCollector = new MetricsCollector();
794
+ }
795
+ return globalCollector;
796
+ }
797
+ /**
798
+ * Set a custom metrics collector instance (useful for testing)
799
+ */
800
+ function setMetricsCollector(collector) {
801
+ globalCollector = collector;
802
+ }
803
+ // (No changes needed in this file for the current UI fixes)