@jagilber-org/index-server 1.22.0

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 (372) hide show
  1. package/CHANGELOG.md +1354 -0
  2. package/CODE_OF_CONDUCT.md +49 -0
  3. package/CONTRIBUTING.md +99 -0
  4. package/LICENSE +21 -0
  5. package/README.md +228 -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 +46 -0
  10. package/dist/config/dashboardConfig.js +67 -0
  11. package/dist/config/defaultValues.d.ts +63 -0
  12. package/dist/config/defaultValues.js +72 -0
  13. package/dist/config/dirConstants.d.ts +18 -0
  14. package/dist/config/dirConstants.js +29 -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 +151 -0
  18. package/dist/config/runtimeConfig.js +380 -0
  19. package/dist/config/serverConfig.d.ts +90 -0
  20. package/dist/config/serverConfig.js +167 -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 +2175 -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 +1587 -0
  29. package/dist/dashboard/client/js/admin.auth.js +179 -0
  30. package/dist/dashboard/client/js/admin.boot.js +359 -0
  31. package/dist/dashboard/client/js/admin.config.js +196 -0
  32. package/dist/dashboard/client/js/admin.embeddings.js +426 -0
  33. package/dist/dashboard/client/js/admin.graph.js +615 -0
  34. package/dist/dashboard/client/js/admin.instances.js +120 -0
  35. package/dist/dashboard/client/js/admin.instructions.js +579 -0
  36. package/dist/dashboard/client/js/admin.logs.js +113 -0
  37. package/dist/dashboard/client/js/admin.maintenance.js +393 -0
  38. package/dist/dashboard/client/js/admin.messaging.js +636 -0
  39. package/dist/dashboard/client/js/admin.monitor.js +184 -0
  40. package/dist/dashboard/client/js/admin.overview.js +221 -0
  41. package/dist/dashboard/client/js/admin.performance.js +61 -0
  42. package/dist/dashboard/client/js/admin.sessions.js +292 -0
  43. package/dist/dashboard/client/js/admin.sqlite.js +373 -0
  44. package/dist/dashboard/client/js/admin.utils.js +49 -0
  45. package/dist/dashboard/client/js/chart.umd.js +14 -0
  46. package/dist/dashboard/client/js/elk.bundled.js +6696 -0
  47. package/dist/dashboard/client/js/marked.umd.js +74 -0
  48. package/dist/dashboard/client/js/mermaid.min.js +3022 -0
  49. package/dist/dashboard/client/mermaid-layout-elk.esm.min.mjs +1 -0
  50. package/dist/dashboard/export/DataExporter.d.ts +169 -0
  51. package/dist/dashboard/export/DataExporter.js +737 -0
  52. package/dist/dashboard/export/exporters/csvExporter.d.ts +11 -0
  53. package/dist/dashboard/export/exporters/csvExporter.js +47 -0
  54. package/dist/dashboard/export/exporters/exportTypes.d.ts +89 -0
  55. package/dist/dashboard/export/exporters/exportTypes.js +5 -0
  56. package/dist/dashboard/export/exporters/jsonExporter.d.ts +7 -0
  57. package/dist/dashboard/export/exporters/jsonExporter.js +23 -0
  58. package/dist/dashboard/export/exporters/xmlExporter.d.ts +17 -0
  59. package/dist/dashboard/export/exporters/xmlExporter.js +176 -0
  60. package/dist/dashboard/integration/APIIntegration.d.ts +41 -0
  61. package/dist/dashboard/integration/APIIntegration.js +95 -0
  62. package/dist/dashboard/security/SecurityMonitor.d.ts +167 -0
  63. package/dist/dashboard/security/SecurityMonitor.js +560 -0
  64. package/dist/dashboard/server/AdminPanel.d.ts +195 -0
  65. package/dist/dashboard/server/AdminPanel.js +861 -0
  66. package/dist/dashboard/server/AdminPanelConfig.d.ts +42 -0
  67. package/dist/dashboard/server/AdminPanelConfig.js +80 -0
  68. package/dist/dashboard/server/AdminPanelState.d.ts +47 -0
  69. package/dist/dashboard/server/AdminPanelState.js +215 -0
  70. package/dist/dashboard/server/ApiRoutes.d.ts +17 -0
  71. package/dist/dashboard/server/ApiRoutes.js +184 -0
  72. package/dist/dashboard/server/DashboardServer.d.ts +49 -0
  73. package/dist/dashboard/server/DashboardServer.js +160 -0
  74. package/dist/dashboard/server/FileMetricsStorage.d.ts +49 -0
  75. package/dist/dashboard/server/FileMetricsStorage.js +196 -0
  76. package/dist/dashboard/server/HttpTransport.d.ts +23 -0
  77. package/dist/dashboard/server/HttpTransport.js +116 -0
  78. package/dist/dashboard/server/InstanceManager.d.ts +53 -0
  79. package/dist/dashboard/server/InstanceManager.js +295 -0
  80. package/dist/dashboard/server/KnowledgeStore.d.ts +35 -0
  81. package/dist/dashboard/server/KnowledgeStore.js +105 -0
  82. package/dist/dashboard/server/LeaderElection.d.ts +81 -0
  83. package/dist/dashboard/server/LeaderElection.js +268 -0
  84. package/dist/dashboard/server/MetricsCollector.d.ts +200 -0
  85. package/dist/dashboard/server/MetricsCollector.js +810 -0
  86. package/dist/dashboard/server/SessionPersistenceManager.d.ts +88 -0
  87. package/dist/dashboard/server/SessionPersistenceManager.js +458 -0
  88. package/dist/dashboard/server/ThinClient.d.ts +64 -0
  89. package/dist/dashboard/server/ThinClient.js +237 -0
  90. package/dist/dashboard/server/WebSocketManager.d.ts +161 -0
  91. package/dist/dashboard/server/WebSocketManager.js +448 -0
  92. package/dist/dashboard/server/httpLifecycle.d.ts +17 -0
  93. package/dist/dashboard/server/httpLifecycle.js +35 -0
  94. package/dist/dashboard/server/legacyDashboardHtml.d.ts +9 -0
  95. package/dist/dashboard/server/legacyDashboardHtml.js +618 -0
  96. package/dist/dashboard/server/legacyDashboardStyles.d.ts +5 -0
  97. package/dist/dashboard/server/legacyDashboardStyles.js +490 -0
  98. package/dist/dashboard/server/metricsAggregation.d.ts +252 -0
  99. package/dist/dashboard/server/metricsAggregation.js +210 -0
  100. package/dist/dashboard/server/metricsSerializer.d.ts +25 -0
  101. package/dist/dashboard/server/metricsSerializer.js +195 -0
  102. package/dist/dashboard/server/middleware/ensureLoadedMiddleware.d.ts +25 -0
  103. package/dist/dashboard/server/middleware/ensureLoadedMiddleware.js +24 -0
  104. package/dist/dashboard/server/routes/admin.routes.d.ts +16 -0
  105. package/dist/dashboard/server/routes/admin.routes.js +574 -0
  106. package/dist/dashboard/server/routes/adminAuth.d.ts +4 -0
  107. package/dist/dashboard/server/routes/adminAuth.js +46 -0
  108. package/dist/dashboard/server/routes/alerts.routes.d.ts +7 -0
  109. package/dist/dashboard/server/routes/alerts.routes.js +91 -0
  110. package/dist/dashboard/server/routes/api.feedback.routes.d.ts +73 -0
  111. package/dist/dashboard/server/routes/api.feedback.routes.js +171 -0
  112. package/dist/dashboard/server/routes/api.instructions.routes.d.ts +101 -0
  113. package/dist/dashboard/server/routes/api.instructions.routes.js +213 -0
  114. package/dist/dashboard/server/routes/api.usage.routes.d.ts +57 -0
  115. package/dist/dashboard/server/routes/api.usage.routes.js +374 -0
  116. package/dist/dashboard/server/routes/embeddings.routes.d.ts +6 -0
  117. package/dist/dashboard/server/routes/embeddings.routes.js +246 -0
  118. package/dist/dashboard/server/routes/graph.routes.d.ts +6 -0
  119. package/dist/dashboard/server/routes/graph.routes.js +279 -0
  120. package/dist/dashboard/server/routes/index.d.ts +39 -0
  121. package/dist/dashboard/server/routes/index.js +229 -0
  122. package/dist/dashboard/server/routes/instances.routes.d.ts +6 -0
  123. package/dist/dashboard/server/routes/instances.routes.js +35 -0
  124. package/dist/dashboard/server/routes/instructions.routes.d.ts +8 -0
  125. package/dist/dashboard/server/routes/instructions.routes.js +268 -0
  126. package/dist/dashboard/server/routes/knowledge.routes.d.ts +6 -0
  127. package/dist/dashboard/server/routes/knowledge.routes.js +80 -0
  128. package/dist/dashboard/server/routes/logs.routes.d.ts +6 -0
  129. package/dist/dashboard/server/routes/logs.routes.js +166 -0
  130. package/dist/dashboard/server/routes/messaging.routes.d.ts +16 -0
  131. package/dist/dashboard/server/routes/messaging.routes.js +307 -0
  132. package/dist/dashboard/server/routes/metrics.routes.d.ts +10 -0
  133. package/dist/dashboard/server/routes/metrics.routes.js +335 -0
  134. package/dist/dashboard/server/routes/scripts.routes.d.ts +9 -0
  135. package/dist/dashboard/server/routes/scripts.routes.js +84 -0
  136. package/dist/dashboard/server/routes/sqlite.routes.d.ts +9 -0
  137. package/dist/dashboard/server/routes/sqlite.routes.js +570 -0
  138. package/dist/dashboard/server/routes/status.routes.d.ts +7 -0
  139. package/dist/dashboard/server/routes/status.routes.js +179 -0
  140. package/dist/dashboard/server/routes/synthetic.routes.d.ts +7 -0
  141. package/dist/dashboard/server/routes/synthetic.routes.js +197 -0
  142. package/dist/dashboard/server/routes/tools.routes.d.ts +6 -0
  143. package/dist/dashboard/server/routes/tools.routes.js +47 -0
  144. package/dist/dashboard/server/routes/usage.routes.d.ts +6 -0
  145. package/dist/dashboard/server/routes/usage.routes.js +26 -0
  146. package/dist/dashboard/server/wsInit.d.ts +16 -0
  147. package/dist/dashboard/server/wsInit.js +35 -0
  148. package/dist/externalClientLib.d.ts +1 -0
  149. package/dist/externalClientLib.js +2 -0
  150. package/dist/minimal/index.d.ts +1 -0
  151. package/dist/minimal/index.js +140 -0
  152. package/dist/models/SessionPersistence.d.ts +115 -0
  153. package/dist/models/SessionPersistence.js +66 -0
  154. package/dist/models/instruction.d.ts +46 -0
  155. package/dist/models/instruction.js +2 -0
  156. package/dist/perf/benchmark.d.ts +1 -0
  157. package/dist/perf/benchmark.js +50 -0
  158. package/dist/portableClientWrapper.d.ts +1 -0
  159. package/dist/portableClientWrapper.js +2 -0
  160. package/dist/schemas/index.d.ts +132 -0
  161. package/dist/schemas/index.js +372 -0
  162. package/dist/scripts/runPerformanceBaseline.d.ts +1 -0
  163. package/dist/scripts/runPerformanceBaseline.js +17 -0
  164. package/dist/server/backgroundServicesStartup.d.ts +3 -0
  165. package/dist/server/backgroundServicesStartup.js +51 -0
  166. package/dist/server/handshakeManager.d.ts +25 -0
  167. package/dist/server/handshakeManager.js +470 -0
  168. package/dist/server/index-server.d.ts +38 -0
  169. package/dist/server/index-server.js +620 -0
  170. package/dist/server/multiInstanceStartup.d.ts +6 -0
  171. package/dist/server/multiInstanceStartup.js +132 -0
  172. package/dist/server/registry.d.ts +44 -0
  173. package/dist/server/registry.js +236 -0
  174. package/dist/server/sdkServer.d.ts +8 -0
  175. package/dist/server/sdkServer.js +299 -0
  176. package/dist/server/shutdownGuard.d.ts +41 -0
  177. package/dist/server/shutdownGuard.js +52 -0
  178. package/dist/server/startupDiagnostics.d.ts +2 -0
  179. package/dist/server/startupDiagnostics.js +33 -0
  180. package/dist/server/thin-client.d.ts +22 -0
  181. package/dist/server/thin-client.js +111 -0
  182. package/dist/server/transport.d.ts +41 -0
  183. package/dist/server/transport.js +312 -0
  184. package/dist/server/transportFactory.d.ts +21 -0
  185. package/dist/server/transportFactory.js +429 -0
  186. package/dist/services/atomicFs.d.ts +22 -0
  187. package/dist/services/atomicFs.js +103 -0
  188. package/dist/services/auditLog.d.ts +38 -0
  189. package/dist/services/auditLog.js +142 -0
  190. package/dist/services/autoBackup.d.ts +14 -0
  191. package/dist/services/autoBackup.js +171 -0
  192. package/dist/services/autoSplit.d.ts +32 -0
  193. package/dist/services/autoSplit.js +113 -0
  194. package/dist/services/backupZip.d.ts +25 -0
  195. package/dist/services/backupZip.js +112 -0
  196. package/dist/services/bootstrapGating.d.ts +123 -0
  197. package/dist/services/bootstrapGating.js +221 -0
  198. package/dist/services/canonical.d.ts +23 -0
  199. package/dist/services/canonical.js +65 -0
  200. package/dist/services/categoryRules.d.ts +7 -0
  201. package/dist/services/categoryRules.js +37 -0
  202. package/dist/services/classificationService.d.ts +42 -0
  203. package/dist/services/classificationService.js +168 -0
  204. package/dist/services/embeddingService.d.ts +62 -0
  205. package/dist/services/embeddingService.js +264 -0
  206. package/dist/services/errors.d.ts +22 -0
  207. package/dist/services/errors.js +31 -0
  208. package/dist/services/featureFlags.d.ts +25 -0
  209. package/dist/services/featureFlags.js +89 -0
  210. package/dist/services/features.d.ts +13 -0
  211. package/dist/services/features.js +35 -0
  212. package/dist/services/handlers/instructions.add.d.ts +1 -0
  213. package/dist/services/handlers/instructions.add.js +510 -0
  214. package/dist/services/handlers/instructions.groom.d.ts +1 -0
  215. package/dist/services/handlers/instructions.groom.js +575 -0
  216. package/dist/services/handlers/instructions.import.d.ts +1 -0
  217. package/dist/services/handlers/instructions.import.js +205 -0
  218. package/dist/services/handlers/instructions.patch.d.ts +1 -0
  219. package/dist/services/handlers/instructions.patch.js +121 -0
  220. package/dist/services/handlers/instructions.query.d.ts +159 -0
  221. package/dist/services/handlers/instructions.query.js +469 -0
  222. package/dist/services/handlers/instructions.reload.d.ts +1 -0
  223. package/dist/services/handlers/instructions.reload.js +13 -0
  224. package/dist/services/handlers/instructions.remove.d.ts +1 -0
  225. package/dist/services/handlers/instructions.remove.js +122 -0
  226. package/dist/services/handlers/instructions.shared.d.ts +32 -0
  227. package/dist/services/handlers/instructions.shared.js +91 -0
  228. package/dist/services/handlers.activation.d.ts +1 -0
  229. package/dist/services/handlers.activation.js +203 -0
  230. package/dist/services/handlers.bootstrap.d.ts +1 -0
  231. package/dist/services/handlers.bootstrap.js +38 -0
  232. package/dist/services/handlers.dashboardConfig.d.ts +34 -0
  233. package/dist/services/handlers.dashboardConfig.js +110 -0
  234. package/dist/services/handlers.diagnostics.d.ts +1 -0
  235. package/dist/services/handlers.diagnostics.js +64 -0
  236. package/dist/services/handlers.feedback.d.ts +15 -0
  237. package/dist/services/handlers.feedback.js +389 -0
  238. package/dist/services/handlers.gates.d.ts +1 -0
  239. package/dist/services/handlers.gates.js +47 -0
  240. package/dist/services/handlers.graph.d.ts +53 -0
  241. package/dist/services/handlers.graph.js +231 -0
  242. package/dist/services/handlers.help.d.ts +1 -0
  243. package/dist/services/handlers.help.js +119 -0
  244. package/dist/services/handlers.instructionSchema.d.ts +1 -0
  245. package/dist/services/handlers.instructionSchema.js +227 -0
  246. package/dist/services/handlers.instructions.d.ts +8 -0
  247. package/dist/services/handlers.instructions.js +14 -0
  248. package/dist/services/handlers.instructionsDiagnostics.d.ts +1 -0
  249. package/dist/services/handlers.instructionsDiagnostics.js +14 -0
  250. package/dist/services/handlers.integrity.d.ts +1 -0
  251. package/dist/services/handlers.integrity.js +35 -0
  252. package/dist/services/handlers.manifest.d.ts +1 -0
  253. package/dist/services/handlers.manifest.js +24 -0
  254. package/dist/services/handlers.messaging.d.ts +12 -0
  255. package/dist/services/handlers.messaging.js +203 -0
  256. package/dist/services/handlers.metrics.d.ts +1 -0
  257. package/dist/services/handlers.metrics.js +43 -0
  258. package/dist/services/handlers.promote.d.ts +1 -0
  259. package/dist/services/handlers.promote.js +326 -0
  260. package/dist/services/handlers.prompt.d.ts +1 -0
  261. package/dist/services/handlers.prompt.js +7 -0
  262. package/dist/services/handlers.search.d.ts +69 -0
  263. package/dist/services/handlers.search.js +669 -0
  264. package/dist/services/handlers.testPrimitive.d.ts +1 -0
  265. package/dist/services/handlers.testPrimitive.js +5 -0
  266. package/dist/services/handlers.trace.d.ts +1 -0
  267. package/dist/services/handlers.trace.js +35 -0
  268. package/dist/services/handlers.usage.d.ts +1 -0
  269. package/dist/services/handlers.usage.js +11 -0
  270. package/dist/services/hotScore.d.ts +137 -0
  271. package/dist/services/hotScore.js +244 -0
  272. package/dist/services/indexContext.d.ts +117 -0
  273. package/dist/services/indexContext.js +989 -0
  274. package/dist/services/indexLoader.d.ts +44 -0
  275. package/dist/services/indexLoader.js +920 -0
  276. package/dist/services/indexRepository.d.ts +32 -0
  277. package/dist/services/indexRepository.js +71 -0
  278. package/dist/services/indexingService.d.ts +1 -0
  279. package/dist/services/indexingService.js +2 -0
  280. package/dist/services/instructions.dispatcher.d.ts +1 -0
  281. package/dist/services/instructions.dispatcher.js +231 -0
  282. package/dist/services/logPrefix.d.ts +1 -0
  283. package/dist/services/logPrefix.js +30 -0
  284. package/dist/services/logger.d.ts +52 -0
  285. package/dist/services/logger.js +268 -0
  286. package/dist/services/manifestManager.d.ts +82 -0
  287. package/dist/services/manifestManager.js +200 -0
  288. package/dist/services/messaging/agentMailbox.d.ts +60 -0
  289. package/dist/services/messaging/agentMailbox.js +353 -0
  290. package/dist/services/messaging/messagingPersistence.d.ts +20 -0
  291. package/dist/services/messaging/messagingPersistence.js +111 -0
  292. package/dist/services/messaging/messagingTypes.d.ts +150 -0
  293. package/dist/services/messaging/messagingTypes.js +66 -0
  294. package/dist/services/ownershipService.d.ts +1 -0
  295. package/dist/services/ownershipService.js +36 -0
  296. package/dist/services/performanceBaseline.d.ts +19 -0
  297. package/dist/services/performanceBaseline.js +210 -0
  298. package/dist/services/preflight.d.ts +12 -0
  299. package/dist/services/preflight.js +79 -0
  300. package/dist/services/promptReviewService.d.ts +44 -0
  301. package/dist/services/promptReviewService.js +101 -0
  302. package/dist/services/responseEnvelope.d.ts +6 -0
  303. package/dist/services/responseEnvelope.js +25 -0
  304. package/dist/services/seedBootstrap.d.ts +34 -0
  305. package/dist/services/seedBootstrap.js +259 -0
  306. package/dist/services/storage/factory.d.ts +17 -0
  307. package/dist/services/storage/factory.js +35 -0
  308. package/dist/services/storage/hashUtils.d.ts +11 -0
  309. package/dist/services/storage/hashUtils.js +35 -0
  310. package/dist/services/storage/index.d.ts +12 -0
  311. package/dist/services/storage/index.js +18 -0
  312. package/dist/services/storage/jsonFileStore.d.ts +32 -0
  313. package/dist/services/storage/jsonFileStore.js +241 -0
  314. package/dist/services/storage/migrationEngine.d.ts +35 -0
  315. package/dist/services/storage/migrationEngine.js +93 -0
  316. package/dist/services/storage/sqliteMessageStore.d.ts +53 -0
  317. package/dist/services/storage/sqliteMessageStore.js +146 -0
  318. package/dist/services/storage/sqliteSchema.d.ts +12 -0
  319. package/dist/services/storage/sqliteSchema.js +123 -0
  320. package/dist/services/storage/sqliteStore.d.ts +42 -0
  321. package/dist/services/storage/sqliteStore.js +361 -0
  322. package/dist/services/storage/sqliteUsageStore.d.ts +35 -0
  323. package/dist/services/storage/sqliteUsageStore.js +94 -0
  324. package/dist/services/storage/types.d.ts +171 -0
  325. package/dist/services/storage/types.js +12 -0
  326. package/dist/services/toolHandlers.d.ts +23 -0
  327. package/dist/services/toolHandlers.js +50 -0
  328. package/dist/services/toolRegistry.d.ts +20 -0
  329. package/dist/services/toolRegistry.js +490 -0
  330. package/dist/services/toolRegistry.zod.d.ts +10 -0
  331. package/dist/services/toolRegistry.zod.js +325 -0
  332. package/dist/services/tracing.d.ts +26 -0
  333. package/dist/services/tracing.js +260 -0
  334. package/dist/services/usageBuckets.d.ts +161 -0
  335. package/dist/services/usageBuckets.js +364 -0
  336. package/dist/services/validationService.d.ts +38 -0
  337. package/dist/services/validationService.js +125 -0
  338. package/dist/utils/BufferRing.d.ts +203 -0
  339. package/dist/utils/BufferRing.js +551 -0
  340. package/dist/utils/BufferRingExamples.d.ts +55 -0
  341. package/dist/utils/BufferRingExamples.js +188 -0
  342. package/dist/utils/envUtils.d.ts +42 -0
  343. package/dist/utils/envUtils.js +80 -0
  344. package/dist/utils/memoryMonitor.d.ts +83 -0
  345. package/dist/utils/memoryMonitor.js +275 -0
  346. package/dist/versioning/schemaVersion.d.ts +6 -0
  347. package/dist/versioning/schemaVersion.js +94 -0
  348. package/package.json +139 -0
  349. package/schemas/README.md +13 -0
  350. package/schemas/feedback-entry.schema.json +27 -0
  351. package/schemas/graph-export-v2.schema.json +60 -0
  352. package/schemas/index-server.code-schema.json +40670 -0
  353. package/schemas/instruction.schema.json +262 -0
  354. package/schemas/json-schema/SessionPersistence-persisted-admin-session.schema.json +54 -0
  355. package/schemas/json-schema/SessionPersistence-persisted-session-history-entry.schema.json +51 -0
  356. package/schemas/json-schema/SessionPersistence-persisted-web-socket-connection.schema.json +54 -0
  357. package/schemas/json-schema/SessionPersistence-session-persistence-config.schema.json +110 -0
  358. package/schemas/json-schema/SessionPersistence-session-persistence-data.schema.json +229 -0
  359. package/schemas/json-schema/SessionPersistence-session-persistence-manifest.schema.json +109 -0
  360. package/schemas/json-schema/SessionPersistence-session-persistence-metadata.schema.json +55 -0
  361. package/schemas/json-schema/instruction-audience-scope.schema.json +14 -0
  362. package/schemas/json-schema/instruction-content-type.schema.json +17 -0
  363. package/schemas/json-schema/instruction-instruction-entry.schema.json +210 -0
  364. package/schemas/json-schema/instruction-requirement-level.schema.json +16 -0
  365. package/schemas/manifest.json +78 -0
  366. package/schemas/manifest.schema.json +33 -0
  367. package/schemas/usage-batch.schema.json +16 -0
  368. package/schemas/usage-buckets.schema.json +30 -0
  369. package/schemas/usage-event.schema.json +17 -0
  370. package/scripts/copy-dashboard-assets.mjs +170 -0
  371. package/scripts/dist/README.md +15 -0
  372. package/scripts/setup-hooks.cjs +28 -0
