@unlimiting/qsc 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.
Files changed (117) hide show
  1. package/dist/chunker/ast.d.ts +7 -0
  2. package/dist/chunker/ast.d.ts.map +1 -0
  3. package/dist/chunker/ast.js +302 -0
  4. package/dist/chunker/ast.js.map +1 -0
  5. package/dist/chunker/index.d.ts +15 -0
  6. package/dist/chunker/index.d.ts.map +1 -0
  7. package/dist/chunker/index.js +26 -0
  8. package/dist/chunker/index.js.map +1 -0
  9. package/dist/chunker/languages/dart.d.ts +3 -0
  10. package/dist/chunker/languages/dart.d.ts.map +1 -0
  11. package/dist/chunker/languages/dart.js +22 -0
  12. package/dist/chunker/languages/dart.js.map +1 -0
  13. package/dist/chunker/languages/go.d.ts +3 -0
  14. package/dist/chunker/languages/go.d.ts.map +1 -0
  15. package/dist/chunker/languages/go.js +20 -0
  16. package/dist/chunker/languages/go.js.map +1 -0
  17. package/dist/chunker/languages/index.d.ts +12 -0
  18. package/dist/chunker/languages/index.d.ts.map +1 -0
  19. package/dist/chunker/languages/index.js +35 -0
  20. package/dist/chunker/languages/index.js.map +1 -0
  21. package/dist/chunker/languages/kotlin.d.ts +3 -0
  22. package/dist/chunker/languages/kotlin.d.ts.map +1 -0
  23. package/dist/chunker/languages/kotlin.js +23 -0
  24. package/dist/chunker/languages/kotlin.js.map +1 -0
  25. package/dist/chunker/languages/python.d.ts +3 -0
  26. package/dist/chunker/languages/python.d.ts.map +1 -0
  27. package/dist/chunker/languages/python.js +21 -0
  28. package/dist/chunker/languages/python.js.map +1 -0
  29. package/dist/chunker/languages/swift.d.ts +3 -0
  30. package/dist/chunker/languages/swift.d.ts.map +1 -0
  31. package/dist/chunker/languages/swift.js +24 -0
  32. package/dist/chunker/languages/swift.js.map +1 -0
  33. package/dist/chunker/languages/typescript.d.ts +4 -0
  34. package/dist/chunker/languages/typescript.d.ts.map +1 -0
  35. package/dist/chunker/languages/typescript.js +34 -0
  36. package/dist/chunker/languages/typescript.js.map +1 -0
  37. package/dist/chunker/token.d.ts +6 -0
  38. package/dist/chunker/token.d.ts.map +1 -0
  39. package/dist/chunker/token.js +107 -0
  40. package/dist/chunker/token.js.map +1 -0
  41. package/dist/collection.d.ts +22 -0
  42. package/dist/collection.d.ts.map +1 -0
  43. package/dist/collection.js +154 -0
  44. package/dist/collection.js.map +1 -0
  45. package/dist/config/index.d.ts +95 -0
  46. package/dist/config/index.d.ts.map +1 -0
  47. package/dist/config/index.js +103 -0
  48. package/dist/config/index.js.map +1 -0
  49. package/dist/embedder/index.d.ts +14 -0
  50. package/dist/embedder/index.d.ts.map +1 -0
  51. package/dist/embedder/index.js +18 -0
  52. package/dist/embedder/index.js.map +1 -0
  53. package/dist/embedder/local.d.ts +11 -0
  54. package/dist/embedder/local.d.ts.map +1 -0
  55. package/dist/embedder/local.js +60 -0
  56. package/dist/embedder/local.js.map +1 -0
  57. package/dist/embedder/openai.d.ts +10 -0
  58. package/dist/embedder/openai.d.ts.map +1 -0
  59. package/dist/embedder/openai.js +69 -0
  60. package/dist/embedder/openai.js.map +1 -0
  61. package/dist/index.d.ts +3 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +824 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/llm/index.d.ts +17 -0
  66. package/dist/llm/index.d.ts.map +1 -0
  67. package/dist/llm/index.js +18 -0
  68. package/dist/llm/index.js.map +1 -0
  69. package/dist/llm/local.d.ts +10 -0
  70. package/dist/llm/local.d.ts.map +1 -0
  71. package/dist/llm/local.js +76 -0
  72. package/dist/llm/local.js.map +1 -0
  73. package/dist/llm/openai.d.ts +10 -0
  74. package/dist/llm/openai.d.ts.map +1 -0
  75. package/dist/llm/openai.js +76 -0
  76. package/dist/llm/openai.js.map +1 -0
  77. package/dist/mcp.d.ts +3 -0
  78. package/dist/mcp.d.ts.map +1 -0
  79. package/dist/mcp.js +393 -0
  80. package/dist/mcp.js.map +1 -0
  81. package/dist/scanner/git.d.ts +26 -0
  82. package/dist/scanner/git.d.ts.map +1 -0
  83. package/dist/scanner/git.js +134 -0
  84. package/dist/scanner/git.js.map +1 -0
  85. package/dist/scanner/index.d.ts +17 -0
  86. package/dist/scanner/index.d.ts.map +1 -0
  87. package/dist/scanner/index.js +174 -0
  88. package/dist/scanner/index.js.map +1 -0
  89. package/dist/search/bm25.d.ts +17 -0
  90. package/dist/search/bm25.d.ts.map +1 -0
  91. package/dist/search/bm25.js +27 -0
  92. package/dist/search/bm25.js.map +1 -0
  93. package/dist/search/expander.d.ts +12 -0
  94. package/dist/search/expander.d.ts.map +1 -0
  95. package/dist/search/expander.js +60 -0
  96. package/dist/search/expander.js.map +1 -0
  97. package/dist/search/fusion.d.ts +32 -0
  98. package/dist/search/fusion.d.ts.map +1 -0
  99. package/dist/search/fusion.js +80 -0
  100. package/dist/search/fusion.js.map +1 -0
  101. package/dist/search/index.d.ts +61 -0
  102. package/dist/search/index.d.ts.map +1 -0
  103. package/dist/search/index.js +137 -0
  104. package/dist/search/index.js.map +1 -0
  105. package/dist/search/reranker.d.ts +18 -0
  106. package/dist/search/reranker.d.ts.map +1 -0
  107. package/dist/search/reranker.js +56 -0
  108. package/dist/search/reranker.js.map +1 -0
  109. package/dist/search/vector.d.ts +23 -0
  110. package/dist/search/vector.d.ts.map +1 -0
  111. package/dist/search/vector.js +47 -0
  112. package/dist/search/vector.js.map +1 -0
  113. package/dist/store.d.ts +119 -0
  114. package/dist/store.d.ts.map +1 -0
  115. package/dist/store.js +500 -0
  116. package/dist/store.js.map +1 -0
  117. package/package.json +48 -0
