@syke1/mcp-server 1.3.10 → 1.3.11
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/web/public/app.js +109 -3
- package/package.json +1 -1
package/dist/web/public/app.js
CHANGED
|
@@ -18,6 +18,8 @@ let crawlData = null;
|
|
|
18
18
|
let modifyingNodes = new Set(); // nodes currently being modified by AI
|
|
19
19
|
let heartbeatNodes = new Map(); // nodeId → { riskLevel, startTime, interval }
|
|
20
20
|
let diffScrollAnim = null; // animation for diff scroll
|
|
21
|
+
let knownNodeIds = new Set(); // track existing nodes for star-birth detection
|
|
22
|
+
let birthAnimations = new Map(); // nodeId → { startTime, spawnPos, targetPos }
|
|
21
23
|
|
|
22
24
|
const LAYER_HEX = {
|
|
23
25
|
FE: "#00d4ff", BE: "#c084fc", DB: "#ff6b35",
|
|
@@ -108,20 +110,62 @@ async function loadGraph() {
|
|
|
108
110
|
}
|
|
109
111
|
hideWelcomeOverlay();
|
|
110
112
|
|
|
113
|
+
const isReload = Graph !== null;
|
|
114
|
+
|
|
115
|
+
// Spawn point for new nodes (top-right corner of 3D space)
|
|
116
|
+
const SPAWN = { x: 5000, y: 4000, z: -2000 };
|
|
117
|
+
|
|
118
|
+
// Preserve existing node positions on reload
|
|
119
|
+
const currentPositions = {};
|
|
120
|
+
if (isReload) {
|
|
121
|
+
const cur = Graph.graphData();
|
|
122
|
+
cur.nodes.forEach(n => {
|
|
123
|
+
currentPositions[n.id] = { x: n.x, y: n.y, z: n.z };
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
111
127
|
const nodes = raw.nodes.map(n => {
|
|
112
128
|
const layer = n.data.layer || "UTIL";
|
|
113
129
|
const c = LAYER_CENTERS[layer] || LAYER_CENTERS.UTIL;
|
|
130
|
+
const isNew = knownNodeIds.size > 0 && !knownNodeIds.has(n.data.id);
|
|
131
|
+
|
|
132
|
+
// For existing nodes on reload: keep their current simulated position
|
|
133
|
+
const targetPos = currentPositions[n.data.id] || {
|
|
134
|
+
x: c.x + (Math.random() - 0.5) * 600,
|
|
135
|
+
y: c.y + (Math.random() - 0.5) * 600,
|
|
136
|
+
z: c.z + (Math.random() - 0.5) * 600,
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// New node: spawn from far corner, will animate to target
|
|
140
|
+
if (isNew) {
|
|
141
|
+
console.log("[SYKE] ★ Star birth:", n.data.id);
|
|
142
|
+
birthAnimations.set(n.data.id, {
|
|
143
|
+
startTime: Date.now(),
|
|
144
|
+
spawnPos: { ...SPAWN },
|
|
145
|
+
targetPos: { ...targetPos },
|
|
146
|
+
duration: 2500, // 2.5s flight time
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
114
150
|
return {
|
|
115
151
|
id: n.data.id, label: n.data.label, fullPath: n.data.fullPath,
|
|
116
152
|
riskLevel: n.data.riskLevel, dependentCount: n.data.dependentCount,
|
|
117
153
|
lineCount: n.data.lineCount || 0, importsCount: n.data.importsCount || 0,
|
|
118
154
|
depth: n.data.depth || 0, group: n.data.group,
|
|
119
155
|
layer, action: n.data.action || "X", env: n.data.env || "PROD",
|
|
120
|
-
x:
|
|
121
|
-
y:
|
|
122
|
-
z:
|
|
156
|
+
x: isNew ? SPAWN.x : targetPos.x,
|
|
157
|
+
y: isNew ? SPAWN.y : targetPos.y,
|
|
158
|
+
z: isNew ? SPAWN.z : targetPos.z,
|
|
159
|
+
// Pin new nodes at SPAWN so simulation doesn't skip their animation
|
|
160
|
+
fx: isNew ? SPAWN.x : undefined,
|
|
161
|
+
fy: isNew ? SPAWN.y : undefined,
|
|
162
|
+
fz: isNew ? SPAWN.z : undefined,
|
|
163
|
+
_isNew: isNew,
|
|
123
164
|
};
|
|
124
165
|
});
|
|
166
|
+
|
|
167
|
+
// Update known node IDs
|
|
168
|
+
knownNodeIds = new Set(nodes.map(n => n.id));
|
|
125
169
|
const links = raw.edges.map(e => ({ source: e.data.source, target: e.data.target }));
|
|
126
170
|
graphData = { nodes, links };
|
|
127
171
|
|
|
@@ -133,6 +177,15 @@ async function loadGraph() {
|
|
|
133
177
|
const highRisk = nodes.filter(n => n.riskLevel === "HIGH").length;
|
|
134
178
|
document.getElementById("stat-high").textContent = highRisk;
|
|
135
179
|
|
|
180
|
+
// ── RELOAD: just update data, no graph re-creation ──
|
|
181
|
+
if (isReload) {
|
|
182
|
+
Graph.graphData(graphData);
|
|
183
|
+
buildLegend(layerCounts);
|
|
184
|
+
console.log("[SYKE] Graph updated (reload), birth animations:", birthAnimations.size);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ── FIRST LOAD: create new Graph instance ──
|
|
136
189
|
const container = document.getElementById("3d-graph");
|
|
137
190
|
|
|
138
191
|
Graph = ForceGraph3D()(container)
|
|
@@ -158,6 +211,14 @@ async function loadGraph() {
|
|
|
158
211
|
const pulse = 0.5 + 0.5 * Math.sin(Date.now() / 200);
|
|
159
212
|
return base * (1 + pulse * 0.4);
|
|
160
213
|
}
|
|
214
|
+
// Star birth: start large, shrink to normal
|
|
215
|
+
const birth = birthAnimations.get(node.id);
|
|
216
|
+
if (birth) {
|
|
217
|
+
const t = Math.min(1, (Date.now() - birth.startTime) / birth.duration);
|
|
218
|
+
if (t >= 1) birthAnimations.delete(node.id);
|
|
219
|
+
const scale = 1 + (3 - 1) * (1 - t) * (1 - t); // ease-out: 3x → 1x
|
|
220
|
+
return base * scale;
|
|
221
|
+
}
|
|
161
222
|
return base;
|
|
162
223
|
})
|
|
163
224
|
.nodeOpacity(1.0)
|
|
@@ -220,6 +281,31 @@ async function loadGraph() {
|
|
|
220
281
|
node.fz = undefined;
|
|
221
282
|
})
|
|
222
283
|
|
|
284
|
+
// Star birth: animate pinned position from SPAWN → target on each tick
|
|
285
|
+
.onEngineTick(() => {
|
|
286
|
+
if (birthAnimations.size === 0) return;
|
|
287
|
+
const now = Date.now();
|
|
288
|
+
for (const [nodeId, anim] of birthAnimations) {
|
|
289
|
+
const node = graphData.nodes.find(n => n.id === nodeId);
|
|
290
|
+
if (!node) continue;
|
|
291
|
+
const t = Math.min(1, (now - anim.startTime) / anim.duration);
|
|
292
|
+
if (t < 1) {
|
|
293
|
+
// Ease-out cubic: fast start, gentle landing
|
|
294
|
+
const ease = 1 - Math.pow(1 - t, 3);
|
|
295
|
+
node.fx = anim.spawnPos.x + (anim.targetPos.x - anim.spawnPos.x) * ease;
|
|
296
|
+
node.fy = anim.spawnPos.y + (anim.targetPos.y - anim.spawnPos.y) * ease;
|
|
297
|
+
node.fz = anim.spawnPos.z + (anim.targetPos.z - anim.spawnPos.z) * ease;
|
|
298
|
+
} else {
|
|
299
|
+
// Animation done: unpin, let simulation fine-tune position
|
|
300
|
+
node.fx = undefined;
|
|
301
|
+
node.fy = undefined;
|
|
302
|
+
node.fz = undefined;
|
|
303
|
+
birthAnimations.delete(nodeId);
|
|
304
|
+
console.log("[SYKE] ★ Star birth complete:", nodeId);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
})
|
|
308
|
+
|
|
223
309
|
.d3AlphaDecay(0.008)
|
|
224
310
|
.d3VelocityDecay(0.3)
|
|
225
311
|
.warmupTicks(300)
|
|
@@ -377,6 +463,26 @@ function getNodeColor(node) {
|
|
|
377
463
|
return `rgb(${r},${g},${b})`;
|
|
378
464
|
}
|
|
379
465
|
|
|
466
|
+
// Star birth: bright white → cyan → normal layer color
|
|
467
|
+
const birth = birthAnimations.get(node.id);
|
|
468
|
+
if (birth) {
|
|
469
|
+
const t = Math.min(1, (Date.now() - birth.startTime) / birth.duration);
|
|
470
|
+
const layerHex = LAYER_HEX[node.layer] || "#ff69b4";
|
|
471
|
+
const lr = parseInt(layerHex.slice(1,3),16);
|
|
472
|
+
const lg = parseInt(layerHex.slice(3,5),16);
|
|
473
|
+
const lb = parseInt(layerHex.slice(5,7),16);
|
|
474
|
+
if (t < 0.3) {
|
|
475
|
+
// Phase 1: white → cyan flash
|
|
476
|
+
const p = t / 0.3;
|
|
477
|
+
return `rgb(${Math.round(255*(1-p))},${255},${255})`;
|
|
478
|
+
} else {
|
|
479
|
+
// Phase 2: cyan → normal layer color (smooth blend)
|
|
480
|
+
const p = (t - 0.3) / 0.7;
|
|
481
|
+
const ease = p * p; // ease-in for gentle arrival
|
|
482
|
+
return `rgb(${Math.round(lr*ease)},${Math.round(255+(lg-255)*ease)},${Math.round(255+(lb-255)*ease)})`;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
380
486
|
// AI is modifying this node → bright pulsing white/orange
|
|
381
487
|
if (modifyingNodes.has(node.id)) {
|
|
382
488
|
const t = Date.now() / 200;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syke1/mcp-server",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.11",
|
|
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",
|