@prosdevlab/dev-agent 0.10.3 → 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
  // ========================================================================
@@ -65448,7 +65438,7 @@ var require_schemas3 = __commonJS({
65448
65438
  "../mcp-server/dist/src/schemas/index.js"(exports2) {
65449
65439
  "use strict";
65450
65440
  Object.defineProperty(exports2, "__esModule", { value: true });
65451
- 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;
65452
65442
  var zod_1 = require_zod();
65453
65443
  exports2.FormatSchema = zod_1.z.enum(["compact", "verbose"]);
65454
65444
  exports2.BaseQuerySchema = zod_1.z.object({
@@ -65456,9 +65446,9 @@ var require_schemas3 = __commonJS({
65456
65446
  limit: zod_1.z.number().int().min(1).max(50).default(10)
65457
65447
  });
65458
65448
  exports2.InspectArgsSchema = zod_1.z.object({
65459
- 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"),
65460
65450
  limit: zod_1.z.number().int().min(1).max(50).default(10),
65461
- format: exports2.FormatSchema.default("compact")
65451
+ format: zod_1.z.enum(["compact", "verbose", "json"]).default("compact")
65462
65452
  }).strict();
65463
65453
  exports2.SearchArgsSchema = zod_1.z.object({
65464
65454
  query: zod_1.z.string().min(1, "Query must be a non-empty string"),
@@ -65489,31 +65479,11 @@ var require_schemas3 = __commonJS({
65489
65479
  format: zod_1.z.string(),
65490
65480
  length: zod_1.z.number()
65491
65481
  });
65492
- exports2.HealthArgsSchema = zod_1.z.object({
65493
- verbose: zod_1.z.boolean().default(false)
65494
- }).strict();
65495
65482
  exports2.SearchOutputSchema = zod_1.z.object({
65496
65483
  query: zod_1.z.string(),
65497
65484
  format: zod_1.z.string(),
65498
65485
  content: zod_1.z.string()
65499
65486
  });
65500
- exports2.HealthCheckResultSchema = zod_1.z.object({
65501
- status: zod_1.z.enum(["pass", "warn", "fail"]),
65502
- message: zod_1.z.string(),
65503
- details: zod_1.z.any().optional()
65504
- // Allow any type for details
65505
- });
65506
- exports2.HealthOutputSchema = zod_1.z.object({
65507
- status: zod_1.z.enum(["healthy", "degraded", "unhealthy"]),
65508
- uptime: zod_1.z.number(),
65509
- timestamp: zod_1.z.string(),
65510
- checks: zod_1.z.object({
65511
- vectorStorage: exports2.HealthCheckResultSchema,
65512
- repository: exports2.HealthCheckResultSchema,
65513
- githubIndex: exports2.HealthCheckResultSchema.optional()
65514
- }),
65515
- formattedReport: zod_1.z.string()
65516
- });
65517
65487
  exports2.MapOutputSchema = zod_1.z.object({
65518
65488
  content: zod_1.z.string(),
65519
65489
  totalComponents: zod_1.z.number(),
@@ -65604,302 +65574,6 @@ var require_validation = __commonJS({
65604
65574
  }
65605
65575
  });
65606
65576
 
65607
- // ../mcp-server/dist/src/adapters/built-in/health-adapter.js
65608
- var require_health_adapter = __commonJS({
65609
- "../mcp-server/dist/src/adapters/built-in/health-adapter.js"(exports2) {
65610
- "use strict";
65611
- var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
65612
- if (k2 === void 0) k2 = k;
65613
- var desc = Object.getOwnPropertyDescriptor(m, k);
65614
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
65615
- desc = { enumerable: true, get: function() {
65616
- return m[k];
65617
- } };
65618
- }
65619
- Object.defineProperty(o, k2, desc);
65620
- }) : (function(o, m, k, k2) {
65621
- if (k2 === void 0) k2 = k;
65622
- o[k2] = m[k];
65623
- }));
65624
- var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
65625
- Object.defineProperty(o, "default", { enumerable: true, value: v });
65626
- }) : function(o, v) {
65627
- o["default"] = v;
65628
- });
65629
- var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
65630
- var ownKeys = function(o) {
65631
- ownKeys = Object.getOwnPropertyNames || function(o2) {
65632
- var ar = [];
65633
- for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
65634
- return ar;
65635
- };
65636
- return ownKeys(o);
65637
- };
65638
- return function(mod) {
65639
- if (mod && mod.__esModule) return mod;
65640
- var result = {};
65641
- if (mod != null) {
65642
- for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
65643
- }
65644
- __setModuleDefault(result, mod);
65645
- return result;
65646
- };
65647
- })();
65648
- Object.defineProperty(exports2, "__esModule", { value: true });
65649
- exports2.HealthAdapter = void 0;
65650
- var fs12 = __importStar(require("fs/promises"));
65651
- var index_js_12 = require_schemas3();
65652
- var tool_adapter_1 = require_tool_adapter();
65653
- var validation_js_1 = require_validation();
65654
- var HealthAdapter = class extends tool_adapter_1.ToolAdapter {
65655
- metadata = {
65656
- name: "health-adapter",
65657
- version: "1.0.0",
65658
- description: "Provides health and readiness checks for the MCP server"
65659
- };
65660
- config;
65661
- startTime;
65662
- constructor(config2) {
65663
- super();
65664
- this.config = config2;
65665
- this.startTime = Date.now();
65666
- }
65667
- async initialize(context) {
65668
- this.initializeBase(context);
65669
- }
65670
- async shutdown() {
65671
- }
65672
- getToolDefinition() {
65673
- return {
65674
- name: "dev_health",
65675
- description: "Check the health status of the dev-agent MCP server and its dependencies (vector storage, repository, GitHub index)",
65676
- inputSchema: {
65677
- type: "object",
65678
- properties: {
65679
- verbose: {
65680
- type: "boolean",
65681
- description: "Include detailed diagnostic information",
65682
- default: false
65683
- }
65684
- }
65685
- }
65686
- };
65687
- }
65688
- async execute(args, context) {
65689
- const validation = (0, validation_js_1.validateArgs)(index_js_12.HealthArgsSchema, args);
65690
- if (!validation.success) {
65691
- return validation.error;
65692
- }
65693
- const { verbose } = validation.data;
65694
- try {
65695
- const health = await this.performHealthChecks(verbose);
65696
- const status = this.getOverallStatus(health);
65697
- const emoji3 = status === "healthy" ? "\u2705" : status === "degraded" ? "\u26A0\uFE0F" : "\u274C";
65698
- const content3 = this.formatHealthReport(health, verbose);
65699
- return {
65700
- success: true,
65701
- data: `${emoji3} **MCP Server Health: ${status.toUpperCase()}**
65702
-
65703
- ${content3}`
65704
- };
65705
- } catch (error47) {
65706
- context.logger.error("Health check failed", {
65707
- error: error47 instanceof Error ? error47.message : String(error47)
65708
- });
65709
- return {
65710
- success: false,
65711
- error: {
65712
- code: "HEALTH_CHECK_ERROR",
65713
- message: error47 instanceof Error ? error47.message : "Health check failed",
65714
- recoverable: true
65715
- }
65716
- };
65717
- }
65718
- }
65719
- async performHealthChecks(verbose) {
65720
- const [vectorStorage, repository, githubIndex] = await Promise.all([
65721
- this.checkVectorStorage(verbose),
65722
- this.checkRepository(verbose),
65723
- this.config.githubStatePath ? this.checkGitHubIndex(verbose) : Promise.resolve(void 0)
65724
- ]);
65725
- const checks = {
65726
- vectorStorage,
65727
- repository
65728
- };
65729
- if (githubIndex) {
65730
- checks.githubIndex = githubIndex;
65731
- }
65732
- return {
65733
- status: this.getOverallStatus({ checks }),
65734
- checks,
65735
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
65736
- uptime: Date.now() - this.startTime
65737
- };
65738
- }
65739
- async checkVectorStorage(verbose) {
65740
- try {
65741
- const stats = await fs12.stat(this.config.vectorStorePath);
65742
- if (!stats.isDirectory()) {
65743
- return {
65744
- status: "fail",
65745
- message: "Vector storage path is not a directory"
65746
- };
65747
- }
65748
- const files = await fs12.readdir(this.config.vectorStorePath);
65749
- const hasData = files.length > 0;
65750
- if (!hasData) {
65751
- return {
65752
- status: "warn",
65753
- message: "Vector storage is empty (repository may not be indexed)",
65754
- details: verbose ? { path: this.config.vectorStorePath } : void 0
65755
- };
65756
- }
65757
- return {
65758
- status: "pass",
65759
- message: `Vector storage operational (${files.length} files)`,
65760
- details: verbose ? { path: this.config.vectorStorePath, fileCount: files.length } : void 0
65761
- };
65762
- } catch (error47) {
65763
- return {
65764
- status: "fail",
65765
- message: `Vector storage not accessible: ${error47 instanceof Error ? error47.message : String(error47)}`,
65766
- details: verbose ? { path: this.config.vectorStorePath } : void 0
65767
- };
65768
- }
65769
- }
65770
- async checkRepository(verbose) {
65771
- try {
65772
- const stats = await fs12.stat(this.config.repositoryPath);
65773
- if (!stats.isDirectory()) {
65774
- return {
65775
- status: "fail",
65776
- message: "Repository path is not a directory"
65777
- };
65778
- }
65779
- try {
65780
- await fs12.stat(`${this.config.repositoryPath}/.git`);
65781
- return {
65782
- status: "pass",
65783
- message: "Repository accessible and is a Git repository",
65784
- details: verbose ? { path: this.config.repositoryPath } : void 0
65785
- };
65786
- } catch {
65787
- return {
65788
- status: "warn",
65789
- message: "Repository accessible but not a Git repository",
65790
- details: verbose ? { path: this.config.repositoryPath } : void 0
65791
- };
65792
- }
65793
- } catch (error47) {
65794
- return {
65795
- status: "fail",
65796
- message: `Repository not accessible: ${error47 instanceof Error ? error47.message : String(error47)}`,
65797
- details: verbose ? { path: this.config.repositoryPath } : void 0
65798
- };
65799
- }
65800
- }
65801
- async checkGitHubIndex(verbose) {
65802
- if (!this.config.githubStatePath) {
65803
- return {
65804
- status: "warn",
65805
- message: "GitHub index not configured"
65806
- };
65807
- }
65808
- try {
65809
- const content3 = await fs12.readFile(this.config.githubStatePath, "utf-8");
65810
- const state = JSON.parse(content3);
65811
- const lastIndexed = state.lastIndexed ? new Date(state.lastIndexed) : null;
65812
- const itemCount = state.items?.length ?? 0;
65813
- if (!lastIndexed) {
65814
- return {
65815
- status: "warn",
65816
- message: "GitHub index exists but has no lastIndexed timestamp",
65817
- details: verbose ? { path: this.config.githubStatePath } : void 0
65818
- };
65819
- }
65820
- const ageMs = Date.now() - lastIndexed.getTime();
65821
- const ageHours = Math.floor(ageMs / (1e3 * 60 * 60));
65822
- if (ageHours > 24) {
65823
- return {
65824
- status: "warn",
65825
- message: `GitHub index is ${ageHours}h old (${itemCount} items) - consider re-indexing`,
65826
- details: verbose ? { path: this.config.githubStatePath, lastIndexed: lastIndexed.toISOString() } : void 0
65827
- };
65828
- }
65829
- return {
65830
- status: "pass",
65831
- message: `GitHub index operational (${itemCount} items, indexed ${ageHours}h ago)`,
65832
- details: verbose ? { path: this.config.githubStatePath, lastIndexed: lastIndexed.toISOString() } : void 0
65833
- };
65834
- } catch (error47) {
65835
- return {
65836
- status: "warn",
65837
- message: `GitHub index not accessible: ${error47 instanceof Error ? error47.message : String(error47)}`,
65838
- details: verbose ? { path: this.config.githubStatePath } : void 0
65839
- };
65840
- }
65841
- }
65842
- getOverallStatus(health) {
65843
- const checks = Object.values(health.checks).filter((check2) => check2 !== void 0);
65844
- const hasFail = checks.some((check2) => check2.status === "fail");
65845
- const hasWarn = checks.some((check2) => check2.status === "warn");
65846
- if (hasFail) {
65847
- return "unhealthy";
65848
- }
65849
- if (hasWarn) {
65850
- return "degraded";
65851
- }
65852
- return "healthy";
65853
- }
65854
- formatHealthReport(health, verbose) {
65855
- const lines = [];
65856
- const uptimeMs = health.uptime;
65857
- const uptimeStr = this.formatUptime(uptimeMs);
65858
- lines.push(`**Uptime:** ${uptimeStr}`);
65859
- lines.push(`**Timestamp:** ${new Date(health.timestamp).toLocaleString()}`);
65860
- lines.push("");
65861
- lines.push("**Component Status:**");
65862
- lines.push("");
65863
- for (const [name, check2] of Object.entries(health.checks)) {
65864
- if (!check2)
65865
- continue;
65866
- const statusEmoji = check2.status === "pass" ? "\u2705" : check2.status === "warn" ? "\u26A0\uFE0F" : "\u274C";
65867
- const componentName = this.formatComponentName(name);
65868
- lines.push(`${statusEmoji} **${componentName}:** ${check2.message}`);
65869
- if (verbose && check2.details) {
65870
- lines.push(` *Details:* ${JSON.stringify(check2.details)}`);
65871
- }
65872
- }
65873
- return lines.join("\n");
65874
- }
65875
- formatComponentName(name) {
65876
- return name.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase()).trim();
65877
- }
65878
- formatUptime(ms) {
65879
- const seconds = Math.floor(ms / 1e3);
65880
- const minutes = Math.floor(seconds / 60);
65881
- const hours = Math.floor(minutes / 60);
65882
- const days = Math.floor(hours / 24);
65883
- if (days > 0) {
65884
- return `${days}d ${hours % 24}h ${minutes % 60}m`;
65885
- }
65886
- if (hours > 0) {
65887
- return `${hours}h ${minutes % 60}m`;
65888
- }
65889
- if (minutes > 0) {
65890
- return `${minutes}m ${seconds % 60}s`;
65891
- }
65892
- return `${seconds}s`;
65893
- }
65894
- async healthCheck() {
65895
- const health = await this.performHealthChecks(false);
65896
- return health.status === "healthy";
65897
- }
65898
- };
65899
- exports2.HealthAdapter = HealthAdapter;
65900
- }
65901
- });
65902
-
65903
65577
  // ../mcp-server/dist/src/adapters/built-in/inspect-adapter.js
