codesearch-mcp 0.0.16-alpha → 0.0.17-alpha.1

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 (38) hide show
  1. package/CHANGELOG.md +37 -1
  2. package/README.md +59 -36
  3. package/dist/app.d.ts +1 -1
  4. package/dist/app.js +67 -16
  5. package/dist/src/commands/BackfillCommand.js +15 -5
  6. package/dist/src/commands/ConfigCommand.d.ts +12 -0
  7. package/dist/src/commands/ConfigCommand.js +98 -0
  8. package/dist/src/commands/IndexCommand.js +1 -1
  9. package/dist/src/config-store.d.ts +53 -0
  10. package/dist/src/config-store.js +197 -0
  11. package/dist/src/config.d.ts +22 -8
  12. package/dist/src/config.js +103 -58
  13. package/dist/src/container.d.ts +1 -1
  14. package/dist/src/container.js +8 -7
  15. package/dist/src/db/index.d.ts +1 -1
  16. package/dist/src/db/index.js +2 -1
  17. package/dist/src/db/schema.d.ts +160 -0
  18. package/dist/src/db/schema.js +12 -1
  19. package/dist/src/help.js +28 -12
  20. package/dist/src/interfaces/IAstParser.d.ts +14 -1
  21. package/dist/src/interfaces/IEmbedder.d.ts +1 -0
  22. package/dist/src/project-selector.d.ts +14 -5
  23. package/dist/src/project-selector.js +74 -60
  24. package/dist/src/services/AstParserService.d.ts +5 -1
  25. package/dist/src/services/AstParserService.js +107 -16
  26. package/dist/src/services/DatabaseService.js +18 -0
  27. package/dist/src/services/IndexerService.d.ts +7 -0
  28. package/dist/src/services/IndexerService.js +160 -40
  29. package/dist/src/services/LoggerService.d.ts +5 -1
  30. package/dist/src/services/LoggerService.js +8 -5
  31. package/dist/src/services/McpServer.d.ts +1 -0
  32. package/dist/src/services/McpServer.js +72 -4
  33. package/dist/src/services/OllamaEmbedder.d.ts +2 -0
  34. package/dist/src/services/OllamaEmbedder.js +29 -0
  35. package/dist/src/services/SearcherService.d.ts +13 -0
  36. package/dist/src/services/SearcherService.js +118 -22
  37. package/dist/src/setup.js +57 -62
  38. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -3,6 +3,42 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  Format based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
5
 
