codesearch-mcp 0.0.9-alpha → 0.0.10-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 (48) hide show
  1. package/README.md +26 -14
  2. package/dist/app.js +24 -143
  3. package/dist/src/commands/BackfillCommand.d.ts +7 -0
  4. package/dist/src/commands/BackfillCommand.js +27 -0
  5. package/dist/src/commands/ICommand.d.ts +3 -0
  6. package/dist/src/commands/ICommand.js +2 -0
  7. package/dist/src/commands/IndexCommand.d.ts +9 -0
  8. package/dist/src/commands/IndexCommand.js +75 -0
  9. package/dist/src/commands/McpCommand.d.ts +7 -0
  10. package/dist/src/commands/McpCommand.js +21 -0
  11. package/dist/src/commands/SetupCommand.d.ts +4 -0
  12. package/dist/src/commands/SetupCommand.js +10 -0
  13. package/dist/src/config.d.ts +1 -0
  14. package/dist/src/config.js +41 -2
  15. package/dist/src/container.d.ts +15 -0
  16. package/dist/src/container.js +21 -0
  17. package/dist/src/db/entities/code-chunk.entity.d.ts +1 -1
  18. package/dist/src/db/entities/code-chunk.entity.js +2 -2
  19. package/dist/src/db/entities/code-symbol.entity.d.ts +10 -0
  20. package/dist/src/db/entities/code-symbol.entity.js +59 -0
  21. package/dist/src/db/index.d.ts +1 -2
  22. package/dist/src/db/index.js +3 -6
  23. package/dist/src/file-utils.d.ts +2 -1
  24. package/dist/src/file-utils.js +10 -5
  25. package/dist/src/graph.js +5 -4
  26. package/dist/src/help.js +1 -1
  27. package/dist/src/interfaces/IAstParser.d.ts +24 -0
  28. package/dist/src/interfaces/IAstParser.js +2 -0
  29. package/dist/src/interfaces/IEmbedder.d.ts +4 -0
  30. package/dist/src/interfaces/IEmbedder.js +2 -0
  31. package/dist/src/interrupt.d.ts +1 -3
  32. package/dist/src/interrupt.js +14 -16
  33. package/dist/src/services/AstParserService.d.ts +14 -0
  34. package/dist/src/services/AstParserService.js +256 -0
  35. package/dist/src/services/DatabaseService.d.ts +14 -0
  36. package/dist/src/services/DatabaseService.js +133 -0
  37. package/dist/src/services/IndexerService.d.ts +39 -0
  38. package/dist/src/services/IndexerService.js +286 -0
  39. package/dist/src/services/LoggerService.d.ts +12 -0
  40. package/dist/src/services/LoggerService.js +73 -0
  41. package/dist/src/services/McpServer.d.ts +13 -0
  42. package/dist/src/services/McpServer.js +414 -0
  43. package/dist/src/services/OllamaEmbedder.d.ts +9 -0
  44. package/dist/src/services/OllamaEmbedder.js +27 -0
  45. package/dist/src/services/SearcherService.d.ts +91 -0
  46. package/dist/src/services/SearcherService.js +453 -0
  47. package/dist/src/setup.js +23 -7
  48. package/package.json +11 -10
package/README.md CHANGED
@@ -34,6 +34,7 @@ rag-setup
34
34
  Walks you through:
35
35
  - **Local Docker** — copies `docker-compose.yml`, starts PostgreSQL + Ollama, pulls `bge-m3` automatically
36
36
  - **Remote DB** — enter connection details for Supabase, Railway, or self-hosted; connection is verified before saving
37
+ - **Logging** — choose log level and file path (defaults: `error` level, `~/.config/codesearch-mcp/rag.log`)
37
38
 
38
39
  Config is saved to `~/.config/codesearch-mcp/.env`.
39
40
 
@@ -43,18 +44,7 @@ Config is saved to `~/.config/codesearch-mcp/.env`.
43
44
  rag-index /home/user/Projects