@@ -0,0 +1,615 @@
1
+ /* eslint-disable */
2
+ // Extracted graph/mermaid logic from admin.html
3
+ (function(){
4
+ // State
5
+ window.graphOriginalSource = '';
6
+ let graphEditing = false;
7
+
8
+ let __graphReloadInFlight = false;
9
+ let __graphReloadAttempt = 0;
10
+ let __graphReloadWatchdog = null;
11
+ function setGraphMetaProgress(stage, extra){
12
+ try {
13
+ const meta = document.getElementById('graph-meta2') || document.getElementById('graph-meta');
14
+ if(meta){
15
+ const ts = Date.now()%100000;
16
+ const base = meta.textContent || '';
17
+ const marker = `[stage:${stage}${extra?';'+extra:''};t=${ts}]`;
18
+ if(!/\[stage:/.test(base)) meta.textContent = base + ' ' + marker; else meta.textContent = base.replace(/\[stage:[^\]]+\]/, marker);
19
+ }
20
+ } catch{}
21
+ }
22
+
23
+ function renderGraphTextMessage(host, message){
24
+ if(!host) return;
25
+ const box = document.createElement('div');
26
+ box.style.color = '#f2495c';
27
+ box.style.fontFamily = 'monospace';
28
+ box.style.whiteSpace = 'pre';
29
+ box.textContent = message;
30
+ host.replaceChildren(box);
31
+ }
32
+
33
+ function renderGraphSvg(host, svgMarkup){
34
+ if(!host) return;
35
+ const parsed = new DOMParser().parseFromString(String(svgMarkup || ''), 'image/svg+xml');
36
+ if(parsed.querySelector('parsererror') || parsed.documentElement.tagName.toLowerCase() !== 'svg'){
37
+ renderGraphTextMessage(host, 'Mermaid render failed:: invalid SVG output');
38
+ return;
39
+ }
40
+ parsed.querySelectorAll('script, foreignObject, iframe, object, embed, style, base, meta').forEach(node => node.remove());
41
+ parsed.querySelectorAll('*').forEach((node) => {
42
+ Array.from(node.attributes).forEach((attr) => {
43
+ const name = attr.name.toLowerCase();
44
+ const value = attr.value || '';
45
+ if(name.startsWith('on')){
46
+ node.removeAttribute(attr.name);
47
+ return;
48
+ }
49
+ if((name === 'href' || name === 'xlink:href') && /^\s*(javascript:|data:)/i.test(value)){
50
+ node.removeAttribute(attr.name);
51
+ }
52
+ });
53
+ });
54
+ host.replaceChildren(document.importNode(parsed.documentElement, true));
55
+ }
56
+
57
+ async function reloadGraphMermaid(){
58
+ if(__graphReloadInFlight){ setGraphMetaProgress('skip-concurrent'); return; }
59
+ __graphReloadInFlight = true; __graphReloadAttempt++;
60
+ const attemptId = __graphReloadAttempt;
61
+ clearTimeout(__graphReloadWatchdog);
62
+ __graphReloadWatchdog = setTimeout(()=>{
63
+ setGraphMetaProgress('watchdog-expired','a='+attemptId);
64
+ __graphReloadInFlight = false;
65
+ }, 15000);
66
+ setGraphMetaProgress('start','a='+attemptId);
67
+ const enrichEl = document.getElementById('graph-enrich');
68
+ const categoriesEl = document.getElementById('graph-categories');
69
+ const usageEl = document.getElementById('graph-usage');
70
+ const edgeTypesEl = document.getElementById('graph-edgeTypes');
71
+ const layoutSel = document.getElementById('graph-layout');
72
+ // Default enrich & categories to true if element not yet bound so initial meta shows enriched schema
73
+ const enrich = enrichEl && 'checked' in enrichEl ? enrichEl.checked : true;
74
+ const categories = categoriesEl && 'checked' in categoriesEl ? categoriesEl.checked : true;
75
+ const usage = usageEl && 'checked' in usageEl ? usageEl.checked : false;
76
+ const edgeTypesRaw = edgeTypesEl && 'value' in edgeTypesEl ? (edgeTypesEl.value || '').trim() : '';
77
+ let layout = (layoutSel && 'value' in layoutSel) ? layoutSel.value : 'elk';
78
+ const theme = 'base'; // fixed project-standard theme
79
+ const params = new URLSearchParams();
80
+ const selCatsEl = document.getElementById('drill-categories');
81
+ const selInstEl = document.getElementById('drill-instructions');
82
+ const selectedCategories = selCatsEl ? Array.from(selCatsEl.selectedOptions).map(o=>o.value).filter(Boolean) : [];
83
+ const selectedIds = selInstEl ? Array.from(selInstEl.selectedOptions).map(o=>o.value).filter(Boolean) : [];
84
+ const scopeFiltered = selectedCategories.length > 0 || selectedIds.length > 0;
85
+ // Always include toggle flags irrespective of scope filtering so meta (schema version, categories)
86
+ // remains accurate and tests expecting enrichment signals succeed.
87
+ if(enrich) params.set('enrich','1');
88
+ if(categories) params.set('categories','1');
89
+ if(usage) params.set('usage','1');
90
+ if(edgeTypesRaw) params.set('edgeTypes', edgeTypesRaw);
91
+ if(selectedCategories.length) params.set('selectedCategories', selectedCategories.join(','));
92
+ if(selectedIds.length) params.set('selectedIds', selectedIds.join(','));
93
+ const target = document.getElementById('graph-mermaid');
94
+ const metaEl = document.getElementById('graph-meta');
95
+ if(target) target.textContent = '(loading graph...)';
96
+ const skeleton = document.querySelector('.graph-loading-skeleton');
97
+ if(skeleton) skeleton.style.display = '';
98
+ const manualOverride = window.__GRAPH_MANUAL_OVERRIDE === true;
99
+ const persistedOverride = !manualOverride ? null : (function(){
100
+ try { return localStorage.getItem('mcp.graph.manualOverrideSource') || null; } catch { return null; }
101
+ })();
102
+ setGraphMetaProgress('params', 'en='+(enrich?1:0)+';cat='+(categories?1:0)+';use='+(usage?1:0)+';selCats='+selectedCategories.length+';selIds='+selectedIds.length);
103
+ let fetchOk = false; let data = null; let lastErr = null;
104
+ try {
105
+ setGraphMetaProgress('fetch','a='+attemptId);
106
+ const res = await adminAuth.adminFetch('/api/graph/mermaid?'+params.toString());
107
+ if(!res.ok) throw new Error('http '+res.status);
108
+ data = await res.json();
109
+ fetchOk = !!(data && data.success && data.mermaid);
110
+ setGraphMetaProgress(fetchOk? 'fetch-ok':'fetch-empty','a='+attemptId);
111
+ } catch(e){ lastErr = e; setGraphMetaProgress('fetch-error','a='+attemptId); }
112
+ if(!fetchOk && attemptId === 1){
113
+ // Retry once with ultra-minimal params
114
+ try {
115
+ setGraphMetaProgress('retry1');
116
+ const res2 = await adminAuth.adminFetch('/api/graph/mermaid?enrich=1');
117
+ if(res2.ok){ const d2 = await res2.json(); if(d2?.success && d2.mermaid){ data = d2; fetchOk = true; setGraphMetaProgress('retry-ok'); }}
118
+ } catch{ setGraphMetaProgress('retry-fail'); }
119
+ }
120
+ if(fetchOk){
121
+ try {
122
+ let mermaidSource = data.mermaid;
123
+ setGraphMetaProgress('fetched-bytes','len='+ (mermaidSource? mermaidSource.length:0));
124
+ const effectiveLayout = layout === 'elk' ? 'elk' : 'default';
125
+ if(effectiveLayout === 'elk') await ensureMermaidElk();
126
+ // Merge or create frontmatter ensuring single config.theme + config.layout entries
127
+ function mergeFrontmatter(src){
128
+ if(!src) return src;
129
+ const wantThemeLine = theme ? ` theme: ${theme}` : null;
130
+ const wantLayoutLine = (effectiveLayout === 'elk') ? ' layout: elk' : null;
131
+ const wantThemeVariables = ` themeVariables:\n primaryColor: '#3b82f6'\n primaryTextColor: '#d0d4d8'\n primaryBorderColor: '#2c3038'\n lineColor: '#363b44'\n secondaryColor: '#1f2228'\n tertiaryColor: '#181b1f'\n background: '#111217'\n mainBkg: '#181b1f'\n secondBkg: '#1f2228'`;
132
+ const hasFrontmatter = src.startsWith('---\n');
133
+ // If frontmatter missing OR malformed ensure we create a fresh one
134
+ const m = hasFrontmatter ? /^---\n([\s\S]*?)\n---\n([\s\S]*)$/m.exec(src) : null;
135
+ if(!m){
136
+ const lines = ['config:'];
137
+ if(wantThemeLine) lines.push(wantThemeLine);
138
+ if(wantLayoutLine) lines.push(wantLayoutLine);
139
+ lines.push(wantThemeVariables);
140
+ // If there was an orphan leading '---' without closing, strip it first
141
+ const cleaned = hasFrontmatter ? src.replace(/^---\n?/, '') : src;
142
+ return `---\n${lines.join('\n')}\n---\n${cleaned}`;
143
+ }
144
+ // Split existing frontmatter header & body (valid pattern)
145
+ let header = m[1];
146
+ const body = m[2];
147
+ // Ensure config: section exists
148
+ if(!/^config:/m.test(header)){
149
+ header = 'config:\n'+header;
150
+ }
151
+ // Remove existing simple theme/layout lines; keep a single themeVariables block (first occurrence)
152
+ const lines = header.split(/\r?\n/);
153
+ let seenThemeVars = false;
154
+ const filtered = [];
155
+ for(let i=0;i<lines.length;i++){
156
+ const l = lines[i];
157
+ if(/(^\s*theme:\s)/.test(l) || /(^\s*layout:\s)/.test(l)) continue;
158
+ if(/^\s*themeVariables:/.test(l)){
159
+ if(seenThemeVars){ continue; }
160
+ seenThemeVars = true;
161
+ filtered.push(l);
162
+ // retain following indented lines belonging to existing themeVariables block
163
+ for(let j=i+1;j<lines.length;j++){
164
+ const nl = lines[j];
165
+ if(/^\s{2,}\S/.test(nl)) { filtered.push(nl); i=j; continue; }
166
+ break;
167
+ }
168
+ continue;
169
+ }
170
+ filtered.push(l);
171
+ }
172
+ // Rebuild and inject desired lines after config:
173
+ const rebuilt = filtered;
174
+ let cfgIdx = rebuilt.findIndex(l=>/^config:/.test(l));
175
+ if(cfgIdx === -1){ rebuilt.unshift('config:'); cfgIdx = 0; }
176
+ const inject = [];
177
+ if(wantThemeLine) inject.push(wantThemeLine);
178
+ if(wantLayoutLine) inject.push(wantLayoutLine);
179
+ if(!seenThemeVars) inject.push(wantThemeVariables);
180
+ rebuilt.splice(cfgIdx+1,0,...inject);
181
+ return `---\n${rebuilt.join('\n')}\n---\n${body}`;
182
+ }
183
+ mermaidSource = mergeFrontmatter(mermaidSource);
184
+ // Sanitize duplicated YAML mapping keys in frontmatter (e.g., accidental repeated darkMode)
185
+ function sanitizeFrontmatter(src){
186
+ if(!src || src.indexOf('---') !== 0) return src;
187
+ try {
188
+ const segMatch = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/m.exec(src);
189
+ if(!segMatch) return src; // not standard frontmatter pattern
190
+ const header = segMatch[1];
191
+ const body = segMatch[2];
192
+ const lines = header.split(/\r?\n/);
193
+ const seenAtIndent = {}; // key -> indent level signature
194
+ const out = [];
195
+ for(const line of lines){
196
+ // Match YAML simple key: value OR key: (end) respecting indentation
197
+ const m = /^(\s*)([A-Za-z0-9_-]+):/.exec(line);
198
+ if(m){
199
+ const indent = m[1].length;
200
+ const key = m[2];
201
+ const sig = indent+':'+key;
202
+ if(seenAtIndent[sig]){
203
+ // Skip duplicate at same nesting level
204
+ continue;
205
+ }
206
+ seenAtIndent[sig] = true;
207
+ }
208
+ out.push(line);
209
+ }
210
+ return `---\n${out.join('\n')}\n---\n${body}`;
211
+ } catch{ return src; }
212
+ }
213
+ let ensured = ensureMermaidDirective(mermaidSource);
214
+ ensured = sanitizeFrontmatter(ensured);
215
+ // If manual override is active, sanitize it too so duplicate keys (e.g. darkMode) don't break parse
216
+ let sanitizedOverride = null;
217
+ if(manualOverride && persistedOverride){
218
+ sanitizedOverride = sanitizeFrontmatter(persistedOverride);
219
+ setGraphMetaProgress('manual-override');
220
+ window.graphOriginalSource = sanitizedOverride; // lgtm[js/xss-through-dom]
221
+ if(target) target.textContent = sanitizedOverride;
222
+ } else {
223
+ window.graphOriginalSource = ensured;
224
+ if(target) target.textContent = ensured;
225
+ }
226
+ // Include scope filtering indicator so user sees when selection scoping applied
227
+ if(metaEl){
228
+ const scopeNote = scopeFiltered ? ' (scoped)' : '';
229
+ metaEl.textContent = `schema=v${data.meta?.graphSchemaVersion} nodes=${data.meta?.nodeCount} edges=${data.meta?.edgeCount}${scopeNote}`; // lgtm[js/xss-through-exception]
230
+ }
231
+ setGraphMetaProgress('render-prep','a='+attemptId);
232
+ try { await ensureMermaid(); } catch{}
233
+ try { if(effectiveLayout === 'elk' && !window.mermaid?.mcpElkRegistered) await ensureMermaidElk(); } catch{}
234
+ if(window.mermaid){
235
+ setGraphMetaProgress('render-run','a='+attemptId);
236
+ try {
237
+ const renderSource = (manualOverride && sanitizedOverride) ? sanitizedOverride : ensured;
238
+ // Lightweight syntax validation before attempting full render (helps surface parse errors explicitly)
239
+ try {
240
+ if(window.mermaid.parse){
241
+ await window.mermaid.parse(renderSource);
242
+ }
243
+ } catch(parseErr){
244
+ setGraphMetaProgress('parse-fail','a='+attemptId);
245
+ const hostParse = document.getElementById('graph-mermaid-svg');
246
+ if(hostParse){
247
+ renderGraphTextMessage(hostParse, `Mermaid parse error:: ${String((parseErr && parseErr.message) || parseErr || '').slice(0, 200)}`);
248
+ }
249
+ // Abort further render attempt
250
+ throw parseErr;
251
+ }
252
+ let svg; ({ svg } = await window.mermaid.render('graphMermaidSvg', renderSource));
253
+ const host = document.getElementById('graph-mermaid-svg'); if(host) renderGraphSvg(host, svg);
254
+ const skel = document.querySelector('.graph-loading-skeleton'); if(skel) skel.style.display = 'none';
255
+ setGraphMetaProgress('render-ok','a='+attemptId);
256
+ } catch(rendErr){
257
+ setGraphMetaProgress('render-fail','a='+attemptId);
258
+ const skelFail = document.querySelector('.graph-loading-skeleton'); if(skelFail) skelFail.style.display = 'none';
259
+ const hostErr = document.getElementById('graph-mermaid-svg');
260
+ if(hostErr && !/Mermaid parse error/.test(hostErr.textContent||'')){
261
+ renderGraphTextMessage(hostErr, `Mermaid render failed:: ${String((rendErr && rendErr.message) || rendErr || '').slice(0, 200)}`);
262
+ }
263
+ try { console.warn('[mermaid render failed]', rendErr); } catch{}
264
+ }
265
+ }
266
+ } catch(procErr){ setGraphMetaProgress('process-error','a='+attemptId); }
267
+ } else {
268
+ if(target) target.textContent = `(graph unavailable${lastErr?': '+(lastErr.message||lastErr):''})`;
269
+ setGraphMetaProgress('unavailable','err='+(lastErr && (lastErr.message||String(lastErr))||'none'));
270
+ }
271
+ clearTimeout(__graphReloadWatchdog);
272
+ __graphReloadInFlight = false;
273
+ }
274
+
275
+ function ensureMermaidDirective(src){
276
+ if(!src) return 'flowchart TB';
277
+ const hasDirective = /^(---[\s\S]*?---\s*)?(%%.*\n)*\s*(flowchart|graph)\b/m.test(src);
278
+ if(hasDirective) return src;
279
+ if(/^---/.test(src)){
280
+ const parts = src.split(/---\s*\n/);
281
+ if(parts.length>=3){ const rest = parts.slice(2).join('---\n'); return `---\n${parts[1]}---\nflowchart TB\n${rest}`; }
282
+ }
283
+ return 'flowchart TB\n'+src;
284
+ }
285
+
286
+ // Mermaid loader state (copied behavior)
287
+ let mermaidLoading = null;
288
+ let mermaidElkLoading = null;
289
+ function mermaidNeedsReload(force){ if(force) return true; if(!window.mermaid) return true; const ver = window.mermaid.version || window.mermaid.mermaidAPI?.getConfig?.()?.version || ''; if(ver.startsWith('10.')) return true; return false; }
290
+ async function ensureMermaid(force){
291
+ if(mermaidNeedsReload(force)){
292
+ if(window.mermaid && (force || !window.mermaid.registerLayoutLoaders)){
293
+ try{ [...document.querySelectorAll('script[src*="mermaid"]')].forEach(s=>s.remove()); } catch{}
294
+ try{ delete window.mermaid; } catch{}
295
+ mermaidLoading = null;
296
+ }
297
+ }
298
+ if(window.mermaid && !force) return;
299
+ if(mermaidLoading) return mermaidLoading;
300
+ mermaidLoading = new Promise((resolve,reject)=>{
301
+ const s = document.createElement('script');
302
+ s.src = '/js/mermaid.min.js';
303
+ s.onload = ()=>{ try { const large = !!window.__MERMAID_LARGE_GRAPH_FLAG; let configuredMaxEdges; if(typeof window.__MERMAID_MAX_EDGES === 'number' && window.__MERMAID_MAX_EDGES>0){ configuredMaxEdges = window.__MERMAID_MAX_EDGES; } else { configuredMaxEdges = large ? 20000 : 3000; } const maxTextSize = large ? 10000000 : 1000000; // Standardize base theme (frontmatter may still override per-graph)
304
+ window.mermaid.initialize({ startOnLoad:false, theme:'base', maxEdges: configuredMaxEdges, maxTextSize, securityLevel:'strict' }); window.__MERMAID_ACTIVE_MAX_EDGES = configuredMaxEdges; window.__MERMAID_ACTIVE_MAX_TEXT_SIZE = maxTextSize; resolve(null);} catch(e){ reject(e);} };
305
+ s.onerror = (e)=>reject(e instanceof Error? e : new Error('mermaid load failed'));
306
+ document.head.appendChild(s);
307
+ });
308
+ return mermaidLoading;
309
+ }
310
+
311
+ async function ensureMermaidElk(){
312
+ await ensureMermaid();
313
+ if(window.mermaid && !window.mermaid.registerLayoutLoaders && !window.mermaid.__reloadedOnce){ window.mermaid.__reloadedOnce = true; await ensureMermaid(true); }
314
+ if(window.mermaid?.mcpElkRegistered) return;
315
+ if(mermaidElkLoading) return mermaidElkLoading;
316
+ mermaidElkLoading = new Promise((resolve)=>{
317
+ const localElk = './mermaid-layout-elk.esm.min.mjs';
318
+ const urls = [ localElk ];
319
+ let idx = 0;
320
+ function tryNext(){ if(window.mermaid?.mcpElkRegistered) return resolve(null); if(idx >= urls.length) return resolve(null); const url = urls[idx++]; (async ()=>{ try{ const mod = await import(url); let descriptorArray = (mod && mod.default && Array.isArray(mod.default)) ? mod.default : (Array.isArray(mod) ? mod : null); if(!descriptorArray && typeof mod === 'object'){ const arr = Array.isArray(mod.default)? mod.default : null; descriptorArray = arr || null; } if(descriptorArray && window.mermaid?.registerLayoutLoaders){ try{ window.mermaid.registerLayoutLoaders(descriptorArray); window.mermaid.mcpElkRegistered = true; resolve(null); return; } catch(e){ /* try next */ } } } catch(e){ /* try next */ } tryNext(); })(); }
321
+ tryNext();
322
+ });
323
+ return mermaidElkLoading;
324
+ }
325
+
326
+ function initGraphScopeDefaults(){
327
+ const catSel = document.getElementById('drill-categories');
328
+ const instSel = document.getElementById('drill-instructions');
329
+ if(catSel && !catSel.options.length) refreshDrillCategories().catch(()=>{});
330
+ if(instSel && !instSel.options.length) loadDrillInstructions().catch(()=>{});
331
+ const mer = document.getElementById('graph-mermaid'); if(mer) mer.textContent='(no selection - choose categories and/or instructions then Refresh)';
332
+ }
333
+
334
+ function copyMermaidSource(){ const el = document.getElementById('graph-mermaid'); if(!el) return; const txt = el.textContent || ''; navigator.clipboard.writeText(txt).catch(()=>{}); }
335
+
336
+ function toggleGraphEdit(){
337
+ if(graphEditing){
338
+ cancelGraphEdit();
339
+ return;
340
+ }
341
+ const target = document.getElementById('graph-mermaid');
342
+ if(!target) return;
343
+ // Capture current content as restore baseline when entering edit mode
344
+ window.graphOriginalSource = target.textContent || ''; // lgtm[js/xss-through-dom]
345
+ graphEditing = true;
346
+ target.setAttribute('contenteditable','true');
347
+ target.style.outline = '1px solid #3b82f6';
348
+ window.__GRAPH_MANUAL_OVERRIDE = true; // enable manual override mode
349
+ setGraphMetaProgress('edit-start');
350
+ try { document.getElementById('graph-edit-btn').style.display='none'; } catch{}
351
+ try { document.getElementById('graph-apply-btn').style.display='inline-block'; } catch{}
352
+ try { document.getElementById('graph-cancel-btn').style.display='inline-block'; } catch{}
353
+ }
354
+
355
+ function applyGraphEdit(){
356
+ const target = document.getElementById('graph-mermaid');
357
+ if(!target) return;
358
+ const code = target.textContent || '';
359
+ // Promote edited content to new baseline so subsequent cancel doesn't revert it
360
+ window.graphOriginalSource = code;
361
+ persistGraphSource(code);
362
+ try { localStorage.setItem('mcp.graph.manualOverrideSource', code); } catch{}
363
+ setGraphMetaProgress('apply');
364
+ (async ()=>{
365
+ try {
366
+ await ensureMermaid();
367
+ const { svg } = await window.mermaid.render('graphMermaidSvg', code);
368
+ const legacyHost = document.getElementById('graph-mermaid-svg'); if(legacyHost) renderGraphSvg(legacyHost, svg);
369
+ setGraphMetaProgress('apply-ok');
370
+ } catch(e){
371
+ setGraphMetaProgress('apply-fail');
372
+ try { alert('Render failed: '+ ((e && e.message) || e)); } catch{}
373
+ }
374
+ })();
375
+ cancelGraphEdit(true); // keep edited content visible
376
+ }
377
+
378
+ function cancelGraphEdit(keep){
379
+ if(!graphEditing) return;
380
+ const target = document.getElementById('graph-mermaid');
381
+ if(target){
382
+ target.removeAttribute('contenteditable');
383
+ target.style.outline='none';
384
+ if(!keep){
385
+ // Restore baseline content
386
+ target.textContent = window.graphOriginalSource;
387
+ }
388
+ }
389
+ graphEditing=false;
390
+ setGraphMetaProgress('edit-end');
391
+ try { document.getElementById('graph-edit-btn').style.display='inline-block'; } catch{}
392
+ try { document.getElementById('graph-apply-btn').style.display='none'; } catch{}
393
+ try { document.getElementById('graph-cancel-btn').style.display='none'; } catch{}
394
+ }
395
+
396
+ // Drilldown helpers (absorbed from admin.drilldown.js)
397
+ async function refreshDrillCategories(){
398
+ const el = document.getElementById('drill-categories');
399
+ if(!el) return;
400
+ try{
401
+ const res = await adminAuth.adminFetch('/api/graph/categories');
402
+ const data = await res.json();
403
+ el.innerHTML = '';
404
+ if(Array.isArray(data?.categories)){
405
+ data.categories.forEach(c=>{ const o = document.createElement('option'); o.value=c.id||c.name; o.textContent = c.name||c.id; el.appendChild(o); });
406
+ let auto = 0; for(const opt of Array.from(el.options)){ if(auto<3){ opt.selected = true; auto++; } }
407
+ }
408
+ if(typeof window.reloadGraphMermaid === 'function') { try { window.reloadGraphMermaid(); } catch(_){} }
409
+ }catch(e){ console.warn('failed refreshDrillCategories',e); }
410
+ }
411
+
412
+ async function loadDrillInstructions(){
413
+ const el = document.getElementById('drill-instructions');
414
+ if(!el) return;
415
+ try{
416
+ const res = await adminAuth.adminFetch('/api/graph/instructions');
417
+ const data = await res.json();
418
+ el.innerHTML = '';
419
+ if(Array.isArray(data?.instructions)){
420
+ data.instructions.forEach(i=>{ const o = document.createElement('option'); o.value=i.id; o.textContent = `${i.title||i.id}`; el.appendChild(o); });
421
+ }
422
+ }catch(e){ console.warn('failed loadDrillInstructions',e); }
423
+ }
424
+
425
+ function clearSelections(){
426
+ const catSel = document.getElementById('drill-categories');
427
+ const instSel = document.getElementById('drill-instructions');
428
+ if(catSel) { for(const opt of Array.from(catSel.options)) opt.selected = false; }
429
+ if(instSel) { for(const opt of Array.from(instSel.options)) opt.selected = false; }
430
+ }
431
+
432
+ // Expose
433
+ window.reloadGraphMermaid = reloadGraphMermaid;
434
+ window.reloadGraphMermaidForce = function(){ // lgtm[js/xss-through-dom]
435
+ try { clearTimeout(__graphReloadWatchdog); } catch{}
436
+ __graphReloadInFlight = false; // clear guard
437
+ reloadGraphMermaid();
438
+ };
439
+ window.ensureMermaid = ensureMermaid;
440
+ window.ensureMermaidElk = ensureMermaidElk;
441
+ window.initGraphScopeDefaults = initGraphScopeDefaults;
442
+ window.ensureMermaidDirective = ensureMermaidDirective;
443
+ window.copyMermaidSource = copyMermaidSource;
444
+ window.toggleGraphEdit = toggleGraphEdit;
445
+ window.applyGraphEdit = applyGraphEdit;
446
+ window.cancelGraphEdit = cancelGraphEdit;
447
+ window.refreshDrillCategories = refreshDrillCategories;
448
+ window.loadDrillInstructions = loadDrillInstructions;
449
+ window.clearSelections = clearSelections;
450
+
451
+ // Local persistence helpers
452
+ const LS_KEY = 'mcp.graph.lastSource';
453
+ function persistGraphSource(src){ try { if(src && src.trim().length) localStorage.setItem(LS_KEY, src); } catch{} }
454
+ function loadPersistedGraphSource(){ try { return localStorage.getItem(LS_KEY) || ''; } catch { return ''; } }
455
+ window.__persistGraphSource = persistGraphSource;
456
+
457
+ // Auto render on content edits when checkbox enabled
458
+ function bindAutoRender(){
459
+ const pre = document.getElementById('graph-mermaid');
460
+ if(!pre) return;
461
+ pre.addEventListener('input', ()=>{
462
+ const auto = (document.getElementById('graph-auto-render')||{}).checked;
463
+ if(auto && graphEditing){
464
+ const code = pre.textContent || '';
465
+ persistGraphSource(code);
466
+ // Debounced lightweight render (cancel previous if still pending)
467
+ clearTimeout(window.__graphAutoRenderTimer);
468
+ window.__graphAutoRenderTimer = setTimeout(()=>{
469
+ (async ()=>{ try { await ensureMermaid(); const { svg } = await window.mermaid.render('graphMermaidSvg', code); const legacyHost = document.getElementById('graph-mermaid-svg'); if(legacyHost) renderGraphSvg(legacyHost, svg); } catch{} })();
470
+ }, 400);
471
+ }
472
+ });
473
+ }
474
+
475
+ // Theme insertion removed (fixed theme configuration)
476
+
477
+ document.addEventListener('DOMContentLoaded', ()=>{
478
+ bindAutoRender();
479
+ // If we have a persisted manual edit, restore it (but allow fresh reload to overwrite when refreshed)
480
+ const persisted = loadPersistedGraphSource();
481
+ if(persisted){
482
+ const target = document.getElementById('graph-mermaid');
483
+ if(target && target.textContent && !/\(loading graph/.test(target.textContent)){
484
+ // Only restore if existing content is a real graph
485
+ target.textContent = persisted;
486
+ }
487
+ }
488
+ // Restore manual override source if present
489
+ try {
490
+ const mo = localStorage.getItem('mcp.graph.manualOverrideSource');
491
+ if(mo){ window.__GRAPH_MANUAL_OVERRIDE = true; const t = document.getElementById('graph-mermaid'); if(t) t.textContent = mo; }
492
+ } catch{}
493
+ });
494
+
495
+ let __graphInitialAutoReload = false;
496
+ async function graphEnsureReadyAndReload(){
497
+ // Avoid multiple concurrent auto reloads
498
+ if(__graphInitialAutoReload) return; __graphInitialAutoReload = true;
499
+ try {
500
+ // Ensure categories then instructions then mermaid libs before reload
501
+ try { await refreshDrillCategories(); } catch {}
502
+ try { await loadDrillInstructions(); } catch {}
503
+ // Ensure mermaid (and elk) prior to first fetch so meta elements ready quickly
504
+ try { await ensureMermaid(); } catch {}
505
+ try { await ensureMermaidElk(); } catch {}
506
+ await reloadGraphMermaid();
507
+ } catch(e){
508
+ try { console.warn('[graphEnsureReadyAndReload] failed', e); } catch{}
509
+ }
510
+ }
511
+ window.graphEnsureReadyAndReload = graphEnsureReadyAndReload;
512
+
513
+ // Attach refresh button listener (id added in admin.html)
514
+ document.addEventListener('DOMContentLoaded', ()=>{
515
+ const btn = document.getElementById('graph-refresh-btn');
516
+ if(btn){ btn.addEventListener('click', ()=> window.reloadGraphMermaidForce()); }
517
+ });
518
+
519
+ // Inject selection change listeners to trigger reload and clear manual override mode
520
+ function bindScopeSelectionListeners(){
521
+ try {
522
+ const catSel = document.getElementById('drill-categories');
523
+ const instSel = document.getElementById('drill-instructions');
524
+ const handler = ()=>{
525
+ // Clear manual override so new scope fetch isn't masked
526
+ if(window.__GRAPH_MANUAL_OVERRIDE){
527
+ try { delete window.__GRAPH_MANUAL_OVERRIDE; } catch{}
528
+ try { localStorage.removeItem('mcp.graph.manualOverrideSource'); } catch{}
529
+ setGraphMetaProgress('scope-clear-override');
530
+ }
531
+ // If user is not editing custom graph text, trigger debounced reload
532
+ if(!graphEditing){
533
+ clearTimeout(window.__graphScopeReloadTimer);
534
+ setGraphMetaProgress('scope-change');
535
+ window.__graphScopeReloadTimer = setTimeout(()=>{ window.reloadGraphMermaid && window.reloadGraphMermaid(); }, 200);
536
+ }
537
+ };
538
+ if(catSel && !catSel.__mcpScopeBound){ catSel.addEventListener('change', handler); catSel.addEventListener('input', handler); catSel.__mcpScopeBound = true; }
539
+ if(instSel && !instSel.__mcpScopeBound){ instSel.addEventListener('change', handler); instSel.addEventListener('input', handler); instSel.__mcpScopeBound = true; }
540
+ } catch{}
541
+ }
542
+ window.bindScopeSelectionListeners = bindScopeSelectionListeners;
543
+
544
+ // Helper to explicitly clear manual override and force reload
545
+ window.clearGraphManualOverride = function(force){
546
+ try { delete window.__GRAPH_MANUAL_OVERRIDE; } catch{}
547
+ try { localStorage.removeItem('mcp.graph.manualOverrideSource'); } catch{}
548
+ if(force) window.reloadGraphMermaid && window.reloadGraphMermaid();
549
+ };
550
+
551
+ document.addEventListener('DOMContentLoaded', ()=>{
552
+ try { bindScopeSelectionListeners(); } catch{}
553
+ });
554
+
555
+ // Auto-load graph when section becomes visible (tab switch via MutationObserver)
556
+ document.addEventListener('DOMContentLoaded', () => {
557
+ const graphSection = document.getElementById('graph-section');
558
+ if (graphSection) {
559
+ const observer = new MutationObserver((mutations) => {
560
+ for (const mutation of mutations) {
561
+ if (mutation.attributeName === 'class' && !graphSection.classList.contains('hidden')) {
562
+ graphEnsureReadyAndReload();
563
+ break;
564
+ }
565
+ }
566
+ });
567
+ observer.observe(graphSection, { attributes: true, attributeFilter: ['class'] });
568
+ }
569
+ });
570
+
571
+ // ── Phase 4.3 — Zoom controls and fullscreen ──────────────────────────
572
+ let zoomLevel = 1;
573
+ const ZOOM_STEP = 0.15;
574
+ const ZOOM_MIN = 0.2;
575
+ const ZOOM_MAX = 5;
576
+
577
+ function applyZoom(){
578
+ const svg = document.getElementById('graph-mermaid-svg');
579
+ if(svg) svg.style.transform = 'scale(' + zoomLevel + ')';
580
+ if(svg) svg.style.transformOrigin = 'top left';
581
+ }
582
+
583
+ document.addEventListener('DOMContentLoaded', () => {
584
+ const zoomIn = document.getElementById('graph-zoom-in');
585
+ const zoomOut = document.getElementById('graph-zoom-out');
586
+ const zoomReset = document.getElementById('graph-zoom-reset');
587
+ const fullscreenBtn = document.getElementById('graph-fullscreen-btn');
588
+ const renderCard = document.getElementById('graph-render-card');
589
+
590
+ if(zoomIn) zoomIn.addEventListener('click', () => { zoomLevel = Math.min(ZOOM_MAX, zoomLevel + ZOOM_STEP); applyZoom(); });
591
+ if(zoomOut) zoomOut.addEventListener('click', () => { zoomLevel = Math.max(ZOOM_MIN, zoomLevel - ZOOM_STEP); applyZoom(); });
592
+ if(zoomReset) zoomReset.addEventListener('click', () => { zoomLevel = 1; applyZoom(); });
593
+
594
+ if(fullscreenBtn && renderCard){
595
+ fullscreenBtn.addEventListener('click', () => {
596
+ renderCard.classList.toggle('graph-fullscreen');
597
+ fullscreenBtn.textContent = renderCard.classList.contains('graph-fullscreen') ? '✕' : '⛶';
598
+ });
599
+ }
600
+
601
+ // Mousewheel zoom on the rendered diagram
602
+ const rendered = document.getElementById('graph-mermaid-rendered');
603
+ if(rendered){
604
+ rendered.addEventListener('wheel', (e) => {
605
+ if(e.ctrlKey || e.metaKey){
606
+ e.preventDefault();
607
+ zoomLevel = e.deltaY < 0
608
+ ? Math.min(ZOOM_MAX, zoomLevel + ZOOM_STEP)
609
+ : Math.max(ZOOM_MIN, zoomLevel - ZOOM_STEP);
610
+ applyZoom();
611
+ }
612
+ }, { passive: false });
613
+ }
614
+ });
615
+ })();