6
+ ## [0.0.17-alpha] - 2026-05-13
7
+
8
+ ### Added
9
+
10
+ - **`get_callers` MCP tool** — finds all call sites of a function or method by exact name. Uses the `code_call` table populated by `rag-index backfill --calls`. Requires both `symbol` and `project`; optional `callee_file` to disambiguate overloaded names. Returns empty if backfill has not been run.
11
+
12
+ - **Call graph indexing** — `code_call` table records per-call-site entries `(project, fromFile, fromSymbol, calleeName, calleeFile, calleeSymbol, line, col)`. Populated during normal indexing (`ingestFile`) and via `rag-index backfill --calls` for existing installations. `AstParserService` extracts call expressions using ts-morph `CallExpression` nodes.
13
+
14
+ - **`analyzeProject` `skipDependencyResolution` option** — `IAstParser.analyzeProject` now accepts `opts?: { skipDependencyResolution?: boolean }`. `AstParserService.createMorphProject` propagates the flag to ts-morph `Project` options. Used by `IndexerService` for large projects to avoid OOM.
15
+
16
+ - **Configurable AST batch size (`indexing.astBatchSize`)** — `IndexerService` splits large projects into ts-morph batches. Threshold and batch size are now controlled by `indexing.astBatchSize` (default `3000`, configurable via `rag-config set indexing.astBatchSize <N>`). Projects above the threshold use `skipDependencyResolution: true` and print a console warning about potentially incomplete cross-batch dependency edges.
17
+
18
+ - **`include_graph_context` parameter for `search_codebase`** — appends direct imports and dependents inline with each result (`Imports: X · Y` / `Used by: Z`), eliminating separate `get_dependencies` / `get_dependents` calls for basic context. Single batch SQL query (UNION ALL + VALUES) for all result files — no N+1. Deduplicates via Sets; limits to 50 entries per direction per file.
19
+
20
+ - **Cross-encoder reranking** — optional second-pass via `POST /api/rerank` (requires Ollama ≥ 0.6). Controlled by `reranker.enabled`, `reranker.model`, `reranker.url` (defaults to `${ollama.host}/api/rerank`), `reranker.overfetch`. When enabled, `search_codebase` overfetches `limit × reranker.overfetch` vector candidates and reranks before returning `limit` results. Falls back gracefully to vector order on error (`warn` log). `rerank?` is an optional method on `IEmbedder` — `OllamaEmbedder` assigns it only when both `reranker.enabled=true` and `reranker.model` is set.
21
+
22
+ - **`ProjectSelector` unit tests** — full test coverage for project selection workflows including first-run auto-select, `--select` flag, `.ragprojects` / `.ragskip` persistence
23
+
24
+ - **`rag-config` command** — manage `~/.config/codesearch-mcp/config.json` from the CLI: `rag-config show`, `rag-config get <key>`, `rag-config set <key> <value>`, `rag-config reset <key>`. Supports all config keys with type coercion (string / number / boolean).
25
+
26
+ ### Changed
27
+
28
+ - **Config migrated from `.env` to `config.json`** — configuration is now stored in `~/.config/codesearch-mcp/config.json` instead of a `.env` file. `rag-setup` writes JSON; `dotenv` dependency removed. Existing `.env` files are no longer read — run `rag-setup` once to migrate.
29
+
30
+ - **`Config` class replaces module-level singleton** — `src/config.ts` now exports a `Config` class instantiated in `createContainer()`. Reads `config.json` via `readConfigJson()`, Zod-validates, throws `ConfigError` on missing required fields (caught in `app.ts` with a user-friendly message).
31
+
32
+ - **`LoggerService.fromConfig(cfg, name?)`** replaces `fromEnv()` — takes the `logging` sub-object from `Config` directly instead of reading `LOG_LEVEL` / `LOG_DIR` from `process.env`.
33
+
34
+ - **`reranker.*` and `search.*` config keys** — `RERANKER_ENABLED` and `RERANKER_OVERFETCH` in `config.search`; `config.ollama` retains only `rerankerModel` and `rerankerUrl`
35
+ - **`fetchLimit` capped at 200** — prevents runaway DB queries when `reranker.overfetch` is high
36
+ - **Reranker index validation** — indices from cross-encoder filtered for bounds before mapping
37
+ - **30s timeout + truncated error body on rerank HTTP call** — `AbortSignal.timeout(30_000)`; error body sliced to 200 chars
38
+ - **Enriched embedding context** — chunks now include `Project`, `Role` (inferred from file path), `Symbols` (overlapping definitions), and `Dependencies` in the embedding prompt. Improves semantic search quality for architectural queries. **Requires full re-index** (`rag-index --reindex`).
39
+ - **`ProjectSelector` refactored** — improved modularity and maintainability; extracted logic into smaller focused methods
40
+ - **`IndexCommand` argument validation** — enhanced error handling and validation across CLI modes
41
+
6
42
  ## [0.0.16-alpha] - 2026-05-02
7
43
 
8
44
  ### Added
@@ -12,7 +48,7 @@ Format based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
12
48
 
13
49
  ### Changed
14
50
 
15
- - **Migrated from TypeORM to Drizzle ORM**
51
+ - **Migrated from TypeORM to Drizzle ORM** — schema management and queries rewritten with Drizzle API; TypeORM decorators and metadata removed
16
52
  - **Batch AST parsing (`analyzeProject`)** — `IndexerService` now parses all project files in a single `MorphProject` instance instead of one per file, reducing ts-morph overhead on large projects
17
53
  - **Enriched embedding context** — chunks now include `[Symbols: class Foo, function bar]` tag when the chunk overlaps known symbol definitions, improving semantic search quality for partial/truncated chunks. **Requires full re-index** (`rag-index /path --reindex`) — existing embeddings were built without symbol context and will produce degraded similarity scores against new chunks if mixed.
18
54
  - **`endLine` added to `SymbolEntry`** — enables accurate chunk-to-symbol overlap detection used by enriched prompts
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # codesearch-mcp
2
2
 
