codesearch-mcp 0.0.17-alpha → 0.0.18-alpha

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.
Files changed (83) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +30 -26
  3. package/dist/app.js +34 -10
  4. package/dist/src/commands/ConfigCommand.d.ts +1 -0
  5. package/dist/src/commands/ConfigCommand.js +84 -4
  6. package/dist/src/commands/IndexCommand.js +22 -7
  7. package/dist/src/commands/McpCommand.js +4 -3
  8. package/dist/src/commands/WebCommand.d.ts +8 -0
  9. package/dist/src/commands/WebCommand.js +56 -0
  10. package/dist/src/config-store.d.ts +43 -0
  11. package/dist/src/config-store.js +92 -27
  12. package/dist/src/config.js +16 -17
  13. package/dist/src/constants.d.ts +2 -1
  14. package/dist/src/constants.js +6 -4
  15. package/dist/src/container.d.ts +10 -6
  16. package/dist/src/container.js +6 -3
  17. package/dist/src/graph.d.ts +60 -0
  18. package/dist/src/graph.js +239 -120
  19. package/dist/src/help.js +15 -1
  20. package/dist/src/interfaces/IAstParser.d.ts +6 -3
  21. package/dist/src/interfaces/IDatabase.d.ts +13 -0
  22. package/dist/src/interfaces/IDatabase.js +2 -0
  23. package/dist/src/interfaces/IEmbedder.d.ts +1 -0
  24. package/dist/src/interfaces/ILogger.d.ts +10 -0
  25. package/dist/src/interfaces/ILogger.js +2 -0
  26. package/dist/src/interfaces/IMcpToolHandler.d.ts +22 -0
  27. package/dist/src/interfaces/IMcpToolHandler.js +2 -0
  28. package/dist/src/interfaces/IMonorepoResolver.d.ts +33 -0
  29. package/dist/src/interfaces/IMonorepoResolver.js +2 -0
  30. package/dist/src/interfaces/IProjectDiscovery.d.ts +28 -0
  31. package/dist/src/interfaces/IProjectDiscovery.js +2 -0
  32. package/dist/src/interfaces/ISearcher.d.ts +36 -0
  33. package/dist/src/interfaces/ISearcher.js +2 -0
  34. package/dist/src/interfaces/index.d.ts +7 -0
  35. package/dist/src/interfaces/index.js +2 -0
  36. package/dist/src/project-selector.d.ts +1 -1
  37. package/dist/src/services/AstParserService.d.ts +4 -6
  38. package/dist/src/services/AstParserService.js +29 -13
  39. package/dist/src/services/DatabaseService.d.ts +2 -1
  40. package/dist/src/services/IndexerService.d.ts +6 -8
  41. package/dist/src/services/IndexerService.js +5 -8
  42. package/dist/src/services/LoggerService.d.ts +2 -1
  43. package/dist/src/services/McpServer.d.ts +16 -7
  44. package/dist/src/services/McpServer.js +54 -367
  45. package/dist/src/services/MonorepoAwareDiscoveryService.d.ts +62 -0
  46. package/dist/src/services/MonorepoAwareDiscoveryService.js +125 -0
  47. package/dist/src/services/NxMonorepoResolver.d.ts +45 -0
  48. package/dist/src/services/NxMonorepoResolver.js +308 -0
  49. package/dist/src/services/OllamaEmbedder.d.ts +5 -2
  50. package/dist/src/services/OllamaEmbedder.js +9 -2
  51. package/dist/src/services/ProjectDiscoveryService.d.ts +8 -0
  52. package/dist/src/services/ProjectDiscoveryService.js +52 -0
  53. package/dist/src/services/SearcherService.d.ts +39 -6
  54. package/dist/src/services/SearcherService.js +151 -40
  55. package/dist/src/services/WebServerService.d.ts +72 -0
  56. package/dist/src/services/WebServerService.js +247 -0
  57. package/dist/src/setup.js +7 -7
  58. package/dist/src/tools/FindSymbolTool.d.ts +8 -0
  59. package/dist/src/tools/FindSymbolTool.js +45 -0
  60. package/dist/src/tools/GetCallersTool.d.ts +8 -0
  61. package/dist/src/tools/GetCallersTool.js +42 -0
  62. package/dist/src/tools/GetDependenciesTool.d.ts +8 -0
  63. package/dist/src/tools/GetDependenciesTool.js +38 -0
  64. package/dist/src/tools/GetDependentsTool.d.ts +8 -0
  65. package/dist/src/tools/GetDependentsTool.js +57 -0
  66. package/dist/src/tools/ListFilesTool.d.ts +8 -0
  67. package/dist/src/tools/ListFilesTool.js +39 -0
  68. package/dist/src/tools/ListProjectsTool.d.ts +8 -0
  69. package/dist/src/tools/ListProjectsTool.js +44 -0
  70. package/dist/src/tools/ReadFileRangeTool.d.ts +8 -0
  71. package/dist/src/tools/ReadFileRangeTool.js +44 -0
  72. package/dist/src/tools/ReadFileTool.d.ts +8 -0
  73. package/dist/src/tools/ReadFileTool.js +42 -0
  74. package/dist/src/tools/SearchCodebaseTool.d.ts +13 -0
  75. package/dist/src/tools/SearchCodebaseTool.js +81 -0
  76. package/dist/src/tools/format-helpers.d.ts +8 -0
  77. package/dist/src/tools/format-helpers.js +57 -0
  78. package/dist/src/tools/index.d.ts +9 -0
  79. package/dist/src/tools/index.js +21 -0
  80. package/dist/src/web/dashboard.d.ts +9 -0
  81. package/dist/src/web/dashboard.js +337 -0
  82. package/docs/web-dashboard.md +187 -0
  83. package/package.json +5 -2
