codesearch-mcp 0.2.2-alpha → 0.3.0-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.
- package/CHANGELOG.md +65 -1
- package/README.md +60 -33
- package/dist/app.js +46 -22
- package/dist/src/chunking/AstChunker.d.ts +12 -0
- package/dist/src/chunking/AstChunker.js +30 -0
- package/dist/src/chunking/CharacterChunkStrategy.d.ts +8 -0
- package/dist/src/chunking/CharacterChunkStrategy.js +15 -0
- package/dist/src/chunking/DeclarationChunkStrategy.d.ts +15 -0
- package/dist/src/chunking/DeclarationChunkStrategy.js +87 -0
- package/dist/src/chunking/FragmentMerger.d.ts +11 -0
- package/dist/src/chunking/FragmentMerger.js +61 -0
- package/dist/src/chunking/ImportOnlyFilter.d.ts +5 -0
- package/dist/src/chunking/ImportOnlyFilter.js +14 -0
- package/dist/src/chunking/LangchainTextSplitter.d.ts +21 -0
- package/dist/src/chunking/LangchainTextSplitter.js +133 -0
- package/dist/src/chunking/MinSizeSplitPolicy.d.ts +9 -0
- package/dist/src/chunking/MinSizeSplitPolicy.js +18 -0
- package/dist/src/chunking/RunPacker.d.ts +12 -0
- package/dist/src/chunking/RunPacker.js +84 -0
- package/dist/src/chunking/create-chunker.d.ts +3 -0
- package/dist/src/chunking/create-chunker.js +15 -0
- package/dist/src/chunking/interfaces.d.ts +27 -0
- package/dist/src/chunking/interfaces.js +2 -0
- package/dist/src/commands/ConfigCommand.js +1 -9
- package/dist/src/commands/EvalCommand.d.ts +11 -0
- package/dist/src/commands/EvalCommand.js +264 -0
- package/dist/src/commands/IndexCommand.js +70 -66
- package/dist/src/commands/McpCommand.js +2 -8
- package/dist/src/commands/WebCommand.js +2 -5
- package/dist/src/config-error.d.ts +0 -4
- package/dist/src/config-error.js +0 -4
- package/dist/src/config-store.d.ts +1 -54
- package/dist/src/config-store.js +8 -69
- package/dist/src/config.d.ts +8 -17
- package/dist/src/config.js +35 -34
- package/dist/src/constants.d.ts +2 -28
- package/dist/src/constants.js +6 -28
- package/dist/src/container.d.ts +6 -0
- package/dist/src/container.js +12 -3
- package/dist/src/db/index.d.ts +1 -1
- package/dist/src/db/index.js +1 -2
- package/dist/src/db/schema.d.ts +22 -29
- package/dist/src/db/schema.js +3 -14
- package/dist/src/declarations/DeclarationTree.d.ts +19 -0
- package/dist/src/declarations/DeclarationTree.js +66 -0
- package/dist/src/declarations/DeclarationTreeBuilder.d.ts +22 -0
- package/dist/src/declarations/DeclarationTreeBuilder.js +179 -0
- package/dist/src/declarations/SourceLines.d.ts +37 -0
- package/dist/src/declarations/SourceLines.js +415 -0
- package/dist/src/dependency-traversal.d.ts +10 -0
- package/dist/src/dependency-traversal.js +39 -0
- package/dist/src/enriched-prompt.d.ts +0 -5
- package/dist/src/enriched-prompt.js +0 -5
- package/dist/src/error-record.d.ts +12 -0
- package/dist/src/error-record.js +248 -0
- package/dist/src/eval-corpus.d.ts +16 -0
- package/dist/src/eval-corpus.js +169 -0
- package/dist/src/eval-results.d.ts +15 -0
- package/dist/src/eval-results.js +397 -0
- package/dist/src/file-utils.d.ts +10 -0
- package/dist/src/file-utils.js +19 -1
- package/dist/src/graph.d.ts +0 -25
- package/dist/src/graph.js +0 -28
- package/dist/src/help.js +4 -1
- package/dist/src/hnsw-settings.d.ts +3 -0
- package/dist/src/hnsw-settings.js +24 -0
- package/dist/src/interfaces/IAstParser.d.ts +5 -30
- package/dist/src/interfaces/IChunker.d.ts +3 -12
- package/dist/src/interfaces/ICorpusInspector.d.ts +7 -0
- package/dist/src/interfaces/ICorpusInspector.js +2 -0
- package/dist/src/interfaces/IDatabase.d.ts +2 -36
- package/dist/src/interfaces/IEmbedder.d.ts +0 -9
- package/dist/src/interfaces/ILogger.d.ts +1 -11
- package/dist/src/interfaces/IMcpToolHandler.d.ts +0 -5
- package/dist/src/interfaces/IMonorepoResolver.d.ts +0 -22
- package/dist/src/interfaces/IProjectDiscovery.d.ts +0 -17
- package/dist/src/interfaces/IRetrievalEvaluator.d.ts +216 -0
- package/dist/src/interfaces/IRetrievalEvaluator.js +2 -0
- package/dist/src/interfaces/ISearcher.d.ts +26 -20
- package/dist/src/interfaces/index.d.ts +1 -0
- package/dist/src/interrupt.js +0 -2
- package/dist/src/owner-path.d.ts +9 -10
- package/dist/src/owner-path.js +11 -23
- package/dist/src/project-scope.d.ts +7 -0
- package/dist/src/project-scope.js +37 -0
- package/dist/src/project-selector.d.ts +1 -0
- package/dist/src/project-selector.js +13 -6
- package/dist/src/retrieval-eval.d.ts +24 -0
- package/dist/src/retrieval-eval.js +500 -0
- package/dist/src/search/result-shaping.d.ts +4 -0
- package/dist/src/search/result-shaping.js +19 -0
- package/dist/src/services/AstParserService.d.ts +28 -23
- package/dist/src/services/AstParserService.js +391 -98
- package/dist/src/services/DatabaseService.d.ts +2 -19
- package/dist/src/services/DatabaseService.js +44 -81
- package/dist/src/services/EmbedderFactory.d.ts +0 -4
- package/dist/src/services/EmbedderFactory.js +0 -5
- package/dist/src/services/IndexerService.d.ts +2 -10
- package/dist/src/services/IndexerService.js +29 -45
- package/dist/src/services/InfinityEmbedder.d.ts +0 -21
- package/dist/src/services/InfinityEmbedder.js +0 -15
- package/dist/src/services/LoggerService.d.ts +7 -5
- package/dist/src/services/LoggerService.js +37 -41
- package/dist/src/services/McpServer.d.ts +25 -10
- package/dist/src/services/McpServer.js +101 -64
- package/dist/src/services/MonorepoAwareDiscoveryService.d.ts +1 -45
- package/dist/src/services/MonorepoAwareDiscoveryService.js +1 -51
- package/dist/src/services/NxMonorepoResolver.d.ts +0 -29
- package/dist/src/services/NxMonorepoResolver.js +5 -56
- package/dist/src/services/OpenAICompatibleEmbedder.d.ts +0 -6
- package/dist/src/services/OpenAICompatibleEmbedder.js +1 -14
- package/dist/src/services/ProjectDiscoveryService.d.ts +0 -4
- package/dist/src/services/ProjectDiscoveryService.js +0 -4
- package/dist/src/services/SearcherService.d.ts +127 -70
- package/dist/src/services/SearcherService.js +526 -305
- package/dist/src/services/VoyageEmbedder.d.ts +0 -6
- package/dist/src/services/VoyageEmbedder.js +0 -6
- package/dist/src/services/WebServerService.d.ts +1 -53
- package/dist/src/services/WebServerService.js +11 -57
- package/dist/src/services/http-retry.d.ts +0 -7
- package/dist/src/services/http-retry.js +1 -10
- package/dist/src/services/infinity-provisioning.d.ts +0 -74
- package/dist/src/services/infinity-provisioning.js +5 -88
- package/dist/src/services/legacy-ollama-index.d.ts +0 -16
- package/dist/src/services/legacy-ollama-index.js +0 -23
- package/dist/src/services/reranker.d.ts +0 -9
- package/dist/src/services/reranker.js +46 -12
- package/dist/src/setup.d.ts +11 -23
- package/dist/src/setup.js +98 -71
- package/dist/src/symbol-name.d.ts +0 -12
- package/dist/src/symbol-name.js +0 -13
- package/dist/src/symbol-rows.d.ts +2 -11
- package/dist/src/symbol-rows.js +5 -13
- package/dist/src/tool-call-log.d.ts +2 -0
- package/dist/src/tool-call-log.js +24 -0
- package/dist/src/tools/FindSymbolTool.js +14 -5
- package/dist/src/tools/GetCallersTool.d.ts +3 -1
- package/dist/src/tools/GetCallersTool.js +16 -6
- package/dist/src/tools/GetDependenciesTool.d.ts +3 -1
- package/dist/src/tools/GetDependenciesTool.js +15 -8
- package/dist/src/tools/GetDependentsTool.d.ts +3 -1
- package/dist/src/tools/GetDependentsTool.js +31 -16
- package/dist/src/tools/ListFilesTool.d.ts +3 -1
- package/dist/src/tools/ListFilesTool.js +14 -12
- package/dist/src/tools/ListProjectsTool.js +5 -1
- package/dist/src/tools/ReadFileRangeTool.d.ts +3 -1
- package/dist/src/tools/ReadFileRangeTool.js +12 -11
- package/dist/src/tools/ReadFileTool.d.ts +3 -1
- package/dist/src/tools/ReadFileTool.js +12 -10
- package/dist/src/tools/SearchCodebaseTool.js +7 -2
- package/dist/src/tools/format-helpers.d.ts +10 -1
- package/dist/src/tools/format-helpers.js +145 -8
- package/dist/src/web/dashboard.d.ts +0 -8
- package/dist/src/web/dashboard.js +7 -10
- package/package.json +10 -9
- package/dist/src/services/AstChunker.d.ts +0 -42
- package/dist/src/services/AstChunker.js +0 -158
- package/docs/web-dashboard.md +0 -206
|
@@ -6,7 +6,6 @@ import * as schema from '../db/schema';
|
|
|
6
6
|
type Schema = typeof schema;
|
|
7
7
|
export type DrizzleDb = NodePgDatabase<Schema>;
|
|
8
8
|
export type DrizzleTx = NodePgTransaction<Schema, ExtractTablesWithRelations<Schema>>;
|
|
9
|
-
export declare const CURRENT_SYMBOL_INDEX_VERSION = 2;
|
|
10
9
|
export declare class DatabaseService implements IDatabase {
|
|
11
10
|
private config;
|
|
12
11
|
private pool;
|
|
@@ -14,17 +13,13 @@ export declare class DatabaseService implements IDatabase {
|
|
|
14
13
|
constructor(config: Config);
|
|
15
14
|
get orm(): DrizzleDb;
|
|
16
15
|
query<T = any>(sql: string, params?: any[]): Promise<T>;
|
|
16
|
+
queryWithLocalSettings<T = any>(settings: Record<string, string | number>, sql: string, params?: any[]): Promise<T>;
|
|
17
|
+
pgvectorVersion(): Promise<string | null>;
|
|
17
18
|
transaction<T>(fn: (tx: DrizzleTx) => Promise<T>): Promise<T>;
|
|
18
19
|
destroy(): Promise<void>;
|
|
19
20
|
initDb(): Promise<void>;
|
|
20
21
|
initDbWithSchema(): Promise<void>;
|
|
21
|
-
/**
|
|
22
|
-
* Create `code_chunk` at `dimensions` if it does not exist, plus its HNSW and
|
|
23
|
-
* (serviceName, filePath) indexes and the additive `contentHash`/`ownerPath`
|
|
24
|
-
* columns for pre-existing tables. Idempotent — safe to call repeatedly.
|
|
25
|
-
*/
|
|
26
22
|
ensureChunkTable(dimensions: number): Promise<void>;
|
|
27
|
-
/** Drop and recreate `code_chunk` at `dimensions` — used on a dimension change. */
|
|
28
23
|
recreateChunkTable(dimensions: number): Promise<void>;
|
|
29
24
|
readIndexMeta(): Promise<IndexMeta | null>;
|
|
30
25
|
writeIndexMeta(meta: IndexMeta): Promise<void>;
|
|
@@ -32,18 +27,6 @@ export declare class DatabaseService implements IDatabase {
|
|
|
32
27
|
deleteFiles(project: string, filePaths: string[]): Promise<void>;
|
|
33
28
|
listIndexedProjects(): Promise<string[]>;
|
|
34
29
|
deleteProject(name: string): Promise<void>;
|
|
35
|
-
listProjectsWithIndexRows(): Promise<string[]>;
|
|
36
|
-
/**
|
|
37
|
-
* Among `projectNames` (or every project with rows when null), those with at
|
|
38
|
-
* least one row in `code_chunk`/`code_symbol` and a `symbol_index_version`
|
|
39
|
-
* below `CURRENT_SYMBOL_INDEX_VERSION` (a missing row counts as version 1).
|
|
40
|
-
* A missing `symbol_index_version` table (un-migrated DB, `rag-mcp`/`rag-web`
|
|
41
|
-
* bootstrapped with `initDb`) counts as "no marker rows" — every project with
|
|
42
|
-
* rows is then outdated. Any other database error propagates.
|
|
43
|
-
*/
|
|
44
|
-
listOutdatedProjects(projectNames: string[] | null): Promise<string[]>;
|
|
45
|
-
upsertSymbolIndexVersion(project: string): Promise<void>;
|
|
46
|
-
/** Guard against SQL injection — the dimension is interpolated into DDL. */
|
|
47
30
|
private assertDim;
|
|
48
31
|
private assertMinPostgresVersion;
|
|
49
32
|
private ensureDatabaseExists;
|
|
@@ -33,14 +33,15 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.DatabaseService =
|
|
36
|
+
exports.DatabaseService = void 0;
|
|
37
37
|
const node_postgres_1 = require("drizzle-orm/node-postgres");
|
|
38
38
|
const pg_1 = require("pg");
|
|
39
39
|
const drizzle_orm_1 = require("drizzle-orm");
|
|
40
40
|
const schema = __importStar(require("../db/schema"));
|
|
41
41
|
const db_1 = require("../db");
|
|
42
42
|
const MIN_PG_VERSION_NUM = 150000;
|
|
43
|
-
|
|
43
|
+
const SETTING_NAME = /^[a-z_]+(\.[a-z_]+)*$/;
|
|
44
|
+
const SETTING_VALUE = /^[A-Za-z0-9_]+$/;
|
|
44
45
|
class DatabaseService {
|
|
45
46
|
config;
|
|
46
47
|
pool;
|
|
@@ -53,6 +54,41 @@ class DatabaseService {
|
|
|
53
54
|
const result = await this.pool.query(sql, params);
|
|
54
55
|
return result.rows;
|
|
55
56
|
}
|
|
57
|
+
async queryWithLocalSettings(settings, sql, params) {
|
|
58
|
+
const setStatements = Object.entries(settings).map(([name, value]) => {
|
|
59
|
+
if (!SETTING_NAME.test(name) || !SETTING_VALUE.test(String(value))) {
|
|
60
|
+
throw new Error(`DatabaseService: invalid local setting ${JSON.stringify(name)} = ${JSON.stringify(value)}`);
|
|
61
|
+
}
|
|
62
|
+
return `SET LOCAL ${name} = ${value}`;
|
|
63
|
+
});
|
|
64
|
+
const client = await this.pool.connect();
|
|
65
|
+
let began = false;
|
|
66
|
+
let broken;
|
|
67
|
+
const onError = (err) => { broken ??= err; };
|
|
68
|
+
client.on('error', onError);
|
|
69
|
+
try {
|
|
70
|
+
await client.query('BEGIN');
|
|
71
|
+
began = true;
|
|
72
|
+
for (const statement of setStatements)
|
|
73
|
+
await client.query(statement);
|
|
74
|
+
const result = await client.query(sql, params);
|
|
75
|
+
await client.query('COMMIT');
|
|
76
|
+
return result.rows;
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
if (began)
|
|
80
|
+
await client.query('ROLLBACK').catch((e) => { broken ??= e; });
|
|
81
|
+
throw err;
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
client.removeListener('error', onError);
|
|
85
|
+
client.release(broken);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async pgvectorVersion() {
|
|
89
|
+
const rows = await this.query(`SELECT extversion FROM pg_extension WHERE extname = 'vector'`);
|
|
90
|
+
return rows[0]?.extversion ?? null;
|
|
91
|
+
}
|
|
56
92
|
transaction(fn) {
|
|
57
93
|
return this._db.transaction(fn);
|
|
58
94
|
}
|
|
@@ -70,17 +106,8 @@ class DatabaseService {
|
|
|
70
106
|
async initDbWithSchema() {
|
|
71
107
|
await this.ensureDatabaseExists();
|
|
72
108
|
await this.initDb();
|
|
73
|
-
// Read as the very first statement on the application database, before any
|
|
74
|
-
// CREATE TABLE / CREATE INDEX / ALTER TABLE / DROP — `NULLS NOT DISTINCT`
|
|
75
|
-
// (used below) requires PostgreSQL 15+, and the DROP/CREATE pair must never
|
|
76
|
-
// run against an older server (it would fail after the DROP and leave
|
|
77
|
-
// code_symbol without a unique index).
|
|
78
109
|
await this.assertMinPostgresVersion();
|
|
79
|
-
// code_chunk table — created at the legacy default width (1024) so search
|
|
80
|
-
// tools always have a table. IndexerService recreates it at the resolved
|
|
81
|
-
// width before indexing when the active model's dimension differs.
|
|
82
110
|
await this.ensureChunkTable(1024);
|
|
83
|
-
// index_meta table — source of truth for the model that built the index.
|
|
84
111
|
await this.query(`
|
|
85
112
|
CREATE TABLE IF NOT EXISTS index_meta (
|
|
86
113
|
id BOOLEAN PRIMARY KEY DEFAULT true,
|
|
@@ -90,7 +117,6 @@ class DatabaseService {
|
|
|
90
117
|
"indexedAt" TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
91
118
|
)
|
|
92
119
|
`);
|
|
93
|
-
// code_dependency table
|
|
94
120
|
const [{ existsDep }] = await this.query(`
|
|
95
121
|
SELECT EXISTS (
|
|
96
122
|
SELECT 1 FROM information_schema.tables
|
|
@@ -115,7 +141,6 @@ class DatabaseService {
|
|
|
115
141
|
await this.query(`DROP INDEX IF EXISTS idx_dep_from`);
|
|
116
142
|
await this.query(`DROP INDEX IF EXISTS idx_dep_to`);
|
|
117
143
|
await this.query(`DROP INDEX IF EXISTS idx_dep_project`);
|
|
118
|
-
// code_symbol table
|
|
119
144
|
const [{ existsSym }] = await this.query(`
|
|
120
145
|
SELECT EXISTS (
|
|
121
146
|
SELECT 1 FROM information_schema.tables
|
|
@@ -140,23 +165,13 @@ class DatabaseService {
|
|
|
140
165
|
await this.query(`CREATE INDEX IF NOT EXISTS idx_symbol_file ON code_symbol (project, "filePath")`);
|
|
141
166
|
await this.query(`ALTER TABLE code_symbol ADD COLUMN IF NOT EXISTS container TEXT`);
|
|
142
167
|
await this.query(`ALTER TABLE code_symbol ADD COLUMN IF NOT EXISTS "isStatic" BOOLEAN NOT NULL DEFAULT false`);
|
|
143
|
-
|
|
144
|
-
// neither does, so a failure here never leaves code_symbol without a
|
|
145
|
-
// unique index (the old idx_symbol_unique is dropped only once the new
|
|
146
|
-
// one is confirmed to exist).
|
|
168
|
+
await this.query(`ALTER TABLE code_symbol ADD COLUMN IF NOT EXISTS "target" TEXT`);
|
|
147
169
|
await this.transaction(async (tx) => {
|
|
148
170
|
await tx.execute('DROP INDEX IF EXISTS idx_symbol_unique');
|
|
149
171
|
await tx.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_symbol_unique_v2 ' +
|
|
150
172
|
'ON code_symbol (project, "filePath", container, name, kind, line) NULLS NOT DISTINCT');
|
|
151
173
|
});
|
|
152
174
|
await this.query(`
|
|
153
|
-
CREATE TABLE IF NOT EXISTS symbol_index_version (
|
|
154
|
-
project TEXT PRIMARY KEY,
|
|
155
|
-
version INT NOT NULL
|
|
156
|
-
)
|
|
157
|
-
`);
|
|
158
|
-
// code_call table
|
|
159
|
-
await this.query(`
|
|
160
175
|
CREATE TABLE IF NOT EXISTS code_call (
|
|
161
176
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
162
177
|
project TEXT NOT NULL,
|
|
@@ -173,11 +188,6 @@ class DatabaseService {
|
|
|
173
188
|
await this.query(`CREATE INDEX IF NOT EXISTS idx_call_callee_file ON code_call (project, "calleeFile")`);
|
|
174
189
|
await this.query(`CREATE INDEX IF NOT EXISTS idx_call_from ON code_call (project, "fromFile")`);
|
|
175
190
|
}
|
|
176
|
-
/**
|
|
177
|
-
* Create `code_chunk` at `dimensions` if it does not exist, plus its HNSW and
|
|
178
|
-
* (serviceName, filePath) indexes and the additive `contentHash`/`ownerPath`
|
|
179
|
-
* columns for pre-existing tables. Idempotent — safe to call repeatedly.
|
|
180
|
-
*/
|
|
181
191
|
async ensureChunkTable(dimensions) {
|
|
182
192
|
const dim = this.assertDim(dimensions);
|
|
183
193
|
await this.query(`
|
|
@@ -190,15 +200,16 @@ class DatabaseService {
|
|
|
190
200
|
embedding vector(${dim}) NOT NULL,
|
|
191
201
|
"lastModified" DOUBLE PRECISION,
|
|
192
202
|
"contentHash" VARCHAR(64),
|
|
193
|
-
"ownerPath" VARCHAR
|
|
203
|
+
"ownerPath" VARCHAR,
|
|
204
|
+
"endLine" INT
|
|
194
205
|
)
|
|
195
206
|
`);
|
|
196
207
|
await this.query(`ALTER TABLE code_chunk ADD COLUMN IF NOT EXISTS "contentHash" varchar(64) NULL`);
|
|
197
208
|
await this.query(`ALTER TABLE code_chunk ADD COLUMN IF NOT EXISTS "ownerPath" varchar NULL`);
|
|
209
|
+
await this.query(`ALTER TABLE code_chunk ADD COLUMN IF NOT EXISTS "endLine" integer NULL`);
|
|
198
210
|
await this.query(`CREATE INDEX IF NOT EXISTS idx_code_chunk_embedding ON code_chunk USING hnsw (embedding vector_cosine_ops)`);
|
|
199
211
|
await this.query(`CREATE INDEX IF NOT EXISTS idx_code_chunk_service_file ON code_chunk ("serviceName", "filePath")`);
|
|
200
212
|
}
|
|
201
|
-
/** Drop and recreate `code_chunk` at `dimensions` — used on a dimension change. */
|
|
202
213
|
async recreateChunkTable(dimensions) {
|
|
203
214
|
const dim = this.assertDim(dimensions);
|
|
204
215
|
await this.query(`DROP TABLE IF EXISTS code_chunk`);
|
|
@@ -211,7 +222,6 @@ class DatabaseService {
|
|
|
211
222
|
return row ? { provider: row.provider, model: row.model, dimensions: Number(row.dimensions) } : null;
|
|
212
223
|
}
|
|
213
224
|
catch {
|
|
214
|
-
// Table absent (un-migrated DB) — treat as "no metadata".
|
|
215
225
|
return null;
|
|
216
226
|
}
|
|
217
227
|
}
|
|
@@ -237,8 +247,6 @@ class DatabaseService {
|
|
|
237
247
|
async deleteFiles(project, filePaths) {
|
|
238
248
|
if (filePaths.length === 0)
|
|
239
249
|
return;
|
|
240
|
-
// PostgreSQL limits ~32 767 bind params per statement; OR queries bind the
|
|
241
|
-
// array twice (fromFile + calleeFile), so cap each batch at 10 000 entries.
|
|
242
250
|
const BATCH = 10_000;
|
|
243
251
|
await this.transaction(async (tx) => {
|
|
244
252
|
for (let i = 0; i < filePaths.length; i += BATCH) {
|
|
@@ -268,51 +276,6 @@ class DatabaseService {
|
|
|
268
276
|
await tx.delete(db_1.codeDependency).where((0, drizzle_orm_1.eq)(db_1.codeDependency.project, name));
|
|
269
277
|
});
|
|
270
278
|
}
|
|
271
|
-
async listProjectsWithIndexRows() {
|
|
272
|
-
const rows = await this.query(`SELECT DISTINCT name FROM (
|
|
273
|
-
SELECT "serviceName" AS name FROM code_chunk
|
|
274
|
-
UNION
|
|
275
|
-
SELECT project AS name FROM code_symbol
|
|
276
|
-
) t`);
|
|
277
|
-
return rows.map(r => r.name);
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Among `projectNames` (or every project with rows when null), those with at
|
|
281
|
-
* least one row in `code_chunk`/`code_symbol` and a `symbol_index_version`
|
|
282
|
-
* below `CURRENT_SYMBOL_INDEX_VERSION` (a missing row counts as version 1).
|
|
283
|
-
* A missing `symbol_index_version` table (un-migrated DB, `rag-mcp`/`rag-web`
|
|
284
|
-
* bootstrapped with `initDb`) counts as "no marker rows" — every project with
|
|
285
|
-
* rows is then outdated. Any other database error propagates.
|
|
286
|
-
*/
|
|
287
|
-
async listOutdatedProjects(projectNames) {
|
|
288
|
-
const rowsUnion = `
|
|
289
|
-
SELECT "serviceName" AS name FROM code_chunk
|
|
290
|
-
UNION
|
|
291
|
-
SELECT project AS name FROM code_symbol
|
|
292
|
-
`;
|
|
293
|
-
const filterSql = projectNames ? 'AND t.name = ANY($1)' : '';
|
|
294
|
-
const params = projectNames ? [projectNames] : [];
|
|
295
|
-
try {
|
|
296
|
-
const rows = await this.query(`SELECT DISTINCT t.name FROM (${rowsUnion}) t
|
|
297
|
-
WHERE NOT EXISTS (
|
|
298
|
-
SELECT 1 FROM symbol_index_version v
|
|
299
|
-
WHERE v.project = t.name AND v.version >= ${exports.CURRENT_SYMBOL_INDEX_VERSION}
|
|
300
|
-
)
|
|
301
|
-
${filterSql}`, params);
|
|
302
|
-
return rows.map(r => r.name);
|
|
303
|
-
}
|
|
304
|
-
catch (err) {
|
|
305
|
-
if (!/relation "symbol_index_version" does not exist/i.test(err.message))
|
|
306
|
-
throw err;
|
|
307
|
-
const rows = await this.query(`SELECT DISTINCT t.name FROM (${rowsUnion}) t ${projectNames ? 'WHERE t.name = ANY($1)' : ''}`, params);
|
|
308
|
-
return rows.map(r => r.name);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
async upsertSymbolIndexVersion(project) {
|
|
312
|
-
await this.query(`INSERT INTO symbol_index_version (project, version) VALUES ($1, $2)
|
|
313
|
-
ON CONFLICT (project) DO UPDATE SET version = EXCLUDED.version`, [project, exports.CURRENT_SYMBOL_INDEX_VERSION]);
|
|
314
|
-
}
|
|
315
|
-
/** Guard against SQL injection — the dimension is interpolated into DDL. */
|
|
316
279
|
assertDim(dimensions) {
|
|
317
280
|
if (!Number.isInteger(dimensions) || dimensions <= 0 || dimensions > 2000) {
|
|
318
281
|
throw new Error(`Invalid vector dimension: ${dimensions} (must be an integer 1–2000)`);
|
|
@@ -326,7 +289,7 @@ class DatabaseService {
|
|
|
326
289
|
versionNum = Number(rows[0]?.v);
|
|
327
290
|
}
|
|
328
291
|
catch (err) {
|
|
329
|
-
throw new Error(`Failed to read PostgreSQL server_version_num (requires PostgreSQL 15+): ${err.message}
|
|
292
|
+
throw new Error(`Failed to read PostgreSQL server_version_num (requires PostgreSQL 15+): ${err.message}`, { cause: err });
|
|
330
293
|
}
|
|
331
294
|
if (!Number.isFinite(versionNum) || versionNum < MIN_PG_VERSION_NUM) {
|
|
332
295
|
throw new Error(`PostgreSQL 15+ is required (server_version_num=${versionNum}) — ` +
|
|
@@ -360,7 +323,7 @@ class DatabaseService {
|
|
|
360
323
|
catch (err) {
|
|
361
324
|
await client.end().catch(() => { });
|
|
362
325
|
const msg = err instanceof Error ? err.message : String(err);
|
|
363
|
-
throw new Error(`Failed to ensure database "${database}" exists: ${msg}
|
|
326
|
+
throw new Error(`Failed to ensure database "${database}" exists: ${msg}`, { cause: err });
|
|
364
327
|
}
|
|
365
328
|
}
|
|
366
329
|
}
|
|
@@ -2,8 +2,4 @@ import type { Config } from '../config';
|
|
|
2
2
|
import type { IEmbedder } from '../interfaces/IEmbedder';
|
|
3
3
|
import type { ILogger } from '../interfaces/ILogger';
|
|
4
4
|
import { type EmbedderDeps } from './OpenAICompatibleEmbedder';
|
|
5
|
-
/**
|
|
6
|
-
* Construct the `IEmbedder` implementation selected by `config.embedding.provider`.
|
|
7
|
-
* The default (`infinity`) is the recommended local backend.
|
|
8
|
-
*/
|
|
9
5
|
export declare function createEmbedder(config: Config, logger?: ILogger, deps?: EmbedderDeps): IEmbedder;
|
|
@@ -5,10 +5,6 @@ const LoggerService_1 = require("./LoggerService");
|
|
|
5
5
|
const OpenAICompatibleEmbedder_1 = require("./OpenAICompatibleEmbedder");
|
|
6
6
|
const InfinityEmbedder_1 = require("./InfinityEmbedder");
|
|
7
7
|
const VoyageEmbedder_1 = require("./VoyageEmbedder");
|
|
8
|
-
/**
|
|
9
|
-
* Construct the `IEmbedder` implementation selected by `config.embedding.provider`.
|
|
10
|
-
* The default (`infinity`) is the recommended local backend.
|
|
11
|
-
*/
|
|
12
8
|
function createEmbedder(config, logger = LoggerService_1.LoggerService.silent(), deps = {}) {
|
|
13
9
|
switch (config.embedding.provider) {
|
|
14
10
|
case 'openai-compatible':
|
|
@@ -18,7 +14,6 @@ function createEmbedder(config, logger = LoggerService_1.LoggerService.silent(),
|
|
|
18
14
|
case 'voyage':
|
|
19
15
|
return new VoyageEmbedder_1.VoyageEmbedder(config, logger, deps);
|
|
20
16
|
default: {
|
|
21
|
-
// The Zod enum should already reject this; guard anyway for a clear message.
|
|
22
17
|
const p = config.embedding.provider;
|
|
23
18
|
throw new Error(`Unknown embedding provider: "${p}". Expected one of: openai-compatible, voyage, infinity.`);
|
|
24
19
|
}
|
|
@@ -3,6 +3,7 @@ import type { IEmbedder } from '../interfaces/IEmbedder';
|
|
|
3
3
|
import type { IAstParser } from '../interfaces/IAstParser';
|
|
4
4
|
import type { IChunker } from '../interfaces/IChunker';
|
|
5
5
|
import type { IDatabase } from '../interfaces/IDatabase';
|
|
6
|
+
import type { DiscoveredProject } from '../interfaces/IProjectDiscovery';
|
|
6
7
|
import type { ILogger } from '../interfaces/ILogger';
|
|
7
8
|
import type { IndexMeta } from '../interfaces/IDatabase';
|
|
8
9
|
export interface IndexStats {
|
|
@@ -22,16 +23,6 @@ export declare class IndexerService {
|
|
|
22
23
|
private config;
|
|
23
24
|
private logger;
|
|
24
25
|
constructor(db: IDatabase, embedder: IEmbedder, ast: IAstParser, chunker: IChunker, config: Config, logger?: ILogger);
|
|
25
|
-
/**
|
|
26
|
-
* Resolve the active embedding dimension (config override → registry → probe),
|
|
27
|
-
* reconcile it against `index_meta`, and prepare `code_chunk` accordingly:
|
|
28
|
-
* a dimension change drops+recreates the table; a same-dimension model/provider
|
|
29
|
-
* change clears its rows (vector spaces are not comparable across models); an
|
|
30
|
-
* unchanged model keeps the rows for incremental indexing. Back-compat: an
|
|
31
|
-
* existing populated table with no `index_meta` row is treated as the legacy
|
|
32
|
-
* `ollama`/`bge-m3`/1024 index. Writes `index_meta` to reflect the active model.
|
|
33
|
-
* Call once per run, before the scan loop.
|
|
34
|
-
*/
|
|
35
26
|
prepareEmbeddingSchema(): Promise<IndexMeta>;
|
|
36
27
|
private reconcileIndex;
|
|
37
28
|
private countChunks;
|
|
@@ -39,6 +30,7 @@ export declare class IndexerService {
|
|
|
39
30
|
scanAndIndex(dir: string, serviceName: string, force?: boolean, signal?: AbortSignal, preCollectedFiles?: string[], opts?: {
|
|
40
31
|
rootTsConfigPath?: string;
|
|
41
32
|
}): Promise<IndexStats>;
|
|
33
|
+
scanProjects(targets: DiscoveredProject[], force: boolean, signal: AbortSignal, filesPerProject: string[][]): Promise<IndexStats[]>;
|
|
42
34
|
pruneProjects(keep: string[]): Promise<{
|
|
43
35
|
removed: string[];
|
|
44
36
|
failed: string[];
|
|
@@ -40,13 +40,17 @@ const crypto_1 = require("crypto");
|
|
|
40
40
|
const cli_progress_1 = require("cli-progress");
|
|
41
41
|
const drizzle_orm_1 = require("drizzle-orm");
|
|
42
42
|
const owner_path_1 = require("../owner-path");
|
|
43
|
+
const DeclarationTree_1 = require("../declarations/DeclarationTree");
|
|
44
|
+
const SourceLines_1 = require("../declarations/SourceLines");
|
|
43
45
|
const enriched_prompt_1 = require("../enriched-prompt");
|
|
44
46
|
const symbol_rows_1 = require("../symbol-rows");
|
|
45
47
|
const db_1 = require("../db");
|
|
46
48
|
const file_utils_1 = require("../file-utils");
|
|
47
49
|
const LoggerService_1 = require("./LoggerService");
|
|
48
50
|
const constants_1 = require("../constants");
|
|
51
|
+
const error_record_1 = require("../error-record");
|
|
49
52
|
const SCHEMA_EXTENSIONS = /\.(prisma|graphql|gql)$/;
|
|
53
|
+
const JSX_EXTENSIONS = /\.(tsx|jsx|js)$/;
|
|
50
54
|
class IndexerService {
|
|
51
55
|
db;
|
|
52
56
|
embedder;
|
|
@@ -62,16 +66,6 @@ class IndexerService {
|
|
|
62
66
|
this.config = config;
|
|
63
67
|
this.logger = logger;
|
|
64
68
|
}
|
|
65
|
-
/**
|
|
66
|
-
* Resolve the active embedding dimension (config override → registry → probe),
|
|
67
|
-
* reconcile it against `index_meta`, and prepare `code_chunk` accordingly:
|
|
68
|
-
* a dimension change drops+recreates the table; a same-dimension model/provider
|
|
69
|
-
* change clears its rows (vector spaces are not comparable across models); an
|
|
70
|
-
* unchanged model keeps the rows for incremental indexing. Back-compat: an
|
|
71
|
-
* existing populated table with no `index_meta` row is treated as the legacy
|
|
72
|
-
* `ollama`/`bge-m3`/1024 index. Writes `index_meta` to reflect the active model.
|
|
73
|
-
* Call once per run, before the scan loop.
|
|
74
|
-
*/
|
|
75
69
|
async prepareEmbeddingSchema() {
|
|
76
70
|
const { provider, model, dimensions: override } = this.config.embedding;
|
|
77
71
|
const next = {
|
|
@@ -86,13 +80,11 @@ class IndexerService {
|
|
|
86
80
|
if (!meta) {
|
|
87
81
|
const chunkCount = await this.countChunks();
|
|
88
82
|
if (chunkCount === 0) {
|
|
89
|
-
// Fresh index — create the table at the resolved width and record it.
|
|
90
83
|
await this.db.recreateChunkTable(next.dimensions);
|
|
91
84
|
await this.db.writeIndexMeta(next);
|
|
92
85
|
this.logger.debug('IndexerService: prepared fresh index', { ...next });
|
|
93
86
|
return next;
|
|
94
87
|
}
|
|
95
|
-
// Legacy index (pre-index_meta): assume the historical default model.
|
|
96
88
|
await this.reconcileIndex({ provider: 'ollama', model: 'bge-m3', dimensions: 1024 }, next);
|
|
97
89
|
return next;
|
|
98
90
|
}
|
|
@@ -118,9 +110,6 @@ class IndexerService {
|
|
|
118
110
|
return Number(rows[0]?.n ?? 0);
|
|
119
111
|
}
|
|
120
112
|
catch (err) {
|
|
121
|
-
// A missing table means a fresh install → 0. Any other (transient) error
|
|
122
|
-
// must propagate — returning 0 here could wrongly recreate/drop a populated
|
|
123
|
-
// table on the `!meta` path.
|
|
124
113
|
if (/does not exist/i.test(err.message))
|
|
125
114
|
return 0;
|
|
126
115
|
throw err;
|
|
@@ -142,9 +131,6 @@ class IndexerService {
|
|
|
142
131
|
const startTime = Date.now();
|
|
143
132
|
this.logger.debug('IndexerService: scanAndIndex start', { serviceName, dir, force });
|
|
144
133
|
if (force) {
|
|
145
|
-
// Reset incremental state and clear the project's symbol/call rows in one
|
|
146
|
-
// transaction: a file whose re-ingestion later fails must hold no rows at
|
|
147
|
-
// all, never rows in the previous (pre-member-extraction) format.
|
|
148
134
|
await this.db.transaction(async (tx) => {
|
|
149
135
|
await tx.update(db_1.codeChunk)
|
|
150
136
|
.set({ lastModified: null, contentHash: null })
|
|
@@ -250,16 +236,10 @@ class IndexerService {
|
|
|
250
236
|
]);
|
|
251
237
|
}
|
|
252
238
|
catch (err) {
|
|
253
|
-
this.logger.error('IndexerService: mtime refresh batch failed', {
|
|
239
|
+
this.logger.error('IndexerService: mtime refresh batch failed', { err });
|
|
254
240
|
}
|
|
255
241
|
}
|
|
256
242
|
this.ast.clearCache(dir);
|
|
257
|
-
// The marker is written exactly when the scan reaches here without having
|
|
258
|
-
// been interrupted — never on the early-return abort path above, and never
|
|
259
|
-
// when anything in this method throws (the error propagates instead).
|
|
260
|
-
if (!signal?.aborted) {
|
|
261
|
-
await this.db.upsertSymbolIndexVersion(serviceName);
|
|
262
|
-
}
|
|
263
243
|
stats.elapsedSec = Math.round((Date.now() - startTime) / 100) / 10;
|
|
264
244
|
this.logger.debug('IndexerService: project indexed', {
|
|
265
245
|
project: serviceName,
|
|
@@ -271,6 +251,16 @@ class IndexerService {
|
|
|
271
251
|
});
|
|
272
252
|
return stats;
|
|
273
253
|
}
|
|
254
|
+
async scanProjects(targets, force, signal, filesPerProject) {
|
|
255
|
+
const allStats = [];
|
|
256
|
+
for (let i = 0; i < targets.length; i++) {
|
|
257
|
+
if (signal.aborted)
|
|
258
|
+
break;
|
|
259
|
+
const stats = await this.scanAndIndex(targets[i].path, targets[i].name, force, signal, filesPerProject[i], { rootTsConfigPath: targets[i].rootTsConfigPath ?? undefined });
|
|
260
|
+
allStats.push(stats);
|
|
261
|
+
}
|
|
262
|
+
return allStats;
|
|
263
|
+
}
|
|
274
264
|
async pruneProjects(keep) {
|
|
275
265
|
if (keep.length === 0)
|
|
276
266
|
return { removed: [], failed: [] };
|
|
@@ -286,7 +276,7 @@ class IndexerService {
|
|
|
286
276
|
}
|
|
287
277
|
catch (err) {
|
|
288
278
|
console.error(`Failed to prune project ${name}: ${err.message}`);
|
|
289
|
-
this.logger.error('IndexerService: pruneProject failed', { name,
|
|
279
|
+
this.logger.error('IndexerService: pruneProject failed', { name, err });
|
|
290
280
|
failed.push(name);
|
|
291
281
|
}
|
|
292
282
|
}
|
|
@@ -303,21 +293,17 @@ class IndexerService {
|
|
|
303
293
|
.from(db_1.codeChunk)
|
|
304
294
|
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(db_1.codeChunk.serviceName, serviceName), (0, drizzle_orm_1.eq)(db_1.codeChunk.filePath, relFilePath)))
|
|
305
295
|
.limit(1);
|
|
306
|
-
// Fast path: mtime unchanged — skip without reading file
|
|
307
296
|
if (existing?.lastModified === mtimeMs) {
|
|
308
297
|
return { status: 'skipped', chunks: 0 };
|
|
309
298
|
}
|
|
310
299
|
const t0 = Date.now();
|
|
311
300
|
const code = fs.readFileSync(filePath, 'utf-8');
|
|
312
301
|
const hash = IndexerService.hashContent(code);
|
|
313
|
-
// Content unchanged (mtime drifted — DB transfer, git clone, touch)
|
|
314
302
|
if (existing !== undefined && existing.contentHash !== null && existing.contentHash === hash) {
|
|
315
303
|
return { status: 'skipped', chunks: 0, pendingMtimeRefresh: relFilePath };
|
|
316
304
|
}
|
|
317
305
|
const tAst = Date.now();
|
|
318
|
-
const { edges: rawEdges, symbols: rawSymbols, members: rawMembers = [], calls: rawCalls,
|
|
319
|
-
// astMs is near-zero — actual AST time is spent upfront in analyzeProject()
|
|
320
|
-
// Normalize edges to workspace-relative paths
|
|
306
|
+
const { edges: rawEdges, symbols: rawSymbols, members: rawMembers = [], calls: rawCalls, graphqlNames: rawGraphqlNames = [], } = analysis ?? { edges: [], symbols: [], calls: [] };
|
|
321
307
|
const edges = rawEdges
|
|
322
308
|
.filter(e => e.toFile.startsWith(this.config.workspaceRoot))
|
|
323
309
|
.map(e => ({
|
|
@@ -325,7 +311,6 @@ class IndexerService {
|
|
|
325
311
|
fromFile: path.relative(this.config.workspaceRoot, e.fromFile),
|
|
326
312
|
toFile: path.relative(this.config.workspaceRoot, e.toFile),
|
|
327
313
|
}));
|
|
328
|
-
// Normalize call edges to workspace-relative paths; keep only resolved internal calls
|
|
329
314
|
const calls = rawCalls
|
|
330
315
|
.filter(c => c.calleeFile.startsWith(this.config.workspaceRoot))
|
|
331
316
|
.map(c => ({
|
|
@@ -338,26 +323,25 @@ class IndexerService {
|
|
|
338
323
|
line: c.line,
|
|
339
324
|
col: c.col,
|
|
340
325
|
}));
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
const symbolRows = (0, symbol_rows_1.buildSymbolRows)(rawSymbols, rawMembers).map(s => ({ ...s, filePath: relFilePath }));
|
|
326
|
+
const symbolRows = (0, symbol_rows_1.buildSymbolRows)(rawSymbols, rawMembers, rawGraphqlNames).map(s => ({ ...s, filePath: relFilePath }));
|
|
327
|
+
const promptEdges = edges.filter(e => e.depType !== 'import-side-effect');
|
|
344
328
|
const astMs = Date.now() - tAst;
|
|
329
|
+
const jsx = JSX_EXTENSIONS.test(filePath);
|
|
345
330
|
const chunks = await this.chunker.chunk(code, {
|
|
346
331
|
strategy: this.config.indexer.chunkStrategy,
|
|
347
332
|
isSchemaFile: SCHEMA_EXTENSIONS.test(filePath),
|
|
348
|
-
|
|
333
|
+
declarations: analysis?.declarations,
|
|
334
|
+
jsx,
|
|
349
335
|
});
|
|
350
336
|
const relPath = path.relative(projectRoot, filePath);
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
// containing a chunk's start line wins.
|
|
354
|
-
const ownerRanges = rawOwnerRanges;
|
|
337
|
+
const sourceLines = new SourceLines_1.SourceLines(code, { jsx });
|
|
338
|
+
const ownerTree = analysis?.declarations ?? DeclarationTree_1.DeclarationTree.EMPTY;
|
|
355
339
|
const t2 = Date.now();
|
|
356
340
|
const records = [];
|
|
357
341
|
const embedBatchSize = this.config.embedding.batchSize;
|
|
358
342
|
for (let i = 0; i < chunks.length; i += embedBatchSize) {
|
|
359
343
|
const batch = chunks.slice(i, i + embedBatchSize);
|
|
360
|
-
const prompts = batch.map(piece => (0, enriched_prompt_1.getEnrichedPrompt)(piece, relPath, serviceName,
|
|
344
|
+
const prompts = batch.map(piece => (0, enriched_prompt_1.getEnrichedPrompt)(piece, relPath, serviceName, promptEdges, rawSymbols));
|
|
361
345
|
const vectors = await this.embedder.embedBatch(prompts, 'document');
|
|
362
346
|
for (let j = 0; j < batch.length; j++) {
|
|
363
347
|
const piece = batch[j];
|
|
@@ -367,7 +351,8 @@ class IndexerService {
|
|
|
367
351
|
embedding: `[${vectors[j]}]`,
|
|
368
352
|
lastModified: mtimeMs,
|
|
369
353
|
contentHash: hash,
|
|
370
|
-
ownerPath: (0, owner_path_1.
|
|
354
|
+
ownerPath: (0, owner_path_1.ownerOf)(piece, ownerTree, sourceLines),
|
|
355
|
+
endLine: piece.startLine + (piece.content.match(/\n/g)?.length ?? 0),
|
|
371
356
|
});
|
|
372
357
|
}
|
|
373
358
|
}
|
|
@@ -398,9 +383,8 @@ class IndexerService {
|
|
|
398
383
|
return { status: 'indexed', chunks: chunks.length };
|
|
399
384
|
}
|
|
400
385
|
catch (err) {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
this.logger.error('IndexerService: failed to index file', { file: filePath, reason });
|
|
386
|
+
console.error(`\n[indexer] Failed: ${filePath} — ${(0, error_record_1.rootCauseMessage)(err)}`);
|
|
387
|
+
this.logger.error('IndexerService: failed to index file', { file: filePath, err });
|
|
404
388
|
return { status: 'failed', chunks: 0 };
|
|
405
389
|
}
|
|
406
390
|
}
|
|
@@ -4,35 +4,14 @@ import { OpenAICompatibleEmbedder, type EmbedderDeps } from './OpenAICompatibleE
|
|
|
4
4
|
import { serverRoot, probeInfinityHealth, listInfinityModels, type ProvisioningDeps } from './infinity-provisioning';
|
|
5
5
|
export { serverRoot, probeInfinityHealth, listInfinityModels };
|
|
6
6
|
export type { CommandResult } from './infinity-provisioning';
|
|
7
|
-
/** Extra injection seams for `InfinityEmbedder` beyond the shared `EmbedderDeps`. */
|
|
8
7
|
export interface InfinityDeps extends EmbedderDeps, ProvisioningDeps {
|
|
9
|
-
/**
|
|
10
|
-
* Path to the managed docker-compose.yml. Defaults to the file `rag-setup`
|
|
11
|
-
* writes into `~/.config/codesearch-mcp/`. A missing file (or one without an
|
|
12
|
-
* `infinity` service) means "external backend" — the Docker path is skipped.
|
|
13
|
-
*/
|
|
14
8
|
composePath?: string;
|
|
15
9
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Embedder for a local Infinity server. Inherits the OpenAI-style `/embeddings`
|
|
18
|
-
* HTTP path, batching, retry, and reranker wiring from `OpenAICompatibleEmbedder`
|
|
19
|
-
* unchanged — it adds ONLY container-readiness behavior (`ensureModelAvailable`,
|
|
20
|
-
* `listModels`), delegating to the standalone `infinity-provisioning` primitive
|
|
21
|
-
* because Infinity binds its model set at container startup and exposes no
|
|
22
|
-
* runtime model-pull API.
|
|
23
|
-
*/
|
|
24
10
|
export declare class InfinityEmbedder extends OpenAICompatibleEmbedder {
|
|
25
11
|
private readonly base;
|
|
26
12
|
private readonly composePath;
|
|
27
13
|
private readonly provisioningDeps;
|
|
28
14
|
constructor(config: Config, logger?: ILogger, deps?: InfinityDeps);
|
|
29
|
-
/**
|
|
30
|
-
* Index-time embed readiness (see `local-backend-provisioning`): verifies only
|
|
31
|
-
* the embedding model — indexing does not use the reranker, so a missing
|
|
32
|
-
* reranker model never blocks or restarts indexing. Whenever a recreate is
|
|
33
|
-
* needed, the full configured set is written so an already-served reranker
|
|
34
|
-
* model is never dropped. Called by `IndexCommand` before indexing.
|
|
35
|
-
*/
|
|
36
15
|
ensureModelAvailable(): Promise<void>;
|
|
37
16
|
listModels(): Promise<string[]>;
|
|
38
17
|
}
|
|
@@ -42,14 +42,6 @@ Object.defineProperty(exports, "serverRoot", { enumerable: true, get: function (
|
|
|
42
42
|
Object.defineProperty(exports, "probeInfinityHealth", { enumerable: true, get: function () { return infinity_provisioning_1.probeInfinityHealth; } });
|
|
43
43
|
Object.defineProperty(exports, "listInfinityModels", { enumerable: true, get: function () { return infinity_provisioning_1.listInfinityModels; } });
|
|
44
44
|
const path = __importStar(require("path"));
|
|
45
|
-
/**
|
|
46
|
-
* Embedder for a local Infinity server. Inherits the OpenAI-style `/embeddings`
|
|
47
|
-
* HTTP path, batching, retry, and reranker wiring from `OpenAICompatibleEmbedder`
|
|
48
|
-
* unchanged — it adds ONLY container-readiness behavior (`ensureModelAvailable`,
|
|
49
|
-
* `listModels`), delegating to the standalone `infinity-provisioning` primitive
|
|
50
|
-
* because Infinity binds its model set at container startup and exposes no
|
|
51
|
-
* runtime model-pull API.
|
|
52
|
-
*/
|
|
53
45
|
class InfinityEmbedder extends OpenAICompatibleEmbedder_1.OpenAICompatibleEmbedder {
|
|
54
46
|
base;
|
|
55
47
|
composePath;
|
|
@@ -65,13 +57,6 @@ class InfinityEmbedder extends OpenAICompatibleEmbedder_1.OpenAICompatibleEmbedd
|
|
|
65
57
|
readinessTimeoutMs: deps.readinessTimeoutMs,
|
|
66
58
|
};
|
|
67
59
|
}
|
|
68
|
-
/**
|
|
69
|
-
* Index-time embed readiness (see `local-backend-provisioning`): verifies only
|
|
70
|
-
* the embedding model — indexing does not use the reranker, so a missing
|
|
71
|
-
* reranker model never blocks or restarts indexing. Whenever a recreate is
|
|
72
|
-
* needed, the full configured set is written so an already-served reranker
|
|
73
|
-
* model is never dropped. Called by `IndexCommand` before indexing.
|
|
74
|
-
*/
|
|
75
60
|
async ensureModelAvailable() {
|
|
76
61
|
await (0, infinity_provisioning_1.ensureBackendReady)({
|
|
77
62
|
baseURL: this.config.embedding.baseURL,
|
|
@@ -3,17 +3,19 @@ import type { ILogger } from '../interfaces/ILogger';
|
|
|
3
3
|
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
4
4
|
export declare class LoggerService implements ILogger {
|
|
5
5
|
private readonly logger;
|
|
6
|
-
private readonly
|
|
7
|
-
constructor(
|
|
6
|
+
private readonly context;
|
|
7
|
+
private constructor();
|
|
8
8
|
static silent(): LoggerService;
|
|
9
9
|
static fromConfig(cfg: {
|
|
10
10
|
level: string;
|
|
11
11
|
dir?: string;
|
|
12
|
-
}, name?: string): LoggerService;
|
|
13
|
-
|
|
12
|
+
}, name?: string, bindings?: Record<string, unknown>): LoggerService;
|
|
13
|
+
static toStream(level: LogLevel, stream: pino.DestinationStream, bindings?: Record<string, unknown>): LoggerService;
|
|
14
|
+
private static fileTransport;
|
|
15
|
+
private static build;
|
|
14
16
|
debug(msg: string, data?: Record<string, unknown>): void;
|
|
15
17
|
info(msg: string, data?: Record<string, unknown>): void;
|
|
16
18
|
warn(msg: string, data?: Record<string, unknown>): void;
|
|
17
19
|
error(msg: string, data?: Record<string, unknown>): void;
|
|
18
|
-
|
|
20
|
+
withContext<T>(context: Record<string, unknown>, fn: () => Promise<T>): Promise<T>;
|
|
19
21
|
}
|