@prosdevlab/dev-agent 0.10.2 → 0.10.4

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/cli.js CHANGED
@@ -23547,6 +23547,35 @@ var init_vector = __esm({
23547
23547
  this.assertReady();
23548
23548
  return this.store.getAll(options);
23549
23549
  }
23550
+ /**
23551
+ * Get indexed documents grouped by file path.
23552
+ *
23553
+ * Uses getAll with a capped limit + client-side exact path filter.
23554
+ * More reliable than BM25 search which tokenizes paths unpredictably.
23555
+ *
23556
+ * Note: Fetches up to 5,000 docs client-side. Fine for single repos,
23557
+ * won't scale to monorepos with 50k+ files. See .claude/scratchpad.md.
23558
+ */
23559
+ async getDocsByFilePath(filePaths) {
23560
+ this.assertReady();
23561
+ const DOC_LIMIT = 5e3;
23562
+ const pathSet = new Set(filePaths);
23563
+ const allDocs = await this.getAll({ limit: DOC_LIMIT });
23564
+ if (allDocs.length >= DOC_LIMIT) {
23565
+ console.error(
23566
+ `[dev-agent] Warning: getDocsByFilePath hit ${DOC_LIMIT} doc limit. Some files may be missing.`
23567
+ );
23568
+ }
23569
+ const byFile = /* @__PURE__ */ new Map();
23570
+ for (const doc of allDocs) {
23571
+ const docPath = doc.metadata.path;
23572
+ if (pathSet.has(docPath)) {
23573
+ if (!byFile.has(docPath)) byFile.set(docPath, []);
23574
+ byFile.get(docPath).push(doc);
23575
+ }
23576
+ }
23577
+ return byFile;
23578
+ }
23550
23579
  /**
23551
23580
  * Get a document by ID
23552
23581
  */
@@ -42034,6 +42063,44 @@ var init_test_utils = __esm({
42034
42063
  });
42035
42064
 
42036
42065
  // ../core/src/services/pattern-analysis-service.ts
42066
+ function extractImportStyleFromContent(content3) {
42067
+ const esmImports = content3.match(/^import\s/gm) || [];
42068
+ const cjsImports = content3.match(/require\s*\(/g) || [];
42069
+ const hasESM = esmImports.length > 0;
42070
+ const hasCJS = cjsImports.length > 0;
42071
+ if (!hasESM && !hasCJS) return { style: "unknown", importCount: 0 };
42072
+ const importCount = esmImports.length + cjsImports.length;
42073
+ const style = hasESM && hasCJS ? "mixed" : hasESM ? "esm" : "cjs";
42074
+ return { style, importCount };
42075
+ }
42076
+ function extractErrorHandlingFromContent(content3) {
42077
+ const counts = {
42078
+ throw: [...content3.matchAll(/throw\s+new\s+\w*Error/g)].length,
42079
+ result: [...content3.matchAll(/Result<|{\s*ok:\s*(true|false)/g)].length,
42080
+ errorReturn: [...content3.matchAll(/\)\s*:\s*\([^)]*,\s*error\)/g)].length
42081
+ };
42082
+ const total = counts.throw + counts.result + counts.errorReturn;
42083
+ if (total === 0) return { style: "unknown", examples: [] };
42084
+ const max = Math.max(counts.throw, counts.result, counts.errorReturn);
42085
+ const hasMultiple = Object.values(counts).filter((c) => c > 0).length > 1;
42086
+ let style = "unknown";
42087
+ if (hasMultiple) style = "mixed";
42088
+ else if (counts.throw === max) style = "throw";
42089
+ else if (counts.result === max) style = "result";
42090
+ else if (counts.errorReturn === max) style = "error-return";
42091
+ return { style, examples: [] };
42092
+ }
42093
+ function extractTypeCoverageFromSignatures(signatures) {
42094
+ if (signatures.length === 0) return { coverage: "none", annotatedCount: 0, totalCount: 0 };
42095
+ const annotated = signatures.filter((sig) => /(\)|=>)\s*:\s*\w+/.test(sig));
42096
+ const ratio = annotated.length / signatures.length;
42097
+ let coverage;
42098
+ if (ratio >= 0.9) coverage = "full";
42099
+ else if (ratio >= 0.5) coverage = "partial";
42100
+ else if (ratio > 0) coverage = "minimal";
42101
+ else coverage = "none";
42102
+ return { coverage, annotatedCount: annotated.length, totalCount: signatures.length };
42103
+ }
42037
42104
  var fs9, path13, PatternAnalysisService;
