@syke1/mcp-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -0
- package/dist/ai/analyzer.d.ts +3 -0
- package/dist/ai/analyzer.js +120 -0
- package/dist/ai/realtime-analyzer.d.ts +20 -0
- package/dist/ai/realtime-analyzer.js +182 -0
- package/dist/graph.d.ts +13 -0
- package/dist/graph.js +105 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +518 -0
- package/dist/languages/cpp.d.ts +2 -0
- package/dist/languages/cpp.js +109 -0
- package/dist/languages/dart.d.ts +2 -0
- package/dist/languages/dart.js +162 -0
- package/dist/languages/go.d.ts +2 -0
- package/dist/languages/go.js +111 -0
- package/dist/languages/java.d.ts +2 -0
- package/dist/languages/java.js +113 -0
- package/dist/languages/plugin.d.ts +20 -0
- package/dist/languages/plugin.js +148 -0
- package/dist/languages/python.d.ts +2 -0
- package/dist/languages/python.js +129 -0
- package/dist/languages/ruby.d.ts +2 -0
- package/dist/languages/ruby.js +97 -0
- package/dist/languages/rust.d.ts +2 -0
- package/dist/languages/rust.js +121 -0
- package/dist/languages/typescript.d.ts +2 -0
- package/dist/languages/typescript.js +138 -0
- package/dist/license/validator.d.ts +23 -0
- package/dist/license/validator.js +297 -0
- package/dist/tools/analyze-impact.d.ts +23 -0
- package/dist/tools/analyze-impact.js +102 -0
- package/dist/tools/gate-build.d.ts +25 -0
- package/dist/tools/gate-build.js +243 -0
- package/dist/watcher/file-cache.d.ts +56 -0
- package/dist/watcher/file-cache.js +241 -0
- package/dist/web/public/app.js +2398 -0
- package/dist/web/public/index.html +258 -0
- package/dist/web/public/style.css +1827 -0
- package/dist/web/server.d.ts +29 -0
- package/dist/web/server.js +744 -0
- package/package.json +50 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
export interface FileChange {
|
|
3
|
+
filePath: string;
|
|
4
|
+
relativePath: string;
|
|
5
|
+
type: "modified" | "added" | "deleted";
|
|
6
|
+
oldContent: string | null;
|
|
7
|
+
newContent: string | null;
|
|
8
|
+
diff: LineDiff[];
|
|
9
|
+
timestamp: number;
|
|
10
|
+
}
|
|
11
|
+
export interface LineDiff {
|
|
12
|
+
line: number;
|
|
13
|
+
type: "added" | "removed" | "changed";
|
|
14
|
+
old?: string;
|
|
15
|
+
new?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* FileCache: Holds ALL source files in memory.
|
|
19
|
+
* Emits "change" events when files are modified on disk.
|
|
20
|
+
*/
|
|
21
|
+
export declare class FileCache extends EventEmitter {
|
|
22
|
+
private projectRoot;
|
|
23
|
+
private cache;
|
|
24
|
+
private sourceDirs;
|
|
25
|
+
private extensions;
|
|
26
|
+
private plugins;
|
|
27
|
+
private watcher;
|
|
28
|
+
private debounceTimers;
|
|
29
|
+
private readonly DEBOUNCE_MS;
|
|
30
|
+
constructor(projectRoot: string);
|
|
31
|
+
/** Primary source directory (backward compat) */
|
|
32
|
+
get sourceDir(): string;
|
|
33
|
+
/** Load ALL source files into memory on startup */
|
|
34
|
+
initialize(): {
|
|
35
|
+
fileCount: number;
|
|
36
|
+
totalLines: number;
|
|
37
|
+
};
|
|
38
|
+
/** Start watching source directories for changes */
|
|
39
|
+
startWatching(): void;
|
|
40
|
+
private isWatchedFile;
|
|
41
|
+
private handleFileEvent;
|
|
42
|
+
/** Simple line-by-line diff */
|
|
43
|
+
private computeDiff;
|
|
44
|
+
/** Get content of a specific file from cache */
|
|
45
|
+
getFile(absPath: string): string | null;
|
|
46
|
+
/** Get content by relative path (relative to first sourceDir) */
|
|
47
|
+
getFileByRelPath(relPath: string): string | null;
|
|
48
|
+
/** Get all cached files as {relativePath → content} */
|
|
49
|
+
getAllFiles(): Map<string, string>;
|
|
50
|
+
/** Get file count */
|
|
51
|
+
get size(): number;
|
|
52
|
+
/** Get total lines across all files */
|
|
53
|
+
get totalLines(): number;
|
|
54
|
+
/** Cleanup */
|
|
55
|
+
stop(): void;
|
|
56
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.FileCache = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const events_1 = require("events");
|
|
40
|
+
const plugin_1 = require("../languages/plugin");
|
|
41
|
+
/**
|
|
42
|
+
* FileCache: Holds ALL source files in memory.
|
|
43
|
+
* Emits "change" events when files are modified on disk.
|
|
44
|
+
*/
|
|
45
|
+
class FileCache extends events_1.EventEmitter {
|
|
46
|
+
constructor(projectRoot) {
|
|
47
|
+
super();
|
|
48
|
+
this.projectRoot = projectRoot;
|
|
49
|
+
this.cache = new Map(); // abs path → content
|
|
50
|
+
this.sourceDirs = [];
|
|
51
|
+
this.watcher = null;
|
|
52
|
+
this.debounceTimers = new Map();
|
|
53
|
+
this.DEBOUNCE_MS = 300;
|
|
54
|
+
this.plugins = (0, plugin_1.detectLanguages)(projectRoot);
|
|
55
|
+
// Collect all extensions from detected plugins
|
|
56
|
+
const allExts = new Set();
|
|
57
|
+
for (const plugin of this.plugins) {
|
|
58
|
+
for (const ext of plugin.extensions) {
|
|
59
|
+
allExts.add(ext);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
this.extensions = allExts.size > 0 ? allExts : new Set([".ts"]);
|
|
63
|
+
// Collect all source dirs
|
|
64
|
+
for (const plugin of this.plugins) {
|
|
65
|
+
for (const dir of plugin.getSourceDirs(projectRoot)) {
|
|
66
|
+
if (!this.sourceDirs.includes(dir)) {
|
|
67
|
+
this.sourceDirs.push(dir);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Primary source directory (backward compat) */
|
|
73
|
+
get sourceDir() {
|
|
74
|
+
return this.sourceDirs[0] || path.join(this.projectRoot, "src");
|
|
75
|
+
}
|
|
76
|
+
/** Load ALL source files into memory on startup */
|
|
77
|
+
initialize() {
|
|
78
|
+
let totalLines = 0;
|
|
79
|
+
for (const plugin of this.plugins) {
|
|
80
|
+
for (const dir of plugin.getSourceDirs(this.projectRoot)) {
|
|
81
|
+
const files = plugin.discoverFiles(dir);
|
|
82
|
+
for (const file of files) {
|
|
83
|
+
try {
|
|
84
|
+
const content = fs.readFileSync(file, "utf-8");
|
|
85
|
+
this.cache.set(path.normalize(file), content);
|
|
86
|
+
totalLines += content.split("\n").length;
|
|
87
|
+
}
|
|
88
|
+
catch (_) {
|
|
89
|
+
// skip unreadable files
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
console.error(`[syke:cache] Loaded ${this.cache.size} files (${totalLines.toLocaleString()} lines) into memory`);
|
|
95
|
+
return { fileCount: this.cache.size, totalLines };
|
|
96
|
+
}
|
|
97
|
+
/** Start watching source directories for changes */
|
|
98
|
+
startWatching() {
|
|
99
|
+
if (this.watcher)
|
|
100
|
+
return;
|
|
101
|
+
// Watch each source directory
|
|
102
|
+
for (const dir of this.sourceDirs) {
|
|
103
|
+
try {
|
|
104
|
+
const watcher = fs.watch(dir, { recursive: true }, (eventType, filename) => {
|
|
105
|
+
if (!filename)
|
|
106
|
+
return;
|
|
107
|
+
if (!this.isWatchedFile(filename))
|
|
108
|
+
return;
|
|
109
|
+
const absPath = path.normalize(path.join(dir, filename));
|
|
110
|
+
const relPath = filename.replace(/\\/g, "/");
|
|
111
|
+
const existing = this.debounceTimers.get(absPath);
|
|
112
|
+
if (existing)
|
|
113
|
+
clearTimeout(existing);
|
|
114
|
+
this.debounceTimers.set(absPath, setTimeout(() => {
|
|
115
|
+
this.debounceTimers.delete(absPath);
|
|
116
|
+
this.handleFileEvent(absPath, relPath);
|
|
117
|
+
}, this.DEBOUNCE_MS));
|
|
118
|
+
});
|
|
119
|
+
// Store first watcher for backward compat
|
|
120
|
+
if (!this.watcher)
|
|
121
|
+
this.watcher = watcher;
|
|
122
|
+
console.error(`[syke:cache] Watching ${dir} for changes`);
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
console.error(`[syke:cache] Watch failed for ${dir}: ${err.message}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
isWatchedFile(filename) {
|
|
130
|
+
if (filename.endsWith(".d.ts"))
|
|
131
|
+
return false;
|
|
132
|
+
for (const ext of this.extensions) {
|
|
133
|
+
if (filename.endsWith(ext))
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
handleFileEvent(absPath, relPath) {
|
|
139
|
+
const oldContent = this.cache.get(absPath) || null;
|
|
140
|
+
let newContent = null;
|
|
141
|
+
let type;
|
|
142
|
+
try {
|
|
143
|
+
if (fs.existsSync(absPath)) {
|
|
144
|
+
newContent = fs.readFileSync(absPath, "utf-8");
|
|
145
|
+
if (oldContent === null) {
|
|
146
|
+
type = "added";
|
|
147
|
+
}
|
|
148
|
+
else if (oldContent === newContent) {
|
|
149
|
+
return; // no actual change
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
type = "modified";
|
|
153
|
+
}
|
|
154
|
+
this.cache.set(absPath, newContent);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
type = "deleted";
|
|
158
|
+
this.cache.delete(absPath);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch (_) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const diff = this.computeDiff(oldContent, newContent);
|
|
165
|
+
const change = {
|
|
166
|
+
filePath: absPath,
|
|
167
|
+
relativePath: relPath,
|
|
168
|
+
type,
|
|
169
|
+
oldContent,
|
|
170
|
+
newContent,
|
|
171
|
+
diff,
|
|
172
|
+
timestamp: Date.now(),
|
|
173
|
+
};
|
|
174
|
+
console.error(`[syke:cache] ${type.toUpperCase()}: ${relPath} (${diff.length} changes)`);
|
|
175
|
+
this.emit("change", change);
|
|
176
|
+
}
|
|
177
|
+
/** Simple line-by-line diff */
|
|
178
|
+
computeDiff(oldContent, newContent) {
|
|
179
|
+
const diffs = [];
|
|
180
|
+
const oldLines = oldContent ? oldContent.split("\n") : [];
|
|
181
|
+
const newLines = newContent ? newContent.split("\n") : [];
|
|
182
|
+
const maxLen = Math.max(oldLines.length, newLines.length);
|
|
183
|
+
for (let i = 0; i < maxLen; i++) {
|
|
184
|
+
const oldLine = i < oldLines.length ? oldLines[i] : undefined;
|
|
185
|
+
const newLine = i < newLines.length ? newLines[i] : undefined;
|
|
186
|
+
if (oldLine === undefined && newLine !== undefined) {
|
|
187
|
+
diffs.push({ line: i + 1, type: "added", new: newLine });
|
|
188
|
+
}
|
|
189
|
+
else if (oldLine !== undefined && newLine === undefined) {
|
|
190
|
+
diffs.push({ line: i + 1, type: "removed", old: oldLine });
|
|
191
|
+
}
|
|
192
|
+
else if (oldLine !== newLine) {
|
|
193
|
+
diffs.push({ line: i + 1, type: "changed", old: oldLine, new: newLine });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return diffs;
|
|
197
|
+
}
|
|
198
|
+
/** Get content of a specific file from cache */
|
|
199
|
+
getFile(absPath) {
|
|
200
|
+
return this.cache.get(path.normalize(absPath)) ?? null;
|
|
201
|
+
}
|
|
202
|
+
/** Get content by relative path (relative to first sourceDir) */
|
|
203
|
+
getFileByRelPath(relPath) {
|
|
204
|
+
const absPath = path.normalize(path.join(this.sourceDir, relPath));
|
|
205
|
+
return this.cache.get(absPath) ?? null;
|
|
206
|
+
}
|
|
207
|
+
/** Get all cached files as {relativePath → content} */
|
|
208
|
+
getAllFiles() {
|
|
209
|
+
const result = new Map();
|
|
210
|
+
for (const [absPath, content] of this.cache) {
|
|
211
|
+
const rel = path.relative(this.sourceDir, absPath).replace(/\\/g, "/");
|
|
212
|
+
result.set(rel, content);
|
|
213
|
+
}
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
/** Get file count */
|
|
217
|
+
get size() {
|
|
218
|
+
return this.cache.size;
|
|
219
|
+
}
|
|
220
|
+
/** Get total lines across all files */
|
|
221
|
+
get totalLines() {
|
|
222
|
+
let total = 0;
|
|
223
|
+
for (const content of this.cache.values()) {
|
|
224
|
+
total += content.split("\n").length;
|
|
225
|
+
}
|
|
226
|
+
return total;
|
|
227
|
+
}
|
|
228
|
+
/** Cleanup */
|
|
229
|
+
stop() {
|
|
230
|
+
if (this.watcher) {
|
|
231
|
+
this.watcher.close();
|
|
232
|
+
this.watcher = null;
|
|
233
|
+
}
|
|
234
|
+
for (const timer of this.debounceTimers.values()) {
|
|
235
|
+
clearTimeout(timer);
|
|
236
|
+
}
|
|
237
|
+
this.debounceTimers.clear();
|
|
238
|
+
console.error("[syke:cache] Watcher stopped");
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
exports.FileCache = FileCache;
|