@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,84 @@
1
+ "use strict";
2
+ /**
3
+ * Scripts Routes — Serve client scripts for download
4
+ * Routes: GET /scripts, GET /scripts/:name
5
+ *
6
+ * Provides downloadable REST client scripts for agents and users
7
+ * that lack MCP tool access and need to interact via HTTP.
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.createScriptsRoutes = createScriptsRoutes;
14
+ const express_1 = require("express");
15
+ const promises_1 = require("fs/promises");
16
+ const path_1 = __importDefault(require("path"));
17
+ /** Allowed script files with metadata */
18
+ const AVAILABLE_SCRIPTS = {
19
+ 'index-server-client.ps1': {
20
+ file: 'index-server-client.ps1',
21
+ contentType: 'application/octet-stream',
22
+ description: 'PowerShell REST client for Index Server (agents without MCP)',
23
+ },
24
+ 'index-server-client.sh': {
25
+ file: 'index-server-client.sh',
26
+ contentType: 'application/octet-stream',
27
+ description: 'Bash REST client for Index Server (agents without MCP)',
28
+ },
29
+ };
30
+ function createScriptsRoutes() {
31
+ const router = (0, express_1.Router)();
32
+ /**
33
+ * GET /api/scripts — List available client scripts with download URLs
34
+ */
35
+ router.get('/scripts', (_req, res) => {
36
+ const scripts = Object.entries(AVAILABLE_SCRIPTS).map(([name, meta]) => ({
37
+ name,
38
+ description: meta.description,
39
+ downloadUrl: `/api/scripts/${name}`,
40
+ }));
41
+ res.setHeader('Cache-Control', 'no-store');
42
+ res.json({ scripts });
43
+ });
44
+ /**
45
+ * GET /api/scripts/:name — Download a specific client script
46
+ */
47
+ router.get('/scripts/:name', async (req, res) => {
48
+ const name = req.params.name;
49
+ // Validate against allowlist (no path traversal)
50
+ const meta = AVAILABLE_SCRIPTS[name];
51
+ if (!meta) {
52
+ res.status(404).json({
53
+ error: `Script not found: ${name}`,
54
+ available: Object.keys(AVAILABLE_SCRIPTS),
55
+ });
56
+ return;
57
+ }
58
+ try {
59
+ const scriptsDir = path_1.default.join(process.cwd(), 'scripts');
60
+ const filePath = path_1.default.join(scriptsDir, meta.file);
61
+ // Verify resolved path is within scripts directory (defense in depth)
62
+ const resolved = path_1.default.resolve(filePath);
63
+ if (!resolved.startsWith(path_1.default.resolve(scriptsDir))) {
64
+ res.status(400).json({ error: 'Invalid script path' });
65
+ return;
66
+ }
67
+ const content = await (0, promises_1.readFile)(resolved, 'utf-8');
68
+ res.setHeader('Content-Type', meta.contentType);
69
+ res.setHeader('Content-Disposition', `attachment; filename="${meta.file}"`);
70
+ res.setHeader('X-Content-Type-Options', 'nosniff');
71
+ res.send(content);
72
+ }
73
+ catch (err) {
74
+ const message = err instanceof Error ? err.message : String(err);
75
+ if (message.includes('ENOENT')) {
76
+ res.status(404).json({ error: `Script file not found on disk: ${name}` });
77
+ }
78
+ else {
79
+ res.status(500).json({ error: `Failed to read script: ${message}` });
80
+ }
81
+ }
82
+ });
83
+ return router;
84
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * SQLite dashboard routes — DB info, ad-hoc query, maintenance,
3
+ * backup/restore, WAL management, grooming, migration & export.
4
+ *
5
+ * Only active when INDEX_SERVER_STORAGE_BACKEND=sqlite.
6
+ * All routes prefixed with /sqlite/.
7
+ */
8
+ import { Router } from 'express';
9
+ export declare function createSqliteRoutes(): Router;
@@ -0,0 +1,569 @@
1
+ "use strict";
2
+ /**
3
+ * SQLite dashboard routes — DB info, ad-hoc query, maintenance,
4
+ * backup/restore, WAL management, grooming, migration & export.
5
+ *
6
+ * Only active when INDEX_SERVER_STORAGE_BACKEND=sqlite.
7
+ * All routes prefixed with /sqlite/.
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.createSqliteRoutes = createSqliteRoutes;
14
+ const express_1 = require("express");
15
+ const runtimeConfig_js_1 = require("../../../config/runtimeConfig.js");
16
+ const node_sqlite_1 = require("node:sqlite");
17
+ const migrationEngine_js_1 = require("../../../services/storage/migrationEngine.js");
18
+ const sqliteSchema_js_1 = require("../../../services/storage/sqliteSchema.js");
19
+ const fs_1 = __importDefault(require("fs"));
20
+ const path_1 = __importDefault(require("path"));
21
+ function getSqlitePath() {
22
+ return (0, runtimeConfig_js_1.getRuntimeConfig)().storage?.sqlitePath ?? '';
23
+ }
24
+ function assertSqliteActive() {
25
+ if (((0, runtimeConfig_js_1.getRuntimeConfig)().storage?.backend ?? 'json') !== 'sqlite') {
26
+ throw Object.assign(new Error('SQLite backend not active'), { statusCode: 400 });
27
+ }
28
+ }
29
+ function getBackupsDir() {
30
+ return (0, runtimeConfig_js_1.getRuntimeConfig)().dashboard.admin.backupsDir;
31
+ }
32
+ function createSqliteRoutes() {
33
+ const router = (0, express_1.Router)();
34
+ /** GET /sqlite/info — Database stats and config */
35
+ router.get('/sqlite/info', (_req, res) => {
36
+ try {
37
+ const config = (0, runtimeConfig_js_1.getRuntimeConfig)();
38
+ const backend = config.storage?.backend ?? 'json';
39
+ const sqlitePath = config.storage?.sqlitePath ?? '';
40
+ const walEnabled = config.storage?.sqliteWal ?? true;
41
+ if (backend !== 'sqlite') {
42
+ return res.json({
43
+ success: true,
44
+ active: false,
45
+ backend: 'json',
46
+ message: 'SQLite backend is not active. Set INDEX_SERVER_STORAGE_BACKEND=sqlite to enable.',
47
+ });
48
+ }
49
+ // Get file size if DB exists
50
+ let fileSize = 0;
51
+ let walSize = 0;
52
+ let shmSize = 0;
53
+ let exists = false;
54
+ try {
55
+ if (fs_1.default.existsSync(sqlitePath)) {
56
+ exists = true;
57
+ fileSize = fs_1.default.statSync(sqlitePath).size;
58
+ const walPath = sqlitePath + '-wal';
59
+ const shmPath = sqlitePath + '-shm';
60
+ if (fs_1.default.existsSync(walPath))
61
+ walSize = fs_1.default.statSync(walPath).size;
62
+ if (fs_1.default.existsSync(shmPath))
63
+ shmSize = fs_1.default.statSync(shmPath).size;
64
+ }
65
+ }
66
+ catch { /* ignore */ }
67
+ // Query DB stats using node:sqlite
68
+ const tableStats = {};
69
+ const pragmas = {};
70
+ try {
71
+ const db = new node_sqlite_1.DatabaseSync(sqlitePath, { readOnly: true });
72
+ try {
73
+ // Count rows in key tables
74
+ for (const table of ['instructions', 'messages', 'usage', 'metadata']) {
75
+ try {
76
+ const row = db.prepare(`SELECT COUNT(*) as cnt FROM ${table}`).get();
77
+ tableStats[table] = row?.cnt ?? 0;
78
+ }
79
+ catch { /* table may not exist */ }
80
+ }
81
+ // Read pragmas
82
+ try {
83
+ const jm = db.prepare('PRAGMA journal_mode').get();
84
+ pragmas.journalMode = jm?.journal_mode ?? 'unknown';
85
+ }
86
+ catch { /* ignore */ }
87
+ try {
88
+ const ps = db.prepare('PRAGMA page_size').get();
89
+ pragmas.pageSize = ps?.page_size ?? 0;
90
+ }
91
+ catch { /* ignore */ }
92
+ try {
93
+ const pc = db.prepare('PRAGMA page_count').get();
94
+ pragmas.pageCount = pc?.page_count ?? 0;
95
+ }
96
+ catch { /* ignore */ }
97
+ try {
98
+ const fl = db.prepare('PRAGMA freelist_count').get();
99
+ pragmas.freelistCount = fl?.freelist_count ?? 0;
100
+ }
101
+ catch { /* ignore */ }
102
+ }
103
+ finally {
104
+ db.close();
105
+ }
106
+ }
107
+ catch { /* node:sqlite not available */ }
108
+ return res.json({
109
+ success: true,
110
+ active: true,
111
+ backend: 'sqlite',
112
+ dbPath: sqlitePath,
113
+ exists,
114
+ fileSize,
115
+ walSize,
116
+ shmSize,
117
+ walEnabled,
118
+ tableStats,
119
+ pragmas,
120
+ });
121
+ }
122
+ catch (err) {
123
+ return res.status(500).json({ success: false, error: err.message });
124
+ }
125
+ });
126
+ /** POST /sqlite/query — Execute read-only SQL query */
127
+ router.post('/sqlite/query', (req, res) => {
128
+ try {
129
+ assertSqliteActive();
130
+ const { sql } = req.body;
131
+ if (!sql || typeof sql !== 'string') {
132
+ return res.status(400).json({ success: false, error: 'Missing "sql" field in request body' });
133
+ }
134
+ // Safety: only allow SELECT and PRAGMA
135
+ const trimmed = sql.trim().toUpperCase();
136
+ if (!trimmed.startsWith('SELECT') && !trimmed.startsWith('PRAGMA') && !trimmed.startsWith('EXPLAIN')) {
137
+ return res.status(403).json({
138
+ success: false,
139
+ error: 'Only SELECT, PRAGMA, and EXPLAIN queries are allowed',
140
+ });
141
+ }
142
+ // Reject multi-statement queries and enforce length limit
143
+ if (sql.length > 10000) {
144
+ return res.status(400).json({ success: false, error: 'Query exceeds maximum length (10000 chars)' });
145
+ }
146
+ if (/;\s*\S/.test(sql)) {
147
+ return res.status(403).json({ success: false, error: 'Multi-statement queries are not allowed' });
148
+ }
149
+ const sqlitePath = getSqlitePath();
150
+ const db = new node_sqlite_1.DatabaseSync(sqlitePath, { readOnly: true });
151
+ try {
152
+ const rows = db.prepare(sql).all();
153
+ const columns = rows.length > 0 ? Object.keys(rows[0]) : [];
154
+ return res.json({
155
+ success: true,
156
+ columns,
157
+ rows,
158
+ rowCount: rows.length,
159
+ });
160
+ }
161
+ finally {
162
+ db.close();
163
+ }
164
+ }
165
+ catch (err) {
166
+ const code = err.statusCode ?? 400;
167
+ return res.status(code).json({ success: false, error: err.message });
168
+ }
169
+ });
170
+ /** POST /sqlite/vacuum — Run VACUUM to reclaim space */
171
+ router.post('/sqlite/vacuum', (_req, res) => {
172
+ try {
173
+ assertSqliteActive();
174
+ const sqlitePath = getSqlitePath();
175
+ const db = new node_sqlite_1.DatabaseSync(sqlitePath);
176
+ try {
177
+ db.exec('VACUUM');
178
+ const sizeAfter = fs_1.default.existsSync(sqlitePath) ? fs_1.default.statSync(sqlitePath).size : 0;
179
+ return res.json({ success: true, message: 'VACUUM completed', sizeAfter });
180
+ }
181
+ finally {
182
+ db.close();
183
+ }
184
+ }
185
+ catch (err) {
186
+ const code = err.statusCode ?? 500;
187
+ return res.status(code).json({ success: false, error: err.message });
188
+ }
189
+ });
190
+ /** POST /sqlite/optimize — Run FTS5 optimize */
191
+ router.post('/sqlite/optimize', (_req, res) => {
192
+ try {
193
+ assertSqliteActive();
194
+ const sqlitePath = getSqlitePath();
195
+ const db = new node_sqlite_1.DatabaseSync(sqlitePath);
196
+ try {
197
+ db.exec("INSERT INTO instructions_fts(instructions_fts) VALUES('optimize')");
198
+ return res.json({ success: true, message: 'FTS5 index optimized' });
199
+ }
200
+ finally {
201
+ db.close();
202
+ }
203
+ }
204
+ catch (err) {
205
+ const code = err.statusCode ?? 500;
206
+ return res.status(code).json({ success: false, error: err.message });
207
+ }
208
+ });
209
+ /** POST /sqlite/integrity-check — Run SQLite integrity check */
210
+ router.post('/sqlite/integrity-check', (_req, res) => {
211
+ try {
212
+ assertSqliteActive();
213
+ const sqlitePath = getSqlitePath();
214
+ const db = new node_sqlite_1.DatabaseSync(sqlitePath, { readOnly: true });
215
+ try {
216
+ const rows = db.prepare('PRAGMA integrity_check').all();
217
+ const ok = rows.length === 1 && rows[0].integrity_check === 'ok';
218
+ return res.json({ success: true, ok, results: rows });
219
+ }
220
+ finally {
221
+ db.close();
222
+ }
223
+ }
224
+ catch (err) {
225
+ const code = err.statusCode ?? 500;
226
+ return res.status(code).json({ success: false, error: err.message });
227
+ }
228
+ });
229
+ // ── Backup / Restore ──────────────────────────────────────────────────
230
+ /** POST /sqlite/backup — Create manual backup of the SQLite DB */
231
+ router.post('/sqlite/backup', (_req, res) => {
232
+ try {
233
+ assertSqliteActive();
234
+ const sqlitePath = getSqlitePath();
235
+ if (!fs_1.default.existsSync(sqlitePath)) {
236
+ return res.status(404).json({ success: false, error: 'Database file not found' });
237
+ }
238
+ const backupsRoot = getBackupsDir();
239
+ fs_1.default.mkdirSync(backupsRoot, { recursive: true });
240
+ const stamp = new Date().toISOString().replace(/[:.]/g, '').replace('T', '-').slice(0, 15);
241
+ const backupDir = path_1.default.join(backupsRoot, `manual-backup-${stamp}`);
242
+ fs_1.default.mkdirSync(backupDir, { recursive: true });
243
+ // Checkpoint WAL before backup for consistency
244
+ try {
245
+ const db = new node_sqlite_1.DatabaseSync(sqlitePath);
246
+ try {
247
+ db.exec('PRAGMA wal_checkpoint(TRUNCATE)');
248
+ }
249
+ finally {
250
+ db.close();
251
+ }
252
+ }
253
+ catch { /* best-effort checkpoint */ }
254
+ fs_1.default.copyFileSync(sqlitePath, path_1.default.join(backupDir, 'index.db'));
255
+ if (fs_1.default.existsSync(sqlitePath + '-wal'))
256
+ fs_1.default.copyFileSync(sqlitePath + '-wal', path_1.default.join(backupDir, 'index.db-wal'));
257
+ if (fs_1.default.existsSync(sqlitePath + '-shm'))
258
+ fs_1.default.copyFileSync(sqlitePath + '-shm', path_1.default.join(backupDir, 'index.db-shm'));
259
+ const backupSize = fs_1.default.statSync(path_1.default.join(backupDir, 'index.db')).size;
260
+ return res.json({ success: true, message: 'Backup created', backupDir, backupSize });
261
+ }
262
+ catch (err) {
263
+ const code = err.statusCode ?? 500;
264
+ return res.status(code).json({ success: false, error: err.message });
265
+ }
266
+ });
267
+ /** GET /sqlite/backups — List available backups */
268
+ router.get('/sqlite/backups', (_req, res) => {
269
+ try {
270
+ const backupsRoot = getBackupsDir();
271
+ if (!fs_1.default.existsSync(backupsRoot)) {
272
+ return res.json({ success: true, backups: [] });
273
+ }
274
+ const dirs = fs_1.default.readdirSync(backupsRoot)
275
+ .filter(d => {
276
+ const full = path_1.default.join(backupsRoot, d);
277
+ return fs_1.default.statSync(full).isDirectory() && fs_1.default.existsSync(path_1.default.join(full, 'index.db'));
278
+ })
279
+ .map(d => {
280
+ const full = path_1.default.join(backupsRoot, d);
281
+ const dbSize = fs_1.default.statSync(path_1.default.join(full, 'index.db')).size;
282
+ const created = fs_1.default.statSync(full).mtime.toISOString();
283
+ return { name: d, path: full, dbSize, created };
284
+ })
285
+ .sort((a, b) => b.created.localeCompare(a.created));
286
+ return res.json({ success: true, backups: dirs });
287
+ }
288
+ catch (err) {
289
+ return res.status(500).json({ success: false, error: err.message });
290
+ }
291
+ });
292
+ /** POST /sqlite/restore — Restore from a named backup */
293
+ router.post('/sqlite/restore', (req, res) => {
294
+ try {
295
+ assertSqliteActive();
296
+ const { backupName } = req.body;
297
+ if (!backupName || typeof backupName !== 'string') {
298
+ return res.status(400).json({ success: false, error: 'Missing "backupName" field' });
299
+ }
300
+ // Sanitize: no path traversal
301
+ if (backupName.includes('..') || backupName.includes('/') || backupName.includes('\\')) {
302
+ return res.status(400).json({ success: false, error: 'Invalid backup name' });
303
+ }
304
+ const backupsRoot = getBackupsDir();
305
+ const backupDir = path_1.default.join(backupsRoot, backupName);
306
+ const backupDb = path_1.default.join(backupDir, 'index.db');
307
+ if (!fs_1.default.existsSync(backupDb)) {
308
+ return res.status(404).json({ success: false, error: 'Backup not found: ' + backupName });
309
+ }
310
+ const sqlitePath = getSqlitePath();
311
+ // Auto-backup current DB before overwriting
312
+ if (fs_1.default.existsSync(sqlitePath)) {
313
+ const stamp = new Date().toISOString().replace(/[:.]/g, '').replace('T', '-').slice(0, 15);
314
+ const preRestoreDir = path_1.default.join(backupsRoot, `pre-restore-${stamp}`);
315
+ fs_1.default.mkdirSync(preRestoreDir, { recursive: true });
316
+ fs_1.default.copyFileSync(sqlitePath, path_1.default.join(preRestoreDir, 'index.db'));
317
+ if (fs_1.default.existsSync(sqlitePath + '-wal'))
318
+ fs_1.default.copyFileSync(sqlitePath + '-wal', path_1.default.join(preRestoreDir, 'index.db-wal'));
319
+ if (fs_1.default.existsSync(sqlitePath + '-shm'))
320
+ fs_1.default.copyFileSync(sqlitePath + '-shm', path_1.default.join(preRestoreDir, 'index.db-shm'));
321
+ }
322
+ // Restore: copy backup files over current DB
323
+ fs_1.default.copyFileSync(backupDb, sqlitePath);
324
+ const walFile = path_1.default.join(backupDir, 'index.db-wal');
325
+ const shmFile = path_1.default.join(backupDir, 'index.db-shm');
326
+ if (fs_1.default.existsSync(walFile)) {
327
+ fs_1.default.copyFileSync(walFile, sqlitePath + '-wal');
328
+ }
329
+ else {
330
+ // Remove stale WAL/SHM from previous DB
331
+ try {
332
+ fs_1.default.unlinkSync(sqlitePath + '-wal');
333
+ }
334
+ catch { /* ok */ }
335
+ }
336
+ if (fs_1.default.existsSync(shmFile)) {
337
+ fs_1.default.copyFileSync(shmFile, sqlitePath + '-shm');
338
+ }
339
+ else {
340
+ try {
341
+ fs_1.default.unlinkSync(sqlitePath + '-shm');
342
+ }
343
+ catch { /* ok */ }
344
+ }
345
+ return res.json({ success: true, message: 'Restored from ' + backupName });
346
+ }
347
+ catch (err) {
348
+ const code = err.statusCode ?? 500;
349
+ return res.status(code).json({ success: false, error: err.message });
350
+ }
351
+ });
352
+ // ── Reset / Migrate ───────────────────────────────────────────────────
353
+ /** POST /sqlite/reset — Drop all tables and reinitialize schema */
354
+ router.post('/sqlite/reset', (_req, res) => {
355
+ try {
356
+ assertSqliteActive();
357
+ const sqlitePath = getSqlitePath();
358
+ // Auto-backup before reset
359
+ if (fs_1.default.existsSync(sqlitePath)) {
360
+ const backupsRoot = getBackupsDir();
361
+ fs_1.default.mkdirSync(backupsRoot, { recursive: true });
362
+ const stamp = new Date().toISOString().replace(/[:.]/g, '').replace('T', '-').slice(0, 15);
363
+ const preResetDir = path_1.default.join(backupsRoot, `pre-reset-${stamp}`);
364
+ fs_1.default.mkdirSync(preResetDir, { recursive: true });
365
+ fs_1.default.copyFileSync(sqlitePath, path_1.default.join(preResetDir, 'index.db'));
366
+ }
367
+ // Delete the DB file and WAL/SHM — fresh start
368
+ try {
369
+ fs_1.default.unlinkSync(sqlitePath);
370
+ }
371
+ catch { /* ok */ }
372
+ try {
373
+ fs_1.default.unlinkSync(sqlitePath + '-wal');
374
+ }
375
+ catch { /* ok */ }
376
+ try {
377
+ fs_1.default.unlinkSync(sqlitePath + '-shm');
378
+ }
379
+ catch { /* ok */ }
380
+ // Reinitialize schema
381
+ const db = new node_sqlite_1.DatabaseSync(sqlitePath);
382
+ try {
383
+ db.exec(sqliteSchema_js_1.PRAGMAS);
384
+ db.exec(sqliteSchema_js_1.INSTRUCTIONS_DDL);
385
+ try {
386
+ db.exec(sqliteSchema_js_1.FTS5_DDL);
387
+ }
388
+ catch { /* FTS5 may already exist */ }
389
+ return res.json({ success: true, message: 'Database reset — schema reinitialized' });
390
+ }
391
+ finally {
392
+ db.close();
393
+ }
394
+ }
395
+ catch (err) {
396
+ const code = err.statusCode ?? 500;
397
+ return res.status(code).json({ success: false, error: err.message });
398
+ }
399
+ });
400
+ /** POST /sqlite/migrate — Migrate instructions from JSON files to SQLite */
401
+ router.post('/sqlite/migrate', async (_req, res) => {
402
+ try {
403
+ assertSqliteActive();
404
+ const instrDir = (0, runtimeConfig_js_1.getRuntimeConfig)().index.baseDir;
405
+ const sqlitePath = getSqlitePath();
406
+ const result = await (0, migrationEngine_js_1.migrateJsonToSqlite)(instrDir, sqlitePath);
407
+ return res.json({
408
+ success: true,
409
+ message: `Migrated ${result.migrated} instructions`,
410
+ migrated: result.migrated,
411
+ errors: result.errors,
412
+ });
413
+ }
414
+ catch (err) {
415
+ const code = err.statusCode ?? 500;
416
+ return res.status(code).json({ success: false, error: err.message });
417
+ }
418
+ });
419
+ /** POST /sqlite/export — Export SQLite instructions back to JSON files */
420
+ router.post('/sqlite/export', async (_req, res) => {
421
+ try {
422
+ assertSqliteActive();
423
+ const instrDir = (0, runtimeConfig_js_1.getRuntimeConfig)().index.baseDir;
424
+ const sqlitePath = getSqlitePath();
425
+ const result = await (0, migrationEngine_js_1.migrateSqliteToJson)(sqlitePath, instrDir);
426
+ return res.json({
427
+ success: true,
428
+ message: `Exported ${result.exported} instructions to JSON`,
429
+ exported: result.exported,
430
+ errors: result.errors,
431
+ });
432
+ }
433
+ catch (err) {
434
+ const code = err.statusCode ?? 500;
435
+ return res.status(code).json({ success: false, error: err.message });
436
+ }
437
+ });
438
+ // ── WAL Management ────────────────────────────────────────────────────
439
+ /** POST /sqlite/wal-checkpoint — Flush WAL to main database file */
440
+ router.post('/sqlite/wal-checkpoint', (_req, res) => {
441
+ try {
442
+ assertSqliteActive();
443
+ const sqlitePath = getSqlitePath();
444
+ const db = new node_sqlite_1.DatabaseSync(sqlitePath);
445
+ try {
446
+ const row = db.prepare('PRAGMA wal_checkpoint(TRUNCATE)').get();
447
+ const walSizeAfter = fs_1.default.existsSync(sqlitePath + '-wal') ? fs_1.default.statSync(sqlitePath + '-wal').size : 0;
448
+ return res.json({
449
+ success: true,
450
+ message: 'WAL checkpoint completed (TRUNCATE)',
451
+ checkpoint: row,
452
+ walSizeAfter,
453
+ });
454
+ }
455
+ finally {
456
+ db.close();
457
+ }
458
+ }
459
+ catch (err) {
460
+ const code = err.statusCode ?? 500;
461
+ return res.status(code).json({ success: false, error: err.message });
462
+ }
463
+ });
464
+ /** POST /sqlite/analyze — Update query planner statistics */
465
+ router.post('/sqlite/analyze', (_req, res) => {
466
+ try {
467
+ assertSqliteActive();
468
+ const sqlitePath = getSqlitePath();
469
+ const db = new node_sqlite_1.DatabaseSync(sqlitePath);
470
+ try {
471
+ db.exec('ANALYZE');
472
+ return res.json({ success: true, message: 'ANALYZE completed — query planner stats updated' });
473
+ }
474
+ finally {
475
+ db.close();
476
+ }
477
+ }
478
+ catch (err) {
479
+ const code = err.statusCode ?? 500;
480
+ return res.status(code).json({ success: false, error: err.message });
481
+ }
482
+ });
483
+ /** POST /sqlite/reindex — Rebuild all indexes */
484
+ router.post('/sqlite/reindex', (_req, res) => {
485
+ try {
486
+ assertSqliteActive();
487
+ const sqlitePath = getSqlitePath();
488
+ const db = new node_sqlite_1.DatabaseSync(sqlitePath);
489
+ try {
490
+ db.exec('REINDEX');
491
+ return res.json({ success: true, message: 'REINDEX completed — all indexes rebuilt' });
492
+ }
493
+ finally {
494
+ db.close();
495
+ }
496
+ }
497
+ catch (err) {
498
+ const code = err.statusCode ?? 500;
499
+ return res.status(code).json({ success: false, error: err.message });
500
+ }
501
+ });
502
+ // ── Grooming ──────────────────────────────────────────────────────────
503
+ /** POST /sqlite/groom — Clean up orphans, stale data, run optimizations */
504
+ router.post('/sqlite/groom', (_req, res) => {
505
+ try {
506
+ assertSqliteActive();
507
+ const sqlitePath = getSqlitePath();
508
+ const db = new node_sqlite_1.DatabaseSync(sqlitePath);
509
+ const results = [];
510
+ try {
511
+ // 1. Remove orphaned messages (messages referencing non-existent instructions)
512
+ try {
513
+ const orphanMsgs = db.prepare(`
514
+ DELETE FROM messages WHERE id IN (
515
+ SELECT m.id FROM messages m
516
+ LEFT JOIN instructions i ON m.recipient = i.id
517
+ WHERE m.recipient IS NOT NULL AND i.id IS NULL
518
+ )
519
+ `).run();
520
+ results.push(`Orphaned messages removed: ${orphanMsgs.changes}`);
521
+ }
522
+ catch {
523
+ results.push('Messages table: skipped (may not exist)');
524
+ }
525
+ // 2. Remove orphaned usage records
526
+ try {
527
+ const orphanUsage = db.prepare(`
528
+ DELETE FROM usage WHERE instruction_id NOT IN (SELECT id FROM instructions)
529
+ `).run();
530
+ results.push(`Orphaned usage records removed: ${orphanUsage.changes}`);
531
+ }
532
+ catch {
533
+ results.push('Usage table: skipped (may not exist)');
534
+ }
535
+ // 3. Remove deprecated instructions (status = 'deprecated' and older than 90 days)
536
+ try {
537
+ const deprecated = db.prepare(`
538
+ DELETE FROM instructions WHERE json_extract(data, '$.governanceStatus') = 'deprecated'
539
+ AND updated_at < datetime('now', '-90 days')
540
+ `).run();
541
+ results.push(`Deprecated instructions removed (>90 days): ${deprecated.changes}`);
542
+ }
543
+ catch {
544
+ results.push('Deprecated cleanup: skipped');
545
+ }
546
+ // 4. Optimize FTS5
547
+ try {
548
+ db.exec("INSERT INTO instructions_fts(instructions_fts) VALUES('optimize')");
549
+ results.push('FTS5 index optimized');
550
+ }
551
+ catch {
552
+ results.push('FTS5 optimize: skipped');
553
+ }
554
+ // 5. ANALYZE for query planner
555
+ db.exec('ANALYZE');
556
+ results.push('ANALYZE completed');
557
+ return res.json({ success: true, message: 'Grooming completed', results });
558
+ }
559
+ finally {
560
+ db.close();
561
+ }
562
+ }
563
+ catch (err) {
564
+ const code = err.statusCode ?? 500;
565
+ return res.status(code).json({ success: false, error: err.message });
566
+ }
567
+ });
568
+ return router;
569
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Status & Health Routes
3
+ * Routes: GET /status, GET /health, GET /system/health, GET /system/resources
4
+ */
5
+ import { Router } from 'express';
6
+ import { MetricsCollector } from '../MetricsCollector.js';
7
+ export declare function createStatusRoutes(metricsCollector: MetricsCollector): Router;