sdl-mcp 0.12.2 → 0.12.3
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/README.md +10 -0
- package/config/sdlmcp.config.example.json +53 -8
- package/config/sdlmcp.config.schema.json +530 -106
- package/dist/.tsbuildinfo +1 -1
- package/dist/benchmark/external-manifest.d.ts +162 -0
- package/dist/benchmark/external-manifest.d.ts.map +1 -0
- package/dist/benchmark/external-manifest.js +336 -0
- package/dist/benchmark/external-manifest.js.map +1 -0
- package/dist/benchmark/external-runner.d.ts +100 -0
- package/dist/benchmark/external-runner.d.ts.map +1 -0
- package/dist/benchmark/external-runner.js +1171 -0
- package/dist/benchmark/external-runner.js.map +1 -0
- package/dist/benchmark/output-file.d.ts +3 -0
- package/dist/benchmark/output-file.d.ts.map +1 -0
- package/dist/benchmark/output-file.js +8 -0
- package/dist/benchmark/output-file.js.map +1 -0
- package/dist/cli/argParsing.d.ts.map +1 -1
- package/dist/cli/argParsing.js +6 -0
- package/dist/cli/argParsing.js.map +1 -1
- package/dist/cli/commands/benchmark.d.ts.map +1 -1
- package/dist/cli/commands/benchmark.js +3 -2
- package/dist/cli/commands/benchmark.js.map +1 -1
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +13 -7
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +5 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +73 -3
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/serve.d.ts.map +1 -1
- package/dist/cli/commands/serve.js +2 -0
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/transport/http.d.ts +1 -35
- package/dist/cli/transport/http.d.ts.map +1 -1
- package/dist/cli/transport/http.js +151 -175
- package/dist/cli/transport/http.js.map +1 -1
- package/dist/cli/types.d.ts +1 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/config/constants.d.ts +30 -0
- package/dist/config/constants.d.ts.map +1 -1
- package/dist/config/constants.js +30 -0
- package/dist/config/constants.js.map +1 -1
- package/dist/config/types.d.ts +53 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +62 -14
- package/dist/config/types.js.map +1 -1
- package/dist/db/ladybug-batching.d.ts +1 -0
- package/dist/db/ladybug-batching.d.ts.map +1 -1
- package/dist/db/ladybug-batching.js +1 -0
- package/dist/db/ladybug-batching.js.map +1 -1
- package/dist/db/ladybug-core.d.ts +3 -0
- package/dist/db/ladybug-core.d.ts.map +1 -1
- package/dist/db/ladybug-core.js +72 -2
- package/dist/db/ladybug-core.js.map +1 -1
- package/dist/db/ladybug-embeddings.d.ts +6 -1
- package/dist/db/ladybug-embeddings.d.ts.map +1 -1
- package/dist/db/ladybug-embeddings.js +6 -1
- package/dist/db/ladybug-embeddings.js.map +1 -1
- package/dist/db/ladybug-file-summaries.d.ts.map +1 -1
- package/dist/db/ladybug-file-summaries.js +23 -0
- package/dist/db/ladybug-file-summaries.js.map +1 -1
- package/dist/db/ladybug-queries.js +1 -1
- package/dist/db/ladybug-queries.js.map +1 -1
- package/dist/db/migrations/index.d.ts.map +1 -1
- package/dist/db/migrations/index.js +2 -0
- package/dist/db/migrations/index.js.map +1 -1
- package/dist/db/migrations/m007-copy-embeddings-to-symbol.d.ts +5 -9
- package/dist/db/migrations/m007-copy-embeddings-to-symbol.d.ts.map +1 -1
- package/dist/db/migrations/m007-copy-embeddings-to-symbol.js +24 -126
- package/dist/db/migrations/m007-copy-embeddings-to-symbol.js.map +1 -1
- package/dist/db/migrations/m021-remediate-symbol-embeddings.d.ts +5 -0
- package/dist/db/migrations/m021-remediate-symbol-embeddings.d.ts.map +1 -0
- package/dist/db/migrations/m021-remediate-symbol-embeddings.js +7 -0
- package/dist/db/migrations/m021-remediate-symbol-embeddings.js.map +1 -0
- package/dist/db/migrations/symbol-embedding-remediation.d.ts +57 -0
- package/dist/db/migrations/symbol-embedding-remediation.d.ts.map +1 -0
- package/dist/db/migrations/symbol-embedding-remediation.js +335 -0
- package/dist/db/migrations/symbol-embedding-remediation.js.map +1 -0
- package/dist/graph/layout/force-layout.d.ts +4 -0
- package/dist/graph/layout/force-layout.d.ts.map +1 -0
- package/dist/graph/layout/force-layout.js +127 -0
- package/dist/graph/layout/force-layout.js.map +1 -0
- package/dist/graph/layout/layout-service.d.ts +37 -0
- package/dist/graph/layout/layout-service.d.ts.map +1 -0
- package/dist/graph/layout/layout-service.js +172 -0
- package/dist/graph/layout/layout-service.js.map +1 -0
- package/dist/graph/layout/native-engine.d.ts +9 -0
- package/dist/graph/layout/native-engine.d.ts.map +1 -0
- package/dist/graph/layout/native-engine.js +59 -0
- package/dist/graph/layout/native-engine.js.map +1 -0
- package/dist/graph/layout/prng.d.ts +3 -0
- package/dist/graph/layout/prng.d.ts.map +1 -0
- package/dist/graph/layout/prng.js +19 -0
- package/dist/graph/layout/prng.js.map +1 -0
- package/dist/graph/layout/serializer.d.ts +3 -0
- package/dist/graph/layout/serializer.d.ts.map +1 -0
- package/dist/graph/layout/serializer.js +20 -0
- package/dist/graph/layout/serializer.js.map +1 -0
- package/dist/graph/layout/types.d.ts +30 -0
- package/dist/graph/layout/types.d.ts.map +1 -0
- package/dist/graph/layout/types.js +2 -0
- package/dist/graph/layout/types.js.map +1 -0
- package/dist/indexer/embeddings.d.ts +7 -0
- package/dist/indexer/embeddings.d.ts.map +1 -1
- package/dist/indexer/embeddings.js +44 -4
- package/dist/indexer/embeddings.js.map +1 -1
- package/dist/indexer/file-summary-embeddings.d.ts +12 -0
- package/dist/indexer/file-summary-embeddings.d.ts.map +1 -1
- package/dist/indexer/file-summary-embeddings.js +83 -21
- package/dist/indexer/file-summary-embeddings.js.map +1 -1
- package/dist/indexer/fileWalker.d.ts.map +1 -1
- package/dist/indexer/fileWalker.js +2 -1
- package/dist/indexer/fileWalker.js.map +1 -1
- package/dist/indexer/metrics-updater.d.ts.map +1 -1
- package/dist/indexer/metrics-updater.js +27 -4
- package/dist/indexer/metrics-updater.js.map +1 -1
- package/dist/indexer/watcher.d.ts.map +1 -1
- package/dist/indexer/watcher.js +2 -1
- package/dist/indexer/watcher.js.map +1 -1
- package/dist/mcp/context-response-projection.d.ts.map +1 -1
- package/dist/mcp/context-response-projection.js +49 -13
- package/dist/mcp/context-response-projection.js.map +1 -1
- package/dist/mcp/tools/search-edit/planner.d.ts.map +1 -1
- package/dist/mcp/tools/search-edit/planner.js +10 -3
- package/dist/mcp/tools/search-edit/planner.js.map +1 -1
- package/dist/observability/event-tap.d.ts +2 -1
- package/dist/observability/event-tap.d.ts.map +1 -1
- package/dist/observability/event-tap.js.map +1 -1
- package/dist/observability/service.d.ts +11 -4
- package/dist/observability/service.d.ts.map +1 -1
- package/dist/observability/service.js +83 -13
- package/dist/observability/service.js.map +1 -1
- package/dist/observability/types.d.ts +48 -2
- package/dist/observability/types.d.ts.map +1 -1
- package/dist/ui/.tsbuildinfo +1 -0
- package/dist/ui/vendor/fflate.js +2692 -0
- package/dist/ui/vendor/jsm/controls/ArcballControls.js +3543 -0
- package/dist/ui/vendor/jsm/controls/DragControls.js +452 -0
- package/dist/ui/vendor/jsm/controls/FirstPersonControls.js +488 -0
- package/dist/ui/vendor/jsm/controls/FlyControls.js +384 -0
- package/dist/ui/vendor/jsm/controls/MapControls.js +116 -0
- package/dist/ui/vendor/jsm/controls/OrbitControls.js +1963 -0
- package/dist/ui/vendor/jsm/controls/PointerLockControls.js +264 -0
- package/dist/ui/vendor/jsm/controls/TrackballControls.js +1001 -0
- package/dist/ui/vendor/jsm/controls/TransformControls.js +2003 -0
- package/dist/ui/vendor/jsm/loaders/3DMLoader.js +1836 -0
- package/dist/ui/vendor/jsm/loaders/3MFLoader.js +1621 -0
- package/dist/ui/vendor/jsm/loaders/AMFLoader.js +541 -0
- package/dist/ui/vendor/jsm/loaders/BVHLoader.js +484 -0
- package/dist/ui/vendor/jsm/loaders/ColladaLoader.js +153 -0
- package/dist/ui/vendor/jsm/loaders/DDSLoader.js +385 -0
- package/dist/ui/vendor/jsm/loaders/DRACOLoader.js +772 -0
- package/dist/ui/vendor/jsm/loaders/EXRLoader.js +3395 -0
- package/dist/ui/vendor/jsm/loaders/FBXLoader.js +4580 -0
- package/dist/ui/vendor/jsm/loaders/FontLoader.js +260 -0
- package/dist/ui/vendor/jsm/loaders/GCodeLoader.js +318 -0
- package/dist/ui/vendor/jsm/loaders/GLTFLoader.js +4860 -0
- package/dist/ui/vendor/jsm/loaders/HDRCubeTextureLoader.js +164 -0
- package/dist/ui/vendor/jsm/loaders/HDRLoader.js +463 -0
- package/dist/ui/vendor/jsm/loaders/IESLoader.js +379 -0
- package/dist/ui/vendor/jsm/loaders/KMZLoader.js +163 -0
- package/dist/ui/vendor/jsm/loaders/KTX2Loader.js +1276 -0
- package/dist/ui/vendor/jsm/loaders/KTXLoader.js +197 -0
- package/dist/ui/vendor/jsm/loaders/LDrawLoader.js +2510 -0
- package/dist/ui/vendor/jsm/loaders/LUT3dlLoader.js +205 -0
- package/dist/ui/vendor/jsm/loaders/LUTCubeLoader.js +190 -0
- package/dist/ui/vendor/jsm/loaders/LUTImageLoader.js +190 -0
- package/dist/ui/vendor/jsm/loaders/LWOLoader.js +1051 -0
- package/dist/ui/vendor/jsm/loaders/LottieLoader.js +130 -0
- package/dist/ui/vendor/jsm/loaders/MD2Loader.js +435 -0
- package/dist/ui/vendor/jsm/loaders/MDDLoader.js +147 -0
- package/dist/ui/vendor/jsm/loaders/MTLLoader.js +593 -0
- package/dist/ui/vendor/jsm/loaders/MaterialXLoader.js +1126 -0
- package/dist/ui/vendor/jsm/loaders/NRRDLoader.js +718 -0
- package/dist/ui/vendor/jsm/loaders/OBJLoader.js +955 -0
- package/dist/ui/vendor/jsm/loaders/PCDLoader.js +620 -0
- package/dist/ui/vendor/jsm/loaders/PDBLoader.js +272 -0
- package/dist/ui/vendor/jsm/loaders/PLYLoader.js +968 -0
- package/dist/ui/vendor/jsm/loaders/PVRLoader.js +270 -0
- package/dist/ui/vendor/jsm/loaders/RGBELoader.js +18 -0
- package/dist/ui/vendor/jsm/loaders/STLLoader.js +421 -0
- package/dist/ui/vendor/jsm/loaders/SVGLoader.js +3319 -0
- package/dist/ui/vendor/jsm/loaders/TDSLoader.js +1142 -0
- package/dist/ui/vendor/jsm/loaders/TGALoader.js +538 -0
- package/dist/ui/vendor/jsm/loaders/TIFFLoader.js +59 -0
- package/dist/ui/vendor/jsm/loaders/TTFLoader.js +261 -0
- package/dist/ui/vendor/jsm/loaders/USDLoader.js +303 -0
- package/dist/ui/vendor/jsm/loaders/USDZLoader.js +16 -0
- package/dist/ui/vendor/jsm/loaders/UltraHDRLoader.js +755 -0
- package/dist/ui/vendor/jsm/loaders/VOXLoader.js +919 -0
- package/dist/ui/vendor/jsm/loaders/VRMLLoader.js +3646 -0
- package/dist/ui/vendor/jsm/loaders/VTKLoader.js +1293 -0
- package/dist/ui/vendor/jsm/loaders/XYZLoader.js +143 -0
- package/dist/ui/vendor/jsm/loaders/collada/ColladaComposer.js +3044 -0
- package/dist/ui/vendor/jsm/loaders/collada/ColladaParser.js +1977 -0
- package/dist/ui/vendor/jsm/loaders/lwo/IFFParser.js +1217 -0
- package/dist/ui/vendor/jsm/loaders/lwo/LWO2Parser.js +414 -0
- package/dist/ui/vendor/jsm/loaders/lwo/LWO3Parser.js +373 -0
- package/dist/ui/vendor/jsm/loaders/usd/USDAParser.js +901 -0
- package/dist/ui/vendor/jsm/loaders/usd/USDCParser.js +1878 -0
- package/dist/ui/vendor/jsm/loaders/usd/USDComposer.js +4627 -0
- package/dist/ui/vendor/jsm/utils/BufferGeometryUtils.js +1501 -0
- package/dist/ui/vendor/jsm/utils/CameraUtils.js +82 -0
- package/dist/ui/vendor/jsm/utils/ColorUtils.js +76 -0
- package/dist/ui/vendor/jsm/utils/GeometryCompressionUtils.js +547 -0
- package/dist/ui/vendor/jsm/utils/GeometryUtils.js +226 -0
- package/dist/ui/vendor/jsm/utils/LDrawUtils.js +211 -0
- package/dist/ui/vendor/jsm/utils/SceneOptimizer.js +458 -0
- package/dist/ui/vendor/jsm/utils/SceneUtils.js +363 -0
- package/dist/ui/vendor/jsm/utils/ShadowMapViewer.js +244 -0
- package/dist/ui/vendor/jsm/utils/ShadowMapViewerGPU.js +233 -0
- package/dist/ui/vendor/jsm/utils/SkeletonUtils.js +496 -0
- package/dist/ui/vendor/jsm/utils/SortUtils.js +175 -0
- package/dist/ui/vendor/jsm/utils/UVsDebug.js +173 -0
- package/dist/ui/vendor/jsm/utils/WebGLTextureUtils.js +115 -0
- package/dist/ui/vendor/jsm/utils/WebGPUTextureUtils.js +81 -0
- package/dist/ui/vendor/jsm/utils/WorkerPool.js +167 -0
- package/dist/ui/vendor/three.core.min.js +6 -0
- package/dist/ui/vendor/three.module.min.js +6 -0
- package/dist/ui/viewer/ambient.js +39 -0
- package/dist/ui/viewer/api.js +93 -0
- package/dist/ui/viewer/chrome.js +36 -0
- package/dist/ui/viewer/edges.js +33 -0
- package/dist/ui/viewer/index.html +32 -0
- package/dist/ui/viewer/inspector.js +23 -0
- package/dist/ui/viewer/lenses/activity.js +24 -0
- package/dist/ui/viewer/lenses/community.js +5 -0
- package/dist/ui/viewer/lenses/edges.js +4 -0
- package/dist/ui/viewer/lenses/impact.js +6 -0
- package/dist/ui/viewer/lenses/search.js +69 -0
- package/dist/ui/viewer/lod.js +100 -0
- package/dist/ui/viewer/main.js +92 -0
- package/dist/ui/viewer/picking.js +45 -0
- package/dist/ui/viewer/scene.js +85 -0
- package/dist/ui/viewer/skins/default-skin.js +15 -0
- package/dist/ui/viewer/skins/loader.js +44 -0
- package/dist/ui/viewer/skins/manifest-schema.js +30 -0
- package/dist/ui/viewer/state.js +44 -0
- package/dist/ui/viewer/theme.js +23 -0
- package/dist/ui/viewer/universe.js +151 -0
- package/dist/ui/viewer/viewer.css +85 -0
- package/dist/util/safeRegex.d.ts.map +1 -1
- package/dist/util/safeRegex.js +221 -68
- package/dist/util/safeRegex.js.map +1 -1
- package/dist/viewer/legacy-graph.d.ts +40 -0
- package/dist/viewer/legacy-graph.d.ts.map +1 -0
- package/dist/viewer/legacy-graph.js +152 -0
- package/dist/viewer/legacy-graph.js.map +1 -0
- package/dist/viewer/routes.d.ts +10 -0
- package/dist/viewer/routes.d.ts.map +1 -0
- package/dist/viewer/routes.js +221 -0
- package/dist/viewer/routes.js.map +1 -0
- package/dist/viewer/service.d.ts +44 -0
- package/dist/viewer/service.d.ts.map +1 -0
- package/dist/viewer/service.js +160 -0
- package/dist/viewer/service.js.map +1 -0
- package/dist/viewer/types.d.ts +63 -0
- package/dist/viewer/types.d.ts.map +1 -0
- package/dist/viewer/types.js +2 -0
- package/dist/viewer/types.js.map +1 -0
- package/dist/viewer/viewer-config.d.ts +12 -0
- package/dist/viewer/viewer-config.d.ts.map +1 -0
- package/dist/viewer/viewer-config.js +36 -0
- package/dist/viewer/viewer-config.js.map +1 -0
- package/package.json +18 -9
- package/templates/SDL.md +19 -0
- package/templates/claude-code.json +8 -43
- package/dist/ui/graph.css +0 -108
- package/dist/ui/graph.d.ts +0 -2
- package/dist/ui/graph.d.ts.map +0 -1
- package/dist/ui/graph.html +0 -52
- package/dist/ui/graph.js +0 -259
- package/dist/ui/graph.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createReadStream, existsSync, statSync } from "fs";
|
|
2
2
|
import { createHash, randomBytes, randomUUID, timingSafeEqual } from "crypto";
|
|
3
3
|
import { createServer } from "http";
|
|
4
|
-
import { join } from "path";
|
|
4
|
+
import { extname, isAbsolute, join, relative, resolve } from "path";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
7
7
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
@@ -9,8 +9,6 @@ import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
|
9
9
|
import { createMCPServer, } from "../../server.js";
|
|
10
10
|
import { logger } from "../../util/logger.js";
|
|
11
11
|
import * as ladybugDb from "../../db/ladybug-queries.js";
|
|
12
|
-
import { computeDelta } from "../../delta/diff.js";
|
|
13
|
-
import { runGovernorLoop } from "../../delta/blastRadius.js";
|
|
14
12
|
import { getLadybugConn } from "../../db/ladybug.js";
|
|
15
13
|
import { indexRepo } from "../../indexer/indexer.js";
|
|
16
14
|
import { formatDeferredWorkStatus, getActiveDeferredWorkStatus, } from "../../runtime/deferred-work-state.js";
|
|
@@ -18,14 +16,16 @@ import { BufferCheckpointRequestSchema, BufferPushRequestSchema, } from "../../m
|
|
|
18
16
|
import { handleSymbolGetCard, handleSymbolSearch, } from "../../mcp/tools/symbol.js";
|
|
19
17
|
import { getDefaultLiveIndexCoordinator } from "../../live-index/coordinator.js";
|
|
20
18
|
import { routeConfigAdminApiRequest } from "../../config/admin-api.js";
|
|
19
|
+
import { handleViewerApiRequest } from "../../viewer/routes.js";
|
|
20
|
+
import { buildBlastRadiusGraph, buildGraphForSliceHandle, buildNeighborhood } from "../../viewer/legacy-graph.js";
|
|
21
21
|
import { SessionManager } from "../../mcp/session-manager.js";
|
|
22
22
|
import { createRuntimeIdentity } from "../../util/runtime-identity.js";
|
|
23
23
|
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
24
24
|
const UI_DIR_CANDIDATE = join(__dirname, "..", "..", "ui");
|
|
25
|
-
// Ensure
|
|
26
|
-
// folder may
|
|
27
|
-
//
|
|
28
|
-
const UI_DIR = existsSync(join(UI_DIR_CANDIDATE, "
|
|
25
|
+
// Ensure observability.html actually exists in the candidate. The compiled
|
|
26
|
+
// dist/ui folder may be missing copied html/css assets, in which case we must
|
|
27
|
+
// fall back to src/ui.
|
|
28
|
+
const UI_DIR = existsSync(join(UI_DIR_CANDIDATE, "observability.html"))
|
|
29
29
|
? UI_DIR_CANDIDATE
|
|
30
30
|
: join(__dirname, "..", "..", "..", "src", "ui");
|
|
31
31
|
/**
|
|
@@ -57,6 +57,7 @@ const OBSERVABILITY_UI_PATHS = new Set([
|
|
|
57
57
|
"/ui/observability",
|
|
58
58
|
"/ui/observability.js",
|
|
59
59
|
"/ui/observability.css",
|
|
60
|
+
"/ui/viewer",
|
|
60
61
|
]);
|
|
61
62
|
const LOCALHOST_ORIGIN_RE = /^https?:\/\/(localhost|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|\[::1\]|\[::ffff:127\.\d{1,3}\.\d{1,3}\.\d{1,3}\])(:\d+)?$/;
|
|
62
63
|
function isLoopbackBindHost(host) {
|
|
@@ -217,7 +218,7 @@ class InMemoryEventStore {
|
|
|
217
218
|
async replayEventsAfter(lastEventId, { send, }) {
|
|
218
219
|
const entry = this.events.get(lastEventId);
|
|
219
220
|
if (!entry) {
|
|
220
|
-
// Event was evicted by FIFO
|
|
221
|
+
// Event was evicted by FIFO — return an empty replay rather than
|
|
221
222
|
// throwing, which would crash the SDK's resumability path (M4).
|
|
222
223
|
return "";
|
|
223
224
|
}
|
|
@@ -379,165 +380,44 @@ export async function routeSymbolCardApiRequest(request, services = {}) {
|
|
|
379
380
|
},
|
|
380
381
|
};
|
|
381
382
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
async function buildNodes(conn, symbolIds) {
|
|
393
|
-
const symbolMap = await ladybugDb.getSymbolsByIds(conn, symbolIds);
|
|
394
|
-
const metricsMap = await ladybugDb.getMetricsBySymbolIds(conn, symbolIds);
|
|
395
|
-
const fileIds = new Set();
|
|
396
|
-
for (const symbol of symbolMap.values()) {
|
|
397
|
-
fileIds.add(symbol.fileId);
|
|
398
|
-
}
|
|
399
|
-
const fileMap = await ladybugDb.getFilesByIds(conn, Array.from(fileIds));
|
|
400
|
-
const nodes = [];
|
|
401
|
-
for (const symbolId of symbolIds) {
|
|
402
|
-
const symbol = symbolMap.get(symbolId);
|
|
403
|
-
if (!symbol)
|
|
404
|
-
continue;
|
|
405
|
-
const file = fileMap.get(symbol.fileId);
|
|
406
|
-
const metrics = metricsMap.get(symbolId);
|
|
407
|
-
nodes.push({
|
|
408
|
-
id: symbolId,
|
|
409
|
-
label: symbol.name,
|
|
410
|
-
kind: symbol.kind,
|
|
411
|
-
file: file?.relPath,
|
|
412
|
-
fanIn: metrics?.fanIn,
|
|
413
|
-
fanOut: metrics?.fanOut,
|
|
414
|
-
size: Math.max(5, Math.min(40, (metrics?.fanIn ?? 0) + 6)),
|
|
415
|
-
cluster: toClusterPath(file?.relPath ?? ""),
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
return nodes;
|
|
419
|
-
}
|
|
420
|
-
async function buildLinksForNodes(conn, ids) {
|
|
421
|
-
const idList = Array.from(ids);
|
|
422
|
-
const edgeMap = await ladybugDb.getEdgesFromSymbolsForSlice(conn, idList);
|
|
423
|
-
const links = [];
|
|
424
|
-
for (const fromSymbolId of idList) {
|
|
425
|
-
const edges = edgeMap.get(fromSymbolId) ?? [];
|
|
426
|
-
for (const edge of edges) {
|
|
427
|
-
if (!ids.has(edge.toSymbolId))
|
|
428
|
-
continue;
|
|
429
|
-
links.push({
|
|
430
|
-
source: fromSymbolId,
|
|
431
|
-
target: edge.toSymbolId,
|
|
432
|
-
type: edge.edgeType,
|
|
433
|
-
weight: edge.weight,
|
|
434
|
-
});
|
|
435
|
-
}
|
|
383
|
+
function contentTypeForUiPath(filePath) {
|
|
384
|
+
switch (extname(filePath)) {
|
|
385
|
+
case ".html":
|
|
386
|
+
return "text/html; charset=utf-8";
|
|
387
|
+
case ".css":
|
|
388
|
+
return "text/css; charset=utf-8";
|
|
389
|
+
case ".js":
|
|
390
|
+
return "application/javascript; charset=utf-8";
|
|
391
|
+
default:
|
|
392
|
+
return null;
|
|
436
393
|
}
|
|
437
|
-
return links;
|
|
438
|
-
}
|
|
439
|
-
function collapseClusters(nodes, maxChildrenPerCluster = 10) {
|
|
440
|
-
const byCluster = new Map();
|
|
441
|
-
for (const node of nodes) {
|
|
442
|
-
const key = node.cluster ?? "root";
|
|
443
|
-
const list = byCluster.get(key) ?? [];
|
|
444
|
-
list.push(node);
|
|
445
|
-
byCluster.set(key, list);
|
|
446
|
-
}
|
|
447
|
-
const collapsed = [];
|
|
448
|
-
for (const [cluster, list] of byCluster) {
|
|
449
|
-
if (list.length <= maxChildrenPerCluster) {
|
|
450
|
-
collapsed.push(...list);
|
|
451
|
-
continue;
|
|
452
|
-
}
|
|
453
|
-
const sorted = [...list].sort((a, b) => (b.fanIn ?? 0) - (a.fanIn ?? 0));
|
|
454
|
-
collapsed.push(...sorted.slice(0, maxChildrenPerCluster));
|
|
455
|
-
collapsed.push({
|
|
456
|
-
id: `cluster:${cluster}`,
|
|
457
|
-
label: `${cluster} (+${list.length - maxChildrenPerCluster})`,
|
|
458
|
-
kind: "module",
|
|
459
|
-
cluster,
|
|
460
|
-
size: 10,
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
return collapsed;
|
|
464
|
-
}
|
|
465
|
-
async function buildNeighborhood(conn, symbolId, maxNodes) {
|
|
466
|
-
const ids = new Set();
|
|
467
|
-
ids.add(symbolId);
|
|
468
|
-
for (const edge of await ladybugDb.getEdgesFrom(conn, symbolId)) {
|
|
469
|
-
ids.add(edge.toSymbolId);
|
|
470
|
-
}
|
|
471
|
-
const edgesTo = await ladybugDb.getEdgesToSymbols(conn, [symbolId]);
|
|
472
|
-
for (const edge of edgesTo.get(symbolId) ?? []) {
|
|
473
|
-
ids.add(edge.fromSymbolId);
|
|
474
|
-
}
|
|
475
|
-
const limited = new Set(Array.from(ids).slice(0, maxNodes));
|
|
476
|
-
const nodes = await buildNodes(conn, Array.from(limited));
|
|
477
|
-
const links = await buildLinksForNodes(conn, limited);
|
|
478
|
-
return {
|
|
479
|
-
nodes: collapseClusters(nodes),
|
|
480
|
-
links,
|
|
481
|
-
};
|
|
482
394
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
const symbolIds = top.map((row) => row.symbolId);
|
|
486
|
-
const ids = new Set(symbolIds);
|
|
487
|
-
const nodes = await buildNodes(conn, symbolIds);
|
|
488
|
-
const links = await buildLinksForNodes(conn, ids);
|
|
489
|
-
return {
|
|
490
|
-
nodes: collapseClusters(nodes),
|
|
491
|
-
links,
|
|
492
|
-
};
|
|
493
|
-
}
|
|
494
|
-
export async function buildGraphForSliceHandle(conn, repoId, handle, maxNodes, deps = {}) {
|
|
495
|
-
const getSliceHandleFn = deps.getSliceHandle ?? ladybugDb.getSliceHandle;
|
|
496
|
-
const buildRepoPreviewFn = deps.buildRepoPreview ?? buildRepoPreview;
|
|
497
|
-
const buildBlastRadiusGraphFn = deps.buildBlastRadiusGraph ?? buildBlastRadiusGraph;
|
|
498
|
-
const handleRow = await getSliceHandleFn(conn, handle);
|
|
499
|
-
if (!handleRow || handleRow.repoId !== repoId) {
|
|
395
|
+
function getPrefixUiAsset(pathname) {
|
|
396
|
+
if (!pathname.startsWith("/ui/viewer/") && !pathname.startsWith("/ui/vendor/")) {
|
|
500
397
|
return null;
|
|
501
398
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
}
|
|
505
|
-
return buildRepoPreviewFn(conn, repoId, maxNodes);
|
|
399
|
+
const file = pathname.slice("/ui/".length);
|
|
400
|
+
const type = contentTypeForUiPath(file);
|
|
401
|
+
return type ? { file, type } : null;
|
|
506
402
|
}
|
|
507
|
-
|
|
508
|
-
const
|
|
509
|
-
const
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
runDiagnostics: false,
|
|
514
|
-
});
|
|
515
|
-
const ids = new Set();
|
|
516
|
-
for (const changed of delta.changedSymbols) {
|
|
517
|
-
ids.add(changed.symbolId);
|
|
518
|
-
}
|
|
519
|
-
for (const affected of governor.blastRadius) {
|
|
520
|
-
ids.add(affected.symbolId);
|
|
403
|
+
function resolveUiAssetPath(file) {
|
|
404
|
+
const rootDir = resolve(UI_DIR);
|
|
405
|
+
const fullPath = resolve(rootDir, file);
|
|
406
|
+
const relativePath = relative(rootDir, fullPath);
|
|
407
|
+
if (relativePath.startsWith("..") || isAbsolute(relativePath)) {
|
|
408
|
+
return null;
|
|
521
409
|
}
|
|
522
|
-
|
|
523
|
-
const nodes = await buildNodes(conn, Array.from(limited));
|
|
524
|
-
const links = await buildLinksForNodes(conn, limited);
|
|
525
|
-
return {
|
|
526
|
-
nodes: collapseClusters(nodes),
|
|
527
|
-
links,
|
|
528
|
-
};
|
|
410
|
+
return fullPath;
|
|
529
411
|
}
|
|
530
|
-
// ---------------------------------------------------------------------------
|
|
531
|
-
// Static UI assets
|
|
532
|
-
// ---------------------------------------------------------------------------
|
|
533
412
|
function serveUiAsset(pathname, res) {
|
|
413
|
+
if (pathname === "/ui/graph" || pathname === "/ui/graph.html") {
|
|
414
|
+
res.writeHead(308, { Location: "/ui/viewer" });
|
|
415
|
+
res.end();
|
|
416
|
+
return true;
|
|
417
|
+
}
|
|
534
418
|
const map = {
|
|
535
|
-
"/ui/
|
|
536
|
-
"/ui/
|
|
537
|
-
file: "graph.js",
|
|
538
|
-
type: "application/javascript; charset=utf-8",
|
|
539
|
-
},
|
|
540
|
-
"/ui/graph.css": { file: "graph.css", type: "text/css; charset=utf-8" },
|
|
419
|
+
"/ui/viewer": { file: "viewer/index.html", type: "text/html; charset=utf-8" },
|
|
420
|
+
"/ui/viewer/index.html": { file: "viewer/index.html", type: "text/html; charset=utf-8" },
|
|
541
421
|
"/ui/observability": {
|
|
542
422
|
file: "observability.html",
|
|
543
423
|
type: "text/html; charset=utf-8",
|
|
@@ -561,11 +441,15 @@ function serveUiAsset(pathname, res) {
|
|
|
561
441
|
},
|
|
562
442
|
"/ui/config.css": { file: "config.css", type: "text/css; charset=utf-8" },
|
|
563
443
|
};
|
|
564
|
-
const asset = map[pathname];
|
|
444
|
+
const asset = map[pathname] ?? getPrefixUiAsset(pathname);
|
|
565
445
|
if (!asset) {
|
|
566
446
|
return false;
|
|
567
447
|
}
|
|
568
|
-
const fullPath =
|
|
448
|
+
const fullPath = resolveUiAssetPath(asset.file);
|
|
449
|
+
if (!fullPath) {
|
|
450
|
+
json(res, 404, { error: "UI asset not found" });
|
|
451
|
+
return true;
|
|
452
|
+
}
|
|
569
453
|
try {
|
|
570
454
|
if (!statSync(fullPath).isFile()) {
|
|
571
455
|
json(res, 500, { error: "Failed to read UI asset" });
|
|
@@ -599,15 +483,18 @@ function serveUiAsset(pathname, res) {
|
|
|
599
483
|
res.destroy(error instanceof Error ? error : undefined);
|
|
600
484
|
});
|
|
601
485
|
stream.once("open", () => {
|
|
602
|
-
res.writeHead(200, { "Content-Type": asset.type });
|
|
486
|
+
res.writeHead(200, { "Content-Type": asset.type, "Cache-Control": "no-cache" });
|
|
603
487
|
stream.pipe(res);
|
|
604
488
|
});
|
|
605
489
|
return true;
|
|
606
490
|
}
|
|
607
491
|
// ---------------------------------------------------------------------------
|
|
608
492
|
function serveObservabilityUiAsset(pathname, res) {
|
|
609
|
-
if (!OBSERVABILITY_UI_PATHS.has(pathname)
|
|
493
|
+
if (!OBSERVABILITY_UI_PATHS.has(pathname) &&
|
|
494
|
+
!pathname.startsWith("/ui/viewer/") &&
|
|
495
|
+
!pathname.startsWith("/ui/vendor/")) {
|
|
610
496
|
return false;
|
|
497
|
+
}
|
|
611
498
|
return serveUiAsset(pathname, res);
|
|
612
499
|
}
|
|
613
500
|
async function handleHealthRequest(req, res, checkHealth) {
|
|
@@ -695,6 +582,87 @@ async function routeObservabilityApiRequest(req, res, url, services) {
|
|
|
695
582
|
json(res, 503, { error: "observability_disabled" });
|
|
696
583
|
return true;
|
|
697
584
|
}
|
|
585
|
+
if ((url.searchParams.get("types") ?? "").trim() === "graph") {
|
|
586
|
+
setCorsHeaders(req, res);
|
|
587
|
+
res.writeHead(200, {
|
|
588
|
+
"Content-Type": "text/event-stream",
|
|
589
|
+
"Cache-Control": "no-cache, no-transform",
|
|
590
|
+
Connection: "keep-alive",
|
|
591
|
+
"X-Accel-Buffering": "no",
|
|
592
|
+
});
|
|
593
|
+
let closed = false;
|
|
594
|
+
let unsubscribe = null;
|
|
595
|
+
let heartbeatTimer = null;
|
|
596
|
+
let maxStreamTimer = null;
|
|
597
|
+
const sendGraphEvent = (data) => {
|
|
598
|
+
if (closed || res.destroyed)
|
|
599
|
+
return false;
|
|
600
|
+
try {
|
|
601
|
+
const ok = res.write(`event: graph\ndata: ${JSON.stringify(data)}\n\n`);
|
|
602
|
+
return ok && res.writableLength <= 1_048_576;
|
|
603
|
+
}
|
|
604
|
+
catch (err) {
|
|
605
|
+
logger.warn("Graph SSE write failed", { error: err });
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
const cleanupGraph = () => {
|
|
610
|
+
if (closed)
|
|
611
|
+
return;
|
|
612
|
+
closed = true;
|
|
613
|
+
if (heartbeatTimer) {
|
|
614
|
+
clearInterval(heartbeatTimer);
|
|
615
|
+
heartbeatTimer = null;
|
|
616
|
+
}
|
|
617
|
+
if (maxStreamTimer) {
|
|
618
|
+
clearTimeout(maxStreamTimer);
|
|
619
|
+
maxStreamTimer = null;
|
|
620
|
+
}
|
|
621
|
+
if (unsubscribe) {
|
|
622
|
+
unsubscribe();
|
|
623
|
+
unsubscribe = null;
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
const endGraphStream = () => {
|
|
627
|
+
cleanupGraph();
|
|
628
|
+
try {
|
|
629
|
+
res.end();
|
|
630
|
+
}
|
|
631
|
+
catch {
|
|
632
|
+
/* best-effort */
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
req.on("close", cleanupGraph);
|
|
636
|
+
for (const event of observabilityService.getRecentGraphEvents(200)) {
|
|
637
|
+
if (!sendGraphEvent(event)) {
|
|
638
|
+
endGraphStream();
|
|
639
|
+
return true;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
unsubscribe = observabilityService.onGraphEvent((event) => {
|
|
643
|
+
if (!sendGraphEvent(event)) {
|
|
644
|
+
endGraphStream();
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
heartbeatTimer = setInterval(() => {
|
|
648
|
+
if (closed || res.destroyed) {
|
|
649
|
+
cleanupGraph();
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
try {
|
|
653
|
+
res.write(": heartbeat\n\n");
|
|
654
|
+
}
|
|
655
|
+
catch {
|
|
656
|
+
endGraphStream();
|
|
657
|
+
}
|
|
658
|
+
}, sseHeartbeatMs);
|
|
659
|
+
heartbeatTimer.unref();
|
|
660
|
+
maxStreamTimer = setTimeout(() => {
|
|
661
|
+
endGraphStream();
|
|
662
|
+
}, sseMaxStreamMs);
|
|
663
|
+
maxStreamTimer.unref();
|
|
664
|
+
return true;
|
|
665
|
+
}
|
|
698
666
|
const repoId = (url.searchParams.get("repoId") ?? "").trim();
|
|
699
667
|
if (!repoId) {
|
|
700
668
|
json(res, 400, { error: "missing_repoId" });
|
|
@@ -821,6 +789,10 @@ export async function handleObservabilityDashboardRequest(req, res, host, port,
|
|
|
821
789
|
return true;
|
|
822
790
|
}
|
|
823
791
|
try {
|
|
792
|
+
if (pathname.startsWith("/api/graph/") &&
|
|
793
|
+
(await handleViewerApiRequest(req, res, pathname, url, services.observabilityService ?? null))) {
|
|
794
|
+
return true;
|
|
795
|
+
}
|
|
824
796
|
return await routeObservabilityApiRequest(req, res, url, services);
|
|
825
797
|
}
|
|
826
798
|
catch (error) {
|
|
@@ -899,9 +871,12 @@ async function handleRestRequest(req, res, host, port, checkHealth, services) {
|
|
|
899
871
|
return true;
|
|
900
872
|
}
|
|
901
873
|
}
|
|
902
|
-
// DB-dependent REST API routes
|
|
874
|
+
// DB-dependent REST API routes — wrapped in try/catch for structured errors.
|
|
903
875
|
// Connection is acquired lazily per-route to avoid unnecessary pool checkouts.
|
|
904
876
|
try {
|
|
877
|
+
if (await handleViewerApiRequest(req, res, pathname, url, services.observabilityService)) {
|
|
878
|
+
return true;
|
|
879
|
+
}
|
|
905
880
|
const graphSliceMatch = pathname.match(/^\/api\/graph\/([^/]+)\/slice\/([^/]+)$/);
|
|
906
881
|
if (req.method === "GET" && graphSliceMatch) {
|
|
907
882
|
const conn = await getLadybugConn();
|
|
@@ -1030,7 +1005,7 @@ async function handleRestRequest(req, res, host, port, checkHealth, services) {
|
|
|
1030
1005
|
});
|
|
1031
1006
|
return true;
|
|
1032
1007
|
}
|
|
1033
|
-
// SSE streaming reindex endpoint
|
|
1008
|
+
// SSE streaming reindex endpoint — streams progress events, then a
|
|
1034
1009
|
// final "complete" or "error" event. Used by `sdl-mcp index` when it
|
|
1035
1010
|
// detects a running HTTP server and delegates indexing.
|
|
1036
1011
|
const reindexStreamMatch = pathname.match(/^\/api\/repo\/([^/]+)\/reindex-stream$/);
|
|
@@ -1049,7 +1024,7 @@ async function handleRestRequest(req, res, host, port, checkHealth, services) {
|
|
|
1049
1024
|
}
|
|
1050
1025
|
}
|
|
1051
1026
|
catch {
|
|
1052
|
-
// Empty or invalid body
|
|
1027
|
+
// Empty or invalid body — use default mode
|
|
1053
1028
|
}
|
|
1054
1029
|
// Set up SSE response
|
|
1055
1030
|
setCorsHeaders(req, res);
|
|
@@ -1234,7 +1209,7 @@ async function handleMcpStreamableRequest(req, res, ctx) {
|
|
|
1234
1209
|
ctx.cleanupSession(registeredSessionId);
|
|
1235
1210
|
}
|
|
1236
1211
|
else {
|
|
1237
|
-
// MCPServer was created but never connected
|
|
1212
|
+
// MCPServer was created but never connected — stop it directly
|
|
1238
1213
|
void mcpServer.stop().catch((err) => {
|
|
1239
1214
|
logger.debug("Failed to stop unconnected MCP server", {
|
|
1240
1215
|
error: err,
|
|
@@ -1305,7 +1280,7 @@ async function handleMcpStreamableRequest(req, res, ctx) {
|
|
|
1305
1280
|
}
|
|
1306
1281
|
}
|
|
1307
1282
|
/**
|
|
1308
|
-
* Handle `GET /sse`
|
|
1283
|
+
* Handle `GET /sse` — establishes a new SSE (deprecated) transport session.
|
|
1309
1284
|
* Validates the `Accept: text/event-stream` header, reserves a session slot,
|
|
1310
1285
|
* creates the SSEServerTransport, and connects a new per-session MCP server.
|
|
1311
1286
|
*/
|
|
@@ -1364,7 +1339,7 @@ async function handleSseConnection(req, res, ctx) {
|
|
|
1364
1339
|
}
|
|
1365
1340
|
}
|
|
1366
1341
|
/**
|
|
1367
|
-
* Handle `POST /message`
|
|
1342
|
+
* Handle `POST /message` — routes an incoming MCP message to an existing SSE
|
|
1368
1343
|
* (deprecated) session identified by the `sessionId` query parameter.
|
|
1369
1344
|
*/
|
|
1370
1345
|
function handleSseMessage(req, res, url, ctx) {
|
|
@@ -1436,7 +1411,8 @@ export async function setupObservabilityDashboardSidecar(port, services = {}, ht
|
|
|
1436
1411
|
const url = new URL(req.url ?? "/", `http://${host}:${port}`);
|
|
1437
1412
|
const pathname = url.pathname;
|
|
1438
1413
|
if (req.method !== "OPTIONS" &&
|
|
1439
|
-
pathname.startsWith("/api/observability/")
|
|
1414
|
+
(pathname.startsWith("/api/observability/") ||
|
|
1415
|
+
pathname.startsWith("/api/graph/")) &&
|
|
1440
1416
|
authToken &&
|
|
1441
1417
|
!isAuthorized(req, authToken)) {
|
|
1442
1418
|
const rateLimit = authRateLimiter.consume(getAuthRateLimitKey(req));
|
|
@@ -1536,7 +1512,7 @@ export async function setupHttpTransport(host, port, _graphDbPath, services = {}
|
|
|
1536
1512
|
const cleanedUp = new Set();
|
|
1537
1513
|
const sessionManager = services.sessionManager ?? new SessionManager(8);
|
|
1538
1514
|
/**
|
|
1539
|
-
* Idempotent session cleanup
|
|
1515
|
+
* Idempotent session cleanup — safe to call from onclose, idle reaper,
|
|
1540
1516
|
* error handlers, or graceful shutdown. Cleans transport, MCPServer, and
|
|
1541
1517
|
* session manager state exactly once per session.
|
|
1542
1518
|
*/
|
|
@@ -1584,7 +1560,7 @@ export async function setupHttpTransport(host, port, _graphDbPath, services = {}
|
|
|
1584
1560
|
effectiveServices,
|
|
1585
1561
|
cleanupSession,
|
|
1586
1562
|
};
|
|
1587
|
-
// DB is already initialized by serve.ts
|
|
1563
|
+
// DB is already initialized by serve.ts → initGraphDb() before this
|
|
1588
1564
|
// function is called. A redundant initLadybugDb() here risked a
|
|
1589
1565
|
// close+reopen cycle when normalizeGraphDbPath() returned a different
|
|
1590
1566
|
// path (the DB directory now exists, flipping the hint from "file" to
|
|
@@ -1616,7 +1592,7 @@ export async function setupHttpTransport(host, port, _graphDbPath, services = {}
|
|
|
1616
1592
|
(pathname === "/.well-known/oauth-authorization-server" ||
|
|
1617
1593
|
pathname === "/.well-known/oauth-protected-resource")) {
|
|
1618
1594
|
json(res, 404, {
|
|
1619
|
-
error: "OAuth discovery not supported
|
|
1595
|
+
error: "OAuth discovery not supported — this server does not require authentication",
|
|
1620
1596
|
});
|
|
1621
1597
|
return;
|
|
1622
1598
|
}
|
|
@@ -1666,14 +1642,14 @@ export async function setupHttpTransport(host, port, _graphDbPath, services = {}
|
|
|
1666
1642
|
return;
|
|
1667
1643
|
}
|
|
1668
1644
|
// ---------------------------------------------------------------
|
|
1669
|
-
// Streamable HTTP Transport
|
|
1645
|
+
// Streamable HTTP Transport — /mcp (POST, GET, DELETE)
|
|
1670
1646
|
// ---------------------------------------------------------------
|
|
1671
1647
|
if (pathname === "/mcp") {
|
|
1672
1648
|
await handleMcpStreamableRequest(req, res, sessionCtx);
|
|
1673
1649
|
return;
|
|
1674
1650
|
}
|
|
1675
1651
|
// ---------------------------------------------------------------
|
|
1676
|
-
// Deprecated SSE Transport
|
|
1652
|
+
// Deprecated SSE Transport — /sse (GET) + /message (POST)
|
|
1677
1653
|
// Supports multiple concurrent SSE sessions (no singleton)
|
|
1678
1654
|
// ---------------------------------------------------------------
|
|
1679
1655
|
if (req.method === "GET" && pathname === "/sse") {
|
|
@@ -1734,7 +1710,7 @@ export async function setupHttpTransport(host, port, _graphDbPath, services = {}
|
|
|
1734
1710
|
console.error(` - SSE endpoint: http://${host}:${actualPort}/sse`);
|
|
1735
1711
|
console.error(` - Sessions: http://${host}:${actualPort}/api/sessions`);
|
|
1736
1712
|
console.error(` - Health check: http://${host}:${actualPort}/health`);
|
|
1737
|
-
console.error(` - Graph UI: http://${host}:${actualPort}/ui/
|
|
1713
|
+
console.error(` - Graph UI: http://${host}:${actualPort}/ui/viewer`);
|
|
1738
1714
|
if (host !== "localhost" && host !== "127.0.0.1" && host !== "::1") {
|
|
1739
1715
|
console.error(`\n WARNING: Server is listening on ${host} over plaintext HTTP.` +
|
|
1740
1716
|
`\n Traffic (including code content) is NOT encrypted.` +
|