3
- Semantic codebase search for Claude. Indexes your local projects into a PostgreSQL vector database and exposes search via the Model Context Protocol (MCP).
3
+ Semantic codebase search for AI agents. Indexes your local projects into a PostgreSQL vector database and exposes search via the Model Context Protocol (MCP).
4
4
 
5
- Ask Claude things like *"where is the payment retry logic?"* or *"show me how auth tokens are validated"* — across all your projects at once.
5
+ Ask your AI agent things like *"where is the payment retry logic?"* or *"show me how auth tokens are validated"* — across all your projects at once.
6
6
 
7
7
  > **Alpha** — works well locally, API may change before 1.0.
8
8
 
9
- See [CHANGELOG.md](./CHANGELOG.md) for version history.
9
+ See `CHANGELOG.md` for version history.
10
10
 
11
11
  ## How it works
12
12
 
@@ -14,7 +14,7 @@ See [CHANGELOG.md](./CHANGELOG.md) for version history.
14
14
  2. `rag-mcp` exposes an MCP server — Claude calls it automatically when you ask about code
15
15
  3. Incremental — only changed files are re-indexed on subsequent runs
16
16
 
17
- **Stack:** TypeScript · TypeORM · PostgreSQL + pgvector · Ollama (bge-m3) · LangChain text splitters · ts-morph
17
+ **Stack:** TypeScript · Drizzle ORM · PostgreSQL + pgvector · Ollama (bge-m3) · LangChain text splitters · ts-morph
18
18
 
19
19
  ## Requirements
20
20
 
@@ -34,24 +34,24 @@ rag-setup
34
34
  ```
35
35
 
36
36
  Walks you through:
37
- - **Local Docker** — copies `docker-compose.yml`, starts PostgreSQL + Ollama, pulls `bge-m3` automatically
38
- - **Remote DB** — enter connection details for Supabase, Railway, or self-hosted; connection is verified before saving
37
+ - **Database** — enter connection details; optionally starts Docker containers automatically
38
+ - **Ollama** — configure API URL
39
39
  - **Logging** — choose log level and directory (defaults: `error` level, `~/.config/codesearch-mcp/logs/`)
40
40
 
41
- Config is saved to `~/.config/codesearch-mcp/.env`.
41
+ Config is saved to `~/.config/codesearch-mcp/config.json`.
42
42
 
43
43
  ## Index your projects
44
44
 
45
45
  ```bash
46
- rag-index /home/user/Projects
46
+ rag-index
47
47
  ```
48
48
 
49
- On first run you will be prompted to select which projects to index. Selections are saved in `.ragprojects` / `.ragskip` at the workspace root.
49
+ `workspaceRoot` (set by `rag-setup` or `rag-config set workspaceRoot /path`) determines which directory is scanned. On first run — or when no projects are selected — the selector launches automatically. Selections are saved in `.ragprojects` / `.ragskip` at the workspace root.
50
50
 
51
51
  ```bash
