@sashabogi/argus-mcp 1.2.2 → 2.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 +403 -156
- package/dist/cli.mjs +286 -45
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +70 -1
- package/dist/index.mjs +252 -0
- package/dist/index.mjs.map +1 -1
- package/dist/mcp.mjs +1080 -35
- package/dist/mcp.mjs.map +1 -1
- package/package.json +5 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import * as http from 'http';
|
|
2
|
+
import * as express_serve_static_core from 'express-serve-static-core';
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Argus Onboarding Module
|
|
3
6
|
*
|
|
@@ -238,4 +241,70 @@ declare function getProviderDisplayName(type: ProviderType): string;
|
|
|
238
241
|
*/
|
|
239
242
|
declare function listProviderTypes(): ProviderType[];
|
|
240
243
|
|
|
241
|
-
|
|
244
|
+
interface CachedSnapshot {
|
|
245
|
+
path: string;
|
|
246
|
+
content: string;
|
|
247
|
+
lines: string[];
|
|
248
|
+
fileIndex: Map<string, {
|
|
249
|
+
start: number;
|
|
250
|
+
end: number;
|
|
251
|
+
}>;
|
|
252
|
+
loadedAt: Date;
|
|
253
|
+
fileCount: number;
|
|
254
|
+
mtime: number;
|
|
255
|
+
}
|
|
256
|
+
declare class SnapshotCache {
|
|
257
|
+
private cache;
|
|
258
|
+
private accessOrder;
|
|
259
|
+
private maxSize;
|
|
260
|
+
constructor(options: {
|
|
261
|
+
maxSize: number;
|
|
262
|
+
});
|
|
263
|
+
get size(): number;
|
|
264
|
+
load(path: string): Promise<CachedSnapshot>;
|
|
265
|
+
invalidate(path: string): void;
|
|
266
|
+
search(path: string, pattern: string, options?: {
|
|
267
|
+
caseInsensitive?: boolean;
|
|
268
|
+
maxResults?: number;
|
|
269
|
+
offset?: number;
|
|
270
|
+
}): {
|
|
271
|
+
matches: Array<{
|
|
272
|
+
lineNum: number;
|
|
273
|
+
line: string;
|
|
274
|
+
match: string;
|
|
275
|
+
}>;
|
|
276
|
+
count: number;
|
|
277
|
+
};
|
|
278
|
+
getContext(path: string, file: string, line: number, before?: number, after?: number): {
|
|
279
|
+
content: string;
|
|
280
|
+
range: {
|
|
281
|
+
start: number;
|
|
282
|
+
end: number;
|
|
283
|
+
};
|
|
284
|
+
};
|
|
285
|
+
private buildFileIndex;
|
|
286
|
+
private touchAccess;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
declare class ProjectWatcher {
|
|
290
|
+
private projectPath;
|
|
291
|
+
private snapshotPath;
|
|
292
|
+
private onUpdate;
|
|
293
|
+
private debounceMs;
|
|
294
|
+
private watcher;
|
|
295
|
+
private debounceTimer;
|
|
296
|
+
private changedFiles;
|
|
297
|
+
constructor(projectPath: string, snapshotPath: string, onUpdate: (changedFiles: string[]) => void, debounceMs?: number);
|
|
298
|
+
private start;
|
|
299
|
+
private scheduleUpdate;
|
|
300
|
+
close(): void;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
declare function startWorker(): {
|
|
304
|
+
app: express_serve_static_core.Express;
|
|
305
|
+
server: http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
|
|
306
|
+
cache: SnapshotCache;
|
|
307
|
+
watchers: Map<string, ProjectWatcher>;
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
export { type AIProvider, type ProviderConfig as AIProviderConfig, type AnalysisOptions, type AnalysisResult, type ArgusConfig, type CompletionOptions, type CompletionResult, type ProviderConfig as CoreProviderConfig, type Message, PROVIDER_DEFAULTS, ProjectWatcher, type ProviderType, SnapshotCache, type SnapshotOptions, type SnapshotResult, analyze, createAnthropicProvider, createDeepSeekProvider, createOllamaProvider, createOpenAIProvider, createProvider, createProviderByType, createSnapshot, createZAIProvider, ensureConfigDir, getConfigPath, getProviderConfig, getProviderDisplayName, getSnapshotStats, listProviderTypes, loadConfig, saveConfig, searchDocument, startWorker, validateConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -1023,8 +1023,259 @@ function getProviderDisplayName(type) {
|
|
|
1023
1023
|
function listProviderTypes() {
|
|
1024
1024
|
return ["zai", "anthropic", "openai", "deepseek", "ollama"];
|
|
1025
1025
|
}
|
|
1026
|
+
|
|
1027
|
+
// src/worker/server.ts
|
|
1028
|
+
import express from "express";
|
|
1029
|
+
|
|
1030
|
+
// src/worker/cache.ts
|
|
1031
|
+
import { readFileSync as readFileSync4, statSync as statSync2 } from "fs";
|
|
1032
|
+
var SnapshotCache = class {
|
|
1033
|
+
cache = /* @__PURE__ */ new Map();
|
|
1034
|
+
accessOrder = [];
|
|
1035
|
+
maxSize;
|
|
1036
|
+
constructor(options) {
|
|
1037
|
+
this.maxSize = options.maxSize;
|
|
1038
|
+
}
|
|
1039
|
+
get size() {
|
|
1040
|
+
return this.cache.size;
|
|
1041
|
+
}
|
|
1042
|
+
async load(path) {
|
|
1043
|
+
const stats = statSync2(path);
|
|
1044
|
+
const cached = this.cache.get(path);
|
|
1045
|
+
if (cached && cached.mtime === stats.mtimeMs) {
|
|
1046
|
+
this.touchAccess(path);
|
|
1047
|
+
return cached;
|
|
1048
|
+
}
|
|
1049
|
+
const content = readFileSync4(path, "utf-8");
|
|
1050
|
+
const lines = content.split("\n");
|
|
1051
|
+
const fileIndex = this.buildFileIndex(lines);
|
|
1052
|
+
const fileCount = (content.match(/^FILE: /gm) || []).length;
|
|
1053
|
+
const snapshot = {
|
|
1054
|
+
path,
|
|
1055
|
+
content,
|
|
1056
|
+
lines,
|
|
1057
|
+
fileIndex,
|
|
1058
|
+
loadedAt: /* @__PURE__ */ new Date(),
|
|
1059
|
+
fileCount,
|
|
1060
|
+
mtime: stats.mtimeMs
|
|
1061
|
+
};
|
|
1062
|
+
if (this.cache.size >= this.maxSize) {
|
|
1063
|
+
const oldest = this.accessOrder.shift();
|
|
1064
|
+
this.cache.delete(oldest);
|
|
1065
|
+
}
|
|
1066
|
+
this.cache.set(path, snapshot);
|
|
1067
|
+
this.accessOrder.push(path);
|
|
1068
|
+
return snapshot;
|
|
1069
|
+
}
|
|
1070
|
+
invalidate(path) {
|
|
1071
|
+
this.cache.delete(path);
|
|
1072
|
+
this.accessOrder = this.accessOrder.filter((p) => p !== path);
|
|
1073
|
+
}
|
|
1074
|
+
search(path, pattern, options = {}) {
|
|
1075
|
+
const snapshot = this.cache.get(path);
|
|
1076
|
+
if (!snapshot) {
|
|
1077
|
+
throw new Error("Snapshot not loaded. Call /snapshot/load first.");
|
|
1078
|
+
}
|
|
1079
|
+
const flags = options.caseInsensitive ? "gi" : "g";
|
|
1080
|
+
const regex = new RegExp(pattern, flags);
|
|
1081
|
+
const matches = [];
|
|
1082
|
+
const maxResults = options.maxResults || 50;
|
|
1083
|
+
const offset = options.offset || 0;
|
|
1084
|
+
let found = 0;
|
|
1085
|
+
for (let i = 0; i < snapshot.lines.length; i++) {
|
|
1086
|
+
const line = snapshot.lines[i];
|
|
1087
|
+
const match = regex.exec(line);
|
|
1088
|
+
regex.lastIndex = 0;
|
|
1089
|
+
if (match) {
|
|
1090
|
+
if (found >= offset && matches.length < maxResults) {
|
|
1091
|
+
matches.push({
|
|
1092
|
+
lineNum: i + 1,
|
|
1093
|
+
line: line.trim(),
|
|
1094
|
+
match: match[0]
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
found++;
|
|
1098
|
+
if (matches.length >= maxResults) break;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
return { matches, count: matches.length };
|
|
1102
|
+
}
|
|
1103
|
+
getContext(path, file, line, before = 10, after = 10) {
|
|
1104
|
+
const snapshot = this.cache.get(path);
|
|
1105
|
+
if (!snapshot) throw new Error("Snapshot not loaded");
|
|
1106
|
+
const normalizedFile = file.replace(/^\.\//, "");
|
|
1107
|
+
const fileRange = snapshot.fileIndex.get(normalizedFile);
|
|
1108
|
+
if (!fileRange) throw new Error(`File not found: ${file}`);
|
|
1109
|
+
const fileLines = snapshot.lines.slice(fileRange.start, fileRange.end);
|
|
1110
|
+
const startLine = Math.max(0, line - before - 1);
|
|
1111
|
+
const endLine = Math.min(fileLines.length, line + after);
|
|
1112
|
+
const contextLines = fileLines.slice(startLine, endLine).map((l, idx) => {
|
|
1113
|
+
const lineNum = startLine + idx + 1;
|
|
1114
|
+
const marker = lineNum === line ? ">>>" : " ";
|
|
1115
|
+
return `${marker} ${lineNum.toString().padStart(4)}: ${l}`;
|
|
1116
|
+
});
|
|
1117
|
+
return {
|
|
1118
|
+
content: contextLines.join("\n"),
|
|
1119
|
+
range: { start: startLine + 1, end: endLine }
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
buildFileIndex(lines) {
|
|
1123
|
+
const index = /* @__PURE__ */ new Map();
|
|
1124
|
+
let currentFile = null;
|
|
1125
|
+
let currentStart = 0;
|
|
1126
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1127
|
+
const line = lines[i];
|
|
1128
|
+
if (line.startsWith("FILE: ./")) {
|
|
1129
|
+
if (currentFile) {
|
|
1130
|
+
index.set(currentFile, { start: currentStart, end: i - 1 });
|
|
1131
|
+
}
|
|
1132
|
+
currentFile = line.slice(8);
|
|
1133
|
+
currentStart = i + 2;
|
|
1134
|
+
}
|
|
1135
|
+
if (line.startsWith("METADATA:") && currentFile) {
|
|
1136
|
+
index.set(currentFile, { start: currentStart, end: i - 1 });
|
|
1137
|
+
break;
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
if (currentFile && !index.has(currentFile)) {
|
|
1141
|
+
index.set(currentFile, { start: currentStart, end: lines.length - 1 });
|
|
1142
|
+
}
|
|
1143
|
+
return index;
|
|
1144
|
+
}
|
|
1145
|
+
touchAccess(path) {
|
|
1146
|
+
this.accessOrder = this.accessOrder.filter((p) => p !== path);
|
|
1147
|
+
this.accessOrder.push(path);
|
|
1148
|
+
}
|
|
1149
|
+
};
|
|
1150
|
+
|
|
1151
|
+
// src/worker/watcher.ts
|
|
1152
|
+
import { watch } from "fs";
|
|
1153
|
+
var ProjectWatcher = class {
|
|
1154
|
+
constructor(projectPath, snapshotPath, onUpdate, debounceMs = 1e3) {
|
|
1155
|
+
this.projectPath = projectPath;
|
|
1156
|
+
this.snapshotPath = snapshotPath;
|
|
1157
|
+
this.onUpdate = onUpdate;
|
|
1158
|
+
this.debounceMs = debounceMs;
|
|
1159
|
+
this.start();
|
|
1160
|
+
}
|
|
1161
|
+
watcher = null;
|
|
1162
|
+
debounceTimer = null;
|
|
1163
|
+
changedFiles = /* @__PURE__ */ new Set();
|
|
1164
|
+
start() {
|
|
1165
|
+
try {
|
|
1166
|
+
this.watcher = watch(this.projectPath, { recursive: true }, (eventType, filename) => {
|
|
1167
|
+
if (!filename) return;
|
|
1168
|
+
if (filename.includes("node_modules") || filename.includes(".git") || filename.includes(".argus")) {
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
this.changedFiles.add(filename);
|
|
1172
|
+
this.scheduleUpdate();
|
|
1173
|
+
});
|
|
1174
|
+
} catch (error) {
|
|
1175
|
+
console.error(`Failed to watch ${this.projectPath}:`, error);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
scheduleUpdate() {
|
|
1179
|
+
if (this.debounceTimer) {
|
|
1180
|
+
clearTimeout(this.debounceTimer);
|
|
1181
|
+
}
|
|
1182
|
+
this.debounceTimer = setTimeout(() => {
|
|
1183
|
+
const files = Array.from(this.changedFiles);
|
|
1184
|
+
this.changedFiles.clear();
|
|
1185
|
+
this.onUpdate(files);
|
|
1186
|
+
}, this.debounceMs);
|
|
1187
|
+
}
|
|
1188
|
+
close() {
|
|
1189
|
+
if (this.watcher) {
|
|
1190
|
+
this.watcher.close();
|
|
1191
|
+
this.watcher = null;
|
|
1192
|
+
}
|
|
1193
|
+
if (this.debounceTimer) {
|
|
1194
|
+
clearTimeout(this.debounceTimer);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
};
|
|
1198
|
+
|
|
1199
|
+
// src/worker/server.ts
|
|
1200
|
+
var PORT = process.env.ARGUS_WORKER_PORT || 37778;
|
|
1201
|
+
function startWorker() {
|
|
1202
|
+
const app = express();
|
|
1203
|
+
const cache = new SnapshotCache({ maxSize: 5 });
|
|
1204
|
+
const watchers = /* @__PURE__ */ new Map();
|
|
1205
|
+
app.use(express.json());
|
|
1206
|
+
app.get("/health", (_req, res) => {
|
|
1207
|
+
res.json({
|
|
1208
|
+
status: "ok",
|
|
1209
|
+
version: "2.0.0",
|
|
1210
|
+
cached: cache.size,
|
|
1211
|
+
watching: watchers.size
|
|
1212
|
+
});
|
|
1213
|
+
});
|
|
1214
|
+
app.post("/snapshot/load", async (req, res) => {
|
|
1215
|
+
const { path } = req.body;
|
|
1216
|
+
try {
|
|
1217
|
+
const snapshot = await cache.load(path);
|
|
1218
|
+
res.json({
|
|
1219
|
+
success: true,
|
|
1220
|
+
fileCount: snapshot.fileCount,
|
|
1221
|
+
cached: true
|
|
1222
|
+
});
|
|
1223
|
+
} catch (error) {
|
|
1224
|
+
res.status(400).json({ error: error.message });
|
|
1225
|
+
}
|
|
1226
|
+
});
|
|
1227
|
+
app.post("/search", (req, res) => {
|
|
1228
|
+
const { path, pattern, options } = req.body;
|
|
1229
|
+
try {
|
|
1230
|
+
const results = cache.search(path, pattern, options || {});
|
|
1231
|
+
res.json(results);
|
|
1232
|
+
} catch (error) {
|
|
1233
|
+
res.status(400).json({ error: error.message });
|
|
1234
|
+
}
|
|
1235
|
+
});
|
|
1236
|
+
app.post("/context", (req, res) => {
|
|
1237
|
+
const { path, file, line, before, after } = req.body;
|
|
1238
|
+
try {
|
|
1239
|
+
const context = cache.getContext(path, file, line, before || 10, after || 10);
|
|
1240
|
+
res.json(context);
|
|
1241
|
+
} catch (error) {
|
|
1242
|
+
res.status(400).json({ error: error.message });
|
|
1243
|
+
}
|
|
1244
|
+
});
|
|
1245
|
+
app.post("/notify-change", (req, res) => {
|
|
1246
|
+
const { projectPath } = req.body;
|
|
1247
|
+
const snapshotPath = `${projectPath}/.argus/snapshot.txt`;
|
|
1248
|
+
cache.invalidate(snapshotPath);
|
|
1249
|
+
res.json({ invalidated: true });
|
|
1250
|
+
});
|
|
1251
|
+
app.post("/watch", (req, res) => {
|
|
1252
|
+
const { projectPath, snapshotPath } = req.body;
|
|
1253
|
+
if (!watchers.has(projectPath)) {
|
|
1254
|
+
const watcher = new ProjectWatcher(projectPath, snapshotPath, () => {
|
|
1255
|
+
cache.invalidate(snapshotPath);
|
|
1256
|
+
});
|
|
1257
|
+
watchers.set(projectPath, watcher);
|
|
1258
|
+
}
|
|
1259
|
+
res.json({ watching: true, path: projectPath });
|
|
1260
|
+
});
|
|
1261
|
+
app.delete("/watch", (req, res) => {
|
|
1262
|
+
const { projectPath } = req.body;
|
|
1263
|
+
const watcher = watchers.get(projectPath);
|
|
1264
|
+
if (watcher) {
|
|
1265
|
+
watcher.close();
|
|
1266
|
+
watchers.delete(projectPath);
|
|
1267
|
+
}
|
|
1268
|
+
res.json({ watching: false });
|
|
1269
|
+
});
|
|
1270
|
+
const server = app.listen(PORT, () => {
|
|
1271
|
+
console.log(`Argus worker listening on port ${PORT}`);
|
|
1272
|
+
});
|
|
1273
|
+
return { app, server, cache, watchers };
|
|
1274
|
+
}
|
|
1026
1275
|
export {
|
|
1027
1276
|
PROVIDER_DEFAULTS,
|
|
1277
|
+
ProjectWatcher,
|
|
1278
|
+
SnapshotCache,
|
|
1028
1279
|
analyze,
|
|
1029
1280
|
createAnthropicProvider,
|
|
1030
1281
|
createDeepSeekProvider,
|
|
@@ -1043,6 +1294,7 @@ export {
|
|
|
1043
1294
|
loadConfig,
|
|
1044
1295
|
saveConfig,
|
|
1045
1296
|
searchDocument,
|
|
1297
|
+
startWorker,
|
|
1046
1298
|
validateConfig
|
|
1047
1299
|
};
|
|
1048
1300
|
//# sourceMappingURL=index.mjs.map
|