44
45
  ```
45
46
 
46
- On first run you will be prompted for each discovered project:
47
-
48
- ```
49
- Found 5 new project(s). Select which to index:
50
- y = yes | n = skip this time | s = always skip
51
-
52
- myapp [y/n/s]: y
53
- legacy-app [y/n/s]: s
54
- → added to .ragskip
55
- ```
56
-
57
- Selections are saved in `.ragprojects` / `.ragskip` at the workspace root. Use `--select` to revisit them.
47
+ On first run you will be prompted to select which projects to index. Selections are saved in `.ragprojects` / `.ragskip` at the workspace root.
58
48
 
59
49
  ```bash
60
50
  rag-index /path --select # re-run project selection
@@ -68,7 +58,7 @@ rag-index /path --select --reindex
68
58
  claude mcp add codesearch-mcp -s user -- rag-mcp
69
59
  ```
70
60
 
71
- Then ask Claude anything about your code — it will use `search_codebase`, `list_projects`, `read_file_range`, `get_dependencies`, and `get_dependents` automatically.
61
+ Then ask Claude anything about your code — it will use the tools below automatically.
72
62
 
73
63
  ## MCP Tools
74
64
 
@@ -76,6 +66,9 @@ Then ask Claude anything about your code — it will use `search_codebase`, `lis
76
66
  |------|-------------|
77
67
  | `search_codebase` | Semantic search across all indexed projects |
78
68
  | `list_projects` | List projects with metadata and chunk counts |
69
+ | `find_symbol` | Find a function, class, or type by exact name — faster than semantic search |
70
+ | `list_files` | Browse the directory tree of a project |
71
+ | `read_file` | Read a complete file by absolute path |
79
72
  | `read_file_range` | Read a specific line range from an indexed file |
80
73
  | `get_dependencies` | Show what files a given file imports |
81
74
  | `get_dependents` | Show which files import a given file |
@@ -107,6 +100,22 @@ src/gql/graphql.ts
107
100
  src/generated/
108
101
  ```
109
102
 
103
+ ## Logging
104
+
105
+ Logs are written to `~/.config/codesearch-mcp/rag.log` by default. Only errors are logged unless configured otherwise.
106
+
107
+ ```bash
108
+ # Read logs
109
+ tail -f ~/.config/codesearch-mcp/rag.log
110
+ npx pino-pretty < ~/.config/codesearch-mcp/rag.log
111
+
112
+ # Detailed indexing diagnostics (timing per file: deps / embed / db)
113
+ LOG_LEVEL=debug rag-index /path/to/workspace
114
+
115
+ # Disable file logging
116
+ LOG_FILE=false rag-index /path/to/workspace
117
+ ```
118
+
110
119
  ## Environment variables
111
120
 
112
121
  All set by `rag-setup`. Override any of them in `~/.config/codesearch-mcp/.env`.
@@ -117,12 +126,15 @@ All set by `rag-setup`. Override any of them in `~/.config/codesearch-mcp/.env`.
117
126
  | `DB_PORT` | `5433` | PostgreSQL port |
118
127
  | `DB_USER` | — | PostgreSQL user |
119
128
  | `DB_PASS` | — | PostgreSQL password |
120
- | `DB_NAME` | — | Database name |
129
+ | `DB_NAME` | `rag_<os-username>` | Database name — auto-created on first run |
121
130
  | `WORKSPACE_ROOT` | — | Root of your projects directory |
122
131
  | `OLLAMA_HOST` | `http://localhost:11434` | Ollama API URL |
123
132
  | `OLLAMA_MODEL` | `bge-m3` | Embedding model |
124
133
  | `SIMILARITY_THRESHOLD` | `0.6` | Max cosine distance — raise if search returns nothing |
125
134
  | `AUTO_TRANSLATE` | `false` | Translate non-English queries to English before embedding |
135
+ | `TRANSLATE_MODEL` | `llama3.2` | Ollama model for translation (requires `ollama pull llama3.2`) |
136
+ | `LOG_LEVEL` | `error` | Log level written to file: `error` \| `warn` \| `info` \| `debug` |
137
+ | `LOG_FILE` | `~/.config/codesearch-mcp/rag.log` | Log file path, or `false` to disable |
126
138
 