@@ -33,9 +33,12 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.ALL_KEYS = exports.CONFIG_FILE = exports.CONFIG_DIR = void 0;
36
+ exports.CONFIG_DEFAULTS = exports.ALL_KEYS = exports.SCHEMA_FILE = exports.CONFIG_FILE = exports.CONFIG_DIR = void 0;
37
37
  exports.readConfigJson = readConfigJson;
38
+ exports.parseConfig = parseConfig;
39
+ exports.buildJsonSchema = buildJsonSchema;
38
40
  exports.writeConfigJson = writeConfigJson;
41
+ exports.writeSchemaFile = writeSchemaFile;
39
42
  exports.getNestedValue = getNestedValue;
40
43
  exports.setNestedValue = setNestedValue;
41
44
  exports.deleteNestedValue = deleteNestedValue;
@@ -43,45 +46,51 @@ const fs = __importStar(require("fs"));
43
46
  const path = __importStar(require("path"));
44
47
  const os = __importStar(require("os"));
45
48
  const zod_1 = require("zod");
49
+ const constants_1 = require("./constants");
46
50
  exports.CONFIG_DIR = path.join(os.homedir(), '.config', 'codesearch-mcp');
47
51
  exports.CONFIG_FILE = path.join(exports.CONFIG_DIR, 'config.json');
52
+ exports.SCHEMA_FILE = path.join(exports.CONFIG_DIR, 'config.schema.json');
53
+ // Relative $schema reference written into config.json so editors resolve the
54
+ // sibling schema file for autocomplete / inline validation.
55
+ const SCHEMA_REF = './config.schema.json';
48
56
  // All fields optional — defaults live in config.ts. The file stays minimal.