52
- rag-index /path --select # re-run project selection
53
- rag-index /path --reindex # force re-embed all files (use after model change)
54
- rag-index /path --select --reindex
52
+ rag-index --select # re-run project selection
53
+ rag-index --reindex # force re-embed all files (use after model change)
54
+ rag-index --select --reindex
55
55
  ```
56
56
 
57
57
  ## Register with Claude Code
@@ -66,14 +66,15 @@ Then ask Claude anything about your code — it will use the tools below automat
66
66
 
67
67
  | Tool | Description |
68
68
  |------|-------------|
69
- | `search_codebase` | Semantic search across all indexed projects |
69
+ | `search_codebase` | Semantic search across all indexed projects. Accepts `include_graph_context` to append direct imports/dependents to each result, and `include_neighbors` for surrounding chunks |
70
70
  | `list_projects` | List projects with metadata and chunk counts |
71
71
  | `find_symbol` | Find a function, class, or type by exact name — faster than semantic search |
72
72
  | `list_files` | Browse the directory tree of a project |
73
73
  | `read_file` | Read a complete file by absolute path |
74
74
  | `read_file_range` | Read a specific line range from an indexed file |
75
- | `get_dependencies` | Show what files a given file imports |
76
- | `get_dependents` | Show which files import a given file |
75
+ | `get_dependencies` | Show what files a given file imports (direct or transitive) |
76
+ | `get_dependents` | Show which files import a given file (direct or transitive) |
77
+ | `get_callers` | Find all call sites of a function or method by exact name |
77
78
 
78
79
  ## Project metadata
79
80
 
@@ -92,6 +93,20 @@ Add `.ragmeta.json` to a project root to enrich `list_projects` and generate a v
92
93
 
93
94
  After each indexing run an interactive `project-graph.html` is written to the workspace root.
94
95
 
96
+ ## Graph context
97
+
98
+ Pass `include_graph_context: true` to `search_codebase` to see direct imports and dependents inline with each result — without extra `get_dependencies` / `get_dependents` calls:
99
+
100
+ ```
101
+ **File:** src/services/InvoiceService.ts **Line:** 45
102
+ ...code...
103
+ **Relevance:** 0.32
104
+ **Imports:** src/repositories/InvoiceRepo.ts · src/dto/CreateInvoiceDto.ts
105
+ **Used by:** src/controllers/InvoiceController.ts
106
+ ```
107
+
108
+ Useful for immediately understanding a file's role in the dependency graph.
109
+
95
110
  ## Excluding files
96
111
 
97
112
  Create `.ragignore` in a project root — same syntax as `.gitignore`:
@@ -112,31 +127,39 @@ tail -f ~/.config/codesearch-mcp/logs/indexer/current.log
112
127
  npx pino-pretty < ~/.config/codesearch-mcp/logs/indexer/current.log
113
128
 
114
129
  # Detailed indexing diagnostics (timing per file: deps / embed / db)
115
- LOG_LEVEL=debug rag-index /path/to/workspace
130
+ rag-config set logging.level debug
116
131
 
117
132
  # Disable file logging
118
- LOG_DIR=false rag-index /path/to/workspace
133
+ rag-config set logging.dir false
134
+ ```
135
+
136
+ ## Configuration
137
+
138
+ All set by `rag-setup`. Stored in `~/.config/codesearch-mcp/config.json`.
139
+
140
+ ```bash
141
+ rag-config show # print current config (password redacted)
142
+ rag-config get <key> # print a single value
143
+ rag-config set <key> <value> # update a value
144
+ rag-config reset <key> # remove key (reverts to default)
119
145
  ```
120
146
 
121
- ## Environment variables
122
-
123
- All set by `rag-setup`. Override any of them in `~/.config/codesearch-mcp/.env`.
124
-
125
- | Variable | Default | Description |
126
- |----------|---------|-------------|
127
- | `DB_HOST` | — | PostgreSQL host |
128
- | `DB_PORT` | `5433` | PostgreSQL port |
129
- | `DB_USER` | — | PostgreSQL user |
130
- | `DB_PASS` | — | PostgreSQL password |
131
- | `DB_NAME` | `rag_<os-username>` | Database name — auto-created on first run |
132
- | `WORKSPACE_ROOT` | — | Root of your projects directory |
133
- | `OLLAMA_HOST` | `http://localhost:11434` | Ollama API URL |
134
- | `OLLAMA_MODEL` | `bge-m3` | Embedding model |
135
- | `SIMILARITY_THRESHOLD` | `0.6` | Max cosine distance — raise if search returns nothing |
136
- | `AUTO_TRANSLATE` | `false` | Translate non-English queries to English before embedding |
137
- | `TRANSLATE_MODEL` | `llama3.2` | Ollama model for translation (requires `ollama pull llama3.2`) |
138
- | `LOG_LEVEL` | `error` | Log level written to file: `error` \| `warn` \| `info` \| `debug` |
139
- | `LOG_DIR` | `~/.config/codesearch-mcp/logs` | Base log directory, or `false` to disable |
147
+ | Key | Default | Description |
148
+ |-----|---------|-------------|
149
+ | `db.host` | — | PostgreSQL host |
150
+ | `db.port` | `5433` | PostgreSQL port |
151
+ | `db.user` | — | PostgreSQL user |
152
+ | `db.password` | — | PostgreSQL password |
153
+ | `db.name` | `rag_<os-username>` | Database name — auto-created on first run |
154
+ | `workspaceRoot` | — | Root of your projects directory |
155
+ | `ollama.host` | `http://localhost:11434` | Ollama API URL |
156
+ | `ollama.model` | `bge-m3` | Embedding model |
157
+ | `search.similarityThreshold` | `0.6` | Max cosine distance — raise if search returns nothing |
158
+ | `search.autoTranslate` | `false` | Translate non-English queries to English before embedding |
159
+ | `search.translateModel` | `llama3.2` | Ollama model for translation (requires `ollama pull llama3.2`) |
160
+ | `indexing.astBatchSize` | `3000` | Max files per ts-morph batch — lower if indexing large projects causes OOM |
161
+ | `logging.level` | `error` | Log level written to file: `error` \| `warn` \| `info` \| `debug` |
162
+ | `logging.dir` | `~/.config/codesearch-mcp/logs` | Base log directory, or `"false"` to disable |
140
163
 