42038
42105
  var init_pattern_analysis_service = __esm({
42039
42106
  "../core/src/services/pattern-analysis-service.ts"() {
@@ -42061,38 +42128,72 @@ var init_pattern_analysis_service = __esm({
42061
42128
  return this.analyzeFileWithDocs(filePath, documents);
42062
42129
  }
42063
42130
  /**
42064
- * Compare patterns between target file and similar files
42131
+ * Analyze file patterns using indexed metadata (fast no ts-morph).
42065
42132
  *
42066
- * OPTIMIZED: Batch scans all files in one pass to avoid repeated ts-morph initialization
42133
+ * Reads signatures from the Antfly index, content from disk (for line count
42134
+ * and error handling regex). Falls back gracefully on ENOENT (deleted file).
42135
+ */
42136
+ async analyzeFileFromIndex(filePath, indexedDocs) {
42137
+ const fullPath = path13.join(this.config.repositoryPath, filePath);
42138
+ let content3 = "";
42139
+ let bytes = 0;
42140
+ let lines = 0;
42141
+ try {
42142
+ const [fileContent, stat2] = await Promise.all([
42143
+ fs9.readFile(fullPath, "utf-8"),
42144
+ fs9.stat(fullPath)
42145
+ ]);
42146
+ content3 = fileContent;
42147
+ bytes = stat2.size;
42148
+ lines = content3.split("\n").length;
42149
+ } catch (error47) {
42150
+ if (error47.code !== "ENOENT") throw error47;
42151
+ }
42152
+ const testing = await this.analyzeTesting(filePath);
42153
+ const signatures = indexedDocs.filter((d) => d.metadata.type === "function" || d.metadata.type === "method").map((d) => d.metadata.signature || "").filter(Boolean);
42154
+ return {
42155
+ fileSize: { lines, bytes },
42156
+ testing,
42157
+ importStyle: extractImportStyleFromContent(content3),
42158
+ errorHandling: extractErrorHandlingFromContent(content3),
42159
+ typeAnnotations: extractTypeCoverageFromSignatures(signatures)
42160
+ };
42161
+ }
42162
+ /**
42163
+ * Compare patterns between target file and similar files
42067
42164
  *
42068
- * @param targetFile - Target file to analyze
42069
- * @param similarFiles - Array of similar file paths
42070
- * @returns Pattern comparison results
42165
+ * Uses Antfly index when vectorStorage is available (fast path, ~100ms).
42166
+ * Falls back to ts-morph scanning when not (tests, offline).
42071
42167
  */
42072
42168
  async comparePatterns(targetFile, similarFiles) {
42073
42169
  const allFiles = [targetFile, ...similarFiles];
42074
- const batchResult = await scanRepository({
42075
- repoRoot: this.config.repositoryPath,
42076
- include: allFiles
42077
- });
42078
- const docsByFile = /* @__PURE__ */ new Map();
42079
- for (const doc of batchResult.documents) {
42080
- const file2 = doc.metadata.file;
42081
- if (!docsByFile.has(file2)) {
42082
- docsByFile.set(file2, []);
42083
- }
42084
- const docs = docsByFile.get(file2);
42085
- if (docs) {
42086
- docs.push(doc);
42087
- }
42170
+ let targetPatterns;
42171
+ let similarPatterns;
42172
+ if (this.config.vectorStorage) {
42173
+ const docsByFile = await this.config.vectorStorage.getDocsByFilePath(allFiles);
42174
+ targetPatterns = await this.analyzeFileFromIndex(
42175
+ targetFile,
42176
+ docsByFile.get(targetFile) || []
42177
+ );
42178
+ similarPatterns = await Promise.all(
42179
+ similarFiles.map((f) => this.analyzeFileFromIndex(f, docsByFile.get(f) || []))
42180
+ );
42181
+ } else {
42182
+ const batchResult = await scanRepository({
42183
+ repoRoot: this.config.repositoryPath,
42184
+ include: allFiles
42185
+ });
42186
+ const docsByFile = /* @__PURE__ */ new Map();
42187
+ for (const doc of batchResult.documents) {
42188
+ const file2 = doc.metadata.file;
42189
+ if (!docsByFile.has(file2)) docsByFile.set(file2, []);
42190
+ docsByFile.get(file2).push(doc);
42191
+ }
42192
+ targetPatterns = await this.analyzeFileWithDocs(targetFile, docsByFile.get(targetFile) || []);
42193
+ similarPatterns = await Promise.all(
42194
+ similarFiles.map((f) => this.analyzeFileWithDocs(f, docsByFile.get(f) || []))
42195
+ );
42088
42196
  }
42089
- const targetPatterns = await this.analyzeFileWithDocs(
42090
- targetFile,
42091
- docsByFile.get(targetFile) || []
42092
- );
42093
- const similarPatterns = await Promise.all(
42094
- similarFiles.map((f) => this.analyzeFileWithDocs(f, docsByFile.get(f) || []))
42095
- );
42096
42197
  return {
42097
42198
  fileSize: this.compareFileSize(
42098
42199
  targetPatterns.fileSize,
@@ -42117,34 +42218,26 @@ var init_pattern_analysis_service = __esm({
42117
42218
  };
42118
42219
  }
42119
42220
  /**
42120
- * Analyze file patterns using pre-scanned documents (faster)
42121
- *
42122
- * @param filePath - Relative path from repository root
42123
- * @param documents - Pre-scanned documents for this file
42124
- * @returns Pattern analysis results
42221
+ * Analyze file patterns using pre-scanned documents (fallback path).
42125
42222
  */
42126
42223
  async analyzeFileWithDocs(filePath, documents) {
42127
42224
  const fullPath = path13.join(this.config.repositoryPath, filePath);
42128
- const [stat2, content3] = await Promise.all([fs9.stat(fullPath), fs9.readFile(fullPath, "utf-8")]);
42129
- const lines = content3.split("\n").length;
42225
+ const [content3, stat2, testing] = await Promise.all([
42226
+ fs9.readFile(fullPath, "utf-8"),
42227
+ fs9.stat(fullPath),
42228
+ this.analyzeTesting(filePath)
42229
+ ]);
42230
+ const signatures = documents.filter((d) => d.type === "function" || d.type === "method").map((d) => d.metadata.signature || "").filter(Boolean);
42130
42231
  return {
42131
- fileSize: {
42132
- lines,
42133
- bytes: stat2.size
42134
- },
42135
- testing: await this.analyzeTesting(filePath),
42136
- importStyle: await this.analyzeImportsFromFile(filePath, documents),
42137
- errorHandling: this.analyzeErrorHandling(content3),
42138
- typeAnnotations: this.analyzeTypes(documents)
42232
+ fileSize: { lines: content3.split("\n").length, bytes: stat2.size },
42233
+ testing,
42234
+ importStyle: extractImportStyleFromContent(content3),
42235
+ errorHandling: extractErrorHandlingFromContent(content3),
42236
+ typeAnnotations: extractTypeCoverageFromSignatures(signatures)
42139
42237
  };
42140
42238
  }
42141
- // ========================================================================
42142
- // Pattern Extractors (MVP: 5 core patterns)
42143
- // ========================================================================
42144
42239
  /**
42145
42240
  * Analyze test coverage for a file
42146
- *
42147
- * Checks for co-located test files (*.test.*, *.spec.*)
42148
42241
  */
42149
42242
  async analyzeTesting(filePath) {
42150
42243
  if (isTestFile(filePath)) {
@@ -42156,109 +42249,6 @@ var init_pattern_analysis_service = __esm({
42156
42249
  testPath: testFile || void 0
42157
42250
  };
42158
42251
  }
42159
- /**
42160
- * Analyze import style from documents
42161
- *
42162
- * Always uses content analysis for reliability (scanner may not extract imports from all files).
42163
- */
42164
- async analyzeImportsFromFile(filePath, _documents) {
42165
- const fullPath = path13.join(this.config.repositoryPath, filePath);
42166
- const content3 = await fs9.readFile(fullPath, "utf-8");
42167
- return this.analyzeImportsFromContent(content3);
42168
- }
42169
- /**
42170
- * Analyze imports from raw file content (fallback method)
42171
- */
42172
- analyzeImportsFromContent(content3) {
42173
- const esmImports = content3.match(/^import\s/gm) || [];
42174
- const cjsImports = content3.match(/require\s*\(/g) || [];
42175
- const hasESM = esmImports.length > 0;
42176
- const hasCJS = cjsImports.length > 0;
42177
- if (!hasESM && !hasCJS) {
42178
- return { style: "unknown", importCount: 0 };
42179
- }
42180
- const importCount = esmImports.length + cjsImports.length;
42181
- let style;
42182
- if (hasESM && hasCJS) {
42183
- style = "mixed";
42184
- } else if (hasESM) {
42185
- style = "esm";
42186
- } else {
42187
- style = "cjs";
42188
- }
42189
- return { style, importCount };
42190
- }
42191
- /**
42192
- * Analyze error handling patterns in file content
42193
- *
42194
- * Detects: throw, Result<T>, error returns (Go style)
42195
- */
42196
- analyzeErrorHandling(content3) {
42197
- const patterns = {
42198
- throw: /throw\s+new\s+\w*Error/g,
42199
- result: /Result<|{\s*ok:\s*(true|false)/g,
42200
- errorReturn: /\)\s*:\s*\([^)]*,\s*error\)/g
42201
- // Go: (val, error)
42202
- };
42203
- const matches = {
42204
- throw: [...content3.matchAll(patterns.throw)],
42205
- result: [...content3.matchAll(patterns.result)],
42206
- errorReturn: [...content3.matchAll(patterns.errorReturn)]
42207
- };
42208
- const counts = {
42209
- throw: matches.throw.length,
42210
- result: matches.result.length,
42211
- errorReturn: matches.errorReturn.length
42212
- };
42213
- const total = counts.throw + counts.result + counts.errorReturn;
42214
- if (total === 0) {
42215
- return { style: "unknown", examples: [] };
42216
- }
42217
- const max = Math.max(counts.throw, counts.result, counts.errorReturn);
42218
- const hasMultiple = Object.values(counts).filter((c) => c > 0).length > 1;
42219
- let style = "unknown";
42220
- if (hasMultiple) {
42221
- style = "mixed";
42222
- } else if (counts.throw === max) {
42223
- style = "throw";
42224
- } else if (counts.result === max) {
42225
- style = "result";
42226
- } else if (counts.errorReturn === max) {
42227
- style = "error-return";
42228
- }
42229
- return { style, examples: [] };
42230
- }
42231
- /**
42232
- * Analyze type annotation coverage from documents
42233
- *
42234
- * Checks function/method signatures for explicit types.
42235
- */
42236
- analyzeTypes(documents) {
42237
- const functions = documents.filter((d) => d.type === "function" || d.type === "method");
42238
- if (functions.length === 0) {
42239
- return { coverage: "none", annotatedCount: 0, totalCount: 0 };
42240
- }
42241
- const annotated = functions.filter((d) => {
42242
- const sig = d.metadata.signature || "";
42243
- return /(\)|=>)\s*:\s*\w+/.test(sig);
42244
- });
42245
- const coverage = annotated.length / functions.length;
42246
- let coverageLevel;
42247
- if (coverage >= 0.9) {
42248
- coverageLevel = "full";
42249
- } else if (coverage >= 0.5) {
42250
- coverageLevel = "partial";
42251
- } else if (coverage > 0) {
42252
- coverageLevel = "minimal";
42253
- } else {
42254
- coverageLevel = "none";
42255
- }
42256
- return {
42257
- coverage: coverageLevel,
42258
- annotatedCount: annotated.length,
42259
- totalCount: functions.length
42260
- };
42261
- }
42262
42252
  // ========================================================================
42263
42253
  // Pattern Comparisons
42264
42254
  // ========================================================================
@@ -49367,6 +49357,8 @@ var require_antfly = __commonJS({
49367
49357
  exports2.hasModel = hasModel;
49368
49358
  exports2.hasModelDocker = hasModelDocker;
49369
49359
  var node_child_process_1 = require("child_process");
49360
+ var node_os_1 = require("os");
49361
+ var node_path_1 = require("path");
49370
49362
  var logger_js_1 = require_logger();
49371
49363
  var DEFAULT_ANTFLY_URL = process.env.ANTFLY_URL ?? "http://localhost:18080/api/v1";
49372
49364
  var CONTAINER_NAME = "dev-agent-antfly";
@@ -49374,6 +49366,8 @@ var require_antfly = __commonJS({
49374
49366
  var DOCKER_PORT = 18080;
49375
49367
  var STARTUP_TIMEOUT_MS = 3e4;
49376
49368
  var POLL_INTERVAL_MS = 500;
49369
+ var ANTFLY_DATA_DIR = process.env.ANTFLY_DATA_DIR ?? (0, node_path_1.join)((0, node_os_1.homedir)(), ".antfly");
49370
+ var TERMITE_MODELS_DIR = (0, node_path_1.join)(ANTFLY_DATA_DIR, "models");
49377
49371
  async function ensureAntfly(options) {
49378
49372
  const url2 = getAntflyUrl();
49379
49373
  if (await isServerReady(url2)) {
@@ -49384,6 +49378,8 @@ var require_antfly = __commonJS({
49384
49378
  logger_js_1.logger.info("Starting Antfly server...");
49385
49379
  const child = (0, node_child_process_1.spawn)("antfly", [
49386
49380
  "swarm",
49381
+ "--data-dir",
49382
+ ANTFLY_DATA_DIR,
49387
49383
  "--metadata-api",
49388
49384
  "http://0.0.0.0:18080",
49389
49385
  "--store-api",
@@ -49505,19 +49501,20 @@ var require_antfly = __commonJS({
49505
49501
  }
49506
49502
  }
49507
49503
  function pullModel(model) {
49508
- (0, node_child_process_1.execSync)(`antfly termite pull ${model}`, { stdio: "inherit" });
49504
+ (0, node_child_process_1.execSync)(`antfly termite pull --models-dir ${TERMITE_MODELS_DIR} ${model}`, {
49505
+ stdio: "inherit"
49506
+ });
49509
49507
  }
49510
49508
  function pullModelDocker(model) {
49511
49509
  (0, node_child_process_1.execSync)(`docker exec ${CONTAINER_NAME} /antfly termite pull ${model}`, { stdio: "inherit" });
49512
49510
  }
49513
49511
  function hasModel(model) {
49514
49512
  try {
49515
- const output = (0, node_child_process_1.execSync)("antfly termite list", {
49513
+ const output = (0, node_child_process_1.execSync)(`antfly termite list --models-dir ${TERMITE_MODELS_DIR}`, {
49516
49514
  encoding: "utf-8",
49517
49515
  stdio: ["pipe", "pipe", "pipe"]
49518
49516
  });
49519
- const shortName = model.split("/").pop() ?? model;
49520
- return output.includes(shortName);
49517
+ return modelPresentInOutput(model, output);
49521
49518
  } catch {
49522
49519
  return false;
49523
49520
  }
@@ -49528,12 +49525,18 @@ var require_antfly = __commonJS({
49528
49525
  encoding: "utf-8",
49529
49526
  stdio: ["pipe", "pipe", "pipe"]
49530
49527
  });
49531
- const shortName = model.split("/").pop() ?? model;
49532
- return output.includes(shortName);
49528
+ return modelPresentInOutput(model, output);
49533
49529
  } catch {
49534
49530
  return false;
49535
49531
  }
49536
49532
  }
49533
+ function modelPresentInOutput(model, output) {
49534
+ if (output.includes(model))
49535
+ return true;
49536
+ const shortName = model.split("/").pop() ?? model;
49537
+ const escaped = shortName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
49538
+ return new RegExp(`(?<![\\w/-])${escaped}(?![\\w/-])`).test(output);
49539
+ }
49537
49540
  }
49538
49541
  });
49539
49542
 
@@ -65435,7 +65438,7 @@ var require_schemas3 = __commonJS({
65435
65438
  "../mcp-server/dist/src/schemas/index.js"(exports2) {
65436
65439
  "use strict";
65437
65440
  Object.defineProperty(exports2, "__esModule", { value: true });
65438
- exports2.InspectOutputSchema = exports2.RefsOutputSchema = exports2.RefResultSchema = exports2.MapOutputSchema = exports2.HealthOutputSchema = exports2.HealthCheckResultSchema = exports2.SearchOutputSchema = exports2.HealthArgsSchema = exports2.StatusOutputSchema = exports2.StatusArgsSchema = exports2.MapArgsSchema = exports2.RefsArgsSchema = exports2.SearchArgsSchema = exports2.InspectArgsSchema = exports2.BaseQuerySchema = exports2.FormatSchema = void 0;
65441
+ exports2.InspectOutputSchema = exports2.RefsOutputSchema = exports2.RefResultSchema = exports2.MapOutputSchema = exports2.SearchOutputSchema = exports2.StatusOutputSchema = exports2.StatusArgsSchema = exports2.MapArgsSchema = exports2.RefsArgsSchema = exports2.SearchArgsSchema = exports2.InspectArgsSchema = exports2.BaseQuerySchema = exports2.FormatSchema = void 0;
65439
65442
  var zod_1 = require_zod();
65440
65443
  exports2.FormatSchema = zod_1.z.enum(["compact", "verbose"]);
65441
65444
  exports2.BaseQuerySchema = zod_1.z.object({
@@ -65443,9 +65446,9 @@ var require_schemas3 = __commonJS({
65443
65446
  limit: zod_1.z.number().int().min(1).max(50).default(10)
65444
65447
  });
65445
65448
  exports2.InspectArgsSchema = zod_1.z.object({
65446
- query: zod_1.z.string().min(1, "Query must be a non-empty string (file path)"),
65449
+ filePath: zod_1.z.string().min(1, "filePath must be a non-empty file path"),
65447
65450
  limit: zod_1.z.number().int().min(1).max(50).default(10),
65448
- format: exports2.FormatSchema.default("compact")
65451
+ format: zod_1.z.enum(["compact", "verbose", "json"]).default("compact")
65449
65452
  }).strict();
65450
65453
  exports2.SearchArgsSchema = zod_1.z.object({
65451
65454
  query: zod_1.z.string().min(1, "Query must be a non-empty string"),
@@ -65476,31 +65479,11 @@ var require_schemas3 = __commonJS({
65476
65479
  format: zod_1.z.string(),
65477
65480
  length: zod_1.z.number()
65478
65481
  });
65479
- exports2.HealthArgsSchema = zod_1.z.object({
65480
- verbose: zod_1.z.boolean().default(false)
65481
- }).strict();
65482
65482
  exports2.SearchOutputSchema = zod_1.z.object({
65483
65483
  query: zod_1.z.string(),
65484
65484
  format: zod_1.z.string(),
65485
65485
  content: zod_1.z.string()
65486
65486
  });
65487
- exports2.HealthCheckResultSchema = zod_1.z.object({
65488
- status: zod_1.z.enum(["pass", "warn", "fail"]),
65489
- message: zod_1.z.string(),
65490
- details: zod_1.z.any().optional()
65491
- // Allow any type for details
65492
- });
65493
- exports2.HealthOutputSchema = zod_1.z.object({
65494
- status: zod_1.z.enum(["healthy", "degraded", "unhealthy"]),
65495
- uptime: zod_1.z.number(),
65496
- timestamp: zod_1.z.string(),
65497
- checks: zod_1.z.object({
65498
- vectorStorage: exports2.HealthCheckResultSchema,
65499
- repository: exports2.HealthCheckResultSchema,
65500
- githubIndex: exports2.HealthCheckResultSchema.optional()
65501
- }),
65502
- formattedReport: zod_1.z.string()
65503
- });
65504
65487
  exports2.MapOutputSchema = zod_1.z.object({
65505
65488
  content: zod_1.z.string(),
65506
65489
  totalComponents: zod_1.z.number(),
@@ -65591,302 +65574,6 @@ var require_validation = __commonJS({
65591
65574
  }
65592
65575
  });
65593
65576
 
65594
- // ../mcp-server/dist/src/adapters/built-in/health-adapter.js
65595
- var require_health_adapter = __commonJS({
65596
- "../mcp-server/dist/src/adapters/built-in/health-adapter.js"(exports2) {
65597
- "use strict";
65598
- var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
65599
- if (k2 === void 0) k2 = k;
65600
- var desc = Object.getOwnPropertyDescriptor(m, k);
65601
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
65602
- desc = { enumerable: true, get: function() {
65603
- return m[k];
65604
- } };
65605
- }
65606
- Object.defineProperty(o, k2, desc);
65607
- }) : (function(o, m, k, k2) {
65608
- if (k2 === void 0) k2 = k;
65609
- o[k2] = m[k];
65610
- }));
65611
- var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
65612
- Object.defineProperty(o, "default", { enumerable: true, value: v });
65613
- }) : function(o, v) {
65614
- o["default"] = v;
65615
- });
65616
- var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
65617
- var ownKeys = function(o) {
65618
- ownKeys = Object.getOwnPropertyNames || function(o2) {
65619
- var ar = [];
65620
- for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
65621
- return ar;
65622
- };
65623
- return ownKeys(o);
65624
- };
65625
- return function(mod) {
65626
- if (mod && mod.__esModule) return mod;
65627
- var result = {};
65628
- if (mod != null) {
65629
- for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
65630
- }
65631
- __setModuleDefault(result, mod);
65632
- return result;
65633
- };
65634
- })();
65635
- Object.defineProperty(exports2, "__esModule", { value: true });
65636
- exports2.HealthAdapter = void 0;
65637
- var fs12 = __importStar(require("fs/promises"));
65638
- var index_js_12 = require_schemas3();
65639
- var tool_adapter_1 = require_tool_adapter();
65640
- var validation_js_1 = require_validation();
65641
- var HealthAdapter = class extends tool_adapter_1.ToolAdapter {
65642
- metadata = {
65643
- name: "health-adapter",
65644
- version: "1.0.0",
65645
- description: "Provides health and readiness checks for the MCP server"
65646
- };
65647
- config;
65648
- startTime;
65649
- constructor(config2) {
65650
- super();
65651
- this.config = config2;
65652
- this.startTime = Date.now();
65653
- }
65654
- async initialize(context) {
65655
- this.initializeBase(context);
65656
- }
65657
- async shutdown() {
65658
- }
65659
- getToolDefinition() {
65660
- return {
65661
- name: "dev_health",
65662
- description: "Check the health status of the dev-agent MCP server and its dependencies (vector storage, repository, GitHub index)",
65663
- inputSchema: {
65664
- type: "object",
65665
- properties: {
65666
- verbose: {
65667
- type: "boolean",
65668
- description: "Include detailed diagnostic information",
65669
- default: false
65670
- }
65671
- }
65672
- }
65673
- };
65674
- }
65675
- async execute(args, context) {
65676
- const validation = (0, validation_js_1.validateArgs)(index_js_12.HealthArgsSchema, args);
65677
- if (!validation.success) {
65678
- return validation.error;
65679
- }
65680
- const { verbose } = validation.data;
65681
- try {
65682
- const health = await this.performHealthChecks(verbose);
65683
- const status = this.getOverallStatus(health);
65684
- const emoji3 = status === "healthy" ? "\u2705" : status === "degraded" ? "\u26A0\uFE0F" : "\u274C";
65685
- const content3 = this.formatHealthReport(health, verbose);
65686
- return {
65687
- success: true,
65688
- data: `${emoji3} **MCP Server Health: ${status.toUpperCase()}**
65689
-
65690
- ${content3}`
65691
- };
65692
- } catch (error47) {
65693
- context.logger.error("Health check failed", {
65694
- error: error47 instanceof Error ? error47.message : String(error47)
65695
- });
65696
- return {
65697
- success: false,
65698
- error: {
65699
- code: "HEALTH_CHECK_ERROR",
65700
- message: error47 instanceof Error ? error47.message : "Health check failed",
65701
- recoverable: true
65702
- }
65703
- };
65704
- }
65705
- }
65706
- async performHealthChecks(verbose) {
65707
- const [vectorStorage, repository, githubIndex] = await Promise.all([
65708
- this.checkVectorStorage(verbose),
65709
- this.checkRepository(verbose),
65710
- this.config.githubStatePath ? this.checkGitHubIndex(verbose) : Promise.resolve(void 0)
65711
- ]);
65712
- const checks = {
65713
- vectorStorage,
65714
- repository
65715
- };
65716
- if (githubIndex) {
65717
- checks.githubIndex = githubIndex;
65718
- }
65719
- return {
65720
- status: this.getOverallStatus({ checks }),
65721
- checks,
65722
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
65723
- uptime: Date.now() - this.startTime
65724
- };
65725
- }
65726
- async checkVectorStorage(verbose) {
65727
- try {
65728
- const stats = await fs12.stat(this.config.vectorStorePath);
65729
- if (!stats.isDirectory()) {
65730
- return {
65731
- status: "fail",
65732
- message: "Vector storage path is not a directory"
65733
- };
65734
- }
65735
- const files = await fs12.readdir(this.config.vectorStorePath);
65736
- const hasData = files.length > 0;
65737
- if (!hasData) {
65738
- return {
65739
- status: "warn",
65740
- message: "Vector storage is empty (repository may not be indexed)",
65741
- details: verbose ? { path: this.config.vectorStorePath } : void 0
65742
- };
65743
- }
65744
- return {
65745
- status: "pass",
65746
- message: `Vector storage operational (${files.length} files)`,
65747
- details: verbose ? { path: this.config.vectorStorePath, fileCount: files.length } : void 0
65748
- };
65749
- } catch (error47) {
65750
- return {
65751
- status: "fail",
65752
- message: `Vector storage not accessible: ${error47 instanceof Error ? error47.message : String(error47)}`,
65753
- details: verbose ? { path: this.config.vectorStorePath } : void 0
65754
- };
65755
- }
65756
- }
65757
- async checkRepository(verbose) {
65758
- try {
65759
- const stats = await fs12.stat(this.config.repositoryPath);
65760
- if (!stats.isDirectory()) {
65761
- return {
65762
- status: "fail",
65763
- message: "Repository path is not a directory"
65764
- };
65765
- }
65766
- try {
65767
- await fs12.stat(`${this.config.repositoryPath}/.git`);
65768
- return {
65769
- status: "pass",
65770
- message: "Repository accessible and is a Git repository",
65771
- details: verbose ? { path: this.config.repositoryPath } : void 0
65772
- };
65773
- } catch {
65774
- return {
65775
- status: "warn",
65776
- message: "Repository accessible but not a Git repository",
65777
- details: verbose ? { path: this.config.repositoryPath } : void 0
65778
- };
65779
- }
65780
- } catch (error47) {
65781
- return {
65782
- status: "fail",
65783
- message: `Repository not accessible: ${error47 instanceof Error ? error47.message : String(error47)}`,
65784
- details: verbose ? { path: this.config.repositoryPath } : void 0
65785
- };
65786
- }
65787
- }
65788
- async checkGitHubIndex(verbose) {
65789
- if (!this.config.githubStatePath) {
65790
- return {
65791
- status: "warn",
65792
- message: "GitHub index not configured"
65793
- };
65794
- }
65795
- try {
65796
- const content3 = await fs12.readFile(this.config.githubStatePath, "utf-8");
65797
- const state = JSON.parse(content3);
65798
- const lastIndexed = state.lastIndexed ? new Date(state.lastIndexed) : null;
65799
- const itemCount = state.items?.length ?? 0;
65800
- if (!lastIndexed) {
65801
- return {
65802
- status: "warn",
65803
- message: "GitHub index exists but has no lastIndexed timestamp",
65804
- details: verbose ? { path: this.config.githubStatePath } : void 0
65805
- };
65806
- }
65807
- const ageMs = Date.now() - lastIndexed.getTime();
65808
- const ageHours = Math.floor(ageMs / (1e3 * 60 * 60));
65809
- if (ageHours > 24) {
65810
- return {
65811
- status: "warn",
65812
- message: `GitHub index is ${ageHours}h old (${itemCount} items) - consider re-indexing`,
65813
- details: verbose ? { path: this.config.githubStatePath, lastIndexed: lastIndexed.toISOString() } : void 0
65814
- };
65815
- }
65816
- return {
65817
- status: "pass",
65818
- message: `GitHub index operational (${itemCount} items, indexed ${ageHours}h ago)`,
65819
- details: verbose ? { path: this.config.githubStatePath, lastIndexed: lastIndexed.toISOString() } : void 0
65820
- };
65821
- } catch (error47) {
65822
- return {
65823
- status: "warn",
65824
- message: `GitHub index not accessible: ${error47 instanceof Error ? error47.message : String(error47)}`,
65825
- details: verbose ? { path: this.config.githubStatePath } : void 0
65826
- };
65827
- }
65828
- }
65829
- getOverallStatus(health) {
65830
- const checks = Object.values(health.checks).filter((check2) => check2 !== void 0);
65831
- const hasFail = checks.some((check2) => check2.status === "fail");
65832
- const hasWarn = checks.some((check2) => check2.status === "warn");
65833
- if (hasFail) {
65834
- return "unhealthy";
65835
- }
65836
- if (hasWarn) {
65837
- return "degraded";
65838
- }
65839
- return "healthy";
65840
- }
65841
- formatHealthReport(health, verbose) {
65842
- const lines = [];
65843
- const uptimeMs = health.uptime;
65844
- const uptimeStr = this.formatUptime(uptimeMs);
65845
- lines.push(`**Uptime:** ${uptimeStr}`);
65846
- lines.push(`**Timestamp:** ${new Date(health.timestamp).toLocaleString()}`);
65847
- lines.push("");
65848
- lines.push("**Component Status:**");
65849
- lines.push("");
65850
- for (const [name, check2] of Object.entries(health.checks)) {
65851
- if (!check2)
65852
- continue;
65853
- const statusEmoji = check2.status === "pass" ? "\u2705" : check2.status === "warn" ? "\u26A0\uFE0F" : "\u274C";
65854
- const componentName = this.formatComponentName(name);
65855
- lines.push(`${statusEmoji} **${componentName}:** ${check2.message}`);
65856
- if (verbose && check2.details) {
65857
- lines.push(` *Details:* ${JSON.stringify(check2.details)}`);
65858
- }
65859
- }
65860
- return lines.join("\n");
65861
- }
65862
- formatComponentName(name) {
65863
- return name.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase()).trim();
65864
- }
65865
- formatUptime(ms) {
65866
- const seconds = Math.floor(ms / 1e3);
65867
- const minutes = Math.floor(seconds / 60);
65868
- const hours = Math.floor(minutes / 60);
65869
- const days = Math.floor(hours / 24);
65870
- if (days > 0) {
65871
- return `${days}d ${hours % 24}h ${minutes % 60}m`;
65872
- }
65873
- if (hours > 0) {
65874
- return `${hours}h ${minutes % 60}m`;
65875
- }
65876
- if (minutes > 0) {
65877
- return `${minutes}m ${seconds % 60}s`;
65878
- }
65879
- return `${seconds}s`;
65880
- }
65881
- async healthCheck() {
65882
- const health = await this.performHealthChecks(false);
65883
- return health.status === "healthy";
65884
- }
65885
- };
65886
- exports2.HealthAdapter = HealthAdapter;
65887
- }
65888
- });
65889
-
65890
65577
  // ../mcp-server/dist/src/adapters/built-in/inspect-adapter.js
65891
65578
  var require_inspect_adapter = __commonJS({
65892
65579
  "../mcp-server/dist/src/adapters/built-in/inspect-adapter.js"(exports2) {
@@ -65914,7 +65601,8 @@ var require_inspect_adapter = __commonJS({
65914
65601
  this.repositoryPath = config2.repositoryPath;
65915
65602
  this.searchService = config2.searchService;
65916
65603
  this.patternService = new dev_agent_core_1.PatternAnalysisService({
65917
- repositoryPath: config2.repositoryPath
65604
+ repositoryPath: config2.repositoryPath,
65605
+ vectorStorage: config2.vectorStorage
65918
65606
  });
65919
65607
  this.defaultLimit = config2.defaultLimit ?? 10;
65920
65608
  this.defaultThreshold = config2.defaultThreshold ?? 0.7;
@@ -65933,11 +65621,11 @@ var require_inspect_adapter = __commonJS({
65933
65621
  getToolDefinition() {
65934
65622
  return {
65935
65623
  name: "dev_patterns",
65936
- description: "Analyze coding patterns in a file against the codebase. Compares import style, error handling, type coverage, test coverage, and file size against similar files. Use for code reviews and consistency checks.",
65624
+ description: "Analyze coding patterns in a file against similar code in the codebase. Compares import style, error handling, type coverage, test coverage, and file size. Use for code reviews and consistency checks. NOT for finding code (use dev_search) or tracing calls (use dev_refs).",
65937
65625
  inputSchema: {
65938
65626
  type: "object",
65939
65627
  properties: {
65940
- query: {
65628
+ filePath: {
65941
65629
  type: "string",
65942
65630
  description: 'File path to analyze (e.g., "src/auth/middleware.ts")'
65943
65631
  },
@@ -65950,12 +65638,12 @@ var require_inspect_adapter = __commonJS({
65950
65638
  },
65951
65639
  format: {
65952
65640
  type: "string",
65953
- enum: ["compact", "verbose"],
65954
- description: 'Output format: "compact" for summaries (default), "verbose" for full details',
65641
+ enum: ["compact", "verbose", "json"],
65642
+ description: 'Output format: "compact" (default), "verbose" for details, "json" for structured data',
65955
65643
  default: this.defaultFormat
65956
65644
  }
65957
65645
  },
65958
- required: ["query"]
65646
+ required: ["filePath"]
65959
65647
  }
65960
65648
  };
65961
65649
  }
@@ -65964,34 +65652,42 @@ var require_inspect_adapter = __commonJS({
65964
65652
  if (!validation.success) {
65965
65653
  return validation.error;
65966
65654
  }
65967
- const { query, limit, format: format2 } = validation.data;
65655
+ const { filePath, limit, format: format2 } = validation.data;
65968
65656
  try {
65969
65657
  context.logger.debug("Executing pattern analysis", {
65970
- query,
65658
+ filePath,
65971
65659
  limit,
65972
65660
  format: format2
65973
65661
  });
65974
- const { content: content3, similarFilesCount, patternsAnalyzed } = await this.inspectFile(
65975
- query,
65976
- limit,
65977
- 0,
65978
- // No threshold — let the pattern service decide relevance
65979
- format2
65980
- );
65662
+ const { content: content3, similarFilesCount, patternsAnalyzed, patternComparison } = await this.inspectFile(filePath, limit, 0, format2);
65981
65663
  context.logger.info("File inspection completed", {
65982
- query,
65664
+ filePath,
65983
65665
  similarFilesCount,
65984
65666
  patternsAnalyzed,
65985
65667
  contentLength: content3.length
65986
65668
  });
65669
+ if (format2 === "json" && patternComparison) {
65670
+ const jsonData = JSON.stringify(patternComparison, null, 2);
65671
+ return {
65672
+ success: true,
65673
+ data: jsonData,
65674
+ metadata: {
65675
+ tokens: jsonData.length / 4,
65676
+ duration_ms: 0,
65677
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
65678
+ cached: false,
65679
+ similar_files_count: similarFilesCount,
65680
+ patterns_analyzed: patternsAnalyzed,
65681
+ format: "json"
65682
+ }
65683
+ };
65684
+ }
65987
65685
  return {
65988
65686
  success: true,
65989
65687
  data: content3,
65990
65688
  metadata: {
65991
65689
  tokens: content3.length / 4,
65992
- // Rough estimate
65993
65690
  duration_ms: 0,
65994
- // Calculated by MCP server
65995
65691
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
65996
65692
  cached: false,
65997
65693
  similar_files_count: similarFilesCount,
@@ -66007,7 +65703,7 @@ var require_inspect_adapter = __commonJS({
66007
65703
  success: false,
66008
65704
  error: {
66009
65705
  code: "FILE_NOT_FOUND",
66010
- message: `File not found: ${query}`,
65706
+ message: `File not found: ${filePath}`,
66011
65707
  suggestion: "Check the file path and ensure it exists in the repository."
66012
65708
  }
66013
65709
  };
@@ -66027,7 +65723,8 @@ var require_inspect_adapter = __commonJS({
66027
65723
  success: false,
66028
65724
  error: {
66029
65725
  code: "INSPECTION_ERROR",
66030
- message: error47 instanceof Error ? error47.message : "Unknown inspection error"
65726
+ message: error47 instanceof Error ? error47.message : "Unknown inspection error",
65727
+ suggestion: "Check the file path is valid and the repository is indexed."
66031
65728
  }
66032
65729
  };
66033
65730
  }
@@ -66063,12 +65760,12 @@ var require_inspect_adapter = __commonJS({
66063
65760
  }
66064
65761
  const similarFilePaths = filteredResults.map((r) => r.metadata.path);
66065
65762
  const patternComparison = await this.patternService.comparePatterns(filePath, similarFilePaths);
66066
- const content3 = format2 === "verbose" ? await this.formatInspectionVerbose(filePath, filteredResults, patternComparison) : await this.formatInspectionCompact(filePath, filteredResults, patternComparison);
65763
+ const content3 = format2 === "json" ? "" : format2 === "verbose" ? await this.formatInspectionVerbose(filePath, filteredResults, patternComparison) : await this.formatInspectionCompact(filePath, filteredResults, patternComparison);
66067
65764
  return {
66068
65765
  content: content3,
66069
65766
  similarFilesCount: filteredResults.length,
66070
- patternsAnalyzed: 5
66071
- // Currently analyzing 5 pattern categories
65767
+ patternsAnalyzed: 5,
65768
+ patternComparison
66072
65769
  };
66073
65770
  }
66074
65771
  /**
@@ -66393,7 +66090,7 @@ var require_map_adapter = __commonJS({
66393
66090
  error: {
66394
66091
  code: "MAP_FAILED",
66395
66092
  message: error47 instanceof Error ? error47.message : "Unknown error",
66396
- details: error47
66093
+ suggestion: 'Run "dev index" first. Try a lower depth if the map is too large.'
66397
66094
  }
66398
66095
  };
66399
66096
  }
@@ -66486,7 +66183,8 @@ var require_refs_adapter = __commonJS({
66486
66183
  success: false,
66487
66184
  error: {
66488
66185
  code: "NOT_FOUND",
66489
- message: `Could not find function or method named "${name}"`
66186
+ message: `Could not find function or method named "${name}"`,
66187
+ suggestion: "Verify the function name exists with dev_search first. Names are case-sensitive."
66490
66188
  }
66491
66189
  };
66492
66190
  }
@@ -66531,7 +66229,7 @@ var require_refs_adapter = __commonJS({
66531
66229
  error: {
66532
66230
  code: "REFS_FAILED",
66533
66231
  message: error47 instanceof Error ? error47.message : "Unknown error",
66534
- details: error47
66232
+ suggestion: "Try dev_search to find the correct function name first."
66535
66233
  }
66536
66234
  };
66537
66235
  }
@@ -67285,7 +66983,7 @@ var require_search_adapter = __commonJS({
67285
66983
  error: {
67286
66984
  code: "SEARCH_FAILED",
67287
66985
  message: error47 instanceof Error ? error47.message : "Unknown error",
67288
- details: error47
66986
+ suggestion: 'Run "dev index" to index the repository. Try a different query if no results.'
67289
66987
  }
67290
66988
  };
67291
66989
  }
@@ -67426,7 +67124,7 @@ var require_status_adapter = __commonJS({
67426
67124
  error: {
67427
67125
  code: "STATUS_FAILED",
67428
67126
  message: error47 instanceof Error ? error47.message : "Unknown error",
67429
- details: error47
67127
+ suggestion: 'Run "dev setup" to ensure Antfly is running, then "dev index" to index.'
67430
67128
  }
67431
67129
  };
67432
67130
  }
@@ -67627,11 +67325,7 @@ var require_built_in = __commonJS({
67627
67325
  "../mcp-server/dist/src/adapters/built-in/index.js"(exports2) {
67628
67326
  "use strict";
67629
67327
  Object.defineProperty(exports2, "__esModule", { value: true });
67630
- exports2.StatusAdapter = exports2.SearchAdapter = exports2.RefsAdapter = exports2.MapAdapter = exports2.InspectAdapter = exports2.HealthAdapter = void 0;
67631
- var health_adapter_js_1 = require_health_adapter();
67632
- Object.defineProperty(exports2, "HealthAdapter", { enumerable: true, get: function() {
67633
- return health_adapter_js_1.HealthAdapter;
67634
- } });
67328
+ exports2.StatusAdapter = exports2.SearchAdapter = exports2.RefsAdapter = exports2.MapAdapter = exports2.InspectAdapter = void 0;
67635
67329
  var inspect_adapter_js_1 = require_inspect_adapter();
67636
67330
  Object.defineProperty(exports2, "InspectAdapter", { enumerable: true, get: function() {
67637
67331
  return inspect_adapter_js_1.InspectAdapter;
@@ -68735,9 +68429,9 @@ Setup:
68735
68429
  2. Install MCP integration: dev mcp install --cursor
68736
68430
  3. Restart Cursor to activate
68737
68431
 
68738
- Available Tools (6):
68432
+ Available Tools (5):
68739
68433
  dev_search, dev_status, dev_patterns,
68740
- dev_health, dev_refs, dev_map
68434
+ dev_refs, dev_map
68741
68435
  `).addCommand(new commander_12.Command("start").description("Start MCP server for current repository").option("-p, --port <port>", "Port for HTTP transport (if not using stdio)").option("-t, --transport <type>", "Transport type: stdio (default) or http", "stdio").option("-v, --verbose", "Verbose logging", false).action(async (options) => {
68742
68436
  const repositoryPath = process.env.WORKSPACE_FOLDER_PATHS || process.env.REPOSITORY_PATH || process.cwd();
68743
68437
  const logLevel = options.verbose ? "debug" : "info";
@@ -68777,10 +68471,6 @@ Available Tools (6):
68777
68471
  defaultThreshold: 0.7,
68778
68472
  defaultFormat: "compact"
68779
68473
  });
68780
- const healthAdapter = new dev_agent_mcp_1.HealthAdapter({
68781
- repositoryPath,
68782
- vectorStorePath: vectors
68783
- });
68784
68474
  const refsAdapter = new dev_agent_mcp_1.RefsAdapter({
68785
68475
  searchService,
68786
68476
  defaultLimit: 20
@@ -68801,14 +68491,7 @@ Available Tools (6):
68801
68491
  logLevel
68802
68492
  },
68803
68493
  transport: options.transport === "stdio" ? "stdio" : void 0,
68804
- adapters: [
68805
- searchAdapter,
68806
- statusAdapter,
68807
- inspectAdapter,
68808
- healthAdapter,
68809
- refsAdapter,
68810
- mapAdapter
68811
- ]
68494
+ adapters: [searchAdapter, statusAdapter, inspectAdapter, refsAdapter, mapAdapter]
68812
68495
  });
68813
68496
  const shutdown = async () => {
68814
68497
  logger_1.logger.info("Shutting down MCP server...");
@@ -68820,7 +68503,7 @@ Available Tools (6):
68820
68503
  process.on("SIGTERM", shutdown);
68821
68504
  await server.start();
68822
68505
  logger_1.logger.info(chalk_12.default.green("MCP server started successfully!"));
68823
- logger_1.logger.info("Available tools: dev_search, dev_status, dev_patterns, dev_health, dev_refs, dev_map");
68506
+ logger_1.logger.info("Available tools: dev_search, dev_status, dev_patterns, dev_refs, dev_map");
68824
68507
  if (options.transport === "stdio") {
68825
68508
  logger_1.logger.info("Server running on stdio transport (for AI tools)");
68826
68509
  } else {
@@ -69742,7 +69425,7 @@ var reset_js_1 = require_reset();
69742
69425
  var search_js_1 = require_search();
69743
69426
  var setup_js_1 = require_setup();
69744
69427
  var storage_js_1 = require_storage();
69745
- var VERSION = true ? "0.10.2" : "0.0.0-dev";
69428
+ var VERSION = true ? "0.10.4" : "0.0.0-dev";
69746
69429
  var program = new commander_1.Command();
69747
69430
  program.name("dev").description(chalk_1.default.cyan("\u{1F916} Dev-Agent - Multi-agent code intelligence platform")).version(VERSION);
69748
69431
  program.addCommand(index_js_1.indexCommand);