@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,429 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dynamicImport = void 0;
4
+ exports.setupStdoutDiagnostics = setupStdoutDiagnostics;
5
+ exports.setupDispatcherOverride = setupDispatcherOverride;
6
+ exports.wrapTransportSend = wrapTransportSend;
7
+ exports.setupKeepalive = setupKeepalive;
8
+ /* eslint-disable @typescript-eslint/no-explicit-any */
9
+ /**
10
+ * Transport initialization, request dispatcher override, and diagnostics
11
+ * wrappers for the MCP server.
12
+ */
13
+ const runtimeConfig_1 = require("../config/runtimeConfig");
14
+ const handshakeManager_1 = require("./handshakeManager");
15
+ // Helper to perform a true dynamic ESM import that TypeScript won't down-level to require()
16
+ const dynamicImport = (specifier) => (Function('m', 'return import(m);'))(specifier);
17
+ exports.dynamicImport = dynamicImport;
18
+ /**
19
+ * Set up stdout diagnostics wrapper for backpressure monitoring.
20
+ * Enabled via INDEX_SERVER_TRACE=healthMixed.
21
+ */
22
+ async function setupStdoutDiagnostics() {
23
+ const __diagEnabled = (0, runtimeConfig_1.getRuntimeConfig)().trace.has('healthMixed');
24
+ const __diag = (msg) => { if (__diagEnabled) {
25
+ try {
26
+ process.stderr.write(`[diag] ${Date.now()} ${msg}\n`);
27
+ }
28
+ catch { /* ignore */ }
29
+ } };
30
+ // Emit a one-time version marker so tests can assert the newer diagnostic wrapper code is actually loaded.
31
+ if (__diagEnabled) {
32
+ try {
33
+ const buildMarker = 'sdkServerDiagV1';
34
+ // Include a coarse content hash surrogate: file size + mtime if available
35
+ let fsMeta = '';
36
+ try {
37
+ const fsMod = await import('fs');
38
+ const stat = fsMod.statSync(__filename);
39
+ fsMeta = ` size=${stat.size} mtimeMs=${Math.trunc(stat.mtimeMs)}`;
40
+ }
41
+ catch { /* ignore meta */ }
42
+ process.stderr.write(`[diag] ${Date.now()} diag_start marker=${buildMarker}${fsMeta}\n`);
43
+ }
44
+ catch { /* ignore */ }
45
+ }
46
+ if (__diagEnabled) {
47
+ try {
48
+ const origWrite = process.stdout.write.bind(process.stdout);
49
+ let backpressureEvents = 0;
50
+ let bytesTotal = 0;
51
+ let lastReportAt = Date.now();
52
+ process.stdout.on?.('drain', () => { __diag('stdout_drain'); });
53
+ process.stdout.write = function (chunk, encoding, cb) {
54
+ try {
55
+ const size = Buffer.isBuffer(chunk) ? chunk.length : Buffer.byteLength(String(chunk));
56
+ bytesTotal += size;
57
+ const ret = origWrite(chunk, encoding, cb);
58
+ if (!ret) {
59
+ backpressureEvents++;
60
+ __diag(`stdout_backpressure size=${size} backpressureEvents=${backpressureEvents}`);
61
+ }
62
+ const now = Date.now();
63
+ if (now - lastReportAt > 2000) {
64
+ __diag(`stdout_summary bytesTotal=${bytesTotal} backpressureEvents=${backpressureEvents}`);
65
+ lastReportAt = now;
66
+ }
67
+ return ret;
68
+ }
69
+ catch (e) {
70
+ try {
71
+ __diag(`stdout_write_wrapper_error ${e?.message || String(e)}`);
72
+ }
73
+ catch { /* ignore */ }
74
+ return origWrite(chunk, encoding, cb);
75
+ }
76
+ };
77
+ }
78
+ catch { /* ignore */ }
79
+ }
80
+ }
81
+ // Robust semantic error preservation: deep scan for JSON-RPC code/message
82
+ function deepScan(obj, depth = 0, seen = new Set()) {
83
+ if (!obj || typeof obj !== 'object' || depth > 4 || seen.has(obj))
84
+ return undefined;
85
+ seen.add(obj);
86
+ if (Number.isSafeInteger(obj.code)) {
87
+ const c = obj.code;
88
+ if (c === -32601 || c === -32602)
89
+ return c; // prioritize semantic validation codes
90
+ }
91
+ // Prefer specific well-known nesting keys first
92
+ const keys = ['error', 'original', 'cause', 'data'];
93
+ for (const k of keys) {
94
+ try {
95
+ const child = obj[k];
96
+ const found = deepScan(child, depth + 1, seen);
97
+ if (found !== undefined)
98
+ return found;
99
+ }
100
+ catch { /* ignore */ }
101
+ }
102
+ // Fallback: generic property iteration (shallow) to catch unexpected wrappers
103
+ if (depth < 2) {
104
+ try {
105
+ for (const v of Object.values(obj)) {
106
+ const found = deepScan(v, depth + 1, seen);
107
+ if (found !== undefined)
108
+ return found;
109
+ }
110
+ }
111
+ catch { /* ignore */ }
112
+ }
113
+ return undefined;
114
+ }
115
+ // Categorize request for diagnostics
116
+ function categorizeRequest(request) {
117
+ const metaName = request.method === 'tools/call' ? request?.params?.name : '';
118
+ if (request.method === 'initialize')
119
+ return 'init';
120
+ if (request.method === 'health_check' || metaName === 'health_check')
121
+ return 'health';
122
+ if (request.method === 'metrics_snapshot' || metaName === 'metrics_snapshot')
123
+ return 'metrics';
124
+ if (metaName === 'meta_tools')
125
+ return 'meta';
126
+ return 'other';
127
+ }
128
+ /**
129
+ * Override the internal request dispatcher to retain error.data & emit diagnostics.
130
+ * The upstream SDK has used both `_onRequest` (camel) and `_onrequest` (lower) across versions;
131
+ * we defensively hook whichever exists and assign our wrapper to BOTH names.
132
+ */
133
+ function setupDispatcherOverride(server) {
134
+ const existingLower = server._onrequest;
135
+ const existingCamel = server._onRequest;
136
+ const originalOnRequest = (existingCamel || existingLower) ? (existingCamel || existingLower).bind(server) : undefined;
137
+ let __diagQueueDepth = 0;
138
+ if (originalOnRequest) {
139
+ const wrapped = function (request) {
140
+ const diagEnabled = (0, runtimeConfig_1.getRuntimeConfig)().trace.has('healthMixed');
141
+ let startedAt;
142
+ if (diagEnabled) {
143
+ const category = categorizeRequest(request);
144
+ if (category === 'health' || category === 'meta' || category === 'metrics' || category === 'init') {
145
+ startedAt = Date.now();
146
+ try {
147
+ __diagQueueDepth++;
148
+ process.stderr.write(`[diag] ${startedAt} rq_enqueue method=${request.method} cat=${category} id=${request.id} qdepth=${__diagQueueDepth}\n`);
149
+ if (category === 'health') {
150
+ if (!server.__firstHealthEnqueueAt) {
151
+ server.__firstHealthEnqueueAt = startedAt;
152
+ }
153
+ if (request.id === 1 && !server.__healthId1EnqueueAt) {
154
+ server.__healthId1EnqueueAt = startedAt;
155
+ }
156
+ }
157
+ if (!server.__activeDiagRequests) {
158
+ server.__activeDiagRequests = new Map();
159
+ }
160
+ server.__activeDiagRequests.set(request.id, { id: request.id, method: request.method, cat: category, start: startedAt });
161
+ // Mis-order detection: health/metrics/meta before initialize observed
162
+ if ((category === 'health' || category === 'metrics' || category === 'meta') && !server.__sawInitializeRequest) {
163
+ try {
164
+ process.stderr.write(`[diag] ${Date.now()} rq_misorder_before_init method=${request.method} id=${request.id} cat=${category} qdepth=${__diagQueueDepth}\n`);
165
+ }
166
+ catch { /* ignore */ }
167
+ }
168
+ }
169
+ catch { /* ignore */ }
170
+ }
171
+ }
172
+ const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
173
+ if (handler === undefined) {
174
+ return this._transport?.send({ jsonrpc: '2.0', id: request.id, error: { code: -32601, message: 'Method not found', data: { method: request.method } } }).catch(() => { });
175
+ }
176
+ const abortController = new AbortController();
177
+ this._requestHandlerAbortControllers.set(request.id, abortController);
178
+ // IMPORTANT: We intentionally never early-return without sending a response
179
+ Promise.resolve()
180
+ .then(() => handler(request, { signal: abortController.signal }))
181
+ .then((result) => {
182
+ if (startedAt !== undefined) {
183
+ try {
184
+ const dur = Date.now() - startedAt;
185
+ const category = categorizeRequest(request);
186
+ if (category === 'health' || category === 'meta' || category === 'metrics' || category === 'init') {
187
+ __diagQueueDepth = Math.max(0, __diagQueueDepth - 1);
188
+ process.stderr.write(`[diag] ${Date.now()} rq_complete method=${request.method} cat=${category} id=${request.id} dur_ms=${dur} qdepth=${__diagQueueDepth}\n`);
189
+ try {
190
+ server.__activeDiagRequests?.delete(request.id);
191
+ }
192
+ catch { /* ignore */ }
193
+ }
194
+ }
195
+ catch { /* ignore */ }
196
+ }
197
+ if (abortController.signal.aborted) {
198
+ try {
199
+ if ((0, runtimeConfig_1.getRuntimeConfig)().logging.verbose)
200
+ process.stderr.write(`[rpc] aborted-but-sending method=${request.method} id=${request.id}\n`);
201
+ }
202
+ catch { /* ignore */ }
203
+ }
204
+ else {
205
+ try {
206
+ if ((0, runtimeConfig_1.getRuntimeConfig)().logging.verbose)
207
+ process.stderr.write(`[rpc] response method=${request.method} id=${request.id} ok\n`);
208
+ }
209
+ catch { /* ignore */ }
210
+ }
211
+ const sendPromise = this._transport?.send({ jsonrpc: '2.0', id: request.id, result });
212
+ if (request.method === 'initialize') {
213
+ (0, handshakeManager_1.initFrameLog)('dispatcher_before_send', { id: request.id });
214
+ (sendPromise?.then?.(() => {
215
+ (0, handshakeManager_1.initFrameLog)('dispatcher_send_resolved', { id: request.id });
216
+ server.__initResponseSent = true;
217
+ setTimeout(() => (0, handshakeManager_1.emitReadyGlobal)(server, 'transport-send-hook'), 0);
218
+ }))?.catch(() => { });
219
+ }
220
+ return sendPromise;
221
+ }, (error) => {
222
+ if (startedAt !== undefined) {
223
+ try {
224
+ const dur = Date.now() - startedAt;
225
+ const category = categorizeRequest(request);
226
+ if (category === 'health' || category === 'meta' || category === 'metrics' || category === 'init') {
227
+ __diagQueueDepth = Math.max(0, __diagQueueDepth - 1);
228
+ process.stderr.write(`[diag] ${Date.now()} rq_error method=${request.method} cat=${category} id=${request.id} dur_ms=${dur} qdepth=${__diagQueueDepth}\n`);
229
+ try {
230
+ server.__activeDiagRequests?.delete(request.id);
231
+ }
232
+ catch { /* ignore */ }
233
+ }
234
+ }
235
+ catch { /* ignore */ }
236
+ }
237
+ if (abortController.signal.aborted) {
238
+ try {
239
+ if ((0, runtimeConfig_1.getRuntimeConfig)().logging.verbose)
240
+ process.stderr.write(`[rpc] aborted-error-path method=${request.method} id=${request.id}\n`);
241
+ }
242
+ catch { /* ignore */ }
243
+ }
244
+ // Robust semantic error preservation: search multiple nests for a JSON-RPC code/message
245
+ let errCode = error?.code;
246
+ if (!Number.isSafeInteger(errCode))
247
+ errCode = error?.data?.code;
248
+ if (!Number.isSafeInteger(errCode))
249
+ errCode = error?.original?.code;
250
+ if (!Number.isSafeInteger(errCode))
251
+ errCode = error?.cause?.code;
252
+ if (!Number.isSafeInteger(errCode))
253
+ errCode = error?.error?.code;
254
+ const rawBeforeDeep = errCode;
255
+ if (!Number.isSafeInteger(errCode) || errCode === -32603) {
256
+ const deep = deepScan(error);
257
+ if (Number.isSafeInteger(deep))
258
+ errCode = deep;
259
+ }
260
+ const safeCode = Number.isSafeInteger(errCode) ? errCode : undefined;
261
+ let errMessage = error?.message;
262
+ if (!errMessage)
263
+ errMessage = error?.data?.message;
264
+ if (!errMessage)
265
+ errMessage = error?.original?.message;
266
+ if (!errMessage)
267
+ errMessage = error?.cause?.message;
268
+ if (!errMessage)
269
+ errMessage = error?.error?.message;
270
+ if (typeof errMessage !== 'string' || !errMessage.trim())
271
+ errMessage = 'Internal error';
272
+ let data = error?.data;
273
+ if (data && typeof data === 'object') {
274
+ if (typeof data.message !== 'string')
275
+ data = { ...data, message: errMessage };
276
+ }
277
+ else if (error && typeof error === 'object') {
278
+ data = { message: errMessage, ...(error.method ? { method: error.method } : {}) };
279
+ }
280
+ let finalCode = (safeCode !== undefined) ? safeCode : -32603;
281
+ if (finalCode === -32603 && data && typeof data === 'object') {
282
+ try {
283
+ const reason = data.reason || data.data?.reason;
284
+ if (reason === 'missing_action')
285
+ finalCode = -32602;
286
+ else if (reason === 'unknown_action' || reason === 'mutation_disabled' || reason === 'unknown_handler')
287
+ finalCode = -32601;
288
+ }
289
+ catch { /* ignore */ }
290
+ }
291
+ try {
292
+ if ((0, runtimeConfig_1.getRuntimeConfig)().logging.verbose) {
293
+ const before = Number.isSafeInteger(rawBeforeDeep) ? rawBeforeDeep : 'n/a';
294
+ if ((before === 'n/a' || before === -32603) && (finalCode === -32601 || finalCode === -32602)) {
295
+ const reasonHint = data?.reason || data?.data?.reason;
296
+ process.stderr.write(`[rpc] deep_recover_semantic code=${finalCode} from=${before} reasonHint=${reasonHint || ''}\n`);
297
+ }
298
+ }
299
+ }
300
+ catch { /* ignore */ }
301
+ try {
302
+ if ((0, runtimeConfig_1.getRuntimeConfig)().logging.verbose)
303
+ process.stderr.write(`[rpc] response method=${request.method} id=${request.id} error=${errMessage} code=${finalCode}\n`);
304
+ }
305
+ catch { /* ignore */ }
306
+ return this._transport?.send({ jsonrpc: '2.0', id: request.id, error: { code: finalCode, message: errMessage, data } });
307
+ })
308
+ .catch(() => { })
309
+ .finally(() => { this._requestHandlerAbortControllers.delete(request.id); });
310
+ };
311
+ // Attach wrapper to BOTH potential internal symbols to guarantee interception.
312
+ server._onRequest = wrapped;
313
+ server._onrequest = wrapped;
314
+ server.__dispatcherOverrideActive = true;
315
+ try {
316
+ if ((0, runtimeConfig_1.getRuntimeConfig)().trace.has('healthMixed'))
317
+ process.stderr.write(`[diag] ${Date.now()} dispatcher_override applied props=${[existingCamel ? '_onRequest(original)' : '', existingLower ? '_onrequest(original)' : ''].filter(Boolean).join(',') || 'none'}\n`);
318
+ }
319
+ catch { /* ignore */ }
320
+ // Starvation watchdog
321
+ if ((0, runtimeConfig_1.getRuntimeConfig)().trace.has('healthMixed') && !server.__starvationWatchdogStarted) {
322
+ server.__starvationWatchdogStarted = true;
323
+ let ticks = 0;
324
+ const iv = setInterval(() => {
325
+ try {
326
+ ticks++;
327
+ const active = server.__activeDiagRequests;
328
+ const firstH = server.__healthId1EnqueueAt;
329
+ if (active && active.size) {
330
+ const pending = Array.from(active.values()).map((r) => ({ id: r.id, cat: r.cat, age: Date.now() - r.start })).sort((a, b) => a.id - b.id).slice(0, 12);
331
+ const hasHealth1 = !!active.get?.(1);
332
+ if (hasHealth1 || (firstH && Date.now() - firstH > 40)) {
333
+ process.stderr.write(`[diag] ${Date.now()} starvation_watchdog tick=${ticks} pending=${pending.length} details=${JSON.stringify(pending)} firstHealthAge=${firstH ? Date.now() - firstH : -1} hasHealth1=${hasHealth1}\n`);
334
+ }
335
+ if (!hasHealth1 && firstH && Date.now() - firstH > 400) {
336
+ process.stderr.write(`[diag] ${Date.now()} starvation_watchdog_health1_missing age=${Date.now() - firstH}\n`);
337
+ }
338
+ }
339
+ if (ticks > 40 || (server.__activeDiagRequests && !server.__activeDiagRequests.get(1))) {
340
+ clearInterval(iv);
341
+ }
342
+ }
343
+ catch { /* ignore */ }
344
+ }, 25);
345
+ iv.unref?.();
346
+ }
347
+ }
348
+ else if ((0, runtimeConfig_1.getRuntimeConfig)().trace.has('healthMixed')) {
349
+ try {
350
+ process.stderr.write(`[diag] ${Date.now()} dispatcher_override_skipped no_original_handler_found`);
351
+ }
352
+ catch { /* ignore */ }
353
+ }
354
+ // Enumerate server properties once for debugging missing override
355
+ try {
356
+ if ((0, runtimeConfig_1.getRuntimeConfig)().trace.has('healthMixed')) {
357
+ const props = Object.getOwnPropertyNames(server).filter(p => /_on|request|handler/i.test(p)).slice(0, 60);
358
+ process.stderr.write(`[diag] ${Date.now()} server_props ${props.join(',')}\n`);
359
+ }
360
+ }
361
+ catch { /* ignore */ }
362
+ }
363
+ /**
364
+ * Wrap transport.send to detect initialize response flush and emit ready.
365
+ */
366
+ function wrapTransportSend(server, transport) {
367
+ try {
368
+ const origSend = transport?.send?.bind(transport);
369
+ if (origSend && !transport.__wrappedForReady) {
370
+ transport.__wrappedForReady = true;
371
+ transport.send = (msg) => {
372
+ let isInitResult = false;
373
+ try {
374
+ isInitResult = !!(msg && typeof msg === 'object' && 'id' in msg && msg.result && msg.result.protocolVersion);
375
+ }
376
+ catch { /* ignore */ }
377
+ const sendPromise = origSend(msg);
378
+ // Fallback completion / error logging if dispatcher override not active
379
+ try {
380
+ if ((0, runtimeConfig_1.getRuntimeConfig)().trace.has('healthMixed') && !server.__dispatcherOverrideActive && msg && typeof msg === 'object' && Object.prototype.hasOwnProperty.call(msg, 'id')) {
381
+ const map = server.__diagRQMap;
382
+ if (map && map.has(msg.id)) {
383
+ const rec = map.get(msg.id);
384
+ map.delete(msg.id);
385
+ server.__diagQueueDepthSniff = Math.max(0, server.__diagQueueDepthSniff - 1);
386
+ const kind = msg.error ? 'rq_error' : 'rq_complete';
387
+ const dur = Date.now() - rec.start;
388
+ process.stderr.write(`[diag] ${Date.now()} ${kind} method=${rec.method} cat=${rec.cat} id=${msg.id} dur_ms=${dur} qdepth=${server.__diagQueueDepthSniff} src=sniff-send\n`);
389
+ }
390
+ }
391
+ }
392
+ catch { /* ignore */ }
393
+ if (isInitResult && !server.__readyNotified) {
394
+ server.__sawInitializeRequest = true;
395
+ (0, handshakeManager_1.initFrameLog)('transport_detect_init_result', { id: msg.id });
396
+ sendPromise?.then?.(() => {
397
+ (0, handshakeManager_1.initFrameLog)('transport_send_resolved', { id: msg.id });
398
+ server.__initResponseSent = true;
399
+ setTimeout(() => (0, handshakeManager_1.emitReadyGlobal)(server, 'transport-send-hook-dynamic'), 0);
400
+ })?.catch?.(() => { });
401
+ }
402
+ return sendPromise;
403
+ };
404
+ }
405
+ }
406
+ catch { /* ignore wrapper errors */ }
407
+ }
408
+ /**
409
+ * Explicit keepalive to avoid premature process exit before first client request.
410
+ * @param label - Optional label for diagnostic log messages (e.g. 'secondary')
411
+ */
412
+ function setupKeepalive(label = '') {
413
+ try {
414
+ if (process.stdin.readable)
415
+ process.stdin.resume();
416
+ process.stdin.on('data', () => { }); // no-op to anchor listener
417
+ const ka = setInterval(() => { }, 10_000);
418
+ ka.unref?.();
419
+ if ((0, runtimeConfig_1.getRuntimeConfig)().logging.diagnostics) {
420
+ const prefix = label ? ` (${label})` : '';
421
+ const stdinListenerCount = process.stdin.listenerCount('data');
422
+ try {
423
+ process.stderr.write(`[transport-init]${prefix} keepalive setup complete stdin.dataListeners=${stdinListenerCount}\n`);
424
+ }
425
+ catch { /* ignore */ }
426
+ }
427
+ }
428
+ catch { /* ignore */ }
429
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Atomically write JSON to disk with robust retry semantics for shared index scenarios.
3
+ *
4
+ * Rationale:
5
+ * - Multiple Index Server processes may share the same instructions directory.
6
+ * - On Windows / network filesystems, transient EPERM / EBUSY / EACCES can occur during rename
7
+ * when virus scanners, indexers or another process have the destination briefly open.
8
+ * - We mitigate by:
9
+ * 1. Writing content to a unique temp file.
10
+ * 2. Attempting fs.renameSync (atomic on same volume) with retry/backoff.
11
+ * 3. Falling back to a direct fs.writeFileSync(dest, data) on final attempt if rename keeps failing
12
+ * specifically due to transient lock codes.
13
+ * - No file descriptors are intentionally left open; synchronous methods close before returning.
14
+ *
15
+ * Configuration (via runtime config / env consolidation):
16
+ * - atomicFs.retries (INDEX_SERVER_ATOMIC_WRITE_RETRIES, default 5) : total attempts (initial + retries)
17
+ * - atomicFs.backoffMs (INDEX_SERVER_ATOMIC_WRITE_BACKOFF_MS, default 10): initial backoff in ms (exponential with jitter)
18
+ * @param filePath - Absolute path to the destination file
19
+ * @param obj - Value to serialize as pretty-printed JSON
20
+ * @throws Will throw if all write/rename attempts are exhausted due to non-transient errors
21
+ */
22
+ export declare function atomicWriteJson(filePath: string, obj: unknown): void;
@@ -0,0 +1,103 @@
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.atomicWriteJson = atomicWriteJson;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const crypto_1 = __importDefault(require("crypto"));
10
+ const runtimeConfig_1 = require("../config/runtimeConfig");
11
+ /**
12
+ * Atomically write JSON to disk with robust retry semantics for shared index scenarios.
13
+ *
14
+ * Rationale:
15
+ * - Multiple Index Server processes may share the same instructions directory.
16
+ * - On Windows / network filesystems, transient EPERM / EBUSY / EACCES can occur during rename
17
+ * when virus scanners, indexers or another process have the destination briefly open.
18
+ * - We mitigate by:
19
+ * 1. Writing content to a unique temp file.
20
+ * 2. Attempting fs.renameSync (atomic on same volume) with retry/backoff.
21
+ * 3. Falling back to a direct fs.writeFileSync(dest, data) on final attempt if rename keeps failing
22
+ * specifically due to transient lock codes.
23
+ * - No file descriptors are intentionally left open; synchronous methods close before returning.
24
+ *
25
+ * Configuration (via runtime config / env consolidation):
26
+ * - atomicFs.retries (INDEX_SERVER_ATOMIC_WRITE_RETRIES, default 5) : total attempts (initial + retries)
27
+ * - atomicFs.backoffMs (INDEX_SERVER_ATOMIC_WRITE_BACKOFF_MS, default 10): initial backoff in ms (exponential with jitter)
28
+ * @param filePath - Absolute path to the destination file
29
+ * @param obj - Value to serialize as pretty-printed JSON
30
+ * @throws Will throw if all write/rename attempts are exhausted due to non-transient errors
31
+ */
32
+ function atomicWriteJson(filePath, obj) {
33
+ const dir = path_1.default.dirname(filePath);
34
+ if (!fs_1.default.existsSync(dir))
35
+ fs_1.default.mkdirSync(dir, { recursive: true });
36
+ const data = JSON.stringify(obj, null, 2);
37
+ const atomicConfig = (0, runtimeConfig_1.getRuntimeConfig)().atomicFs;
38
+ const maxAttempts = Math.max(1, atomicConfig.retries);
39
+ const baseBackoff = Math.max(1, atomicConfig.backoffMs);
40
+ let lastErr = null;
41
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
42
+ const tmp = path_1.default.join(dir, `.${path_1.default.basename(filePath)}.${crypto_1.default.randomBytes(6).toString('hex')}.tmp`);
43
+ try {
44
+ fs_1.default.writeFileSync(tmp, data, 'utf8');
45
+ try {
46
+ fs_1.default.renameSync(tmp, filePath);
47
+ return; // success
48
+ }
49
+ catch (renameErr) {
50
+ // If rename failed, decide whether to retry
51
+ const code = renameErr.code;
52
+ const transient = code === 'EPERM' || code === 'EBUSY' || code === 'EACCES' || code === 'ENOENT';
53
+ if (!transient || attempt === maxAttempts) {
54
+ // On final attempt we do NOT fallback to direct write to preserve atomic semantics; propagate.
55
+ lastErr = renameErr;
56
+ try {
57
+ if (fs_1.default.existsSync(tmp))
58
+ fs_1.default.unlinkSync(tmp);
59
+ }
60
+ catch { /* ignore */ }
61
+ break;
62
+ }
63
+ lastErr = renameErr;
64
+ try {
65
+ if (fs_1.default.existsSync(tmp))
66
+ fs_1.default.unlinkSync(tmp);
67
+ }
68
+ catch { /* ignore */ }
69
+ // Backoff (exponential + jitter)
70
+ const sleepMs = baseBackoff * Math.pow(2, attempt - 1) + Math.floor(Math.random() * baseBackoff);
71
+ const start = Date.now();
72
+ while (Date.now() - start < sleepMs) { /* busy-wait tiny backoff (short durations) */ }
73
+ continue; // retry loop
74
+ }
75
+ }
76
+ catch (writeErr) {
77
+ const code = writeErr.code;
78
+ const transient = code === 'EPERM' || code === 'EBUSY' || code === 'EACCES';
79
+ if (!transient || attempt === maxAttempts) {
80
+ lastErr = writeErr;
81
+ try {
82
+ if (fs_1.default.existsSync(tmp))
83
+ fs_1.default.unlinkSync(tmp);
84
+ }
85
+ catch { /* ignore */ }
86
+ break;
87
+ }
88
+ lastErr = writeErr;
89
+ try {
90
+ if (fs_1.default.existsSync(tmp))
91
+ fs_1.default.unlinkSync(tmp);
92
+ }
93
+ catch { /* ignore */ }
94
+ const sleepMs = baseBackoff * Math.pow(2, attempt - 1) + Math.floor(Math.random() * baseBackoff);
95
+ const start = Date.now();
96
+ while (Date.now() - start < sleepMs) { /* busy-wait */ }
97
+ continue;
98
+ }
99
+ }
100
+ // Propagate final error after exhausting attempts
101
+ const err = lastErr instanceof Error ? lastErr : new Error('atomicWriteJson failed');
102
+ throw err;
103
+ }
@@ -0,0 +1,38 @@
1
+ /** Run a function with a correlation ID accessible to all logAudit() calls within. */
2
+ export declare function runWithCorrelation<T>(correlationId: string, fn: () => T): T;
3
+ /** Get the current correlation ID from the async context (if any). */
4
+ export declare function getCurrentCorrelationId(): string | undefined;
5
+ /** Reset the cached audit log path, forcing re-resolution on next write. */
6
+ export declare function resetAuditLogCache(): void;
7
+ export type AuditKind = 'mutation' | 'read' | 'http';
8
+ export interface AuditEntry {
9
+ ts: string;
10
+ kind: AuditKind;
11
+ action: string;
12
+ ids?: string[];
13
+ meta?: Record<string, unknown>;
14
+ }
15
+ /**
16
+ * Append an entry to the audit log file. Silent no-op when logging is disabled.
17
+ * @param action - Tool or operation name being recorded
18
+ * @param ids - Instruction IDs affected by this operation (if any)
19
+ * @param meta - Lightweight result summary (counts, flags, etc.)
20
+ * @param kind - Entry classification; defaults to `'mutation'`
21
+ */
22
+ export declare function logAudit(action: string, ids?: string[] | string, meta?: Record<string, unknown>, kind?: AuditKind): void;
23
+ /**
24
+ * Log a tool invocation to the audit trail. Called from the registry wrapper
25
+ * so ALL tool calls (reads + mutations) are captured automatically.
26
+ */
27
+ export declare function logToolAudit(toolName: string, success: boolean, durationMs: number, correlationId?: string, errorType?: string): void;
28
+ /**
29
+ * Log an HTTP request to the audit trail. Called from dashboard middleware
30
+ * so all API requests are captured with client IP and user-agent.
31
+ */
32
+ export declare function logHttpAudit(method: string, route: string, statusCode: number, durationMs: number, clientIp?: string, userAgent?: string): void;
33
+ /**
34
+ * Read the most recent audit log entries from disk.
35
+ * @param limit - Maximum number of lines to return from the tail of the file (default 1000)
36
+ * @returns Parsed audit entries, or an empty array if logging is disabled or the file is missing
37
+ */
38
+ export declare function readAuditEntries(limit?: number): AuditEntry[];