@syke1/mcp-server 1.4.6 → 1.4.8
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/dist/index.js +7 -4
- package/dist/web/public/app.js +16 -2
- package/dist/web/server.js +13 -16
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -621,11 +621,14 @@ async function main() {
|
|
|
621
621
|
const dashUrl = `http://localhost:${WEB_PORT}`;
|
|
622
622
|
console.error(`[syke] Web dashboard: ${dashUrl}`);
|
|
623
623
|
// Auto-open browser (disable with SYKE_NO_BROWSER=1)
|
|
624
|
+
// Delay 1s to let server fully stabilize before dashboard connects
|
|
624
625
|
if (process.env.SYKE_NO_BROWSER !== "1") {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
: `
|
|
628
|
-
|
|
626
|
+
setTimeout(() => {
|
|
627
|
+
const cmd = process.platform === "win32" ? `start ${dashUrl}`
|
|
628
|
+
: process.platform === "darwin" ? `open ${dashUrl}`
|
|
629
|
+
: `xdg-open ${dashUrl}`;
|
|
630
|
+
(0, child_process_1.exec)(cmd, () => { });
|
|
631
|
+
}, 1000);
|
|
629
632
|
}
|
|
630
633
|
});
|
|
631
634
|
}
|
package/dist/web/public/app.js
CHANGED
|
@@ -2734,11 +2734,17 @@ window.syke = {
|
|
|
2734
2734
|
let sseSource = null;
|
|
2735
2735
|
let sseReconnectTimer = null;
|
|
2736
2736
|
let sseBlocked = false;
|
|
2737
|
+
let sseEverConnected = false; // track if SSE has ever connected successfully
|
|
2737
2738
|
const realtimeLog = []; // recent events for panel
|
|
2738
2739
|
|
|
2739
2740
|
async function initSSE() {
|
|
2740
2741
|
if (sseSource) { sseSource.close(); sseSource = null; }
|
|
2741
2742
|
|
|
2743
|
+
// Show appropriate status based on whether we've connected before
|
|
2744
|
+
if (!sseEverConnected) {
|
|
2745
|
+
updateSSEStatus("CONNECTING...", "warning");
|
|
2746
|
+
}
|
|
2747
|
+
|
|
2742
2748
|
// Pre-check: if Free tier, SSE will 403 — don't attempt connection
|
|
2743
2749
|
try {
|
|
2744
2750
|
const probe = await fetch("/api/events");
|
|
@@ -2749,7 +2755,14 @@ async function initSSE() {
|
|
|
2749
2755
|
}
|
|
2750
2756
|
// Close the successful probe connection (we'll open EventSource next)
|
|
2751
2757
|
if (probe.body) probe.body.cancel().catch(() => {});
|
|
2752
|
-
} catch(e) {
|
|
2758
|
+
} catch(e) {
|
|
2759
|
+
// Server not ready yet — retry after short delay on first attempt
|
|
2760
|
+
if (!sseEverConnected) {
|
|
2761
|
+
if (sseReconnectTimer) clearTimeout(sseReconnectTimer);
|
|
2762
|
+
sseReconnectTimer = setTimeout(() => { initSSE(); }, 2000);
|
|
2763
|
+
return;
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2753
2766
|
|
|
2754
2767
|
sseSource = new EventSource("/api/events");
|
|
2755
2768
|
|
|
@@ -2757,6 +2770,7 @@ async function initSSE() {
|
|
|
2757
2770
|
const data = JSON.parse(e.data);
|
|
2758
2771
|
console.log("[SYKE:SSE] Connected, cache:", data.cacheSize, "files");
|
|
2759
2772
|
healthFailCount = 0; // Reset health failures on SSE connect
|
|
2773
|
+
sseEverConnected = true;
|
|
2760
2774
|
updateSSEStatus("LIVE", "connected");
|
|
2761
2775
|
});
|
|
2762
2776
|
|
|
@@ -2949,7 +2963,7 @@ async function initSSE() {
|
|
|
2949
2963
|
if (sseBlocked) return;
|
|
2950
2964
|
|
|
2951
2965
|
sseRetryCount++;
|
|
2952
|
-
updateSSEStatus("RECONNECTING...", "warning");
|
|
2966
|
+
updateSSEStatus(sseEverConnected ? "RECONNECTING..." : "CONNECTING...", "warning");
|
|
2953
2967
|
|
|
2954
2968
|
// Only show offline after 5 consecutive SSE failures
|
|
2955
2969
|
if (sseRetryCount >= 5) {
|
package/dist/web/server.js
CHANGED
|
@@ -230,6 +230,11 @@ function getAllWarnings() {
|
|
|
230
230
|
function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProjectRoot, getPackageName, getLicenseStatus, hasAIKeyFn, setLicenseKeyFn, setAIKeyFn, getAIInfoFn) {
|
|
231
231
|
const app = (0, express_1.default)();
|
|
232
232
|
app.use(express_1.default.json());
|
|
233
|
+
/** Check if current license is Pro (includes pro_trial) */
|
|
234
|
+
function isProPlan() {
|
|
235
|
+
const license = getLicenseStatus?.();
|
|
236
|
+
return license?.plan === "pro" || license?.plan === "pro_trial";
|
|
237
|
+
}
|
|
233
238
|
// Serve static files from public/
|
|
234
239
|
const publicDir = path.join(__dirname, "public");
|
|
235
240
|
app.use(express_1.default.static(publicDir));
|
|
@@ -264,8 +269,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
|
|
|
264
269
|
}
|
|
265
270
|
app.get("/api/events", (_req, res) => {
|
|
266
271
|
// Pro-only: real-time monitoring via SSE
|
|
267
|
-
|
|
268
|
-
if (!license || license.plan !== "pro") {
|
|
272
|
+
if (!isProPlan()) {
|
|
269
273
|
res.status(403).json(getProFeatureError("Real-time monitoring"));
|
|
270
274
|
return;
|
|
271
275
|
}
|
|
@@ -315,8 +319,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
|
|
|
315
319
|
timestamp: change.timestamp,
|
|
316
320
|
});
|
|
317
321
|
// Run Gemini real-time analysis (Pro only)
|
|
318
|
-
|
|
319
|
-
if (license && license.plan === "pro") {
|
|
322
|
+
if (isProPlan()) {
|
|
320
323
|
broadcastSSE("analysis-start", { file: change.relativePath });
|
|
321
324
|
try {
|
|
322
325
|
const analysis = await (0, realtime_analyzer_1.analyzeChangeRealtime)(change, graph, (relPath) => currentFileCache?.getFileByRelPath(relPath) ?? null);
|
|
@@ -366,8 +369,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
|
|
|
366
369
|
// GET /api/graph — Cytoscape.js compatible JSON
|
|
367
370
|
app.get("/api/graph", (_req, res) => {
|
|
368
371
|
const graph = getGraphFn();
|
|
369
|
-
const
|
|
370
|
-
const isPro = license?.plan === "pro";
|
|
372
|
+
const isPro = isProPlan();
|
|
371
373
|
const FREE_GRAPH_LIMIT = 50;
|
|
372
374
|
const nodes = [];
|
|
373
375
|
const edges = [];
|
|
@@ -460,8 +462,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
|
|
|
460
462
|
});
|
|
461
463
|
// POST /api/ai-analyze — AI semantic analysis (Pro or BYOK)
|
|
462
464
|
app.post("/api/ai-analyze", async (req, res) => {
|
|
463
|
-
const
|
|
464
|
-
const isPro = license?.plan === "pro";
|
|
465
|
+
const isPro = isProPlan();
|
|
465
466
|
const hasKey = hasAIKeyFn?.() || false;
|
|
466
467
|
if (!isPro && !hasKey) {
|
|
467
468
|
return res.status(403).json({
|
|
@@ -498,8 +499,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
|
|
|
498
499
|
});
|
|
499
500
|
// GET /api/hub-files — Top hub files ranking (Pro only)
|
|
500
501
|
app.get("/api/hub-files", (req, res) => {
|
|
501
|
-
|
|
502
|
-
if (!license || license.plan !== "pro") {
|
|
502
|
+
if (!isProPlan()) {
|
|
503
503
|
return res.status(403).json(getProFeatureError("Hub files ranking"));
|
|
504
504
|
}
|
|
505
505
|
const requested = parseInt(req.query.top) || 10;
|
|
@@ -573,8 +573,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
|
|
|
573
573
|
});
|
|
574
574
|
// GET /api/cycles — Detect circular dependencies (Pro only)
|
|
575
575
|
app.get("/api/cycles", (_req, res) => {
|
|
576
|
-
|
|
577
|
-
if (!license || license.plan !== "pro") {
|
|
576
|
+
if (!isProPlan()) {
|
|
578
577
|
return res.status(403).json(getProFeatureError("Cycle detection"));
|
|
579
578
|
}
|
|
580
579
|
const graph = getGraphFn();
|
|
@@ -661,8 +660,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
|
|
|
661
660
|
});
|
|
662
661
|
// GET /api/simulate-delete/:file — Simulate file removal (Pro only)
|
|
663
662
|
app.get("/api/simulate-delete/*splat", (req, res) => {
|
|
664
|
-
|
|
665
|
-
if (!license || license.plan !== "pro") {
|
|
663
|
+
if (!isProPlan()) {
|
|
666
664
|
return res.status(403).json(getProFeatureError("Delete simulation"));
|
|
667
665
|
}
|
|
668
666
|
const splat = req.params.splat;
|
|
@@ -841,8 +839,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
|
|
|
841
839
|
}
|
|
842
840
|
const normalized = path.normalize(projectRoot);
|
|
843
841
|
// Free tier: only 1 project allowed — block switch to a different project
|
|
844
|
-
|
|
845
|
-
if (!license || license.plan !== "pro") {
|
|
842
|
+
if (!isProPlan()) {
|
|
846
843
|
const currentRoot = getProjectRoot ? path.normalize(getProjectRoot()) : null;
|
|
847
844
|
if (currentRoot && normalized !== currentRoot) {
|
|
848
845
|
return res.status(403).json({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syke1/mcp-server",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.8",
|
|
4
4
|
"mcpName": "io.github.khalomsky/syke",
|
|
5
5
|
"description": "AI code impact analysis MCP server — dependency graphs, cascade detection, and a mandatory build gate for AI coding agents",
|
|
6
6
|
"main": "dist/index.js",
|