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