@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,113 @@
1
+ /* eslint-disable */
2
+ // Extracted from admin.html: Log Viewer helpers
3
+ (function(){
4
+ let logEventSource = null;
5
+ let logTailing = false;
6
+
7
+ async function loadLogs() {
8
+ try {
9
+ const lines = document.getElementById('log-lines').value || 100;
10
+ let logsArray = [];
11
+ let rawMode = false;
12
+ let response = await fetch(`/api/logs?lines=${lines}`);
13
+ if (response.ok) {
14
+ const ct = response.headers.get('content-type') || '';
15
+ if (ct.includes('application/json')) {
16
+ try {
17
+ const data = await response.json();
18
+ if (Array.isArray(data.logs)) {
19
+ logsArray = data.logs;
20
+ } else if (typeof data === 'object') {
21
+ logsArray = Object.values(data).filter(v=>typeof v === 'string');
22
+ }
23
+ } catch {
24
+ rawMode = true;
25
+ }
26
+ } else {
27
+ rawMode = true;
28
+ }
29
+ }
30
+ if (rawMode) {
31
+ response = await fetch(`/api/logs?lines=${lines}&raw=1`);
32
+ const txt = await response.text();
33
+ logsArray = txt.split(/\r?\n/);
34
+ }
35
+ const rendered = logsArray.join('\n');
36
+ const el = document.getElementById('log-content');
37
+ if (el) el.innerHTML = `<pre>${escapeHtml(rendered)}</pre>`;
38
+
39
+ if (logTailing) {
40
+ const logContent = document.getElementById('log-content');
41
+ if (logContent) logContent.scrollTop = logContent.scrollHeight;
42
+ }
43
+ } catch (error) {
44
+ console.error('Failed to load logs:', error);
45
+ const el = document.getElementById('log-content');
46
+ if (el) el.innerHTML = '<div class="error">Failed to load logs</div>';
47
+ }
48
+ }
49
+
50
+ function toggleLogTail() {
51
+ const button = document.getElementById('log-tail-btn');
52
+ if (logTailing) {
53
+ if (logEventSource) {
54
+ logEventSource.close();
55
+ logEventSource = null;
56
+ }
57
+ logTailing = false;
58
+ if (button) { button.textContent = '▶️ Start Tail'; button.className = 'action-btn'; }
59
+ } else {
60
+ logTailing = true;
61
+ if (button) { button.textContent = '⏹ Stop Tail'; button.className = 'action-btn warning'; }
62
+ logEventSource = new EventSource('/api/logs/stream');
63
+ logEventSource.onmessage = function(event) {
64
+ try {
65
+ const data = JSON.parse(event.data);
66
+ if (data.line) {
67
+ const logContent = document.getElementById('log-content');
68
+ const pre = logContent.querySelector('pre') || document.createElement('pre');
69
+ if (!logContent.querySelector('pre')) {
70
+ logContent.innerHTML = '';
71
+ logContent.appendChild(pre);
72
+ }
73
+ pre.textContent += data.line + '\n';
74
+ logContent.scrollTop = logContent.scrollHeight;
75
+ const lines = pre.textContent.split('\n');
76
+ const maxLines = 2000;
77
+ if (lines.length > maxLines) {
78
+ pre.textContent = lines.slice(-maxLines).join('\n');
79
+ }
80
+ }
81
+ } catch (error) {
82
+ console.error('Error processing log stream:', error);
83
+ }
84
+ };
85
+ logEventSource.onerror = function(error) {
86
+ console.error('Log stream error:', error);
87
+ setTimeout(() => {
88
+ if (logTailing) {
89
+ toggleLogTail();
90
+ setTimeout(() => toggleLogTail(), 1000);
91
+ }
92
+ }, 2000);
93
+ };
94
+ }
95
+ }
96
+
97
+ function clearLogViewer() {
98
+ const el = document.getElementById('log-content');
99
+ if (el) el.innerHTML = '<div class="info">Log viewer cleared</div>';
100
+ }
101
+
102
+ function escapeHtml(text) {
103
+ const div = document.createElement('div');
104
+ div.textContent = text;
105
+ return div.innerHTML;
106
+ }
107
+
108
+ // Expose functions for staged migration
109
+ window.loadLogs = loadLogs;
110
+ window.toggleLogTail = toggleLogTail;
111
+ window.clearLogViewer = clearLogViewer;
112
+ window.escapeHtml = escapeHtml;
113
+ })();
@@ -0,0 +1,354 @@
1
+ /* eslint-disable */
2
+ // Extracted from admin.html: Backup / Restore and maintenance helpers
3
+ (function(){
4
+ async function loadBackups() {
5
+ try {
6
+ const sel = document.getElementById('backup-select');
7
+ const meta = document.getElementById('backup-list-meta');
8
+ if (!sel) return;
9
+ sel.innerHTML = '<option value="">Loading...</option>';
10
+ const res = await fetch('/api/admin/maintenance/backups');
11
+ if (!res.ok) throw new Error('list failed');
12
+ const data = await res.json();
13
+ const backups = (data.backups || []).slice(0, 200);
14
+ if (!backups.length) {
15
+ sel.innerHTML = '<option value="">(no backups)</option>';
16
+ if (meta) meta.textContent = 'No backups available';
17
+ return;
18
+ }
19
+ sel.innerHTML = backups.map(b => {
20
+ const label = `${b.id} • ${b.instructionCount} files • ${b.schemaVersion || 'schema?'} • ${new Date(b.createdAt).toLocaleString()}`;
21
+ return `<option value="${b.id}">${label}</option>`;
22
+ }).join('');
23
+ if (meta) meta.textContent = `${backups.length} backup(s)`;
24
+ } catch (err) {
25
+ console.warn('loadBackups error', err);
26
+ const sel = document.getElementById('backup-select');
27
+ if (sel) sel.innerHTML = '<option value="">(error loading)</option>';
28
+ }
29
+ }
30
+
31
+ async function restoreSelectedBackup() {
32
+ try {
33
+ const sel = document.getElementById('backup-select');
34
+ const statusEl = document.getElementById('backup-restore-status');
35
+ if (!sel || !sel.value) { if (statusEl) statusEl.textContent = 'Select a backup first'; return; }
36
+ const choice = sel.value;
37
+ if (!confirm(`Restore backup ${choice}? Current instructions will be safety-backed up first.`)) return;
38
+ if (statusEl) statusEl.textContent = 'Restoring...';
39
+ const res = await fetch('/api/admin/maintenance/restore', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ backupId: choice }) });
40
+ const data = await res.json();
41
+ if (data.success) {
42
+ if (statusEl) statusEl.textContent = `Restored ${choice} (${data.restored || 0} files)`;
43
+ // Re-load stats & instructions to reflect changes
44
+ if (typeof loadOverviewData === 'function') loadOverviewData();
45
+ if (typeof currentSection !== 'undefined' && currentSection === 'instructions' && typeof loadInstructions === 'function') loadInstructions();
46
+ } else {
47
+ if (statusEl) statusEl.textContent = `Restore failed: ${data.error || data.message || 'unknown'}`;
48
+ }
49
+ } catch (err) {
50
+ const statusEl = document.getElementById('backup-restore-status');
51
+ if (statusEl) statusEl.textContent = 'Error restoring backup';
52
+ }
53
+ }
54
+
55
+ async function loadMaintenanceStatus() {
56
+ try {
57
+ const response = await fetch('/api/admin/maintenance');
58
+ const data = await response.json();
59
+
60
+ if (data.success) {
61
+ if (typeof displayMaintenanceStatus === 'function') displayMaintenanceStatus(data.maintenance);
62
+ } else {
63
+ if (typeof showError === 'function') showError('Failed to load maintenance status');
64
+ }
65
+ } catch (error) {
66
+ console.error('Error loading maintenance status:', error);
67
+ if (typeof showError === 'function') showError('Failed to load maintenance status');
68
+ }
69
+ }
70
+
71
+ function displayMaintenanceStatus(maintenance) {
72
+ let html = `
73
+ <div style="margin-top:12px; font-weight:600; font-size:13px;">index Normalization</div>
74
+ <div style="margin-top:6px; display:flex; flex-wrap:wrap; gap:6px; align-items:center;">
75
+ <button class="action-btn" id="normalize-dryrun-btn" style="padding:4px 10px; font-size:11px;">Dry Run Normalize</button>
76
+ <button class="action-btn warning" id="normalize-apply-btn" style="padding:4px 10px; font-size:11px;">Apply Normalize</button>
77
+ <label style="display:flex; align-items:center; gap:4px; font-size:11px; opacity:.8;"><input type="checkbox" id="normalize-force-canon"/> Force Canonical Hash</label>
78
+ <span id="normalize-status" style="font-size:11px; opacity:.7;"></span>
79
+ </div>
80
+ <div class="stat-row">
81
+ <span class="stat-label">Last Backup</span>
82
+ <span class="stat-value">${maintenance.lastBackup ? new Date(maintenance.lastBackup).toLocaleString() : 'Never'}</span>
83
+ </div>
84
+ <div style="margin-top:10px; font-weight:600; font-size:13px;">Backups</div>
85
+ <div style="display:flex; gap:6px; flex-wrap:wrap; align-items:center; margin-top:4px;">
86
+ <button class="action-btn" style="padding:4px 8px; font-size:11px;" onclick="selectLatestBackup()">Select Latest</button>
87
+ <button class="action-btn danger" style="padding:4px 8px; font-size:11px;" onclick="deleteSelectedBackup()">Delete Selected</button>
88
+ <button class="action-btn warning" style="padding:4px 8px; font-size:11px;" onclick="promptPruneBackups()">Prune…</button>
89
+ <input id="backup-search" type="text" placeholder="Filter (id / schema)" oninput="filterBackupRows()" style="flex:1; min-width:160px; padding:4px 6px; background:#1f2228; border:1px solid #2c3038; border-radius:4px; color:#d0d4d8; font-size:12px;" />
90
+ <span id="backup-filter-count" style="font-size:11px; opacity:.65;"></span>
91
+ </div>
92
+ <div id="backup-list-full" style="margin-top:6px; font-size:12px; line-height:1.25; max-height:260px; overflow:auto; border:1px solid #2c3038; border-radius:4px; padding:6px; background:#1f2228;">
93
+ Loading backups...
94
+ </div>
95
+ `;
96
+
97
+ const target = document.getElementById('maintenance-control');
98
+ if (target) target.innerHTML = html;
99
+
100
+ // Wire normalization buttons after HTML injection
101
+ setTimeout(() => {
102
+ const dryBtn = document.getElementById('normalize-dryrun-btn');
103
+ const applyBtn = document.getElementById('normalize-apply-btn');
104
+ const statusEl = document.getElementById('normalize-status');
105
+ const forceBox = document.getElementById('normalize-force-canon');
106
+ async function doNormalize(dryRun){
107
+ if(!dryBtn || !applyBtn) return;
108
+ dryBtn.disabled = true; applyBtn.disabled = true;
109
+ if(statusEl) statusEl.textContent = dryRun? 'Running dry run...' : 'Normalizing...';
110
+ try {
111
+ const res = await fetch('/api/admin/maintenance/normalize', { method:'POST', headers:{ 'Content-Type':'application/json' }, body: JSON.stringify({ dryRun, forceCanonical: !!(forceBox&&forceBox.checked) }) });
112
+ const data = await res.json();
113
+ if(data.success){
114
+ const s = data.summary || {};
115
+ const msg = `${dryRun? 'DryRun':'Applied'}: changed=${s.changed||0} hash=${s.fixedHash||0} ver=${s.fixedVersion||0} tier=${s.fixedTier||0} ts=${s.addedTimestamps||0}`;
116
+ if(statusEl) statusEl.textContent = msg;
117
+ if(!dryRun && typeof loadOverviewData==='function') loadOverviewData();
118
+ if(!dryRun && typeof currentSection !== 'undefined' && currentSection==='instructions' && typeof loadInstructions==='function') loadInstructions();
119
+ } else {
120
+ if(statusEl) statusEl.textContent = 'Normalize failed: ' + (data.error||'unknown');
121
+ }
122
+ } catch(e){ if(statusEl) statusEl.textContent = 'Normalize error'; }
123
+ finally { if(dryBtn) dryBtn.disabled=false; if(applyBtn) applyBtn.disabled=false; }
124
+ }
125
+ if(dryBtn) dryBtn.addEventListener('click', ()=> doNormalize(true));
126
+ if(applyBtn) applyBtn.addEventListener('click', ()=> { if(confirm('Apply normalization changes to disk?')) doNormalize(false); });
127
+ },0);
128
+
129
+ // Async load & render full backup list (separate from restore dropdown)
130
+ (async () => {
131
+ const container = document.getElementById('backup-list-full');
132
+ if(!container) return;
133
+ try {
134
+ const res = await fetch('/api/admin/maintenance/backups');
135
+ if(!res.ok) throw new Error('request failed');
136
+ const data = await res.json();
137
+ const backups = Array.isArray(data.backups) ? data.backups : [];
138
+ if(backups.length === 0){
139
+ container.innerHTML = '<div style="opacity:0.6;">(no backups)</div>';
140
+ return;
141
+ }
142
+ const fmtSize = (n) => {
143
+ if(!n) return '0 B';
144
+ const units = ['B','KB','MB','GB'];
145
+ let u=0, v=n;
146
+ while(v >= 1024 && u < units.length-1){ v/=1024; u++; }
147
+ return v.toFixed(v>=100||u===0?0:1)+' '+units[u];
148
+ };
149
+ let table = '<table id="backup-table" style="width:100%; border-collapse:collapse; font-size:11px;">';
150
+ table += '<thead><tr style="text-align:left; background:#1f2228;"><th style="padding:4px;">ID</th><th style="padding:4px;">Created</th><th style="padding:4px;">Files</th><th style="padding:4px;">Size</th><th style="padding:4px;">Schema</th></tr></thead><tbody>';
151
+ backups.forEach(b => {
152
+ const created = b.createdAt ? new Date(b.createdAt).toLocaleString() : '—';
153
+ table += `<tr data-backup-id="${b.id}" style="cursor:pointer; border-top:1px solid #2c3038;">
154
+ <td style="padding:4px; white-space:nowrap;">${b.id}</td>
155
+ <td style="padding:4px; white-space:nowrap;">${created}</td>
156
+ <td style="padding:4px;">${b.instructionCount ?? 0}</td>
157
+ <td style="padding:4px;">${fmtSize(b.sizeBytes||0)}</td>
158
+ <td style="padding:4px;">${b.schemaVersion || '—'}</td>
159
+ </tr>`;
160
+ });
161
+ table += '</tbody></table>';
162
+ table += '<div style="margin-top:4px; opacity:0.55;">Click a row to select it for restore. Use filter box to narrow results.</div>';
163
+ container.innerHTML = table;
164
+ container.querySelectorAll('tr[data-backup-id]').forEach(row => {
165
+ row.addEventListener('click', () => {
166
+ const id = row.getAttribute('data-backup-id');
167
+ const sel = document.getElementById('backup-select');
168
+ if(sel){ sel.value = id; }
169
+ container.querySelectorAll('tr[data-backup-id]').forEach(r => r.style.background='');
170
+ row.style.background = '#1f2228';
171
+ window.__lastSelectedBackupId = id;
172
+ });
173
+ });
174
+ window.__allBackupRows = backups.map(b => ({ id: b.id, schema: b.schemaVersion || '', created: b.createdAt, count: b.instructionCount }));
175
+ updateBackupFilterCount();
176
+ } catch(err){
177
+ container.innerHTML = '<div style="color:#f2495c;">Error loading backups</div>';
178
+ }
179
+ })();
180
+ }
181
+
182
+ function selectLatestBackup(){
183
+ const table = document.getElementById('backup-table');
184
+ if(!table) return;
185
+ const first = table.querySelector('tbody tr[data-backup-id]');
186
+ if(first){ first.click(); }
187
+ }
188
+
189
+ async function deleteSelectedBackup(){
190
+ const sel = document.getElementById('backup-select');
191
+ const id = (sel && sel.value) || window.__lastSelectedBackupId;
192
+ if(!id){ alert('Select a backup first'); return; }
193
+ if(!confirm(`Delete backup ${id}? This cannot be undone.`)) return;
194
+ try {
195
+ const res = await fetch(`/api/admin/maintenance/backup/${encodeURIComponent(id)}`, { method:'DELETE' });
196
+ const data = await res.json();
197
+ if(data.success){ if (typeof showSuccess === 'function') showSuccess(`Deleted ${id}`); loadMaintenanceStatus(); loadBackups(); }
198
+ else { if (typeof showError === 'function') showError(data.error || 'Delete failed'); }
199
+ } catch(e){ if (typeof showError === 'function') showError('Delete failed'); }
200
+ }
201
+
202
+ function promptPruneBackups(){
203
+ const retainStr = prompt('Retain how many newest backups? (0 = delete all)', '10');
204
+ if(retainStr == null) return;
205
+ const retain = parseInt(retainStr,10);
206
+ if(isNaN(retain) || retain < 0){ alert('Enter a non-negative number'); return; }
207
+ pruneBackups(retain);
208
+ }
209
+
210
+ async function pruneBackups(retain){
211
+ try {
212
+ const res = await fetch('/api/admin/maintenance/backups/prune', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ retain })});
213
+ const data = await res.json();
214
+ if(data.success){ if (typeof showSuccess === 'function') showSuccess(data.message || 'Pruned'); loadMaintenanceStatus(); loadBackups(); }
215
+ else { if (typeof showError === 'function') showError(data.error || 'Prune failed'); }
216
+ } catch(e){ if (typeof showError === 'function') showError('Prune failed'); }
217
+ }
218
+
219
+ function filterBackupRows(){
220
+ const q = (document.getElementById('backup-search')||{value:''}).value.trim().toLowerCase();
221
+ const table = document.getElementById('backup-table');
222
+ if(!table){ return; }
223
+ let visible = 0, total = 0;
224
+ table.querySelectorAll('tbody tr[data-backup-id]').forEach(tr => {
225
+ total++;
226
+ const id = tr.getAttribute('data-backup-id') || '';
227
+ const schema = (tr.cells[4]?.textContent||'');
228
+ const match = !q || id.toLowerCase().includes(q) || schema.toLowerCase().includes(q);
229
+ tr.style.display = match ? '' : 'none';
230
+ if(match) visible++;
231
+ });
232
+ updateBackupFilterCount(visible, total);
233
+ }
234
+
235
+ function updateBackupFilterCount(visible, total){
236
+ const el = document.getElementById('backup-filter-count');
237
+ if(!el) return;
238
+ if(visible == null || total == null){
239
+ const table = document.getElementById('backup-table');
240
+ if(!table){ el.textContent=''; return; }
241
+ const rows = table.querySelectorAll('tbody tr[data-backup-id]');
242
+ total = rows.length; visible = Array.from(rows).filter(r=>r.style.display!=='none').length;
243
+ }
244
+ el.textContent = `${visible}/${total}`;
245
+ }
246
+
247
+ async function toggleMaintenanceMode(enable) {
248
+ try {
249
+ const response = await fetch('/api/admin/maintenance/mode', {
250
+ method: 'POST',
251
+ headers: { 'Content-Type': 'application/json' },
252
+ body: JSON.stringify({
253
+ enabled: enable,
254
+ message: enable ? 'Admin panel maintenance' : undefined
255
+ })
256
+ });
257
+
258
+ const data = await response.json();
259
+ if (data.success) {
260
+ if (typeof showSuccess === 'function') showSuccess(data.message);
261
+ loadMaintenanceStatus();
262
+ } else {
263
+ if (typeof showError === 'function') showError('Failed to toggle maintenance mode');
264
+ }
265
+ } catch (error) {
266
+ console.error('Error toggling maintenance mode:', error);
267
+ if (typeof showError === 'function') showError('Failed to toggle maintenance mode');
268
+ }
269
+ }
270
+
271
+ async function exportBackupToFile(){
272
+ const sel = document.getElementById('backup-select');
273
+ const id = (sel && sel.value) || window.__lastSelectedBackupId;
274
+ if(!id){ alert('Select a backup first'); return; }
275
+ try {
276
+ const res = await fetch('/api/admin/maintenance/backup/' + encodeURIComponent(id) + '/export');
277
+ if(!res.ok){ const d = await res.json().catch(()=>({})); alert('Export failed: '+(d.error||res.statusText)); return; }
278
+ const blob = await res.blob();
279
+ const a = document.createElement('a');
280
+ a.href = URL.createObjectURL(blob);
281
+ a.download = id + '.json';
282
+ document.body.appendChild(a); a.click(); a.remove();
283
+ URL.revokeObjectURL(a.href);
284
+ if(typeof showSuccess === 'function') showSuccess('Exported ' + id);
285
+ } catch(e){ alert('Export error: '+(e.message||e)); }
286
+ }
287
+
288
+ function importBackupFromFile(){
289
+ const input = document.getElementById('backup-file-input');
290
+ if(input){ input.value = ''; input.click(); }
291
+ }
292
+
293
+ async function handleBackupFileSelected(ev){
294
+ const file = ev.target && ev.target.files && ev.target.files[0];
295
+ if(!file) return;
296
+ if(!file.name.toLowerCase().endsWith('.json')){ alert('Please select a .json file'); return; }
297
+ try {
298
+ const text = await file.text();
299
+ const bundle = JSON.parse(text);
300
+ if(!bundle.files || typeof bundle.files !== 'object'){ alert('Invalid backup file: must contain a "files" object'); return; }
301
+ if(!confirm('Import backup from ' + file.name + '? (' + Object.keys(bundle.files).length + ' files)')) return;
302
+ const res = await fetch('/api/admin/maintenance/backup/import', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(bundle) });
303
+ const data = await res.json();
304
+ if(data.success){
305
+ if(typeof showSuccess === 'function') showSuccess(data.message || 'Imported');
306
+ loadMaintenanceStatus(); loadBackups();
307
+ } else {
308
+ alert('Import failed: '+(data.error||'unknown'));
309
+ }
310
+ } catch(e){ alert('Import error: '+(e.message||e)); }
311
+ }
312
+
313
+ // Signal Groom: apply usage signals to instruction priority/requirement
314
+ async function runSignalGroom(dryRun) {
315
+ const statusEl = document.getElementById('signal-groom-status');
316
+ if (statusEl) statusEl.innerHTML = '<span style="opacity:.7;">Running groom' + (dryRun ? ' (dry run)' : '') + '...</span>';
317
+ try {
318
+ const res = await fetch('/api/tools/index_groom', {
319
+ method: 'POST',
320
+ headers: { 'Content-Type': 'application/json' },
321
+ body: JSON.stringify({ mode: { dryRun: !!dryRun } })
322
+ });
323
+ const data = await res.json();
324
+ if (!res.ok) throw new Error(data.error || data.message || 'Groom failed');
325
+ const result = data.result || data;
326
+ const parts = [];
327
+ if (result.signalApplied != null) parts.push('Signals applied: ' + result.signalApplied);
328
+ if (result.repairedHashes) parts.push('Hashes repaired: ' + result.repairedHashes);
329
+ if (result.normalizedCategories) parts.push('Categories normalized: ' + result.normalizedCategories);
330
+ if (result.filesRewritten) parts.push('Files rewritten: ' + result.filesRewritten);
331
+ if (result.dryRun) parts.push('(dry run - no changes written)');
332
+ if (statusEl) statusEl.innerHTML = '<span style="color:#73bf69;">' + (parts.join(' | ') || 'Done') + '</span>';
333
+ } catch (e) {
334
+ if (statusEl) statusEl.innerHTML = '<span style="color:#f2495c;">Error: ' + (e.message || e) + '</span>';
335
+ }
336
+ }
337
+
338
+ // Expose to global for staged migration
339
+ window.loadBackups = loadBackups;
340
+ window.restoreSelectedBackup = restoreSelectedBackup;
341
+ window.loadMaintenanceStatus = loadMaintenanceStatus;
342
+ window.displayMaintenanceStatus = displayMaintenanceStatus;
343
+ window.selectLatestBackup = selectLatestBackup;
344
+ window.deleteSelectedBackup = deleteSelectedBackup;
345
+ window.promptPruneBackups = promptPruneBackups;
346
+ window.pruneBackups = pruneBackups;
347
+ window.filterBackupRows = filterBackupRows;
348
+ window.updateBackupFilterCount = updateBackupFilterCount;
349
+ window.toggleMaintenanceMode = toggleMaintenanceMode;
350
+ window.exportBackupToFile = exportBackupToFile;
351
+ window.importBackupFromFile = importBackupFromFile;
352
+ window.handleBackupFileSelected = handleBackupFileSelected;
353
+ window.runSignalGroom = runSignalGroom;
354
+ })();