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.
- package/CHANGELOG.md +37 -1
- package/README.md +59 -36
- package/dist/app.d.ts +1 -1
- package/dist/app.js +67 -16
- package/dist/src/commands/BackfillCommand.js +15 -5
- package/dist/src/commands/ConfigCommand.d.ts +12 -0
- package/dist/src/commands/ConfigCommand.js +98 -0
- package/dist/src/commands/IndexCommand.js +1 -1
- package/dist/src/config-store.d.ts +53 -0
- package/dist/src/config-store.js +197 -0
- package/dist/src/config.d.ts +22 -8
- package/dist/src/config.js +103 -58
- package/dist/src/container.d.ts +1 -1
- package/dist/src/container.js +8 -7
- package/dist/src/db/index.d.ts +1 -1
- package/dist/src/db/index.js +2 -1
- package/dist/src/db/schema.d.ts +160 -0
- package/dist/src/db/schema.js +12 -1
- package/dist/src/help.js +28 -12
- package/dist/src/interfaces/IAstParser.d.ts +14 -1
- package/dist/src/interfaces/IEmbedder.d.ts +1 -0
- package/dist/src/project-selector.d.ts +14 -5
- package/dist/src/project-selector.js +74 -60
- package/dist/src/services/AstParserService.d.ts +5 -1
- package/dist/src/services/AstParserService.js +107 -16
- package/dist/src/services/DatabaseService.js +18 -0
- package/dist/src/services/IndexerService.d.ts +7 -0
- package/dist/src/services/IndexerService.js +160 -40
- package/dist/src/services/LoggerService.d.ts +5 -1
- package/dist/src/services/LoggerService.js +8 -5
- package/dist/src/services/McpServer.d.ts +1 -0
- package/dist/src/services/McpServer.js +72 -4
- package/dist/src/services/OllamaEmbedder.d.ts +2 -0
- package/dist/src/services/OllamaEmbedder.js +29 -0
- package/dist/src/services/SearcherService.d.ts +13 -0
- package/dist/src/services/SearcherService.js +118 -22
- package/dist/src/setup.js +57 -62
- 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
|
|
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
|
|
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
|
|
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 ·
|
|
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
|
-
- **
|
|
38
|
-
- **
|
|
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
|
|
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
|
|
46
|
+
rag-index
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
On first run
|
|
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
|
|
53
|
-
rag-index
|
|
54
|
-
rag-index
|
|
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
|
-
|
|
130
|
+
rag-config set logging.level debug
|
|
116
131
|
|
|
117
132
|
# Disable file logging
|
|
118
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
|
126
|
-
|
|
127
|
-
| `
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
130
|
-
| `
|
|
131
|
-
| `
|
|
132
|
-
| `
|
|
133
|
-
| `
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
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
|
-
|
|
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
|
|
51
|
-
const
|
|
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)(
|
|
57
|
+
(0, help_1.printHelp)(isBinary ? argv1 : mode);
|
|
54
58
|
process.exit(0);
|
|
55
59
|
}
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
if (
|
|
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
|
-
? '
|
|
61
|
-
: 'Run
|
|
62
|
-
console.error(`
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
|
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 {};
|