57
+ // Descriptions surface as tooltips in schema-aware editors (VS Code, JetBrains).
49
58
  const jsonSchema = zod_1.z.object({
50
59
  db: zod_1.z.object({
51
- host: zod_1.z.string().optional(),
52
- port: zod_1.z.number().optional(),
53
- user: zod_1.z.string().optional(),
54
- password: zod_1.z.string().optional(),
55
- name: zod_1.z.string().optional(),
60
+ host: zod_1.z.string().describe('PostgreSQL host').optional(),
61
+ port: zod_1.z.number().int().describe('PostgreSQL port (default 5433)').optional(),
62
+ user: zod_1.z.string().describe('PostgreSQL user').optional(),
63
+ password: zod_1.z.string().describe('PostgreSQL password').optional(),
64
+ name: zod_1.z.string().describe('Database name; defaults to rag_<os-username>, auto-created on first run').optional(),
56
65
  }).optional(),
57
66
  ollama: zod_1.z.object({
58
- host: zod_1.z.string().optional(),
59
- model: zod_1.z.string().optional(),
67
+ host: zod_1.z.string().describe('Ollama API URL (default http://localhost:11434)').optional(),
68
+ model: zod_1.z.string().describe('Embedding model (default bge-m3)').optional(),
60
69
  }).optional(),
61
70
  indexing: zod_1.z.object({
62
- chunkSize: zod_1.z.number().optional(),
63
- chunkOverlap: zod_1.z.number().optional(),
64
- embedBatchSize: zod_1.z.number().optional(),
65
- astBatchSize: zod_1.z.number().optional(),
71
+ chunkSize: zod_1.z.number().int().describe('Max chars per chunk (default 1500)').optional(),
72
+ chunkOverlap: zod_1.z.number().int().describe('Overlap between chunks (default 200)').optional(),
73
+ embedBatchSize: zod_1.z.number().int().describe('Parallel embeddings per batch (default 5)').optional(),
74
+ astBatchSize: zod_1.z.number().int().describe('Max files per ts-morph batch; larger projects skip dependency resolution (default 3000)').optional(),
66
75
  }).optional(),
67
76
  search: zod_1.z.object({
68
- similarityThreshold: zod_1.z.number().optional(),
69
- defaultLimit: zod_1.z.number().optional(),
70
- maxLimit: zod_1.z.number().optional(),
71
- autoTranslate: zod_1.z.boolean().optional(),
72
- translateModel: zod_1.z.string().optional(),
77
+ similarityThreshold: zod_1.z.number().min(0).max(1).describe('Max cosine distance 0–1; lower = stricter (default 0.6)').optional(),
78
+ defaultLimit: zod_1.z.number().int().describe('Default result count (default 5)').optional(),
79
+ maxLimit: zod_1.z.number().int().describe('Hard cap on results (default 20)').optional(),
80
+ autoTranslate: zod_1.z.boolean().describe('Translate non-English queries before embedding').optional(),
81
+ translateModel: zod_1.z.string().describe('Ollama model for translation (default llama3.2)').optional(),
73
82
  }).optional(),
74
83
  reranker: zod_1.z.object({
75
- enabled: zod_1.z.boolean().optional(),
76
- model: zod_1.z.string().optional(),
77
- url: zod_1.z.string().optional(),
78
- overfetch: zod_1.z.number().int().min(1).max(20).optional(),
84
+ enabled: zod_1.z.boolean().describe('Enable cross-encoder reranking; requires reranker.model').optional(),
85
+ model: zod_1.z.string().describe('Reranker model name (e.g. qllama/bge-reranker-v2-m3)').optional(),
86
+ url: zod_1.z.string().describe('Full URL of the rerank endpoint (default ${ollama.host}/api/rerank)').optional(),
87
+ overfetch: zod_1.z.number().int().min(1).max(20).describe('Candidate multiplier before reranking (limit × N, default 3)').optional(),
79
88
  }).optional(),
80
89
  logging: zod_1.z.object({
81
- level: zod_1.z.enum(['debug', 'info', 'warn', 'error']).optional(),
82
- dir: zod_1.z.string().optional(),
90
+ level: zod_1.z.enum(['debug', 'info', 'warn', 'error']).describe('File log level (default error)').optional(),
91
+ dir: zod_1.z.string().describe('Base log directory; "false" to disable file logging').optional(),
83
92
  }).optional(),
84
- workspaceRoot: zod_1.z.string().optional(),
93
+ workspaceRoot: zod_1.z.string().describe('Full path to the directory containing all your projects').optional(),
85
94
  });