65904
65578
  var require_inspect_adapter = __commonJS({
65905
65579
  "../mcp-server/dist/src/adapters/built-in/inspect-adapter.js"(exports2) {
@@ -65927,7 +65601,8 @@ var require_inspect_adapter = __commonJS({
65927
65601
  this.repositoryPath = config2.repositoryPath;
65928
65602
  this.searchService = config2.searchService;
65929
65603
  this.patternService = new dev_agent_core_1.PatternAnalysisService({
65930
- repositoryPath: config2.repositoryPath
65604
+ repositoryPath: config2.repositoryPath,
65605
+ vectorStorage: config2.vectorStorage
65931
65606
  });
65932
65607
  this.defaultLimit = config2.defaultLimit ?? 10;
65933
65608
  this.defaultThreshold = config2.defaultThreshold ?? 0.7;
@@ -65946,11 +65621,11 @@ var require_inspect_adapter = __commonJS({
65946
65621
  getToolDefinition() {
65947
65622
  return {
65948
65623
  name: "dev_patterns",
65949
- 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).",
65950
65625
  inputSchema: {
65951
65626
  type: "object",
65952
65627
  properties: {
65953
- query: {
65628
+ filePath: {
65954
65629
  type: "string",
65955
65630
  description: 'File path to analyze (e.g., "src/auth/middleware.ts")'
65956
65631
  },
@@ -65963,12 +65638,12 @@ var require_inspect_adapter = __commonJS({
65963
65638
  },
65964
65639
  format: {
65965
65640
  type: "string",
65966
- enum: ["compact", "verbose"],
65967
- 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',
65968
65643
  default: this.defaultFormat
65969
65644
  }
65970
65645
  },
65971
- required: ["query"]
65646
+ required: ["filePath"]
65972
65647
  }
65973
65648
  };
65974
65649
  }
@@ -65977,34 +65652,42 @@ var require_inspect_adapter = __commonJS({
65977
65652
  if (!validation.success) {
65978
65653
  return validation.error;
65979
65654
  }
65980
- const { query, limit, format: format2 } = validation.data;
65655
+ const { filePath, limit, format: format2 } = validation.data;
65981
65656
  try {
65982
65657
  context.logger.debug("Executing pattern analysis", {
65983
- query,
65658
+ filePath,
65984
65659
  limit,
65985
65660
  format: format2
65986
65661
  });
65987
- const { content: content3, similarFilesCount, patternsAnalyzed } = await this.inspectFile(
65988
- query,
65989
- limit,
65990
- 0,
65991
- // No threshold — let the pattern service decide relevance
65992
- format2
65993
- );
65662
+ const { content: content3, similarFilesCount, patternsAnalyzed, patternComparison } = await this.inspectFile(filePath, limit, 0, format2);
65994
65663
  context.logger.info("File inspection completed", {
65995
- query,
65664
+ filePath,
65996
65665
  similarFilesCount,
65997
65666
  patternsAnalyzed,
65998
65667
  contentLength: content3.length
65999
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
+ }
66000
65685
  return {
66001
65686
  success: true,
66002
65687
  data: content3,
66003
65688
  metadata: {
66004
65689
  tokens: content3.length / 4,
66005
- // Rough estimate
66006
65690
  duration_ms: 0,
66007
- // Calculated by MCP server
66008
65691
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
66009
65692
  cached: false,
66010
65693
  similar_files_count: similarFilesCount,
@@ -66020,7 +65703,7 @@ var require_inspect_adapter = __commonJS({
66020
65703
  success: false,
66021
65704
  error: {
66022
65705
  code: "FILE_NOT_FOUND",
66023
- message: `File not found: ${query}`,
65706
+ message: `File not found: ${filePath}`,
66024
65707
  suggestion: "Check the file path and ensure it exists in the repository."
66025
65708
  }
66026
65709
  };
@@ -66040,7 +65723,8 @@ var require_inspect_adapter = __commonJS({
66040
65723
  success: false,
66041
65724
  error: {
66042
65725
  code: "INSPECTION_ERROR",
66043
- 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."
66044
65728
  }
66045
65729
  };
66046
65730
  }
@@ -66076,12 +65760,12 @@ var require_inspect_adapter = __commonJS({
66076
65760
  }
66077
65761
  const similarFilePaths = filteredResults.map((r) => r.metadata.path);
66078
65762
  const patternComparison = await this.patternService.comparePatterns(filePath, similarFilePaths);
66079
- 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);
66080
65764
  return {
66081
65765
  content: content3,
66082
65766
  similarFilesCount: filteredResults.length,
66083
- patternsAnalyzed: 5
66084
- // Currently analyzing 5 pattern categories
65767
+ patternsAnalyzed: 5,
65768
+ patternComparison
66085
65769
  };
66086
65770
  }
66087
65771
  /**
@@ -66406,7 +66090,7 @@ var require_map_adapter = __commonJS({
66406
66090
  error: {
66407
66091
  code: "MAP_FAILED",
66408
66092
  message: error47 instanceof Error ? error47.message : "Unknown error",
66409
- details: error47
66093
+ suggestion: 'Run "dev index" first. Try a lower depth if the map is too large.'
66410
66094
  }
66411
66095
  };
66412
66096
  }
@@ -66499,7 +66183,8 @@ var require_refs_adapter = __commonJS({
66499
66183
  success: false,
66500
66184
  error: {
66501
66185
  code: "NOT_FOUND",
66502
- 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."
66503
66188
  }
66504
66189
  };
66505
66190
  }
@@ -66544,7 +66229,7 @@ var require_refs_adapter = __commonJS({
66544
66229
  error: {
66545
66230
  code: "REFS_FAILED",
66546
66231
  message: error47 instanceof Error ? error47.message : "Unknown error",
66547
- details: error47
66232
+ suggestion: "Try dev_search to find the correct function name first."
66548
66233
  }
66549
66234
  };
66550
66235
  }
@@ -67298,7 +66983,7 @@ var require_search_adapter = __commonJS({
67298
66983
  error: {
67299
66984
  code: "SEARCH_FAILED",
67300
66985
  message: error47 instanceof Error ? error47.message : "Unknown error",
67301
- details: error47
66986
+ suggestion: 'Run "dev index" to index the repository. Try a different query if no results.'
67302
66987
  }
67303
66988
  };
67304
66989
  }
@@ -67439,7 +67124,7 @@ var require_status_adapter = __commonJS({
67439
67124
  error: {
67440
67125
  code: "STATUS_FAILED",
67441
67126
  message: error47 instanceof Error ? error47.message : "Unknown error",
67442
- details: error47
67127
+ suggestion: 'Run "dev setup" to ensure Antfly is running, then "dev index" to index.'
67443
67128
  }
67444
67129
  };
67445
67130
  }
@@ -67640,11 +67325,7 @@ var require_built_in = __commonJS({
67640
67325
  "../mcp-server/dist/src/adapters/built-in/index.js"(exports2) {
67641
67326
  "use strict";
67642
67327
  Object.defineProperty(exports2, "__esModule", { value: true });
67643
- exports2.StatusAdapter = exports2.SearchAdapter = exports2.RefsAdapter = exports2.MapAdapter = exports2.InspectAdapter = exports2.HealthAdapter = void 0;
67644
- var health_adapter_js_1 = require_health_adapter();
67645
- Object.defineProperty(exports2, "HealthAdapter", { enumerable: true, get: function() {
67646
- return health_adapter_js_1.HealthAdapter;
67647
- } });
67328
+ exports2.StatusAdapter = exports2.SearchAdapter = exports2.RefsAdapter = exports2.MapAdapter = exports2.InspectAdapter = void 0;
67648
67329
  var inspect_adapter_js_1 = require_inspect_adapter();
67649
67330
  Object.defineProperty(exports2, "InspectAdapter", { enumerable: true, get: function() {
67650
67331
  return inspect_adapter_js_1.InspectAdapter;
@@ -68748,9 +68429,9 @@ Setup:
68748
68429
  2. Install MCP integration: dev mcp install --cursor
68749
68430
  3. Restart Cursor to activate
68750
68431
 
68751
- Available Tools (6):
68432
+ Available Tools (5):
68752
68433
  dev_search, dev_status, dev_patterns,
68753
- dev_health, dev_refs, dev_map
68434
+ dev_refs, dev_map
68754
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) => {
68755
68436
  const repositoryPath = process.env.WORKSPACE_FOLDER_PATHS || process.env.REPOSITORY_PATH || process.cwd();
68756
68437
  const logLevel = options.verbose ? "debug" : "info";
@@ -68790,10 +68471,6 @@ Available Tools (6):
68790
68471
  defaultThreshold: 0.7,
68791
68472
  defaultFormat: "compact"
68792
68473
  });
68793
- const healthAdapter = new dev_agent_mcp_1.HealthAdapter({
68794
- repositoryPath,
68795
- vectorStorePath: vectors
68796
- });
68797
68474
  const refsAdapter = new dev_agent_mcp_1.RefsAdapter({
68798
68475
  searchService,
68799
68476
  defaultLimit: 20
@@ -68814,14 +68491,7 @@ Available Tools (6):
68814
68491
  logLevel
68815
68492
  },
68816
68493
  transport: options.transport === "stdio" ? "stdio" : void 0,
68817
- adapters: [
68818
- searchAdapter,
68819
- statusAdapter,
68820
- inspectAdapter,
68821
- healthAdapter,
68822
- refsAdapter,
68823
- mapAdapter
68824
- ]
68494
+ adapters: [searchAdapter, statusAdapter, inspectAdapter, refsAdapter, mapAdapter]
68825
68495
  });
68826
68496
  const shutdown = async () => {
68827
68497
  logger_1.logger.info("Shutting down MCP server...");
@@ -68833,7 +68503,7 @@ Available Tools (6):
68833
68503
  process.on("SIGTERM", shutdown);
68834
68504
  await server.start();
68835
68505
  logger_1.logger.info(chalk_12.default.green("MCP server started successfully!"));
68836
- 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");
68837
68507
  if (options.transport === "stdio") {
68838
68508
  logger_1.logger.info("Server running on stdio transport (for AI tools)");
68839
68509
  } else {
@@ -69755,7 +69425,7 @@ var reset_js_1 = require_reset();
69755
69425
  var search_js_1 = require_search();
69756
69426
  var setup_js_1 = require_setup();
69757
69427
  var storage_js_1 = require_storage();
69758
- var VERSION = true ? "0.10.3" : "0.0.0-dev";
69428
+ var VERSION = true ? "0.10.4" : "0.0.0-dev";
69759
69429
  var program = new commander_1.Command();
69760
69430
  program.name("dev").description(chalk_1.default.cyan("\u{1F916} Dev-Agent - Multi-agent code intelligence platform")).version(VERSION);
69761
69431
  program.addCommand(index_js_1.indexCommand);