package/dist/mcp.js ADDED
@@ -0,0 +1,393 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { z } from "zod";
5
+ import Database from "better-sqlite3";
6
+ import { existsSync, readFileSync } from "node:fs";
7
+ import { resolve } from "node:path";
8
+ import { createStore } from "./store.js";
9
+ import { createSearchPipeline } from "./search/index.js";
10
+ import { createEmbedder } from "./embedder/index.js";
11
+ import { createLLMProvider } from "./llm/index.js";
12
+ import { loadConfig } from "./config/index.js";
13
+ import { resolveCollectionDb, resolveCollectionSourcePath } from "./collection.js";
14
+ // --- Helpers ---
15
+ function resolveDbPathFromCollection(collectionName) {
16
+ if (collectionName) {
17
+ return resolveCollectionDb(collectionName);
18
+ }
19
+ // Fallback: environment variable QSC_COLLECTION
20
+ const envCollection = process.env.QSC_COLLECTION;
21
+ if (envCollection) {
22
+ return resolveCollectionDb(envCollection);
23
+ }
24
+ // Legacy fallback: QSC_DB_PATH
25
+ if (process.env.QSC_DB_PATH) {
26
+ return resolve(process.env.QSC_DB_PATH);
27
+ }
28
+ throw new Error("No collection specified. Set QSC_COLLECTION environment variable, use --collection flag, or set QSC_DB_PATH.");
29
+ }
30
+ function resolveConfigPath(collectionName) {
31
+ const name = collectionName ?? process.env.QSC_COLLECTION;
32
+ if (name) {
33
+ try {
34
+ return resolveCollectionSourcePath(name);
35
+ }
36
+ catch {
37
+ return undefined;
38
+ }
39
+ }
40
+ return undefined;
41
+ }
42
+ function getVersion() {
43
+ try {
44
+ const pkgPath = new URL("../package.json", import.meta.url);
45
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
46
+ return pkg.version ?? "0.1.0";
47
+ }
48
+ catch {
49
+ return "0.1.0";
50
+ }
51
+ }
52
+ function formatBM25Result(r) {
53
+ const lineInfo = r.start_line != null ? `:${r.start_line}-${r.end_line ?? ""}` : "";
54
+ const nameInfo = r.name ? ` (${r.name})` : "";
55
+ const typeInfo = r.chunk_type ? ` [${r.chunk_type}]` : "";
56
+ return [
57
+ `## ${r.file_path}${lineInfo}${nameInfo}${typeInfo}`,
58
+ `Chunk ID: ${r.chunk_id} | rank: ${r.rank}`,
59
+ "```",
60
+ r.content,
61
+ "```",
62
+ ].join("\n");
63
+ }
64
+ function formatSearchResult(r) {
65
+ const lineInfo = r.startLine != null ? `:${r.startLine}-${r.endLine ?? ""}` : "";
66
+ const nameInfo = r.name ? ` (${r.name})` : "";
67
+ const typeInfo = r.chunkType ? ` [${r.chunkType}]` : "";
68
+ const scoreParts = [];
69
+ if (r.scores.bm25 != null)
70
+ scoreParts.push(`bm25=${r.scores.bm25.toFixed(4)}`);
71
+ if (r.scores.vector != null)
72
+ scoreParts.push(`vector=${r.scores.vector.toFixed(4)}`);
73
+ if (r.scores.rrf != null)
74
+ scoreParts.push(`rrf=${r.scores.rrf.toFixed(4)}`);
75
+ if (r.scores.rerank != null)
76
+ scoreParts.push(`rerank=${r.scores.rerank.toFixed(4)}`);
77
+ const scoreDetail = scoreParts.length > 0 ? `\nScores: ${scoreParts.join(", ")}` : "";
78
+ return [
79
+ `## ${r.filePath}${lineInfo}${nameInfo}${typeInfo} | score: ${r.score.toFixed(4)}`,
80
+ `Chunk ID: ${r.chunkId}${scoreDetail}`,
81
+ "```",
82
+ r.content,
83
+ "```",
84
+ ].join("\n");
85
+ }
86
+ // --- Parse --collection from process.argv ---
87
+ function parseCollectionArg() {
88
+ const args = process.argv.slice(2);
89
+ for (let i = 0; i < args.length; i++) {
90
+ if (args[i] === "--collection" && i + 1 < args.length) {
91
+ return args[i + 1];
92
+ }
93
+ if (args[i].startsWith("--collection=")) {
94
+ return args[i].split("=")[1];
95
+ }
96
+ }
97
+ return undefined;
98
+ }
99
+ // --- Main entry point ---
100
+ export async function startMcpServer() {
101
+ const collectionName = parseCollectionArg();
102
+ const dbPath = resolveDbPathFromCollection(collectionName);
103
+ if (!existsSync(dbPath)) {
104
+ const name = collectionName ?? process.env.QSC_COLLECTION ?? "(unknown)";
105
+ console.error(`Error: Database not found at ${dbPath}\n` +
106
+ `Run 'qsc init ${name} <path>' first to create the collection.`);
107
+ process.exit(1);
108
+ }
109
+ const configPath = resolveConfigPath(collectionName);
110
+ const config = loadConfig(configPath);
111
+ const version = getVersion();
112
+ const displayName = collectionName ?? process.env.QSC_COLLECTION ?? "default";
113
+ // Create main store (read-write, for search operations)
114
+ const store = createStore(dbPath);
115
+ store.initDb(config.embedder.dimensions);
116
+ // Open a read-only connection for get_chunk queries
117
+ const readDb = new Database(dbPath, { readonly: true });
118
+ const getChunkStmt = readDb.prepare(`
119
+ SELECT
120
+ c.id, c.content, c.name, c.chunk_type,
121
+ c.start_line, c.end_line, c.seq,
122
+ f.path AS file_path, f.repo_id
123
+ FROM chunks c
124
+ JOIN files f ON c.file_id = f.id
125
+ WHERE c.id = ?
126
+ `);
127
+ const findRepoStmt = readDb.prepare(`
128
+ SELECT f.repo_id FROM files f WHERE f.path = ? AND f.active = 1 LIMIT 1
129
+ `);
130
+ // Create MCP server
131
+ const server = new McpServer({ name: "qsc", version }, {
132
+ instructions: `QSC (Query Source Code) - Collection: ${displayName}. ` +
133
+ "Search and explore indexed source code repositories. " +
134
+ "Use 'search' for fast BM25 text search, 'query' for full hybrid search (BM25 + vector + LLM reranking), " +
135
+ "'get_file' to retrieve a file's chunks, 'get_chunk' for a specific chunk, and 'status' for index statistics.",
136
+ });
137
+ // Lazily initialized search pipeline components
138
+ let embedder;
139
+ let llmProvider;
140
+ let searchPipeline;
141
+ async function getSearchPipeline() {
142
+ if (searchPipeline)
143
+ return searchPipeline;
144
+ try {
145
+ embedder = await createEmbedder(config.embedder);
146
+ }
147
+ catch {
148
+ // Vector search unavailable
149
+ }
150
+ try {
151
+ llmProvider = await createLLMProvider(config.llm);
152
+ }
153
+ catch {
154
+ // LLM unavailable
155
+ }
156
+ searchPipeline = createSearchPipeline(store, embedder, llmProvider);
157
+ return searchPipeline;
158
+ }
159
+ // --- Tool: search (BM25) ---
160
+ server.registerTool("search", {
161
+ title: "BM25 Search",
162
+ description: "Fast full-text search using BM25 ranking. Best for keyword-based queries. " +
163
+ "Returns matching code chunks with file paths, line numbers, and relevance scores.",
164
+ inputSchema: z.object({
165
+ query: z.string().describe("Search query text"),
166
+ limit: z
167
+ .number()
168
+ .int()
169
+ .min(1)
170
+ .max(100)
171
+ .optional()
172
+ .describe("Maximum number of results (default: 20)"),
173
+ }),
174
+ }, async ({ query, limit }) => {
175
+ if (!query.trim()) {
176
+ return {
177
+ content: [{ type: "text", text: "Error: query must not be empty" }],
178
+ isError: true,
179
+ };
180
+ }
181
+ const results = store.searchBM25(query, limit ?? 20);
182
+ if (results.length === 0) {
183
+ return { content: [{ type: "text", text: "No results found." }] };
184
+ }
185
+ const formatted = results.map(formatBM25Result).join("\n\n---\n\n");
186
+ return {
187
+ content: [
188
+ { type: "text", text: `Found ${results.length} result(s):\n\n${formatted}` },
189
+ ],
190
+ };
191
+ });
192
+ // --- Tool: query (hybrid search) ---
193
+ server.registerTool("query", {
194
+ title: "Hybrid Search",
195
+ description: "Full hybrid search combining BM25, vector similarity, and optional LLM reranking. " +
196
+ "Best for semantic and complex queries. May be slower than 'search' but provides better results.",
197
+ inputSchema: z.object({
198
+ query: z.string().describe("Search query text"),
199
+ limit: z
200
+ .number()
201
+ .int()
202
+ .min(1)
203
+ .max(100)
204
+ .optional()
205
+ .describe("Maximum number of results (default: 20)"),
206
+ expand: z
207
+ .boolean()
208
+ .optional()
209
+ .describe("Enable LLM query expansion (default: true if LLM available)"),
210
+ rerank: z
211
+ .boolean()
212
+ .optional()
213
+ .describe("Enable LLM reranking (default: true if LLM available)"),
214
+ }),
215
+ }, async ({ query, limit, expand, rerank }) => {
216
+ if (!query.trim()) {
217
+ return {
218
+ content: [{ type: "text", text: "Error: query must not be empty" }],
219
+ isError: true,
220
+ };
221
+ }
222
+ const sp = await getSearchPipeline();
223
+ const mode = embedder ? "hybrid" : "bm25";
224
+ const shouldExpand = expand ?? !!llmProvider;
225
+ const shouldRerank = rerank ?? !!llmProvider;
226
+ const response = await sp.search(query, {
227
+ mode,
228
+ limit: limit ?? 20,
229
+ expand: shouldExpand,
230
+ rerank: shouldRerank,
231
+ });
232
+ if (response.results.length === 0) {
233
+ return { content: [{ type: "text", text: "No results found." }] };
234
+ }
235
+ const formatted = response.results.map(formatSearchResult).join("\n\n---\n\n");
236
+ const modeLabel = mode === "hybrid"
237
+ ? `hybrid (expand=${shouldExpand}, rerank=${shouldRerank})`
238
+ : "bm25";
239
+ return {
240
+ content: [
241
+ { type: "text", text: `Found ${response.results.length} result(s) [${modeLabel}]:\n\n${formatted}` },
242
+ ],
243
+ };
244
+ });
245
+ // --- Tool: get_file ---
246
+ server.registerTool("get_file", {
247
+ title: "Get File",
248
+ description: "Retrieve a file's metadata and all its indexed chunks by file path. " +
249
+ "Returns file info (hash, language, active status) and chunk contents.",
250
+ inputSchema: z.object({
251
+ path: z.string().describe("Relative file path within the repository"),
252
+ repo_id: z
253
+ .string()
254
+ .optional()
255
+ .describe("Repository ID. If omitted, searches across all repositories."),
256
+ }),
257
+ }, async ({ path, repo_id }) => {
258
+ if (!path.trim()) {
259
+ return {
260
+ content: [{ type: "text", text: "Error: path must not be empty" }],
261
+ isError: true,
262
+ };
263
+ }
264
+ let repoId = repo_id;
265
+ if (!repoId) {
266
+ const row = findRepoStmt.get(path);
267
+ repoId = row?.repo_id;
268
+ }
269
+ if (!repoId) {
270
+ return {
271
+ content: [
272
+ { type: "text", text: `Error: File not found in index: ${path}. Specify repo_id if needed.` },
273
+ ],
274
+ isError: true,
275
+ };
276
+ }
277
+ const file = store.getFileByPath(repoId, path);
278
+ if (!file) {
279
+ return {
280
+ content: [
281
+ { type: "text", text: `Error: File not found in index: ${path} (repo: ${repoId})` },
282
+ ],
283
+ isError: true,
284
+ };
285
+ }
286
+ const chunks = store.getChunksByFileId(file.id);
287
+ const fileMeta = [
288
+ `# ${file.path}`,
289
+ `- **ID**: ${file.id}`,
290
+ `- **Repository**: ${file.repo_id}`,
291
+ `- **Hash**: ${file.hash}`,
292
+ `- **Language**: ${file.language ?? "unknown"}`,
293
+ `- **Active**: ${file.active ? "yes" : "no"}`,
294
+ `- **Indexed at**: ${file.indexed_at ?? "unknown"}`,
295
+ `- **Chunks**: ${chunks.length}`,
296
+ ].join("\n");
297
+ const chunkTexts = chunks.map((c) => {
298
+ const lineInfo = c.start_line != null ? `L${c.start_line}-${c.end_line}` : "";
299
+ const nameInfo = c.name ? ` ${c.name}` : "";
300
+ const typeInfo = c.chunk_type ? ` [${c.chunk_type}]` : "";
301
+ return `### Chunk #${c.seq} (ID: ${c.id}) ${lineInfo}${nameInfo}${typeInfo}\n\`\`\`\n${c.content}\n\`\`\``;
302
+ });
303
+ return {
304
+ content: [
305
+ { type: "text", text: `${fileMeta}\n\n${chunkTexts.join("\n\n")}` },
306
+ ],
307
+ };
308
+ });
309
+ // --- Tool: get_chunk ---
310
+ server.registerTool("get_chunk", {
311
+ title: "Get Chunk",
312
+ description: "Retrieve a specific code chunk by its ID. Returns the chunk content, metadata, and location.",
313
+ inputSchema: z.object({
314
+ chunk_id: z.number().int().describe("Chunk ID to retrieve"),
315
+ }),
316
+ }, async ({ chunk_id }) => {
317
+ const row = getChunkStmt.get(chunk_id);
318
+ if (!row) {
319
+ return {
320
+ content: [{ type: "text", text: `Error: Chunk not found: ${chunk_id}` }],
321
+ isError: true,
322
+ };
323
+ }
324
+ const lineInfo = row.start_line != null ? `L${row.start_line}-${row.end_line}` : "";
325
+ const nameInfo = row.name ? ` (${row.name})` : "";
326
+ const typeInfo = row.chunk_type ? ` [${row.chunk_type}]` : "";
327
+ const text = [
328
+ `# Chunk ${row.id}${nameInfo}${typeInfo}`,
329
+ `- **File**: ${row.file_path} ${lineInfo}`,
330
+ `- **Repository**: ${row.repo_id}`,
331
+ `- **Sequence**: ${row.seq}`,
332
+ `- **Type**: ${row.chunk_type ?? "unknown"}`,
333
+ "",
334
+ "```",
335
+ row.content,
336
+ "```",
337
+ ].join("\n");
338
+ return { content: [{ type: "text", text }] };
339
+ });
340
+ // --- Tool: status ---
341
+ server.registerTool("status", {
342
+ title: "Index Status",
343
+ description: "Get statistics about the QSC index: repository count, file count, chunk count, and embedding status.",
344
+ inputSchema: z.object({}),
345
+ }, async () => {
346
+ const stats = store.getStats();
347
+ const text = [
348
+ "# QSC Index Status",
349
+ `**Collection**: ${displayName}`,
350
+ "",
351
+ `| Metric | Value |`,
352
+ `|--------|-------|`,
353
+ `| Repositories | ${stats.repositories} |`,
354
+ `| Files (total) | ${stats.files} |`,
355
+ `| Files (active) | ${stats.active_files} |`,
356
+ `| Chunks | ${stats.chunks} |`,
357
+ `| Embedded chunks | ${stats.embedded_chunks} |`,
358
+ `| Pending embed | ${stats.pending_chunks} |`,
359
+ ].join("\n");
360
+ return { content: [{ type: "text", text }] };
361
+ });
362
+ // --- Connect transport and start ---
363
+ const transport = new StdioServerTransport();
364
+ await server.connect(transport);
365
+ // Clean up on exit
366
+ const cleanup = () => {
367
+ try {
368
+ readDb.close();
369
+ }
370
+ catch { /* ignore */ }
371
+ try {
372
+ store.close();
373
+ }
374
+ catch { /* ignore */ }
375
+ };
376
+ process.on("SIGINT", () => { cleanup(); process.exit(0); });
377
+ process.on("SIGTERM", () => { cleanup(); process.exit(0); });
378
+ console.error(`QSC MCP server v${version} running on stdio`);
379
+ console.error(`Collection: ${displayName}`);
380
+ console.error(`Database: ${dbPath}`);
381
+ }
382
+ // Direct execution: only run when this file is the entry point
383
+ const isDirectRun = process.argv[1] &&
384
+ (import.meta.url.endsWith(process.argv[1]) ||
385
+ import.meta.url === `file://${process.argv[1]}` ||
386
+ import.meta.url === `file://${resolve(process.argv[1])}`);
387
+ if (isDirectRun) {
388
+ startMcpServer().catch((err) => {
389
+ console.error("Fatal error:", err);
390
+ process.exit(1);
391
+ });
392
+ }
393
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export interface GitChange {
2
+ status: "added" | "modified" | "deleted" | "renamed";
3
+ path: string;
4
+ oldPath?: string;
5
+ }
6
+ export interface GitInfo {
7
+ currentCommit: string;
8
+ changes: GitChange[];
9
+ isFullScan: boolean;
10
+ }
11
+ /**
12
+ * Get the current HEAD commit hash.
13
+ * Throws if the directory is not a git repository or has no commits.
14
+ */
15
+ export declare function getCurrentCommit(repoPath: string): string;
16
+ /**
17
+ * Check if a path is inside a git repository.
18
+ */
19
+ export declare function isGitRepository(repoPath: string): boolean;
20
+ /**
21
+ * Detect file changes between lastCommit and HEAD.
22
+ * If lastCommit is not provided, returns isFullScan=true with no change list
23
+ * (caller should do a full repository scan instead).
24
+ */
25
+ export declare function detectChanges(repoPath: string, lastCommit?: string): GitInfo;
26
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/scanner/git.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB;AA6CD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQzD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CA2ET"}
@@ -0,0 +1,134 @@
1
+ import { execSync } from "node:child_process";
2
+ import { resolve } from "node:path";
3
+ // --- Helpers ---
4
+ function execGit(args, cwd) {
5
+ try {
6
+ return execSync(`git ${args}`, {
7
+ cwd,
8
+ encoding: "utf-8",
9
+ stdio: ["pipe", "pipe", "pipe"],
10
+ timeout: 30_000,
11
+ }).trim();
12
+ }
13
+ catch (error) {
14
+ const err = error;
15
+ if (err.stderr?.includes("not a git repository")) {
16
+ throw new Error(`Not a git repository: ${cwd}`);
17
+ }
18
+ if (err.message?.includes("ENOENT")) {
19
+ throw new Error("git is not installed or not found in PATH");
20
+ }
21
+ throw new Error(`git command failed: git ${args}\n${err.stderr ?? err.message}`);
22
+ }
23
+ }
24
+ function parseStatusCode(code) {
25
+ switch (code[0]) {
26
+ case "A":
27
+ return "added";
28
+ case "M":
29
+ return "modified";
30
+ case "D":
31
+ return "deleted";
32
+ case "R":
33
+ return "renamed";
34
+ default:
35
+ return "modified"; // treat unknown as modified
36
+ }
37
+ }
38
+ function isValidCommitHash(value) {
39
+ return /^[0-9a-f]{4,40}$/i.test(value);
40
+ }
41
+ // --- Public API ---
42
+ /**
43
+ * Get the current HEAD commit hash.
44
+ * Throws if the directory is not a git repository or has no commits.
45
+ */
46
+ export function getCurrentCommit(repoPath) {
47
+ const cwd = resolve(repoPath);
48
+ return execGit("rev-parse HEAD", cwd);
49
+ }
50
+ /**
51
+ * Check if a path is inside a git repository.
52
+ */
53
+ export function isGitRepository(repoPath) {
54
+ try {
55
+ const cwd = resolve(repoPath);
56
+ execGit("rev-parse --git-dir", cwd);
57
+ return true;
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ }
63
+ /**
64
+ * Detect file changes between lastCommit and HEAD.
65
+ * If lastCommit is not provided, returns isFullScan=true with no change list
66
+ * (caller should do a full repository scan instead).
67
+ */
68
+ export function detectChanges(repoPath, lastCommit) {
69
+ const cwd = resolve(repoPath);
70
+ const currentCommit = getCurrentCommit(cwd);
71
+ if (!lastCommit) {
72
+ return {
73
+ currentCommit,
74
+ changes: [],
75
+ isFullScan: true,
76
+ };
77
+ }
78
+ // Validate commit hash format to prevent command injection
79
+ if (!isValidCommitHash(lastCommit)) {
80
+ return {
81
+ currentCommit,
82
+ changes: [],
83
+ isFullScan: true,
84
+ };
85
+ }
86
+ // Verify lastCommit exists
87
+ try {
88
+ execGit(`cat-file -t ${lastCommit}`, cwd);
89
+ }
90
+ catch {
91
+ // If lastCommit is not valid, fall back to full scan
92
+ return {
93
+ currentCommit,
94
+ changes: [],
95
+ isFullScan: true,
96
+ };
97
+ }
98
+ // Get diff between lastCommit and HEAD
99
+ const output = execGit(`diff --name-status ${lastCommit}..${currentCommit}`, cwd);
100
+ if (!output) {
101
+ return {
102
+ currentCommit,
103
+ changes: [],
104
+ isFullScan: false,
105
+ };
106
+ }
107
+ const changes = [];
108
+ for (const line of output.split("\n")) {
109
+ if (!line.trim())
110
+ continue;
111
+ const parts = line.split("\t");
112
+ const statusCode = parts[0];
113
+ if (statusCode.startsWith("R")) {
114
+ // Renamed: R100\toldPath\tnewPath
115
+ changes.push({
116
+ status: "renamed",
117
+ path: parts[2],
118
+ oldPath: parts[1],
119
+ });
120
+ }
121
+ else {
122
+ changes.push({
123
+ status: parseStatusCode(statusCode),
124
+ path: parts[1],
125
+ });
126
+ }
127
+ }
128
+ return {
129
+ currentCommit,
130
+ changes,
131
+ isFullScan: false,
132
+ };
133
+ }
134
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/scanner/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,kBAAkB;AAElB,SAAS,OAAO,CAAC,IAAY,EAAE,GAAW;IACxC,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,OAAO,IAAI,EAAE,EAAE;YAC7B,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC,IAAI,EAAE,CAAC;IACZ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,KAA+D,CAAC;QAC5E,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,sBAAsB,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,KAAK,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACnF,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,QAAQ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAChB,KAAK,GAAG;YACN,OAAO,OAAO,CAAC;QACjB,KAAK,GAAG;YACN,OAAO,UAAU,CAAC;QACpB,KAAK,GAAG;YACN,OAAO,SAAS,CAAC;QACnB,KAAK,GAAG;YACN,OAAO,SAAS,CAAC;QACnB;YACE,OAAO,UAAU,CAAC,CAAC,4BAA4B;IACnD,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa;IACtC,OAAO,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC;AAED,qBAAqB;AAErB;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9B,OAAO,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC9B,OAAO,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,QAAgB,EAChB,UAAmB;IAEnB,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9B,MAAM,aAAa,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAE5C,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO;YACL,aAAa;YACb,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,IAAI;SACjB,CAAC;IACJ,CAAC;IAED,2DAA2D;IAC3D,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,CAAC;QACnC,OAAO;YACL,aAAa;YACb,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,IAAI;SACjB,CAAC;IACJ,CAAC;IAED,2BAA2B;IAC3B,IAAI,CAAC;QACH,OAAO,CAAC,eAAe,UAAU,EAAE,EAAE,GAAG,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,qDAAqD;QACrD,OAAO;YACL,aAAa;YACb,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,IAAI;SACjB,CAAC;IACJ,CAAC;IAED,uCAAuC;IACvC,MAAM,MAAM,GAAG,OAAO,CACpB,sBAAsB,UAAU,KAAK,aAAa,EAAE,EACpD,GAAG,CACJ,CAAC;IAEF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,aAAa;YACb,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,KAAK;SAClB,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAgB,EAAE,CAAC;IAEhC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,SAAS;QAE3B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAE5B,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,kCAAkC;YAClC,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,SAAS;gBACjB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;gBACd,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;aAClB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,eAAe,CAAC,UAAU,CAAC;gBACnC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;aACf,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO;QACL,aAAa;QACb,OAAO;QACP,UAAU,EAAE,KAAK;KAClB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { ScannerConfig } from "../config/index.js";
2
+ export interface ScannedFile {
3
+ path: string;
4
+ absolutePath: string;
5
+ hash: string;
6
+ size: number;
7
+ language?: string;
8
+ }
9
+ export interface ScanResult {
10
+ files: ScannedFile[];
11
+ repoRoot: string;
12
+ totalSize: number;
13
+ }
14
+ export declare function detectLanguage(filePath: string): string | undefined;
15
+ export declare function hashContent(content: Buffer): string;
16
+ export declare function scanRepository(repoPath: string, config: ScannerConfig): Promise<ScanResult>;
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scanner/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAiED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUnE;AAiCD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAID,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,UAAU,CAAC,CAqErB"}