86
95
  const FIELD_TYPES = {
87
96
  'db.host': 'string',
@@ -109,6 +118,34 @@ const FIELD_TYPES = {
109
118
  'workspaceRoot': 'string',
110
119
  };
111
120
  exports.ALL_KEYS = Object.keys(FIELD_TYPES);
121
+ /**
122
+ * Single source of truth for built-in defaults, keyed by raw config.json dotted
123
+ * key. Consumed both by the web dashboard (`GET /api/defaults`) and by
124
+ * `resolvedSchema` in `src/config.ts`, whose `.default(...)` calls reference
125
+ * these values — so the runtime default and the dashboard-displayed default
126
+ * cannot diverge. `as const` keeps the literal types so those `.default()`
127
+ * lookups stay type-safe. Keys omitted here have no static default (required
128
+ * fields like db.host, or values derived at runtime like db.name → rag_<user>
129
+ * and reranker.url → ${ollama.host}/api/rerank).
130
+ */
131
+ exports.CONFIG_DEFAULTS = {
132
+ 'db.port': 5433,
133
+ 'ollama.host': 'http://localhost:11434',
134
+ 'ollama.model': constants_1.DEFAULT_EMBED_MODEL,
135
+ 'indexing.chunkSize': 1500,
136
+ 'indexing.chunkOverlap': 200,
137
+ 'indexing.embedBatchSize': 5,
138
+ 'indexing.astBatchSize': 3000,
139
+ 'search.similarityThreshold': 0.6,
140
+ 'search.defaultLimit': 5,
141
+ 'search.maxLimit': 20,
142
+ 'search.autoTranslate': false,
143
+ 'search.translateModel': 'llama3.2',
144
+ 'reranker.enabled': false,
145
+ 'reranker.model': '',
146
+ 'reranker.overfetch': 3,
147
+ 'logging.level': 'error',
148
+ };
112
149
  function readConfigJson() {
113
150
  if (!fs.existsSync(exports.CONFIG_FILE))
114
151
  return null;
@@ -127,17 +164,45 @@ function readConfigJson() {
127
164
  throw new Error(`Invalid JSON in ${exports.CONFIG_FILE}: ${e.message}\n` +
128
165
  `Fix the file manually or delete it and run: rag-setup`);
129
166
  }
130
- const result = jsonSchema.safeParse(parsed);
167
+ return parseConfig(parsed, exports.CONFIG_FILE);
168
+ }
169
+ /**
170
+ * Validate a parsed config object against the Zod schema. Unknown keys (e.g.
171
+ * the "$schema" editor reference) are stripped. Throws with a caller-friendly
172
+ * message on validation failure. Pure — no file I/O.
173
+ */
174
+ function parseConfig(raw, source = exports.CONFIG_FILE) {
175
+ const result = jsonSchema.safeParse(raw);
131
176
  if (!result.success) {
132
177
  const issues = result.error.issues.map(i => ` ${i.path.join('.')}: ${i.message}`).join('\n');
133
- throw new Error(`Invalid config in ${exports.CONFIG_FILE}:\n${issues}\n` +
178
+ throw new Error(`Invalid config in ${source}:\n${issues}\n` +
134
179
  `Fix with: rag-config set <key> <value>`);
135
180
  }
136
181
  return result.data;
137
182
  }
183
+ /** Build the JSON Schema object generated from the Zod config schema. Pure. */
184
+ function buildJsonSchema() {
185
+ return {
186
+ $id: 'https://github.com/oleksandr-antoniuk/RAG/config.schema.json',
187
+ title: 'codesearch-mcp config',
188
+ ...zod_1.z.toJSONSchema(jsonSchema),
189
+ };
190
+ }
138
191
  function writeConfigJson(data) {
139
192
  fs.mkdirSync(exports.CONFIG_DIR, { recursive: true });
140
- fs.writeFileSync(exports.CONFIG_FILE, JSON.stringify(data, null, 2) + '\n', { mode: 0o600 });
193
+ writeSchemaFile();
194
+ // $schema first so editors pick it up; readConfigJson strips it on validation.
195
+ const withSchema = { $schema: SCHEMA_REF, ...data };
196
+ fs.writeFileSync(exports.CONFIG_FILE, JSON.stringify(withSchema, null, 2) + '\n', { mode: 0o600 });
197
+ }
198
+ /**
199
+ * Generate a JSON Schema from the Zod config schema and write it next to
200
+ * config.json. Editors resolve it via the "$schema" reference and provide
201
+ * key autocomplete, type hints, and inline validation while editing.
202
+ */
203
+ function writeSchemaFile() {
204
+ fs.mkdirSync(exports.CONFIG_DIR, { recursive: true });
205
+ fs.writeFileSync(exports.SCHEMA_FILE, JSON.stringify(buildJsonSchema(), null, 2) + '\n');
141
206
  }
142
207
  function getNestedValue(cfg, key) {
143
208
  const parts = key.split('.');
@@ -37,7 +37,6 @@ exports.Config = exports.ConfigError = void 0;
37
37
  const os = __importStar(require("os"));
38
38
  const zod_1 = require("zod");
39
39
  const config_store_1 = require("./config-store");
40
- const constants_1 = require("./constants");
41
40
  class ConfigError extends Error {
42
41
  constructor(message) {
43
42
  super(message);
@@ -48,34 +47,34 @@ exports.ConfigError = ConfigError;
48
47
  const resolvedSchema = zod_1.z.object({
49
48
  db: zod_1.z.object({
50
49
  host: zod_1.z.string().min(1, 'required — run rag-setup'),
51
- port: zod_1.z.number().int().positive().default(5433),
50
+ port: zod_1.z.number().int().positive().default(config_store_1.CONFIG_DEFAULTS['db.port']),
52
51
  username: zod_1.z.string().min(1, 'required — run rag-setup'),
53
52
  password: zod_1.z.string().min(1, 'required — run rag-setup'),
54
53
  database: zod_1.z.string().min(1),
55
54
  }),
56
55
  ollama: zod_1.z.object({
57
- host: zod_1.z.string().min(1).default('http://localhost:11434'),
58
- model: zod_1.z.string().min(1).default(constants_1.DEFAULT_EMBED_MODEL),
59
- rerankerModel: zod_1.z.string().default(''),
56
+ host: zod_1.z.string().min(1).default(config_store_1.CONFIG_DEFAULTS['ollama.host']),
57
+ model: zod_1.z.string().min(1).default(config_store_1.CONFIG_DEFAULTS['ollama.model']),
58
+ rerankerModel: zod_1.z.string().default(config_store_1.CONFIG_DEFAULTS['reranker.model']),
60
59
  rerankerUrl: zod_1.z.string().min(1),
61
60
  }),
62
61
  indexer: zod_1.z.object({
63
- chunkSize: zod_1.z.number().int().positive().default(1500),
64
- chunkOverlap: zod_1.z.number().int().min(0).default(200),
65
- batchSize: zod_1.z.number().int().positive().default(5),
66
- astBatchSize: zod_1.z.number().int().positive().default(3000),
62
+ chunkSize: zod_1.z.number().int().positive().default(config_store_1.CONFIG_DEFAULTS['indexing.chunkSize']),
63
+ chunkOverlap: zod_1.z.number().int().min(0).default(config_store_1.CONFIG_DEFAULTS['indexing.chunkOverlap']),
64
+ batchSize: zod_1.z.number().int().positive().default(config_store_1.CONFIG_DEFAULTS['indexing.embedBatchSize']),
65
+ astBatchSize: zod_1.z.number().int().positive().default(config_store_1.CONFIG_DEFAULTS['indexing.astBatchSize']),
67
66
  }),
68
67
  search: zod_1.z.object({
69
- similarityThreshold: zod_1.z.number().min(0).max(1).default(0.6),
70
- defaultLimit: zod_1.z.number().int().positive().default(5),
71
- maxLimit: zod_1.z.number().int().positive().default(20),
72
- autoTranslate: zod_1.z.boolean().default(false),
73
- translateModel: zod_1.z.string().default('llama3.2'),
74
- rerankerEnabled: zod_1.z.boolean().default(false),
75
- rerankerOverfetch: zod_1.z.number().int().min(1).max(20).default(3),
68
+ similarityThreshold: zod_1.z.number().min(0).max(1).default(config_store_1.CONFIG_DEFAULTS['search.similarityThreshold']),
69
+ defaultLimit: zod_1.z.number().int().positive().default(config_store_1.CONFIG_DEFAULTS['search.defaultLimit']),
70
+ maxLimit: zod_1.z.number().int().positive().default(config_store_1.CONFIG_DEFAULTS['search.maxLimit']),
71
+ autoTranslate: zod_1.z.boolean().default(config_store_1.CONFIG_DEFAULTS['search.autoTranslate']),
72
+ translateModel: zod_1.z.string().default(config_store_1.CONFIG_DEFAULTS['search.translateModel']),
73
+ rerankerEnabled: zod_1.z.boolean().default(config_store_1.CONFIG_DEFAULTS['reranker.enabled']),
74
+ rerankerOverfetch: zod_1.z.number().int().min(1).max(20).default(config_store_1.CONFIG_DEFAULTS['reranker.overfetch']),
76
75
  }),
77
76
  logging: zod_1.z.object({
78
- level: zod_1.z.enum(['debug', 'info', 'warn', 'error']).default('error'),
77
+ level: zod_1.z.enum(['debug', 'info', 'warn', 'error']).default(config_store_1.CONFIG_DEFAULTS['logging.level']),
79
78
  dir: zod_1.z.string().optional(),
80
79
  }),
81
80
  workspaceRoot: zod_1.z.string().default(''),
@@ -1 +1,2 @@
1
- export declare const DEFAULT_EMBED_MODEL = "bge-m3";
1
+ export declare const SUPPORTED_EMBED_MODELS: readonly ["bge-m3"];
2
+ export declare const DEFAULT_EMBED_MODEL: string;
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_EMBED_MODEL = void 0;
3
+ exports.DEFAULT_EMBED_MODEL = exports.SUPPORTED_EMBED_MODELS = void 0;
4
4
  // Embedding model is tied to the vector column dimension (bge-m3 → 1024).
5
- // Change both together: update this constant, drop/recreate the `embedding` column,
6
- // and re-run indexing.
7
- exports.DEFAULT_EMBED_MODEL = 'bge-m3';
5
+ // Only 1024-dim models belong here — switching requires dropping/recreating the
6
+ // `embedding` column and re-indexing. The dashboard offers this list as a strict
7
+ // dropdown for ollama.model (no free text) so a mismatched model can't be set.
8
+ exports.SUPPORTED_EMBED_MODELS = ['bge-m3'];
9
+ exports.DEFAULT_EMBED_MODEL = exports.SUPPORTED_EMBED_MODELS[0];
@@ -1,15 +1,19 @@
1
1
  import { Config } from './config';
2
- import { DatabaseService } from './services/DatabaseService';
3
2
  import { IndexerService } from './services/IndexerService';
4
- import { SearcherService } from './services/SearcherService';
5
3
  import { McpServer } from './services/McpServer';
6
- import { LoggerService } from './services/LoggerService';
4
+ import type { IDatabase } from './interfaces';
5
+ import type { IEmbedder } from './interfaces';
6
+ import type { ISearcher } from './interfaces';
7
+ import type { ILogger } from './interfaces';
8
+ import type { IProjectDiscovery } from './interfaces';
7
9
  export interface Container {
8
10
  config: Config;
9
- db: DatabaseService;
11
+ db: IDatabase;
12
+ embedder: IEmbedder;
10
13
  indexer: IndexerService;
11
- searcher: SearcherService;
14
+ searcher: ISearcher;
12
15
  mcp: McpServer;
13
- logger: LoggerService;
16
+ logger: ILogger;
17
+ discovery: IProjectDiscovery;
14
18
  }
15
19
  export declare function createContainer(loggerName?: string): Container;
@@ -9,14 +9,17 @@ const IndexerService_1 = require("./services/IndexerService");
9
9
  const SearcherService_1 = require("./services/SearcherService");
10
10
  const McpServer_1 = require("./services/McpServer");
11
11
  const LoggerService_1 = require("./services/LoggerService");
12
+ const MonorepoAwareDiscoveryService_1 = require("./services/MonorepoAwareDiscoveryService");
13
+ const NxMonorepoResolver_1 = require("./services/NxMonorepoResolver");
12
14
  function createContainer(loggerName) {
13
15
  const config = new config_1.Config();
14
16
  const logger = LoggerService_1.LoggerService.fromConfig(config.logging, loggerName);
15
17
  const db = new DatabaseService_1.DatabaseService(config);
16
- const embedder = new OllamaEmbedder_1.OllamaEmbedder(config);
18
+ const embedder = new OllamaEmbedder_1.OllamaEmbedder(config, logger);
17
19
  const ast = new AstParserService_1.AstParserService(logger);
20
+ const discovery = new MonorepoAwareDiscoveryService_1.MonorepoAwareDiscoveryService([new NxMonorepoResolver_1.NxMonorepoResolver(logger)], logger);
18
21
  const indexer = new IndexerService_1.IndexerService(db, embedder, ast, config, logger);
19
- const searcher = new SearcherService_1.SearcherService(db, embedder, config, logger);
22
+ const searcher = new SearcherService_1.SearcherService(db, embedder, discovery, config, logger);
20
23
  const mcp = new McpServer_1.McpServer(searcher, config, logger);
21
- return { config, db, indexer, searcher, mcp, logger };
24
+ return { config, db, embedder, indexer, searcher, mcp, logger, discovery };
22
25
  }
@@ -1,4 +1,64 @@
1
+ import { type ProjectMeta } from './file-utils';
2
+ type ProjectNode = {
3
+ name: string;
4
+ nxRepo?: boolean;
5
+ } & ProjectMeta;
6
+ type Edge = {
7
+ from: string;
8
+ to: string;
9
+ label: string;
10
+ };
11
+ export interface GraphData {
12
+ nodes: ProjectNode[];
13
+ edges: Edge[];
14
+ }
15
+ /** A single named graph tab (Workspace, or one per nested Nx repo). */
16
+ export interface GraphView {
17
+ name: string;
18
+ nodes: ProjectNode[];
19
+ edges: Edge[];
20
+ }
21
+ /**
22
+ * Build the project graph data (nodes + relation edges) from a project list.
23
+ * Pure apart from reading each project's `.ragmeta.json`. Shared by the console
24
+ * graph, the graph views, and the web dashboard's `/api/graph`.
25
+ */
26
+ export declare function buildGraphData(projects: {
27
+ name: string;
28
+ path: string;
29
+ }[]): GraphData;
30
+ /**
31
+ * Split a project list into graph tabs. A project whose name contains a `/`
32
+ * belongs to a nested Nx repo (`<repo>/<sub-project>`); everything else is a
33
+ * flat top-level project.
34
+ *
35
+ * - **Workspace** tab: flat projects + one node per Nx repo (collapsed to a
36
+ * single `nxRepo` node); edges from `.ragmeta.json` relations.
37
+ * - **One tab per Nx repo**: its sub-projects as nodes, with edges between them
38
+ * taken from real import dependencies (`projectEdges`, from `code_dependency`).
39
+ *
40
+ * Returns the Workspace view first, then repo views sorted by name.
41
+ */
42
+ export declare function buildGraphViews(projects: {
43
+ name: string;
44
+ path: string;
45
+ }[], projectEdges: {
46
+ from: string;
47
+ to: string;
48
+ }[], workspaceRoot: string): GraphView[];
49
+ /**
50
+ * Render the full interactive graph page (vis-network + inner tabs, edge-type
51
+ * filters, legend, project toggle list). Used for the standalone
52
+ * `project-graph.html` and served by the web dashboard at `GET /graph` (embedded
53
+ * via iframe) so both share one implementation. Tab 0 is the Workspace view;
54
+ * double-clicking an Nx-repo node opens that repo's tab.
55
+ */
56
+ export declare function buildHtml(views: GraphView[]): string;
1
57
  export declare function generateProjectGraph(projects: {
2
58
  name: string;
3
59
  path: string;
60
+ }[], projectEdges: {
61
+ from: string;
62
+ to: string;
4
63
  }[], workspacePath: string): void;
64
+ export {};