141
164
  ## License
142
165
 
package/dist/app.d.ts CHANGED
@@ -1 +1 @@
1
- import './src/env-loader';
1
+ export {};
package/dist/app.js CHANGED
@@ -34,38 +34,89 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  };
35
35
  })();
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
- require("./src/env-loader");
38
37
  const path = __importStar(require("path"));
39
- const container_1 = require("./src/container");
40
38
  const help_1 = require("./src/help");
39
+ const container_1 = require("./src/container");
40
+ const config_1 = require("./src/config");
41
41
  const IndexCommand_1 = require("./src/commands/IndexCommand");
42
42
  const McpCommand_1 = require("./src/commands/McpCommand");
43
- const SetupCommand_1 = require("./src/commands/SetupCommand");
44
43
  const BackfillCommand_1 = require("./src/commands/BackfillCommand");
44
+ const ConfigCommand_1 = require("./src/commands/ConfigCommand");
45
+ const setup_1 = require("./src/setup");
45
46
  async function main() {
46
47
  const argv1 = path.basename(process.argv[1] ?? '');
47
- const isIndex = argv1 === 'rag-index' || process.argv[2] === 'index';
48
- const isMcp = argv1 === 'rag-mcp' || process.argv[2] === 'mcp';
49
- const isSetup = argv1 === 'rag-setup' || process.argv[2] === 'setup';
50
- const isBackfill = (argv1 === 'rag-index' || process.argv[2] === 'backfill') && process.argv[2] === 'backfill';
51
- const mode = isBackfill ? 'backfill' : isIndex ? 'index' : isMcp ? 'mcp' : isSetup ? 'setup' : (process.argv[2] ?? '');
48
+ const isIndex = argv1 === 'rag-index' || process.argv[2] === 'index' || process.argv[2] === 'rag-index';
49
+ const isMcp = argv1 === 'rag-mcp' || process.argv[2] === 'mcp' || process.argv[2] === 'rag-mcp';
50
+ const isSetup = argv1 === 'rag-setup' || process.argv[2] === 'setup' || process.argv[2] === 'rag-setup';
51
+ const isConfig = argv1 === 'rag-config' || process.argv[2] === 'config' || process.argv[2] === 'rag-config';
52
+ const isBackfill = process.argv[2] === 'backfill' ||
53
+ (process.argv[2] === 'rag-index' && process.argv[3] === 'backfill');
54
+ const mode = isBackfill ? 'backfill' : isIndex ? 'index' : isMcp ? 'mcp' : isSetup ? 'setup' : isConfig ? 'config' : (process.argv[2] ?? '');
55
+ const isBinary = ['rag-index', 'rag-mcp', 'rag-setup', 'rag-config'].includes(argv1);
52
56
  if (process.argv.includes('--help') || process.argv.includes('-h')) {
53
- (0, help_1.printHelp)(argv1 !== 'app.js' ? argv1 : mode);
57
+ (0, help_1.printHelp)(isBinary ? argv1 : mode);
54
58
  process.exit(0);
55
59
  }
56
- const loggerName = mode === 'index' || mode === 'backfill' ? 'indexer' : mode === 'mcp' ? 'mcp' : mode === 'setup' ? 'setup' : undefined;
57
- const container = (0, container_1.createContainer)(loggerName);
58
- if (!container.config.workspaceRoot && mode !== 'setup') {
60
+ const effectiveArgs = process.argv.slice(isBinary ? 2 : 3);
61
+ // Arg validation
62
+ if (mode === 'index') {
63
+ const knownFlags = new Set(['--reindex', '--select']);
64
+ const unknown = effectiveArgs.filter(a => !a.startsWith('-') || !knownFlags.has(a));
65
+ if (unknown.length > 0) {
66
+ console.error(`Unexpected argument: ${unknown[0]}\n`);
67
+ (0, help_1.printHelp)(isBinary ? argv1 : 'rag-index');
68
+ process.exit(1);
69
+ }
70
+ }
71
+ else if (mode === 'mcp' || mode === 'setup') {
72
+ if (effectiveArgs.length > 0) {
73
+ console.error(`Unexpected argument: ${effectiveArgs[0]}\n`);
74
+ (0, help_1.printHelp)(isBinary ? argv1 : `rag-${mode}`);
75
+ process.exit(1);
76
+ }
77
+ }
78
+ else if (mode === 'backfill') {
79
+ const knownBackfillFlags = new Set(['--calls']);
80
+ const backfillIdx = process.argv.indexOf('backfill');
81
+ const backfillArgs = backfillIdx >= 0 ? process.argv.slice(backfillIdx + 1) : [];
82
+ const unknown = backfillArgs.filter(a => !knownBackfillFlags.has(a));
83
+ if (unknown.length > 0) {
84
+ console.error(`Unexpected argument: ${unknown[0]}\n`);
85
+ (0, help_1.printHelp)('rag-index');
86
+ process.exit(1);
87
+ }
88
+ }
89
+ if (mode === 'setup') {
90
+ await (0, setup_1.runSetup)();
91
+ process.exit(0);
92
+ }
93
+ if (mode === 'config') {
94
+ await new ConfigCommand_1.ConfigCommand(effectiveArgs).execute();
95
+ process.exit(0);
96
+ }
97
+ // All other modes require a valid config.json
98
+ const loggerName = mode === 'index' || mode === 'backfill' ? 'indexer' : mode === 'mcp' ? 'mcp' : undefined;
99
+ let container;
100
+ try {
101
+ container = (0, container_1.createContainer)(loggerName);
102
+ }
103
+ catch (e) {
104
+ if (e instanceof config_1.ConfigError) {
105
+ console.error(e.message);
106
+ process.exit(1);
107
+ }
108
+ throw e;
109
+ }
110
+ if (!container.config.workspaceRoot) {
59
111
  const hint = argv1 === 'rag-mcp'
60
- ? 'Set WORKSPACE_ROOT in ~/.config/codesearch-mcp/.env or run `rag-setup`.'
61
- : 'Run `rag-setup` to configure WORKSPACE_ROOT.';
62
- console.error(`WORKSPACE_ROOT is not configured. ${hint}`);
112
+ ? 'Run rag-setup or: rag-config set workspaceRoot /path/to/projects'
113
+ : 'Run rag-setup to configure workspaceRoot.';
114
+ console.error(`workspaceRoot is not configured. ${hint}`);
63
115
  process.exit(1);
64
116
  }
65
117
  const commands = {
66
118
  index: new IndexCommand_1.IndexCommand(container, argv1),
67
119
  mcp: new McpCommand_1.McpCommand(container),
68
- setup: new SetupCommand_1.SetupCommand(container),
69
120
  backfill: new BackfillCommand_1.BackfillCommand(container),
70
121
  };
71
122
  const cmd = commands[mode];
@@ -10,14 +10,24 @@ class BackfillCommand {
10
10
  async execute() {
11
11
  const { db, indexer } = this.container;
12
12
  await db.initDbWithSchema();
13
+ const doCalls = process.argv.includes('--calls');
13
14
  const controller = new AbortController();
14
15
  const teardown = (0, interrupt_1.setupInterrupt)(controller);
15
16
  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}`);
17
+ if (doCalls) {
18
+ console.log('Backfilling call graph...\n');
19
+ const stats = await indexer.backfillCalls(controller.signal);
20
+ if (controller.signal.aborted)
21
+ console.log('\nBackfill interrupted.');
22
+ console.log(`\nDone. Total: ${stats.total}, Processed: ${stats.processed}, Skipped (not on disk): ${stats.skipped}, Failed: ${stats.failed}`);
23
+ }
24
+ else {
25
+ console.log('Backfilling symbol index...\n');
26
+ const stats = await indexer.backfillSymbols(controller.signal);
27
+ if (controller.signal.aborted)
28
+ console.log('\nBackfill interrupted.');
29
+ console.log(`\nDone. Total: ${stats.total}, Processed: ${stats.processed}, Skipped (not on disk): ${stats.skipped}, Failed: ${stats.failed}`);
30
+ }
21
31
  }
22
32
  finally {
23
33
  teardown();
@@ -0,0 +1,12 @@
1
+ import { ALL_KEYS } from '../config-store';
2
+ import type { ICommand } from './ICommand';
3
+ export declare class ConfigCommand implements ICommand {
4
+ private readonly args;
5
+ constructor(args: string[]);
6
+ execute(): Promise<void>;
7
+ private show;
8
+ private get;
9
+ private set;
10
+ private reset;
11
+ }
12
+ export { ALL_KEYS };
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ALL_KEYS = exports.ConfigCommand = void 0;
4
+ const config_store_1 = require("../config-store");
5
+ Object.defineProperty(exports, "ALL_KEYS", { enumerable: true, get: function () { return config_store_1.ALL_KEYS; } });
6
+ const help_1 = require("../help");
7
+ class ConfigCommand {
8
+ args;
9
+ constructor(args) {
10
+ this.args = args;
11
+ }
12
+ async execute() {
13
+ const [sub, key, value] = this.args;
14
+ switch (sub) {
15
+ case 'show': return this.show();
16
+ case 'get': return this.get(key);
17
+ case 'set': return this.set(key, value);
18
+ case 'reset': return this.reset(key);
19
+ default:
20
+ if (sub)
21
+ console.error(`Unknown subcommand: ${sub}\n`);
22
+ (0, help_1.printHelp)('rag-config');
23
+ process.exit(sub ? 1 : 0);
24
+ }
25
+ }
26
+ show() {
27
+ let cfg = null;
28
+ try {
29
+ cfg = (0, config_store_1.readConfigJson)();
30
+ }
31
+ catch (e) {
32
+ console.error(e.message);
33
+ process.exit(1);
34
+ }
35
+ if (!cfg) {
36
+ console.log(`No config found at ${config_store_1.CONFIG_FILE}. Run rag-setup.`);
37
+ return;
38
+ }
39
+ // redact password for display
40
+ const display = JSON.parse(JSON.stringify(cfg));
41
+ if (display.db?.password !== undefined)
42
+ display.db.password = '***';
43
+ console.log(JSON.stringify(display, null, 2));
44
+ }
45
+ get(key) {
46
+ if (!key) {
47
+ console.error('Usage: rag-config get <key>');
48
+ process.exit(1);
49
+ }
50
+ let cfg = null;
51
+ try {
52
+ cfg = (0, config_store_1.readConfigJson)();
53
+ }
54
+ catch (e) {
55
+ console.error(e.message);
56
+ process.exit(1);
57
+ }
58
+ if (!cfg) {
59
+ console.log('(no config)');
60
+ return;
61
+ }
62
+ const val = (0, config_store_1.getNestedValue)(cfg, key);
63
+ console.log(val === undefined ? '(not set)' : String(val));
64
+ }
65
+ set(key, value) {
66
+ if (!key || value === undefined) {
67
+ console.error('Usage: rag-config set <key> <value>');
68
+ process.exit(1);
69
+ }
70
+ try {
71
+ const cfg = (0, config_store_1.readConfigJson)() ?? {};
72
+ const updated = (0, config_store_1.setNestedValue)(cfg, key, value);
73
+ (0, config_store_1.writeConfigJson)(updated);
74
+ console.log(`${key} = ${value}`);
75
+ }
76
+ catch (e) {
77
+ console.error(e.message);
78
+ process.exit(1);
79
+ }
80
+ }
81
+ reset(key) {
82
+ if (!key) {
83
+ console.error('Usage: rag-config reset <key>');
84
+ process.exit(1);
85
+ }
86
+ try {
87
+ const cfg = (0, config_store_1.readConfigJson)() ?? {};
88
+ const updated = (0, config_store_1.deleteNestedValue)(cfg, key);
89
+ (0, config_store_1.writeConfigJson)(updated);
90
+ console.log(`${key} reset to default`);
91
+ }
92
+ catch (e) {
93
+ console.error(e.message);
94
+ process.exit(1);
95
+ }
96
+ }
97
+ }
98
+ exports.ConfigCommand = ConfigCommand;
@@ -22,7 +22,7 @@ class IndexCommand {
22
22
  const teardown = (0, interrupt_1.setupInterrupt)(controller);
23
23
  try {
24
24
  const discovered = indexer.discoverProjects(config.workspaceRoot);
25
- const projects = await (0, project_selector_1.selectProjects)(discovered, config.workspaceRoot, forceSelect);
25
+ const projects = await new project_selector_1.ProjectSelector(config.workspaceRoot).select(discovered, forceSelect);
26
26
  if (projects.length === 0)
27
27
  return;
28
28
  const filesPerProject = projects.map(p => (0, file_utils_1.collectFiles)(p.path, (0, file_utils_1.loadIgnore)(p.path), p.path));
@@ -0,0 +1,53 @@
1
+ import { z } from 'zod';
2
+ export declare const CONFIG_DIR: string;
3
+ export declare const CONFIG_FILE: string;
4
+ declare const jsonSchema: z.ZodObject<{
5
+ db: z.ZodOptional<z.ZodObject<{
6
+ host: z.ZodOptional<z.ZodString>;
7
+ port: z.ZodOptional<z.ZodNumber>;
8
+ user: z.ZodOptional<z.ZodString>;
9
+ password: z.ZodOptional<z.ZodString>;
10
+ name: z.ZodOptional<z.ZodString>;
11
+ }, z.core.$strip>>;
12
+ ollama: z.ZodOptional<z.ZodObject<{
13
+ host: z.ZodOptional<z.ZodString>;
14
+ model: z.ZodOptional<z.ZodString>;
15
+ }, z.core.$strip>>;
16
+ indexing: z.ZodOptional<z.ZodObject<{
17
+ chunkSize: z.ZodOptional<z.ZodNumber>;
18
+ chunkOverlap: z.ZodOptional<z.ZodNumber>;
19
+ embedBatchSize: z.ZodOptional<z.ZodNumber>;
20
+ astBatchSize: z.ZodOptional<z.ZodNumber>;
21
+ }, z.core.$strip>>;
22
+ search: z.ZodOptional<z.ZodObject<{
23
+ similarityThreshold: z.ZodOptional<z.ZodNumber>;
24
+ defaultLimit: z.ZodOptional<z.ZodNumber>;
25
+ maxLimit: z.ZodOptional<z.ZodNumber>;
26
+ autoTranslate: z.ZodOptional<z.ZodBoolean>;
27
+ translateModel: z.ZodOptional<z.ZodString>;
28
+ }, z.core.$strip>>;
29
+ reranker: z.ZodOptional<z.ZodObject<{
30
+ enabled: z.ZodOptional<z.ZodBoolean>;
31
+ model: z.ZodOptional<z.ZodString>;
32
+ url: z.ZodOptional<z.ZodString>;
33
+ overfetch: z.ZodOptional<z.ZodNumber>;
34
+ }, z.core.$strip>>;
35
+ logging: z.ZodOptional<z.ZodObject<{
36
+ level: z.ZodOptional<z.ZodEnum<{
37
+ error: "error";
38
+ debug: "debug";
39
+ info: "info";
40
+ warn: "warn";
41
+ }>>;
42
+ dir: z.ZodOptional<z.ZodString>;
43
+ }, z.core.$strip>>;
44
+ workspaceRoot: z.ZodOptional<z.ZodString>;
45
+ }, z.core.$strip>;
46
+ export type JsonConfig = z.infer<typeof jsonSchema>;
47
+ export declare const ALL_KEYS: string[];
48
+ export declare function readConfigJson(): JsonConfig | null;
49
+ export declare function writeConfigJson(data: JsonConfig): void;
50
+ export declare function getNestedValue(cfg: JsonConfig, key: string): unknown;
51
+ export declare function setNestedValue(cfg: JsonConfig, key: string, raw: string): JsonConfig;
52
+ export declare function deleteNestedValue(cfg: JsonConfig, key: string): JsonConfig;
53
+ export {};