@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,161 @@
1
+ /**
2
+ * Usage Buckets Service - Phase 2 Temporal Windowing Implementation
3
+ *
4
+ * Provides time-windowed usage tracking with bucket rotation and persistence.
5
+ * Maintains usage-buckets.json sidecar file for temporal analytics.
6
+ */
7
+ /**
8
+ * Time bucket configuration
9
+ */
10
+ export interface BucketConfig {
11
+ /** Bucket size in minutes (default: 60 = 1 hour) */
12
+ bucketSizeMinutes: number;
13
+ /** Number of buckets to maintain (default: 24 = 24 hours) */
14
+ bucketCount: number;
15
+ /** Maximum entries per bucket (default: 1000) */
16
+ maxEntriesPerBucket: number;
17
+ }
18
+ /**
19
+ * Usage entry within a time bucket
20
+ */
21
+ export interface UsageEntry {
22
+ timestamp: string;
23
+ operation: string;
24
+ instructionId?: string;
25
+ clientInfo?: string;
26
+ durationMs?: number;
27
+ success: boolean;
28
+ errorCode?: string;
29
+ }
30
+ /**
31
+ * Time bucket containing usage entries
32
+ */
33
+ export interface UsageBucket {
34
+ /** Bucket start time (ISO 8601 UTC) */
35
+ startTime: string;
36
+ /** Bucket end time (ISO 8601 UTC) */
37
+ endTime: string;
38
+ /** Usage entries in this bucket */
39
+ entries: UsageEntry[];
40
+ /** Entry count for quick access */
41
+ entryCount: number;
42
+ /** Bucket creation timestamp */
43
+ createdAt: string;
44
+ /** Last update timestamp */
45
+ lastUpdated: string;
46
+ }
47
+ /**
48
+ * Usage buckets container with metadata
49
+ */
50
+ export interface UsageBucketsContainer {
51
+ /** Configuration used */
52
+ config: BucketConfig;
53
+ /** Current bucket index (0 to bucketCount-1) */
54
+ currentBucketIndex: number;
55
+ /** Ring of time buckets */
56
+ buckets: UsageBucket[];
57
+ /** Container creation timestamp */
58
+ createdAt: string;
59
+ /** Last rotation timestamp */
60
+ lastRotation: string;
61
+ /** Total entries across all buckets */
62
+ totalEntries: number;
63
+ /** Metrics summary */
64
+ metrics: {
65
+ rotationCount: number;
66
+ totalOperations: number;
67
+ successRate: number;
68
+ avgDurationMs: number;
69
+ };
70
+ /** Integrity hash (sha256) over critical fields */
71
+ containerHash?: string;
72
+ }
73
+ /**
74
+ * Usage Buckets Service
75
+ */
76
+ export declare class UsageBucketsService {
77
+ private container;
78
+ private bucketsFilePath;
79
+ private config;
80
+ private timeProvider;
81
+ constructor(instructionsDir: string, config?: Partial<BucketConfig>, opts?: {
82
+ timeProvider?: () => Date;
83
+ });
84
+ /**
85
+ * Initialize or load existing buckets container
86
+ */
87
+ initialize(): Promise<void>;
88
+ /**
89
+ * Record a usage entry
90
+ */
91
+ recordUsage(entry: Omit<UsageEntry, 'timestamp'>): Promise<void>;
92
+ /**
93
+ * Get current usage statistics
94
+ */
95
+ getStats(): {
96
+ currentBucket: UsageBucket;
97
+ totalEntries: number;
98
+ metrics: UsageBucketsContainer['metrics'];
99
+ bucketCount: number;
100
+ };
101
+ /**
102
+ * Get usage entries for a time range
103
+ */
104
+ getEntriesInRange(startTime: string, endTime: string): UsageEntry[];
105
+ /**
106
+ * Force a bucket rotation (for testing)
107
+ */
108
+ forceRotation(): Promise<void>;
109
+ /**
110
+ * Get the current bucket
111
+ */
112
+ private getCurrentBucket;
113
+ /**
114
+ * Check if bucket rotation is needed and perform it
115
+ */
116
+ private maybeRotate;
117
+ /**
118
+ * Rotate buckets and create new current bucket
119
+ */
120
+ private rotateBuckets;
121
+ /**
122
+ * Create a new container
123
+ */
124
+ private createContainer;
125
+ /**
126
+ * Load container from disk
127
+ */
128
+ private loadContainer;
129
+ /**
130
+ * Save container to disk
131
+ */
132
+ private saveContainer;
133
+ /**
134
+ * Get bucket start time aligned to bucket boundaries
135
+ */
136
+ private getBucketStartTime;
137
+ /**
138
+ * Update container metrics
139
+ */
140
+ private updateMetrics;
141
+ /**
142
+ * Compute integrity hash for container (excluding containerHash field itself)
143
+ */
144
+ private computeHash;
145
+ /**
146
+ * Verify integrity hash of a loaded container
147
+ */
148
+ private verifyHash;
149
+ /**
150
+ * Exposed only for testing: return internal container snapshot
151
+ */
152
+ _debugGetContainer(): UsageBucketsContainer | null;
153
+ }
154
+ /**
155
+ * Get or create the global usage buckets service instance
156
+ */
157
+ export declare function getUsageBucketsService(instructionsDir?: string, config?: Partial<BucketConfig>): UsageBucketsService;
158
+ /**
159
+ * Record usage for the global instance
160
+ */
161
+ export declare function recordUsage(entry: Omit<UsageEntry, 'timestamp'>): Promise<void>;
@@ -0,0 +1,364 @@
1
+ "use strict";
2
+ /**
3
+ * Usage Buckets Service - Phase 2 Temporal Windowing Implementation
4
+ *
5
+ * Provides time-windowed usage tracking with bucket rotation and persistence.
6
+ * Maintains usage-buckets.json sidecar file for temporal analytics.
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.UsageBucketsService = void 0;
13
+ exports.getUsageBucketsService = getUsageBucketsService;
14
+ exports.recordUsage = recordUsage;
15
+ const fs_1 = __importDefault(require("fs"));
16
+ const path_1 = __importDefault(require("path"));
17
+ const crypto_1 = __importDefault(require("crypto"));
18
+ const logger_1 = require("./logger");
19
+ /**
20
+ * Default bucket configuration
21
+ */
22
+ const DEFAULT_CONFIG = {
23
+ bucketSizeMinutes: 60, // 1 hour buckets
24
+ bucketCount: 24, // 24 hours of history
25
+ maxEntriesPerBucket: 1000
26
+ };
27
+ /**
28
+ * Usage Buckets Service
29
+ */
30
+ class UsageBucketsService {
31
+ container = null;
32
+ bucketsFilePath;
33
+ config;
34
+ timeProvider;
35
+ constructor(instructionsDir, config = {}, opts = {}) {
36
+ this.bucketsFilePath = path_1.default.join(instructionsDir, 'usage-buckets.json');
37
+ this.config = { ...DEFAULT_CONFIG, ...config };
38
+ this.timeProvider = opts.timeProvider ?? (() => new Date());
39
+ }
40
+ /**
41
+ * Initialize or load existing buckets container
42
+ */
43
+ async initialize() {
44
+ try {
45
+ if (fs_1.default.existsSync(this.bucketsFilePath)) {
46
+ await this.loadContainer();
47
+ (0, logger_1.logInfo)(`[usageBuckets] Loaded existing container from ${this.bucketsFilePath}`);
48
+ }
49
+ else {
50
+ await this.createContainer();
51
+ (0, logger_1.logInfo)(`[usageBuckets] Created new container at ${this.bucketsFilePath}`);
52
+ }
53
+ // Check if rotation is needed
54
+ await this.maybeRotate();
55
+ }
56
+ catch (error) {
57
+ (0, logger_1.logError)(`[usageBuckets] Failed to initialize`, error);
58
+ // Fallback: create new container
59
+ await this.createContainer();
60
+ }
61
+ }
62
+ /**
63
+ * Record a usage entry
64
+ */
65
+ async recordUsage(entry) {
66
+ if (!this.container) {
67
+ await this.initialize();
68
+ }
69
+ const usageEntry = {
70
+ ...entry,
71
+ timestamp: this.timeProvider().toISOString()
72
+ };
73
+ // Add to current bucket
74
+ const currentBucket = this.getCurrentBucket();
75
+ currentBucket.entries.push(usageEntry);
76
+ currentBucket.entryCount++;
77
+ currentBucket.lastUpdated = usageEntry.timestamp;
78
+ // Update container metrics
79
+ this.updateMetrics(usageEntry);
80
+ // Check for rotation and persistence
81
+ await this.maybeRotate();
82
+ // Persist immediately for reliability
83
+ await this.saveContainer();
84
+ }
85
+ /**
86
+ * Get current usage statistics
87
+ */
88
+ getStats() {
89
+ if (!this.container) {
90
+ throw new Error('UsageBuckets not initialized');
91
+ }
92
+ return {
93
+ currentBucket: this.getCurrentBucket(),
94
+ totalEntries: this.container.totalEntries,
95
+ metrics: this.container.metrics,
96
+ bucketCount: this.container.buckets.length
97
+ };
98
+ }
99
+ /**
100
+ * Get usage entries for a time range
101
+ */
102
+ getEntriesInRange(startTime, endTime) {
103
+ if (!this.container) {
104
+ return [];
105
+ }
106
+ const start = new Date(startTime);
107
+ const end = new Date(endTime);
108
+ const entries = [];
109
+ for (const bucket of this.container.buckets) {
110
+ const bucketStart = new Date(bucket.startTime);
111
+ const bucketEnd = new Date(bucket.endTime);
112
+ // Check if bucket overlaps with requested range
113
+ if (bucketEnd >= start && bucketStart <= end) {
114
+ // Filter entries within the exact time range
115
+ const filteredEntries = bucket.entries.filter(entry => {
116
+ const entryTime = new Date(entry.timestamp);
117
+ return entryTime >= start && entryTime <= end;
118
+ });
119
+ entries.push(...filteredEntries);
120
+ }
121
+ }
122
+ return entries.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
123
+ }
124
+ /**
125
+ * Force a bucket rotation (for testing)
126
+ */
127
+ async forceRotation() {
128
+ if (!this.container) {
129
+ await this.initialize();
130
+ }
131
+ await this.rotateBuckets();
132
+ await this.saveContainer();
133
+ (0, logger_1.logInfo)('[usageBuckets] Forced bucket rotation');
134
+ }
135
+ /**
136
+ * Get the current bucket
137
+ */
138
+ getCurrentBucket() {
139
+ if (!this.container) {
140
+ throw new Error('Container not initialized');
141
+ }
142
+ return this.container.buckets[this.container.currentBucketIndex];
143
+ }
144
+ /**
145
+ * Check if bucket rotation is needed and perform it
146
+ */
147
+ async maybeRotate() {
148
+ if (!this.container)
149
+ return;
150
+ const currentBucket = this.getCurrentBucket();
151
+ const now = this.timeProvider();
152
+ const bucketEnd = new Date(currentBucket.endTime);
153
+ if (now >= bucketEnd) {
154
+ await this.rotateBuckets();
155
+ (0, logger_1.logInfo)(`[usageBuckets] Rotated buckets at ${now.toISOString()}`);
156
+ }
157
+ }
158
+ /**
159
+ * Rotate buckets and create new current bucket
160
+ */
161
+ async rotateBuckets() {
162
+ if (!this.container)
163
+ return;
164
+ const now = this.timeProvider();
165
+ const bucketStartTime = this.getBucketStartTime(now);
166
+ const bucketEndTime = new Date(bucketStartTime.getTime() + this.config.bucketSizeMinutes * 60 * 1000);
167
+ // Move to next bucket index (circular)
168
+ this.container.currentBucketIndex = (this.container.currentBucketIndex + 1) % this.config.bucketCount;
169
+ // Replace the bucket at current index
170
+ const newBucket = {
171
+ startTime: bucketStartTime.toISOString(),
172
+ endTime: bucketEndTime.toISOString(),
173
+ entries: [],
174
+ entryCount: 0,
175
+ createdAt: now.toISOString(),
176
+ lastUpdated: now.toISOString()
177
+ };
178
+ // Update total entries count (subtract old bucket entries)
179
+ const oldBucket = this.container.buckets[this.container.currentBucketIndex];
180
+ this.container.totalEntries -= oldBucket.entryCount;
181
+ // Replace bucket
182
+ this.container.buckets[this.container.currentBucketIndex] = newBucket;
183
+ // Update container metadata
184
+ this.container.lastRotation = now.toISOString();
185
+ this.container.metrics.rotationCount++;
186
+ }
187
+ /**
188
+ * Create a new container
189
+ */
190
+ async createContainer() {
191
+ const now = this.timeProvider();
192
+ const buckets = [];
193
+ // Create initial buckets
194
+ for (let i = 0; i < this.config.bucketCount; i++) {
195
+ const bucketStart = new Date(now.getTime() - (this.config.bucketCount - 1 - i) * this.config.bucketSizeMinutes * 60 * 1000);
196
+ const bucketStartTime = this.getBucketStartTime(bucketStart);
197
+ const bucketEndTime = new Date(bucketStartTime.getTime() + this.config.bucketSizeMinutes * 60 * 1000);
198
+ buckets.push({
199
+ startTime: bucketStartTime.toISOString(),
200
+ endTime: bucketEndTime.toISOString(),
201
+ entries: [],
202
+ entryCount: 0,
203
+ createdAt: now.toISOString(),
204
+ lastUpdated: now.toISOString()
205
+ });
206
+ }
207
+ this.container = {
208
+ config: { ...this.config },
209
+ currentBucketIndex: this.config.bucketCount - 1, // Latest bucket
210
+ buckets,
211
+ createdAt: now.toISOString(),
212
+ lastRotation: now.toISOString(),
213
+ totalEntries: 0,
214
+ metrics: {
215
+ rotationCount: 0,
216
+ totalOperations: 0,
217
+ successRate: 1.0,
218
+ avgDurationMs: 0
219
+ }
220
+ };
221
+ await this.saveContainer();
222
+ }
223
+ /**
224
+ * Load container from disk
225
+ */
226
+ async loadContainer() {
227
+ const attemptLoad = (file) => {
228
+ try {
229
+ const raw = fs_1.default.readFileSync(file, 'utf8');
230
+ const parsed = JSON.parse(raw);
231
+ if (!parsed || !parsed.buckets || !Array.isArray(parsed.buckets)) {
232
+ throw new Error('Invalid format');
233
+ }
234
+ return parsed;
235
+ }
236
+ catch (e) {
237
+ (0, logger_1.logError)(`[usageBuckets] Failed to load ${file}`, e);
238
+ return null;
239
+ }
240
+ };
241
+ const primary = attemptLoad(this.bucketsFilePath);
242
+ const backupPath = this.bucketsFilePath + '.bak';
243
+ let container = primary;
244
+ if (!container || !this.verifyHash(container)) {
245
+ (0, logger_1.logError)('[usageBuckets] Primary container missing or hash mismatch, attempting backup');
246
+ const backup = fs_1.default.existsSync(backupPath) ? attemptLoad(backupPath) : null;
247
+ if (backup && this.verifyHash(backup)) {
248
+ container = backup;
249
+ }
250
+ else {
251
+ (0, logger_1.logError)('[usageBuckets] Backup container invalid or hash mismatch; rebuilding new container');
252
+ await this.createContainer();
253
+ return;
254
+ }
255
+ }
256
+ // Update config if changed
257
+ container.config = { ...container.config, ...this.config };
258
+ this.container = container;
259
+ }
260
+ /**
261
+ * Save container to disk
262
+ */
263
+ async saveContainer() {
264
+ if (!this.container)
265
+ return;
266
+ // Ensure directory exists
267
+ const dir = path_1.default.dirname(this.bucketsFilePath);
268
+ if (!fs_1.default.existsSync(dir)) {
269
+ fs_1.default.mkdirSync(dir, { recursive: true });
270
+ }
271
+ // Write atomically
272
+ // Update hash prior to save
273
+ this.container.containerHash = this.computeHash(this.container);
274
+ const serialized = JSON.stringify(this.container, null, 2);
275
+ const tempFile = this.bucketsFilePath + '.tmp';
276
+ fs_1.default.writeFileSync(tempFile, serialized);
277
+ fs_1.default.renameSync(tempFile, this.bucketsFilePath);
278
+ // Maintain backup copy for recovery
279
+ try {
280
+ fs_1.default.writeFileSync(this.bucketsFilePath + '.bak', serialized);
281
+ }
282
+ catch (e) {
283
+ (0, logger_1.logError)(`[usageBuckets] Failed to write backup`, e);
284
+ }
285
+ }
286
+ /**
287
+ * Get bucket start time aligned to bucket boundaries
288
+ */
289
+ getBucketStartTime(date) {
290
+ const minutes = date.getMinutes();
291
+ const alignedMinutes = Math.floor(minutes / this.config.bucketSizeMinutes) * this.config.bucketSizeMinutes;
292
+ const aligned = new Date(date);
293
+ aligned.setMinutes(alignedMinutes, 0, 0); // Clear seconds and milliseconds
294
+ return aligned;
295
+ }
296
+ /**
297
+ * Update container metrics
298
+ */
299
+ updateMetrics(entry) {
300
+ if (!this.container)
301
+ return;
302
+ this.container.totalEntries++;
303
+ this.container.metrics.totalOperations++;
304
+ // Update success rate
305
+ const totalOps = this.container.metrics.totalOperations;
306
+ const currentSuccessCount = Math.round(this.container.metrics.successRate * (totalOps - 1));
307
+ const newSuccessCount = currentSuccessCount + (entry.success ? 1 : 0);
308
+ this.container.metrics.successRate = newSuccessCount / totalOps;
309
+ // Update average duration
310
+ if (entry.durationMs !== undefined) {
311
+ const currentAvg = this.container.metrics.avgDurationMs;
312
+ const currentCount = totalOps - 1;
313
+ this.container.metrics.avgDurationMs = (currentAvg * currentCount + entry.durationMs) / totalOps;
314
+ }
315
+ }
316
+ /**
317
+ * Compute integrity hash for container (excluding containerHash field itself)
318
+ */
319
+ computeHash(container) {
320
+ const { containerHash: _unusedHash, ...rest } = container; // exclude hash field
321
+ void _unusedHash; // satisfy linter for intentional discard
322
+ const hash = crypto_1.default.createHash('sha256');
323
+ hash.update(JSON.stringify(rest));
324
+ return hash.digest('hex');
325
+ }
326
+ /**
327
+ * Verify integrity hash of a loaded container
328
+ */
329
+ verifyHash(container) {
330
+ if (!container.containerHash)
331
+ return false;
332
+ const expected = this.computeHash(container);
333
+ return expected === container.containerHash;
334
+ }
335
+ /**
336
+ * Exposed only for testing: return internal container snapshot
337
+ */
338
+ /* @internal */
339
+ _debugGetContainer() {
340
+ return this.container ? JSON.parse(JSON.stringify(this.container)) : null;
341
+ }
342
+ }
343
+ exports.UsageBucketsService = UsageBucketsService;
344
+ // Singleton instance for server use
345
+ let usageBucketsInstance = null;
346
+ /**
347
+ * Get or create the global usage buckets service instance
348
+ */
349
+ function getUsageBucketsService(instructionsDir, config = {}) {
350
+ if (!usageBucketsInstance && instructionsDir) {
351
+ usageBucketsInstance = new UsageBucketsService(instructionsDir, config);
352
+ }
353
+ if (!usageBucketsInstance) {
354
+ throw new Error('Usage buckets service not initialized - call with instructionsDir first');
355
+ }
356
+ return usageBucketsInstance;
357
+ }
358
+ /**
359
+ * Record usage for the global instance
360
+ */
361
+ async function recordUsage(entry) {
362
+ const service = getUsageBucketsService();
363
+ await service.recordUsage(entry);
364
+ }
@@ -0,0 +1,38 @@
1
+ import { ErrorObject } from 'ajv';
2
+ interface ValidationCounters {
3
+ zodSuccess: number;
4
+ zodFailure: number;
5
+ ajvSuccess: number;
6
+ ajvFailure: number;
7
+ mode: string;
8
+ }
9
+ declare global {
10
+ var __MCP_VALIDATION_METRICS__: ValidationCounters | undefined;
11
+ }
12
+ /**
13
+ * Validate request parameters against the registered JSON Schema (or Zod schema) for `method`.
14
+ * Returns `{ ok: true }` when no schema is registered (fail-open) or when validation passes.
15
+ * @param method - JSON-RPC method name whose schema should be used for validation
16
+ * @param params - Parameter value received from the caller (may be `undefined`)
17
+ * @returns `{ ok: true }` on success, or `{ ok: false; errors: ErrorObject[] }` on failure
18
+ */
19
+ export declare function validateParams(method: string, params: unknown): {
20
+ ok: true;
21
+ } | {
22
+ ok: false;
23
+ errors: ErrorObject[];
24
+ };
25
+ /** Evict all cached validators, forcing re-compilation on the next call to {@link validateParams}. */
26
+ export declare function clearValidationCache(): void;
27
+ /**
28
+ * Return a snapshot of the validation counters for use in metrics reporting.
29
+ * @returns Copy of the current Zod vs. Ajv success/failure counters and active mode
30
+ */
31
+ export declare function getValidationMetrics(): {
32
+ zodSuccess: number;
33
+ zodFailure: number;
34
+ ajvSuccess: number;
35
+ ajvFailure: number;
36
+ mode: string;
37
+ };
38
+ export {};
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.validateParams = validateParams;
7
+ exports.clearValidationCache = clearValidationCache;
8
+ exports.getValidationMetrics = getValidationMetrics;
9
+ const ajv_1 = __importDefault(require("ajv"));
10
+ const ajv_formats_1 = __importDefault(require("ajv-formats"));
11
+ const json_schema_draft_07_json_1 = __importDefault(require("ajv/dist/refs/json-schema-draft-07.json"));
12
+ const runtimeConfig_1 = require("../config/runtimeConfig");
13
+ const toolRegistry_zod_1 = require("./toolRegistry.zod");
14
+ const zod_1 = require("zod");
15
+ const ajv = new ajv_1.default({ allErrors: true, strict: false });
16
+ (0, ajv_formats_1.default)(ajv);
17
+ try {
18
+ if (!ajv.getSchema('https://json-schema.org/draft-07/schema'))
19
+ ajv.addMetaSchema(json_schema_draft_07_json_1.default, 'https://json-schema.org/draft-07/schema');
20
+ }
21
+ catch (e) {
22
+ // ignore meta-schema registration errors (non-fatal)
23
+ }
24
+ const cache = new Map();
25
+ // Validation mode feature flag is centrally defined via runtime config.
26
+ // Modes: 'ajv' => force Ajv only, 'zod' (default) => prefer Zod with Ajv fallback, 'auto' reserved for future heuristics.
27
+ function resolveValidationMode() {
28
+ const mode = (0, runtimeConfig_1.getRuntimeConfig)().validation.mode;
29
+ return mode && mode.trim().length ? mode : 'zod';
30
+ }
31
+ const validationCounters = { zodSuccess: 0, zodFailure: 0, ajvSuccess: 0, ajvFailure: 0, mode: resolveValidationMode() };
32
+ function resolveValidationSettings() {
33
+ const mode = resolveValidationMode();
34
+ validationCounters.mode = mode;
35
+ return { mode, forceAjv: mode === 'ajv' };
36
+ }
37
+ globalThis.__MCP_VALIDATION_METRICS__ = validationCounters;
38
+ function buildValidator(method) {
39
+ try {
40
+ const reg = (0, toolRegistry_zod_1.getZodEnhancedRegistry)().find(t => t.name === method);
41
+ if (!reg)
42
+ return null;
43
+ const compiled = ajv.compile(reg.inputSchema);
44
+ const { forceAjv } = resolveValidationSettings();
45
+ if (reg.zodSchema && !forceAjv) {
46
+ const z = reg.zodSchema;
47
+ const v = {
48
+ validate: (d) => {
49
+ try {
50
+ z.parse(d ?? {});
51
+ return true;
52
+ }
53
+ catch (e) {
54
+ if (e instanceof zod_1.ZodError) {
55
+ // Map Zod issues into Ajv-like errors for uniform consumption
56
+ compiled.errors = e.issues.map(issue => ({
57
+ instancePath: issue.path.length ? '/' + issue.path.join('/') : '',
58
+ keyword: issue.code,
59
+ message: issue.message,
60
+ params: { issue },
61
+ schemaPath: '#'
62
+ }));
63
+ validationCounters.zodFailure++;
64
+ return false;
65
+ }
66
+ validationCounters.zodFailure++;
67
+ return false;
68
+ }
69
+ },
70
+ errors: null,
71
+ zod: z,
72
+ ajvFn: compiled
73
+ };
74
+ return v;
75
+ }
76
+ return { validate: (d) => compiled(d), errors: null };
77
+ }
78
+ catch {
79
+ return null;
80
+ }
81
+ }
82
+ /**
83
+ * Validate request parameters against the registered JSON Schema (or Zod schema) for `method`.
84
+ * Returns `{ ok: true }` when no schema is registered (fail-open) or when validation passes.
85
+ * @param method - JSON-RPC method name whose schema should be used for validation
86
+ * @param params - Parameter value received from the caller (may be `undefined`)
87
+ * @returns `{ ok: true }` on success, or `{ ok: false; errors: ErrorObject[] }` on failure
88
+ */
89
+ function validateParams(method, params) {
90
+ let entry = cache.get(method);
91
+ if (entry === undefined) {
92
+ entry = buildValidator(method);
93
+ cache.set(method, entry);
94
+ }
95
+ if (!entry)
96
+ return { ok: true }; // no schema => accept
97
+ const { forceAjv } = resolveValidationSettings();
98
+ const ok = entry.validate(params === undefined ? {} : params);
99
+ const hasZod = entry.zod !== undefined && !forceAjv;
100
+ if (ok) {
101
+ if (hasZod) {
102
+ validationCounters.zodSuccess++;
103
+ }
104
+ else {
105
+ validationCounters.ajvSuccess++;
106
+ }
107
+ return { ok: true };
108
+ }
109
+ if (hasZod) {
110
+ validationCounters.zodFailure++;
111
+ }
112
+ else {
113
+ validationCounters.ajvFailure++;
114
+ }
115
+ const v = entry.validate;
116
+ const errors = (v && typeof v === 'object' && 'errors' in v) ? v.errors || [] : [];
117
+ return { ok: false, errors };
118
+ }
119
+ /** Evict all cached validators, forcing re-compilation on the next call to {@link validateParams}. */
120
+ function clearValidationCache() { cache.clear(); }
121
+ /**
122
+ * Return a snapshot of the validation counters for use in metrics reporting.
123
+ * @returns Copy of the current Zod vs. Ajv success/failure counters and active mode
124
+ */
125
+ function getValidationMetrics() { return { ...validationCounters }; }