127
139
  ## License
128
140
 
package/dist/app.js CHANGED
@@ -36,43 +36,12 @@ var __importStar = (this && this.__importStar) || (function () {
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
37
  require("./src/env-loader");
38
38
  const path = __importStar(require("path"));
39
+ const container_1 = require("./src/container");
39
40
  const help_1 = require("./src/help");
40
- function formatEta(sec) {
41
- if (sec < 60)
42
- return `${sec}s`;
43
- const m = Math.floor(sec / 60);
44
- const s = sec % 60;
45
- return s > 0 ? `${m}m ${s}s` : `${m}m`;
46
- }
47
- function printSummary(allStats) {
48
- const cols = { name: 30, num: 8 };
49
- const line = '─'.repeat(cols.name + cols.num * 5 + 5);
50
- console.log('\n=== Indexing Summary ===');
51
- console.log('Service'.padEnd(cols.name), 'Indexed'.padStart(cols.num), 'Skipped'.padStart(cols.num), 'Failed'.padStart(cols.num), 'Chunks'.padStart(cols.num), 'Time(s)'.padStart(cols.num));
52
- console.log(line);
53
- for (const s of allStats) {
54
- console.log(s.serviceName.padEnd(cols.name), String(s.indexed).padStart(cols.num), String(s.skipped).padStart(cols.num), String(s.failed).padStart(cols.num), String(s.chunks).padStart(cols.num), String(s.elapsedSec).padStart(cols.num));
55
- }
56
- console.log(line);
57
- const total = allStats.reduce((acc, s) => ({
58
- indexed: acc.indexed + s.indexed,
59
- skipped: acc.skipped + s.skipped,
60
- failed: acc.failed + s.failed,
61
- chunks: acc.chunks + s.chunks,
62
- elapsedSec: acc.elapsedSec + s.elapsedSec,
63
- }), { indexed: 0, skipped: 0, failed: 0, chunks: 0, elapsedSec: 0 });
64
- console.log('TOTAL'.padEnd(cols.name), String(total.indexed).padStart(cols.num), String(total.skipped).padStart(cols.num), String(total.failed).padStart(cols.num), String(total.chunks).padStart(cols.num), String(total.elapsedSec.toFixed(1)).padStart(cols.num));
65
- // Reprint warnings at the end — progress bar activity scrolls per-project warnings out of
66
- // view, so we collect them on IndexStats and surface them here as an explicit section.
67
- // const projectsWithWarnings = allStats.filter(s => s.warnings.length > 0);
68
- // if (projectsWithWarnings.length > 0) {
69
- // console.log('\n=== Warnings ===');
70
- // for (const s of projectsWithWarnings) {
71
- // console.log(`\n${s.serviceName}:`);
72
- // for (const w of s.warnings) console.log(` ⚠ ${w}`);
73
- // }
74
- // }
75
- }
41
+ const IndexCommand_1 = require("./src/commands/IndexCommand");
42
+ const McpCommand_1 = require("./src/commands/McpCommand");
43
+ const SetupCommand_1 = require("./src/commands/SetupCommand");
44
+ const BackfillCommand_1 = require("./src/commands/BackfillCommand");
76
45
  async function main() {
77
46
  const argv1 = path.basename(process.argv[1] ?? '');
78
47
  const isIndex = argv1 === 'rag-index' || process.argv[2] === 'index';
@@ -84,118 +53,30 @@ async function main() {
84
53
  (0, help_1.printHelp)(argv1 !== 'app.js' ? argv1 : mode);
85
54
  process.exit(0);
86
55
  }
87
- if (mode === 'index') {
88
- const { initDbWithSchema } = await Promise.resolve().then(() => __importStar(require('./src/db')));
89
- const { discoverProjects, scanAndIndex } = await Promise.resolve().then(() => __importStar(require('./src/indexer')));
90
- const { setupInterrupt, teardownInterrupt, signal } = await Promise.resolve().then(() => __importStar(require('./src/interrupt')));
91
- const { selectProjects } = await Promise.resolve().then(() => __importStar(require('./src/project-selector')));
92
- const { generateProjectGraph } = await Promise.resolve().then(() => __importStar(require('./src/graph')));
93
- const args = process.argv.slice(argv1 === 'rag-index' ? 2 : 3);
94
- const argPath = args.find(a => !a.startsWith('--'));
95
- const force = args.includes('--reindex');
96
- const forceSelect = args.includes('--select');
97
- // Prefer explicit arg, then WORKSPACE_ROOT from config
98
- const workspacePath = argPath ?? process.env.WORKSPACE_ROOT;
99
- if (!workspacePath) {
100
- console.error('Usage: rag-index [path] [--reindex] [--select]');
101
- console.error(' path defaults to WORKSPACE_ROOT set during rag-setup');
102
- process.exit(1);
103
- }
104
- process.env.WORKSPACE_ROOT ??= workspacePath;
105
- await initDbWithSchema();
106
- setupInterrupt();
107
- try {
108
- const { collectFiles, loadIgnore } = await Promise.resolve().then(() => __importStar(require('./src/file-utils')));
109
- const discovered = discoverProjects(workspacePath);
110
- const projects = await selectProjects(discovered, workspacePath, forceSelect);
111
- if (projects.length === 0)
112
- process.exit(0);
113
- const filesPerProject = projects.map(p => collectFiles(p.path, loadIgnore(p.path), p.path));
114
- const totalFiles = filesPerProject.reduce((sum, f) => sum + f.length, 0);
115
- console.log(`\n${projects.length} projects — ${totalFiles} files total`);
116
- if (force)
117
- console.log('Reindex mode: all files will be re-indexed.');
118
- const allStats = [];
119
- for (let i = 0; i < projects.length; i++) {
120
- if (signal.aborted)
121
- break;
122
- const stats = await scanAndIndex(projects[i].path, projects[i].name, force, signal, filesPerProject[i]);
123
- allStats.push(stats);
124
- const remaining = projects.length - allStats.length;
125
- if (remaining > 0 && !signal.aborted) {
126
- const doneFiles = allStats.reduce((s, r) => s + r.indexed + r.skipped + r.failed, 0);
127
- const elapsedSec = allStats.reduce((s, r) => s + r.elapsedSec, 0);
128
- const leftFiles = filesPerProject.slice(allStats.length).reduce((sum, f) => sum + f.length, 0);
129
- const eta = doneFiles > 0 ? formatEta(Math.round(elapsedSec / doneFiles * leftFiles)) : '?';
130
- console.log(` ${allStats.length}/${projects.length} projects done — ${remaining} left (~${leftFiles} files) — ETA ~${eta}`);
131
- }
132
- }
133
- if (signal.aborted)
134
- console.log('\nIndexing interrupted.');
135
- printSummary(allStats);
136
- if (!signal.aborted)
137
- generateProjectGraph(projects, workspacePath);
138
- }
139
- finally {
140
- teardownInterrupt();
141
- }
142
- process.exit(0);
143
- }
144
- else if (mode === 'mcp') {
145
- const { initDb } = await Promise.resolve().then(() => __importStar(require('./src/db')));
146
- const { startMCP } = await Promise.resolve().then(() => __importStar(require('./src/mcp')));
147
- if (!process.env.WORKSPACE_ROOT) {
148
- if (argv1 === 'rag-mcp') {
149
- console.error('WORKSPACE_ROOT is required for MCP mode. Set it in ~/.config/codesearch-mcp/.env');
150
- console.error('Run `rag-setup` to configure.');
151
- process.exit(1);
152
- }
153
- // dev fallback: infer from cwd (project lives inside workspace)
154
- process.env.WORKSPACE_ROOT = path.dirname(process.cwd());
155
- }
156
- await initDb();
157
- await startMCP();
56
+ const container = (0, container_1.createContainer)();
57
+ if (!container.config.workspaceRoot && mode !== 'setup') {
58
+ const hint = argv1 === 'rag-mcp'
59
+ ? 'Set WORKSPACE_ROOT in ~/.config/codesearch-mcp/.env or run `rag-setup`.'
60
+ : 'Run `rag-setup` to configure WORKSPACE_ROOT.';
61
+ console.error(`WORKSPACE_ROOT is not configured. ${hint}`);
62
+ process.exit(1);
158
63
  }
159
- else if (mode === 'setup') {
160
- const { runSetup } = await Promise.resolve().then(() => __importStar(require('./src/setup')));
161
- await runSetup();
162
- }
163
- else if (mode === 'backfill') {
164
- const { initDbWithSchema, db } = await Promise.resolve().then(() => __importStar(require('./src/db')));
165
- const { collectDepEdges, writeDepEdges } = await Promise.resolve().then(() => __importStar(require('./src/indexer')));
166
- const { config } = await Promise.resolve().then(() => __importStar(require('./src/config')));
167
- const fs = await Promise.resolve().then(() => __importStar(require('fs')));
168
- const path = await Promise.resolve().then(() => __importStar(require('path')));
169
- await initDbWithSchema();
170
- const rows = await db.query(`SELECT DISTINCT "serviceName", "filePath" FROM code_chunk ORDER BY "serviceName", "filePath"`);
171
- console.log(`Backfilling dependency edges for ${rows.length} indexed files...\n`);
172
- let processed = 0, skipped = 0, totalEdges = 0;
173
- for (const { serviceName, filePath } of rows) {
174
- const absPath = path.join(config.workspaceRoot, filePath);
175
- const projectRoot = path.join(config.workspaceRoot, serviceName);
176
- if (!fs.existsSync(absPath)) {
177
- skipped++;
178
- continue;
179
- }
180
- const edges = await collectDepEdges(absPath, serviceName, projectRoot);
181
- await writeDepEdges(serviceName, filePath, edges);
182
- totalEdges += edges.length;
183
- processed++;
184
- if (processed % 50 === 0)
185
- process.stdout.write(` ${processed}/${rows.length} processed, ${totalEdges} edges...\r`);
186
- }
187
- console.log(`\nDone. Processed: ${processed}, Skipped (not on disk): ${skipped}, Total edges: ${totalEdges}`);
188
- await db.destroy();
189
- process.exit(0);
190
- }
191
- else {
192
- // No command → show help and exit cleanly. Unknown command → error + help + exit 1.
64
+ const commands = {
65
+ index: new IndexCommand_1.IndexCommand(container, argv1),
66
+ mcp: new McpCommand_1.McpCommand(container),
67
+ setup: new SetupCommand_1.SetupCommand(),
68
+ backfill: new BackfillCommand_1.BackfillCommand(container),
69
+ };
70
+ const cmd = commands[mode];
71
+ if (!cmd) {
193
72
  const hasUnknownArg = mode !== '';
194
- const out = hasUnknownArg ? console.error : console.log;
195
73
  if (hasUnknownArg)
196
- out(`Unknown command: ${mode}\n`);
74
+ console.error(`Unknown command: ${mode}\n`);
197
75
  (0, help_1.printHelp)('default');
198
76
  process.exit(hasUnknownArg ? 1 : 0);
199
77
  }
78
+ await cmd.execute();
79
+ await container.db.destroy();
80
+ process.exit(0);
200
81
  }
201
82
  main().catch(err => { console.error(err); process.exit(1); });
@@ -0,0 +1,7 @@
1
+ import type { Container } from '../container';
2
+ import type { ICommand } from './ICommand';
3
+ export declare class BackfillCommand implements ICommand {
4
+ private container;
5
+ constructor(container: Container);
6
+ execute(): Promise<void>;
7
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BackfillCommand = void 0;
4
+ const interrupt_1 = require("../interrupt");
5
+ class BackfillCommand {
6
+ container;
7
+ constructor(container) {
8
+ this.container = container;
9
+ }
10
+ async execute() {
11
+ const { db, indexer } = this.container;
12
+ await db.initDbWithSchema();
13
+ const controller = new AbortController();
14
+ const teardown = (0, interrupt_1.setupInterrupt)(controller);
15
+ try {
16
+ console.log('Backfilling symbol index...\n');
17
+ const stats = await indexer.backfillSymbols(controller.signal);
18
+ if (controller.signal.aborted)
19
+ console.log('\nBackfill interrupted.');
20
+ console.log(`\nDone. Total: ${stats.total}, Processed: ${stats.processed}, Skipped (not on disk): ${stats.skipped}, Failed: ${stats.failed}`);
21
+ }
22
+ finally {
23
+ teardown();
24
+ }
25
+ }
26
+ }
27
+ exports.BackfillCommand = BackfillCommand;
@@ -0,0 +1,3 @@
1
+ export interface ICommand {
2
+ execute(): Promise<void>;
3
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ import type { Container } from '../container';
2
+ import type { ICommand } from './ICommand';
3
+ export declare class IndexCommand implements ICommand {
4
+ private container;
5
+ private argv1;
6
+ constructor(container: Container, argv1: string);
7
+ execute(): Promise<void>;
8
+ private printSummary;
9
+ }
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IndexCommand = void 0;
4
+ const interrupt_1 = require("../interrupt");
5
+ const project_selector_1 = require("../project-selector");
6
+ const graph_1 = require("../graph");
7
+ const file_utils_1 = require("../file-utils");
8
+ class IndexCommand {
9
+ container;
10
+ argv1;
11
+ constructor(container, argv1) {
12
+ this.container = container;
13
+ this.argv1 = argv1;
14
+ }
15
+ async execute() {
16
+ const { db, indexer, config } = this.container;
17
+ const args = process.argv.slice(this.argv1 === 'rag-index' ? 2 : 3);
18
+ const force = args.includes('--reindex');
19
+ const forceSelect = args.includes('--select');
20
+ await db.initDbWithSchema();
21
+ const controller = new AbortController();
22
+ const teardown = (0, interrupt_1.setupInterrupt)(controller);
23
+ try {
24
+ const discovered = indexer.discoverProjects(config.workspaceRoot);
25
+ const projects = await (0, project_selector_1.selectProjects)(discovered, config.workspaceRoot, forceSelect);
26
+ if (projects.length === 0)
27
+ return;
28
+ const filesPerProject = projects.map(p => (0, file_utils_1.collectFiles)(p.path, (0, file_utils_1.loadIgnore)(p.path), p.path));
29
+ const totalFiles = filesPerProject.reduce((sum, f) => sum + f.length, 0);
30
+ console.log(`\n${projects.length} projects — ${totalFiles} files total`);
31
+ if (force)
32
+ console.log('Reindex mode: all files will be re-indexed.');
33
+ const allStats = [];
34
+ for (let i = 0; i < projects.length; i++) {
35
+ if (controller.signal.aborted)
36
+ break;
37
+ const stats = await indexer.scanAndIndex(projects[i].path, projects[i].name, force, controller.signal, filesPerProject[i]);
38
+ allStats.push(stats);
39
+ const remaining = projects.length - allStats.length;
40
+ if (remaining > 0 && !controller.signal.aborted) {
41
+ const leftFiles = filesPerProject.slice(allStats.length).reduce((sum, f) => sum + f.length, 0);
42
+ console.log(` ${allStats.length}/${projects.length} projects — done in ${stats.elapsedSec}s — ${leftFiles} files left`);
43
+ }
44
+ }
45
+ if (controller.signal.aborted)
46
+ console.log('\nIndexing interrupted.');
47
+ this.printSummary(allStats);
48
+ if (!controller.signal.aborted)
49
+ (0, graph_1.generateProjectGraph)(projects, config.workspaceRoot);
50
+ }
51
+ finally {
52
+ teardown();
53
+ }
54
+ }
55
+ printSummary(allStats) {
56
+ const cols = { name: 30, num: 8 };
57
+ const line = '─'.repeat(cols.name + cols.num * 5 + 5);
58
+ console.log('\n=== Indexing Summary ===');
59
+ console.log('Service'.padEnd(cols.name), 'Indexed'.padStart(cols.num), 'Skipped'.padStart(cols.num), 'Failed'.padStart(cols.num), 'Chunks'.padStart(cols.num), 'Time(s)'.padStart(cols.num));
60
+ console.log(line);
61
+ for (const s of allStats) {
62
+ console.log(s.serviceName.padEnd(cols.name), String(s.indexed).padStart(cols.num), String(s.skipped).padStart(cols.num), String(s.failed).padStart(cols.num), String(s.chunks).padStart(cols.num), String(s.elapsedSec).padStart(cols.num));
63
+ }
64
+ console.log(line);
65
+ const total = allStats.reduce((acc, s) => ({
66
+ indexed: acc.indexed + s.indexed,
67
+ skipped: acc.skipped + s.skipped,
68
+ failed: acc.failed + s.failed,
69
+ chunks: acc.chunks + s.chunks,
70
+ elapsedSec: acc.elapsedSec + s.elapsedSec,
71
+ }), { indexed: 0, skipped: 0, failed: 0, chunks: 0, elapsedSec: 0 });
72
+ console.log('TOTAL'.padEnd(cols.name), String(total.indexed).padStart(cols.num), String(total.skipped).padStart(cols.num), String(total.failed).padStart(cols.num), String(total.chunks).padStart(cols.num), String(total.elapsedSec.toFixed(1)).padStart(cols.num));
73
+ }
74
+ }
75
+ exports.IndexCommand = IndexCommand;
@@ -0,0 +1,7 @@
1
+ import type { Container } from '../container';
2
+ import type { ICommand } from './ICommand';
3
+ export declare class McpCommand implements ICommand {
4
+ private container;
5
+ constructor(container: Container);
6
+ execute(): Promise<void>;
7
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.McpCommand = void 0;
4
+ class McpCommand {
5
+ container;
6
+ constructor(container) {
7
+ this.container = container;
8
+ }
9
+ async execute() {
10
+ const { db, mcp } = this.container;
11
+ await db.initDb();
12
+ await mcp.start();
13
+ // server.connect() resolves immediately after setup; keep the process alive
14
+ // until the MCP client disconnects (stdin closes)
15
+ await new Promise(resolve => {
16
+ process.stdin.once('close', resolve);
17
+ process.stdin.once('end', resolve);
18
+ });
19
+ }
20
+ }
21
+ exports.McpCommand = McpCommand;
@@ -0,0 +1,4 @@
1
+ import type { ICommand } from './ICommand';
2
+ export declare class SetupCommand implements ICommand {
3
+ execute(): Promise<void>;
4
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SetupCommand = void 0;
4
+ const setup_1 = require("../setup");
5
+ class SetupCommand {
6
+ async execute() {
7
+ await (0, setup_1.runSetup)();
8
+ }
9
+ }
10
+ exports.SetupCommand = SetupCommand;
@@ -24,3 +24,4 @@ export declare const config: {
24
24
  };
25
25
  workspaceRoot: string;
26
26
  };
27
+ export type Config = typeof config;
@@ -1,15 +1,54 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.config = void 0;
37
+ const os = __importStar(require("os"));
4
38
  const zod_1 = require("zod");
5
39
  const constants_1 = require("./constants");
40
+ function deriveDbName() {
41
+ const username = os.userInfo().username;
42
+ const sanitized = username.toLowerCase().replace(/[^a-z0-9_]/g, '_');
43
+ return 'rag_' + (sanitized || 'user');
44
+ }
6
45
  const schema = zod_1.z.object({
7
46
  // required — no defaults, process exits if missing
8
47
  DB_HOST: zod_1.z.string(),
9
48
  DB_PORT: zod_1.z.coerce.number().default(5433),
10
49
  DB_USER: zod_1.z.string(),
11
50
  DB_PASS: zod_1.z.string(),
12
- DB_NAME: zod_1.z.string(),
51
+ DB_NAME: zod_1.z.string().optional(),
13
52
  // optional with defaults
14
53
  OLLAMA_HOST: zod_1.z.string().url().default('http://localhost:11434'),
15
54
  OLLAMA_MODEL: zod_1.z.string().default(constants_1.DEFAULT_EMBED_MODEL),
@@ -39,7 +78,7 @@ exports.config = {
39
78
  port: env.DB_PORT,
40
79
  username: env.DB_USER,
41
80
  password: env.DB_PASS,
42
- database: env.DB_NAME,
81
+ database: env.DB_NAME ?? deriveDbName(),
43
82
  },
44
83
  ollama: {
45
84
  host: env.OLLAMA_HOST,
@@ -0,0 +1,15 @@
1
+ import { type Config } from './config';
2
+ import { DatabaseService } from './services/DatabaseService';
3
+ import { IndexerService } from './services/IndexerService';
4
+ import { SearcherService } from './services/SearcherService';
5
+ import { McpServer } from './services/McpServer';
6
+ import { LoggerService } from './services/LoggerService';
7
+ export interface Container {
8
+ config: Config;
9
+ db: DatabaseService;
10
+ indexer: IndexerService;
11
+ searcher: SearcherService;
12
+ mcp: McpServer;
13
+ logger: LoggerService;
14
+ }
15
+ export declare function createContainer(): Container;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createContainer = createContainer;
4
+ const config_1 = require("./config");
5
+ const DatabaseService_1 = require("./services/DatabaseService");
6
+ const OllamaEmbedder_1 = require("./services/OllamaEmbedder");
7
+ const AstParserService_1 = require("./services/AstParserService");
8
+ const IndexerService_1 = require("./services/IndexerService");
9
+ const SearcherService_1 = require("./services/SearcherService");
10
+ const McpServer_1 = require("./services/McpServer");
11
+ const LoggerService_1 = require("./services/LoggerService");
12
+ function createContainer() {
13
+ const logger = LoggerService_1.LoggerService.fromEnv();
14
+ const db = new DatabaseService_1.DatabaseService(config_1.config);
15
+ const embedder = new OllamaEmbedder_1.OllamaEmbedder(config_1.config);
16
+ const ast = new AstParserService_1.AstParserService(logger);
17
+ const indexer = new IndexerService_1.IndexerService(db, embedder, ast, config_1.config, logger);
18
+ const searcher = new SearcherService_1.SearcherService(db, embedder, config_1.config, logger);
19
+ const mcp = new McpServer_1.McpServer(searcher, config_1.config, logger);
20
+ return { config: config_1.config, db, indexer, searcher, mcp, logger };
21
+ }
@@ -2,7 +2,7 @@ export declare class CodeChunk {
2
2
  id: string;
3
3
  serviceName: string;
4
4
  filePath: string;
5
- startLine: number;
5
+ startLine: number | null;
6
6
  content: string;
7
7
  embedding: string;
8
8
  lastModified: number;
@@ -34,8 +34,8 @@ __decorate([
34
34
  __metadata("design:type", String)
35
35
  ], CodeChunk.prototype, "filePath", void 0);
36
36
  __decorate([
37
- (0, typeorm_1.Column)({ nullable: true }),
38
- __metadata("design:type", Number)
37
+ (0, typeorm_1.Column)({ type: 'int', nullable: true }),
38
+ __metadata("design:type", Object)
39
39
  ], CodeChunk.prototype, "startLine", void 0);
40
40
  __decorate([
41
41
  (0, typeorm_1.Column)('text'),
@@ -0,0 +1,10 @@
1
+ export declare class CodeSymbol {
2
+ id: string;
3
+ project: string;
4
+ filePath: string;
5
+ name: string;
6
+ kind: string;
7
+ signature: string | null;
8
+ line: number | null;
9
+ col: number | null;
10
+ }