@rce-mcp/retrieval-core 0.1.0

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.
@@ -0,0 +1,116 @@
1
+ export declare const REMOTE_SYNC_STATE_MODE: "remote_delta_v1";
2
+ export declare const DEFAULT_REMOTE_SYNC_MAX_FILE_SIZE_BYTES = 1000000;
3
+ export interface RemoteSyncUploadCandidate {
4
+ path: string;
5
+ content: string;
6
+ language?: string;
7
+ }
8
+ export interface RemoteSyncProjectFileStat {
9
+ path: string;
10
+ full_path: string;
11
+ size: number;
12
+ mtime_ms: number;
13
+ language?: string;
14
+ }
15
+ export interface RemoteSyncStateEntry {
16
+ content_hash: string;
17
+ size: number;
18
+ mtime_ms: number;
19
+ language?: string;
20
+ }
21
+ export interface RemoteSyncStateFile {
22
+ mode: typeof REMOTE_SYNC_STATE_MODE;
23
+ workspace_id?: string;
24
+ last_index_version?: string;
25
+ files: Record<string, RemoteSyncStateEntry>;
26
+ updated_at: string;
27
+ }
28
+ export interface RemoteSyncDeltaPayload {
29
+ upsert_files: RemoteSyncUploadCandidate[];
30
+ deleted_paths: string[];
31
+ }
32
+ export interface RemoteSyncDeltaBatch {
33
+ upsert_files: RemoteSyncUploadCandidate[];
34
+ deleted_paths: string[];
35
+ approx_bytes: number;
36
+ }
37
+ export interface BuildRemoteSyncDeltaResult {
38
+ delta: RemoteSyncDeltaPayload;
39
+ upsert_state_entries: Record<string, RemoteSyncStateEntry>;
40
+ next_files: Record<string, RemoteSyncStateEntry>;
41
+ }
42
+ export interface RemoteSyncScanOptions {
43
+ max_file_size_bytes?: number;
44
+ excluded_dirs?: Set<string>;
45
+ excluded_files?: Set<string>;
46
+ excluded_file_suffixes?: Set<string>;
47
+ }
48
+ export declare class RemoteSyncHttpResponseError extends Error {
49
+ readonly status: number;
50
+ readonly payload?: unknown | undefined;
51
+ constructor(message: string, status: number, payload?: unknown | undefined);
52
+ }
53
+ export interface RunRemoteDeltaSyncInput {
54
+ project_root_path: string;
55
+ scan_root_path?: string;
56
+ workspace_id?: string;
57
+ previous_state?: RemoteSyncStateFile;
58
+ force_full_upsert?: boolean;
59
+ max_body_bytes: number;
60
+ retries?: number;
61
+ initial_delay_ms?: number;
62
+ stale_base_error?: (error: unknown) => boolean;
63
+ persist_state?: (state: RemoteSyncStateFile) => Promise<void>;
64
+ push_delta: (request: {
65
+ workspace_id?: string;
66
+ project_root_path: string;
67
+ base_index_version?: string;
68
+ upsert_files: RemoteSyncUploadCandidate[];
69
+ deleted_paths: string[];
70
+ }) => Promise<{
71
+ workspace_id?: string;
72
+ index_version?: string;
73
+ }>;
74
+ }
75
+ export interface RunRemoteDeltaSyncResult {
76
+ state: RemoteSyncStateFile;
77
+ changed: boolean;
78
+ workspace_id?: string;
79
+ index_version?: string;
80
+ applied_delta: {
81
+ upsert_files: number;
82
+ deleted_paths: number;
83
+ };
84
+ }
85
+ export declare function collectProjectFileStats(project_root_path: string, options?: RemoteSyncScanOptions): Promise<Map<string, RemoteSyncProjectFileStat>>;
86
+ export declare function collectUploadCandidates(project_root_path: string, options?: RemoteSyncScanOptions): Promise<RemoteSyncUploadCandidate[]>;
87
+ export declare function buildRemoteSyncDeltaFromState(input: {
88
+ project_root_path: string;
89
+ previous_state?: RemoteSyncStateFile;
90
+ force_full_upsert: boolean;
91
+ options?: RemoteSyncScanOptions;
92
+ }): Promise<BuildRemoteSyncDeltaResult>;
93
+ export declare function estimateRemoteSyncDeltaRequestSize(input: {
94
+ project_root_path: string;
95
+ workspace_id?: string;
96
+ base_index_version?: string;
97
+ upsert_files: RemoteSyncUploadCandidate[];
98
+ deleted_paths: string[];
99
+ }): number;
100
+ export declare function splitRemoteSyncDeltaIntoBatches(input: {
101
+ project_root_path: string;
102
+ workspace_id?: string;
103
+ base_index_version?: string;
104
+ delta: RemoteSyncDeltaPayload;
105
+ max_body_bytes: number;
106
+ }): RemoteSyncDeltaBatch[];
107
+ export declare function readRemoteSyncState(path: string): Promise<RemoteSyncStateFile | undefined>;
108
+ export declare function writeRemoteSyncState(path: string, state: RemoteSyncStateFile): Promise<void>;
109
+ export declare function isStaleBaseIndexError(error: unknown): boolean;
110
+ export declare function isDeltaUnsupportedError(error: unknown): boolean;
111
+ export declare function retryWithBackoff<T>(input: {
112
+ fn: () => Promise<T>;
113
+ retries: number;
114
+ initial_delay_ms: number;
115
+ }): Promise<T>;
116
+ export declare function runRemoteDeltaSync(input: RunRemoteDeltaSyncInput): Promise<RunRemoteDeltaSyncResult>;
@@ -0,0 +1,476 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync } from "node:fs";
3
+ import { readdir, readFile, stat, writeFile } from "node:fs/promises";
4
+ import { join, relative, resolve } from "node:path";
5
+ export const REMOTE_SYNC_STATE_MODE = "remote_delta_v1";
6
+ export const DEFAULT_REMOTE_SYNC_MAX_FILE_SIZE_BYTES = 1_000_000;
7
+ const DEFAULT_EXCLUDED_DIRS = new Set([
8
+ ".cache",
9
+ ".git",
10
+ ".next",
11
+ ".nuxt",
12
+ ".rce",
13
+ ".rce-tool",
14
+ ".svelte-kit",
15
+ ".turbo",
16
+ "build",
17
+ "coverage",
18
+ "dist",
19
+ "node_modules",
20
+ "out",
21
+ "target"
22
+ ]);
23
+ const DEFAULT_EXCLUDED_FILES = new Set([
24
+ "bun.lock",
25
+ "bun.lockb",
26
+ "Cargo.lock",
27
+ "composer.lock",
28
+ "Gemfile.lock",
29
+ "package-lock.json",
30
+ "Pipfile.lock",
31
+ "pnpm-lock.yaml",
32
+ "yarn.lock"
33
+ ]);
34
+ const DEFAULT_EXCLUDED_FILE_SUFFIXES = new Set([".min.js", ".min.css", ".map"]);
35
+ export class RemoteSyncHttpResponseError extends Error {
36
+ status;
37
+ payload;
38
+ constructor(message, status, payload) {
39
+ super(message);
40
+ this.status = status;
41
+ this.payload = payload;
42
+ }
43
+ }
44
+ function nowIso() {
45
+ return new Date().toISOString();
46
+ }
47
+ function extensionToLanguage(path) {
48
+ if (path.endsWith(".ts") || path.endsWith(".tsx"))
49
+ return "typescript";
50
+ if (path.endsWith(".js") || path.endsWith(".jsx"))
51
+ return "javascript";
52
+ if (path.endsWith(".py"))
53
+ return "python";
54
+ if (path.endsWith(".go"))
55
+ return "go";
56
+ if (path.endsWith(".rs"))
57
+ return "rust";
58
+ if (path.endsWith(".java"))
59
+ return "java";
60
+ if (path.endsWith(".json"))
61
+ return "json";
62
+ if (path.endsWith(".md"))
63
+ return "markdown";
64
+ if (path.endsWith(".yml") || path.endsWith(".yaml"))
65
+ return "yaml";
66
+ return undefined;
67
+ }
68
+ function looksBinary(content) {
69
+ return content.includes("\0");
70
+ }
71
+ function sha256Text(value) {
72
+ return createHash("sha256").update(value).digest("hex");
73
+ }
74
+ function shouldExcludeFile(path, excludedFiles, excludedSuffixes) {
75
+ const lower = path.toLowerCase();
76
+ if (excludedFiles.has(path) || excludedFiles.has(lower)) {
77
+ return true;
78
+ }
79
+ for (const suffix of excludedSuffixes) {
80
+ if (lower.endsWith(suffix)) {
81
+ return true;
82
+ }
83
+ }
84
+ return false;
85
+ }
86
+ function resolveScanOptions(options) {
87
+ return {
88
+ max_file_size_bytes: options?.max_file_size_bytes ?? DEFAULT_REMOTE_SYNC_MAX_FILE_SIZE_BYTES,
89
+ excluded_dirs: options?.excluded_dirs ?? DEFAULT_EXCLUDED_DIRS,
90
+ excluded_files: options?.excluded_files ?? DEFAULT_EXCLUDED_FILES,
91
+ excluded_file_suffixes: options?.excluded_file_suffixes ?? DEFAULT_EXCLUDED_FILE_SUFFIXES
92
+ };
93
+ }
94
+ export async function collectProjectFileStats(project_root_path, options) {
95
+ const root = resolve(project_root_path);
96
+ const resolvedOptions = resolveScanOptions(options);
97
+ const output = new Map();
98
+ async function walk(dir) {
99
+ const entries = await readdir(dir, { withFileTypes: true });
100
+ for (const entry of entries) {
101
+ if (entry.isDirectory()) {
102
+ if (resolvedOptions.excluded_dirs.has(entry.name)) {
103
+ continue;
104
+ }
105
+ await walk(join(dir, entry.name));
106
+ continue;
107
+ }
108
+ if (!entry.isFile()) {
109
+ continue;
110
+ }
111
+ if (shouldExcludeFile(entry.name, resolvedOptions.excluded_files, resolvedOptions.excluded_file_suffixes)) {
112
+ continue;
113
+ }
114
+ const fullPath = join(dir, entry.name);
115
+ const fileStat = await stat(fullPath);
116
+ if (fileStat.size > resolvedOptions.max_file_size_bytes) {
117
+ continue;
118
+ }
119
+ const repoPath = relative(root, fullPath).replace(/\\/g, "/");
120
+ output.set(repoPath, {
121
+ path: repoPath,
122
+ full_path: fullPath,
123
+ size: fileStat.size,
124
+ mtime_ms: Math.trunc(fileStat.mtimeMs),
125
+ language: extensionToLanguage(repoPath)
126
+ });
127
+ }
128
+ }
129
+ await walk(root);
130
+ return output;
131
+ }
132
+ export async function collectUploadCandidates(project_root_path, options) {
133
+ const stats = await collectProjectFileStats(project_root_path, options);
134
+ const output = [];
135
+ for (const repoPath of [...stats.keys()].sort((a, b) => a.localeCompare(b))) {
136
+ const fileStat = stats.get(repoPath);
137
+ let content;
138
+ try {
139
+ content = await readFile(fileStat.full_path, "utf8");
140
+ }
141
+ catch {
142
+ continue;
143
+ }
144
+ if (looksBinary(content)) {
145
+ continue;
146
+ }
147
+ output.push({
148
+ path: repoPath,
149
+ content,
150
+ ...(fileStat.language ? { language: fileStat.language } : {})
151
+ });
152
+ }
153
+ return output;
154
+ }
155
+ export async function buildRemoteSyncDeltaFromState(input) {
156
+ const projectFiles = await collectProjectFileStats(input.project_root_path, input.options);
157
+ const previousFiles = input.previous_state?.files ?? {};
158
+ const upsertFiles = [];
159
+ const deletedPaths = [];
160
+ const upsertStateEntries = {};
161
+ const nextFiles = {};
162
+ const sortedPaths = [...projectFiles.keys()].sort((a, b) => a.localeCompare(b));
163
+ for (const repoPath of sortedPaths) {
164
+ const projectFile = projectFiles.get(repoPath);
165
+ const previous = previousFiles[repoPath];
166
+ const statChanged = !previous ||
167
+ previous.size !== projectFile.size ||
168
+ previous.mtime_ms !== projectFile.mtime_ms ||
169
+ input.force_full_upsert;
170
+ if (!statChanged) {
171
+ nextFiles[repoPath] = previous;
172
+ continue;
173
+ }
174
+ let content;
175
+ try {
176
+ content = await readFile(projectFile.full_path, "utf8");
177
+ }
178
+ catch {
179
+ if (previous) {
180
+ nextFiles[repoPath] = previous;
181
+ }
182
+ continue;
183
+ }
184
+ if (looksBinary(content)) {
185
+ if (previous) {
186
+ nextFiles[repoPath] = previous;
187
+ }
188
+ continue;
189
+ }
190
+ const contentHash = sha256Text(content);
191
+ const nextEntry = {
192
+ content_hash: contentHash,
193
+ size: projectFile.size,
194
+ mtime_ms: projectFile.mtime_ms,
195
+ ...(projectFile.language ? { language: projectFile.language } : {})
196
+ };
197
+ nextFiles[repoPath] = nextEntry;
198
+ if (!input.force_full_upsert && previous?.content_hash === contentHash) {
199
+ continue;
200
+ }
201
+ upsertFiles.push({
202
+ path: repoPath,
203
+ content,
204
+ ...(projectFile.language ? { language: projectFile.language } : {})
205
+ });
206
+ upsertStateEntries[repoPath] = nextEntry;
207
+ }
208
+ for (const previousPath of Object.keys(previousFiles)) {
209
+ if (!projectFiles.has(previousPath)) {
210
+ deletedPaths.push(previousPath);
211
+ }
212
+ }
213
+ return {
214
+ delta: {
215
+ upsert_files: upsertFiles,
216
+ deleted_paths: deletedPaths
217
+ },
218
+ upsert_state_entries: upsertStateEntries,
219
+ next_files: nextFiles
220
+ };
221
+ }
222
+ export function estimateRemoteSyncDeltaRequestSize(input) {
223
+ const payload = {
224
+ project_root_path: input.project_root_path,
225
+ ...(input.workspace_id ? { workspace_id: input.workspace_id } : {}),
226
+ ...(input.base_index_version ? { base_index_version: input.base_index_version } : {}),
227
+ upsert_files: input.upsert_files.map((file) => ({
228
+ path: file.path,
229
+ content: file.content,
230
+ ...(file.language ? { language: file.language } : {})
231
+ })),
232
+ deleted_paths: input.deleted_paths
233
+ };
234
+ return Buffer.byteLength(JSON.stringify(payload), "utf8");
235
+ }
236
+ export function splitRemoteSyncDeltaIntoBatches(input) {
237
+ const budget = Math.max(256 * 1024, Math.floor(input.max_body_bytes * 0.8));
238
+ const upserts = [...input.delta.upsert_files].sort((a, b) => a.path.localeCompare(b.path));
239
+ const deleted = [...new Set(input.delta.deleted_paths)].sort((a, b) => a.localeCompare(b));
240
+ const batches = [];
241
+ let currentUpserts = [];
242
+ let currentDeleted = [];
243
+ const flush = () => {
244
+ if (currentUpserts.length === 0 && currentDeleted.length === 0) {
245
+ return;
246
+ }
247
+ batches.push({
248
+ upsert_files: currentUpserts,
249
+ deleted_paths: currentDeleted,
250
+ approx_bytes: estimateRemoteSyncDeltaRequestSize({
251
+ project_root_path: input.project_root_path,
252
+ workspace_id: input.workspace_id,
253
+ base_index_version: input.base_index_version,
254
+ upsert_files: currentUpserts,
255
+ deleted_paths: currentDeleted
256
+ })
257
+ });
258
+ currentUpserts = [];
259
+ currentDeleted = [];
260
+ };
261
+ const canFit = (nextUpserts, nextDeleted) => estimateRemoteSyncDeltaRequestSize({
262
+ project_root_path: input.project_root_path,
263
+ workspace_id: input.workspace_id,
264
+ base_index_version: input.base_index_version,
265
+ upsert_files: nextUpserts,
266
+ deleted_paths: nextDeleted
267
+ }) <= budget;
268
+ for (const file of upserts) {
269
+ const candidateUpserts = [...currentUpserts, file];
270
+ if (canFit(candidateUpserts, currentDeleted)) {
271
+ currentUpserts = candidateUpserts;
272
+ continue;
273
+ }
274
+ flush();
275
+ if (!canFit([file], [])) {
276
+ throw new Error(`delta upsert payload too large for path ${file.path}`);
277
+ }
278
+ currentUpserts = [file];
279
+ }
280
+ for (const path of deleted) {
281
+ const candidateDeleted = [...currentDeleted, path];
282
+ if (canFit(currentUpserts, candidateDeleted)) {
283
+ currentDeleted = candidateDeleted;
284
+ continue;
285
+ }
286
+ flush();
287
+ if (!canFit([], [path])) {
288
+ throw new Error(`delta delete payload too large for path ${path}`);
289
+ }
290
+ currentDeleted = [path];
291
+ }
292
+ flush();
293
+ return batches;
294
+ }
295
+ export async function readRemoteSyncState(path) {
296
+ if (!existsSync(path)) {
297
+ return undefined;
298
+ }
299
+ try {
300
+ const parsed = JSON.parse(await readFile(path, "utf8"));
301
+ if (!parsed ||
302
+ parsed.mode !== REMOTE_SYNC_STATE_MODE ||
303
+ typeof parsed.files !== "object" ||
304
+ parsed.files === null ||
305
+ Array.isArray(parsed.files)) {
306
+ return undefined;
307
+ }
308
+ return {
309
+ mode: REMOTE_SYNC_STATE_MODE,
310
+ workspace_id: parsed.workspace_id,
311
+ last_index_version: parsed.last_index_version,
312
+ files: parsed.files,
313
+ updated_at: typeof parsed.updated_at === "string" ? parsed.updated_at : nowIso()
314
+ };
315
+ }
316
+ catch {
317
+ return undefined;
318
+ }
319
+ }
320
+ export async function writeRemoteSyncState(path, state) {
321
+ await writeFile(path, JSON.stringify({
322
+ ...state,
323
+ mode: REMOTE_SYNC_STATE_MODE,
324
+ updated_at: nowIso()
325
+ }, null, 2));
326
+ }
327
+ export function isStaleBaseIndexError(error) {
328
+ if (!(error instanceof RemoteSyncHttpResponseError)) {
329
+ return false;
330
+ }
331
+ if (error.status !== 400) {
332
+ return false;
333
+ }
334
+ const message = error.message.toLowerCase();
335
+ return message.includes("invalid_argument") && message.includes("base index version");
336
+ }
337
+ export function isDeltaUnsupportedError(error) {
338
+ if (error instanceof RemoteSyncHttpResponseError) {
339
+ if ([404, 405, 501].includes(error.status)) {
340
+ return true;
341
+ }
342
+ const message = error.message.toLowerCase();
343
+ return message.includes("not_found") && message.includes("push-delta");
344
+ }
345
+ if (error instanceof Error) {
346
+ const message = error.message.toLowerCase();
347
+ return message.includes("push-delta") && (message.includes("not found") || message.includes("404"));
348
+ }
349
+ return false;
350
+ }
351
+ export async function retryWithBackoff(input) {
352
+ let attempt = 0;
353
+ let lastError;
354
+ while (attempt < input.retries) {
355
+ try {
356
+ return await input.fn();
357
+ }
358
+ catch (error) {
359
+ lastError = error;
360
+ attempt += 1;
361
+ if (attempt >= input.retries) {
362
+ break;
363
+ }
364
+ await new Promise((resolveSleep) => setTimeout(resolveSleep, input.initial_delay_ms * 2 ** (attempt - 1)));
365
+ }
366
+ }
367
+ throw lastError;
368
+ }
369
+ export async function runRemoteDeltaSync(input) {
370
+ const retries = input.retries ?? 3;
371
+ const initialDelayMs = input.initial_delay_ms ?? 500;
372
+ const isStaleError = input.stale_base_error ?? isStaleBaseIndexError;
373
+ const execute = async (previousState, forceFullUpsert) => {
374
+ const scanRootPath = input.scan_root_path ?? input.project_root_path;
375
+ const deltaBuild = await buildRemoteSyncDeltaFromState({
376
+ project_root_path: scanRootPath,
377
+ previous_state: previousState,
378
+ force_full_upsert: forceFullUpsert
379
+ });
380
+ const nextWorkspaceId = input.workspace_id ?? previousState?.workspace_id;
381
+ if (deltaBuild.delta.upsert_files.length === 0 && deltaBuild.delta.deleted_paths.length === 0) {
382
+ const unchangedState = {
383
+ mode: REMOTE_SYNC_STATE_MODE,
384
+ workspace_id: nextWorkspaceId,
385
+ last_index_version: previousState?.last_index_version,
386
+ files: deltaBuild.next_files,
387
+ updated_at: nowIso()
388
+ };
389
+ await input.persist_state?.(unchangedState);
390
+ return {
391
+ state: unchangedState,
392
+ changed: false,
393
+ workspace_id: unchangedState.workspace_id,
394
+ index_version: unchangedState.last_index_version,
395
+ applied_delta: {
396
+ upsert_files: 0,
397
+ deleted_paths: 0
398
+ }
399
+ };
400
+ }
401
+ let currentBaseIndexVersion = previousState?.last_index_version;
402
+ let currentWorkspaceId = nextWorkspaceId;
403
+ const progressFiles = { ...(previousState?.files ?? {}) };
404
+ let uploadedCount = 0;
405
+ let deletedCount = 0;
406
+ const batches = splitRemoteSyncDeltaIntoBatches({
407
+ project_root_path: input.project_root_path,
408
+ workspace_id: currentWorkspaceId,
409
+ base_index_version: currentBaseIndexVersion,
410
+ delta: deltaBuild.delta,
411
+ max_body_bytes: input.max_body_bytes
412
+ });
413
+ let latestState;
414
+ for (const batch of batches) {
415
+ const result = await retryWithBackoff({
416
+ retries,
417
+ initial_delay_ms: initialDelayMs,
418
+ fn: async () => input.push_delta({
419
+ workspace_id: currentWorkspaceId,
420
+ project_root_path: input.project_root_path,
421
+ ...(currentBaseIndexVersion ? { base_index_version: currentBaseIndexVersion } : {}),
422
+ upsert_files: batch.upsert_files,
423
+ deleted_paths: batch.deleted_paths
424
+ })
425
+ });
426
+ currentWorkspaceId = result.workspace_id ?? currentWorkspaceId;
427
+ currentBaseIndexVersion = result.index_version ?? currentBaseIndexVersion;
428
+ for (const file of batch.upsert_files) {
429
+ const entry = deltaBuild.upsert_state_entries[file.path];
430
+ if (entry) {
431
+ progressFiles[file.path] = entry;
432
+ }
433
+ }
434
+ for (const path of batch.deleted_paths) {
435
+ delete progressFiles[path];
436
+ }
437
+ uploadedCount += batch.upsert_files.length;
438
+ deletedCount += batch.deleted_paths.length;
439
+ latestState = {
440
+ mode: REMOTE_SYNC_STATE_MODE,
441
+ workspace_id: currentWorkspaceId,
442
+ last_index_version: currentBaseIndexVersion,
443
+ files: progressFiles,
444
+ updated_at: nowIso()
445
+ };
446
+ await input.persist_state?.(latestState);
447
+ }
448
+ const finalState = latestState ?? {
449
+ mode: REMOTE_SYNC_STATE_MODE,
450
+ workspace_id: currentWorkspaceId,
451
+ last_index_version: currentBaseIndexVersion,
452
+ files: progressFiles,
453
+ updated_at: nowIso()
454
+ };
455
+ return {
456
+ state: finalState,
457
+ changed: true,
458
+ workspace_id: currentWorkspaceId,
459
+ index_version: currentBaseIndexVersion,
460
+ applied_delta: {
461
+ upsert_files: uploadedCount,
462
+ deleted_paths: deletedCount
463
+ }
464
+ };
465
+ };
466
+ const forceFullUpsert = input.force_full_upsert ?? false;
467
+ try {
468
+ return await execute(input.previous_state, forceFullUpsert);
469
+ }
470
+ catch (error) {
471
+ if (!forceFullUpsert && input.previous_state && isStaleError(error)) {
472
+ return execute(undefined, true);
473
+ }
474
+ throw error;
475
+ }
476
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@rce-mcp/retrieval-core",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ }
12
+ },
13
+ "dependencies": {
14
+ "@rce-mcp/contracts": "0.1.0",
15
+ "@rce-mcp/data-plane": "0.1.0",
16
+ "@rce-mcp/observability": "0.1.0",
17
+ "tree-sitter": "^0.22.4",
18
+ "tree-sitter-go": "^0.23.4",
19
+ "tree-sitter-javascript": "^0.25.0",
20
+ "tree-sitter-python": "^0.25.0",
21
+ "tree-sitter-typescript": "^0.23.2"
22
+ },
23
+ "devDependencies": {
24
+ "pg-mem": "^3.0.5",
25
+ "tree-sitter-go-v025": "npm:tree-sitter-go@0.25.0",
26
+ "tree-sitter-javascript-v023": "npm:tree-sitter-javascript@0.23.1",
27
+ "tree-sitter-javascript-v025": "npm:tree-sitter-javascript@0.25.0",
28
+ "tree-sitter-python-v023": "npm:tree-sitter-python@0.23.6",
29
+ "tree-sitter-python-v025": "npm:tree-sitter-python@0.25.0",
30
+ "tree-sitter-v025": "npm:tree-sitter@0.25.0",
31
+ "web-tree-sitter": "^0.26.5"
32
+ }
33
+ }