lance-context 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,173 @@
1
+ import * as lancedb from '@lancedb/lancedb';
2
+ import * as fs from 'fs/promises';
3
+ import * as path from 'path';
4
+ const CHUNK_SIZE = 100; // lines per chunk
5
+ const CHUNK_OVERLAP = 20; // overlap between chunks
6
+ /**
7
+ * Code indexer using LanceDB for vector storage
8
+ */
9
+ export class CodeIndexer {
10
+ db = null;
11
+ table = null;
12
+ embeddingBackend;
13
+ indexPath;
14
+ projectPath;
15
+ constructor(projectPath, embeddingBackend) {
16
+ this.projectPath = projectPath;
17
+ this.embeddingBackend = embeddingBackend;
18
+ this.indexPath = path.join(projectPath, '.lance-context');
19
+ }
20
+ async initialize() {
21
+ this.db = await lancedb.connect(this.indexPath);
22
+ }
23
+ async getStatus() {
24
+ const tableNames = await this.db?.tableNames();
25
+ const hasTable = tableNames?.includes('code_chunks') ?? false;
26
+ if (!hasTable) {
27
+ return {
28
+ indexed: false,
29
+ fileCount: 0,
30
+ chunkCount: 0,
31
+ lastUpdated: null,
32
+ indexPath: this.indexPath,
33
+ };
34
+ }
35
+ this.table = await this.db.openTable('code_chunks');
36
+ const count = await this.table.countRows();
37
+ return {
38
+ indexed: true,
39
+ fileCount: 0, // Would need to query distinct files
40
+ chunkCount: count,
41
+ lastUpdated: new Date().toISOString(),
42
+ indexPath: this.indexPath,
43
+ };
44
+ }
45
+ async indexCodebase(patterns = ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.py', '**/*.go', '**/*.rs'], excludePatterns = ['**/node_modules/**', '**/dist/**', '**/.git/**', '**/build/**']) {
46
+ const { glob } = await import('glob');
47
+ // Find all matching files
48
+ const files = [];
49
+ for (const pattern of patterns) {
50
+ const matches = await glob(pattern, {
51
+ cwd: this.projectPath,
52
+ ignore: excludePatterns,
53
+ absolute: true,
54
+ });
55
+ files.push(...matches);
56
+ }
57
+ console.error(`[lance-context] Found ${files.length} files to index`);
58
+ // Process files into chunks
59
+ const allChunks = [];
60
+ for (const filePath of files) {
61
+ const chunks = await this.chunkFile(filePath);
62
+ allChunks.push(...chunks);
63
+ }
64
+ console.error(`[lance-context] Created ${allChunks.length} chunks`);
65
+ // Generate embeddings in batches
66
+ const batchSize = 32;
67
+ for (let i = 0; i < allChunks.length; i += batchSize) {
68
+ const batch = allChunks.slice(i, i + batchSize);
69
+ const texts = batch.map((c) => c.content);
70
+ const embeddings = await this.embeddingBackend.embedBatch(texts);
71
+ batch.forEach((chunk, idx) => {
72
+ chunk.embedding = embeddings[idx];
73
+ });
74
+ console.error(`[lance-context] Embedded ${i + batch.length}/${allChunks.length} chunks`);
75
+ }
76
+ // Store in LanceDB
77
+ const dimensions = this.embeddingBackend.getDimensions();
78
+ const data = allChunks.map((chunk) => ({
79
+ id: chunk.id,
80
+ filePath: chunk.filePath,
81
+ content: chunk.content,
82
+ startLine: chunk.startLine,
83
+ endLine: chunk.endLine,
84
+ language: chunk.language,
85
+ vector: chunk.embedding,
86
+ }));
87
+ // Drop existing table if exists
88
+ const tableNames = await this.db.tableNames();
89
+ if (tableNames.includes('code_chunks')) {
90
+ await this.db.dropTable('code_chunks');
91
+ }
92
+ this.table = await this.db.createTable('code_chunks', data);
93
+ return {
94
+ filesIndexed: files.length,
95
+ chunksCreated: allChunks.length,
96
+ };
97
+ }
98
+ async chunkFile(filePath) {
99
+ const content = await fs.readFile(filePath, 'utf-8');
100
+ const lines = content.split('\n');
101
+ const ext = path.extname(filePath).slice(1);
102
+ const language = this.getLanguage(ext);
103
+ const relativePath = path.relative(this.projectPath, filePath);
104
+ const chunks = [];
105
+ for (let i = 0; i < lines.length; i += CHUNK_SIZE - CHUNK_OVERLAP) {
106
+ const chunkLines = lines.slice(i, i + CHUNK_SIZE);
107
+ const chunkContent = chunkLines.join('\n');
108
+ if (chunkContent.trim().length === 0)
109
+ continue;
110
+ chunks.push({
111
+ id: `${relativePath}:${i + 1}-${i + chunkLines.length}`,
112
+ filePath: relativePath,
113
+ content: chunkContent,
114
+ startLine: i + 1,
115
+ endLine: i + chunkLines.length,
116
+ language,
117
+ });
118
+ }
119
+ return chunks;
120
+ }
121
+ getLanguage(ext) {
122
+ const langMap = {
123
+ ts: 'typescript',
124
+ tsx: 'typescript',
125
+ js: 'javascript',
126
+ jsx: 'javascript',
127
+ py: 'python',
128
+ go: 'go',
129
+ rs: 'rust',
130
+ java: 'java',
131
+ rb: 'ruby',
132
+ php: 'php',
133
+ c: 'c',
134
+ cpp: 'cpp',
135
+ h: 'c',
136
+ hpp: 'cpp',
137
+ cs: 'csharp',
138
+ swift: 'swift',
139
+ kt: 'kotlin',
140
+ md: 'markdown',
141
+ json: 'json',
142
+ yaml: 'yaml',
143
+ yml: 'yaml',
144
+ };
145
+ return langMap[ext] || ext;
146
+ }
147
+ async search(query, limit = 10) {
148
+ if (!this.table) {
149
+ const status = await this.getStatus();
150
+ if (!status.indexed) {
151
+ throw new Error('Codebase not indexed. Run index_codebase first.');
152
+ }
153
+ }
154
+ const queryEmbedding = await this.embeddingBackend.embed(query);
155
+ const results = await this.table.search(queryEmbedding).limit(limit).toArray();
156
+ return results.map((r) => ({
157
+ id: r.id,
158
+ filePath: r.filePath,
159
+ content: r.content,
160
+ startLine: r.startLine,
161
+ endLine: r.endLine,
162
+ language: r.language,
163
+ }));
164
+ }
165
+ async clearIndex() {
166
+ const tableNames = await this.db.tableNames();
167
+ if (tableNames.includes('code_chunks')) {
168
+ await this.db.dropTable('code_chunks');
169
+ }
170
+ this.table = null;
171
+ }
172
+ }
173
+ //# sourceMappingURL=indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.js","sourceRoot":"","sources":["../../src/search/indexer.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "lance-context",
3
+ "version": "0.1.0",
4
+ "description": "MCP plugin for semantic code search using LanceDB - gives AI coding agents deep context from your entire codebase",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "lance-context": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js",
13
+ "dev": "tsx src/index.ts",
14
+ "test": "echo \"Error: no test specified\" && exit 1",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md"
20
+ ],
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/nicholaspsmith/lance-context.git"
24
+ },
25
+ "keywords": [
26
+ "mcp",
27
+ "claude",
28
+ "code-search",
29
+ "embeddings",
30
+ "lancedb",
31
+ "semantic-search",
32
+ "ai-coding"
33
+ ],
34
+ "author": "Nicholas Smith",
35
+ "license": "GPL-3.0",
36
+ "bugs": {
37
+ "url": "https://github.com/nicholaspsmith/lance-context/issues"
38
+ },
39
+ "homepage": "https://github.com/nicholaspsmith/lance-context#readme",
40
+ "dependencies": {
41
+ "@lancedb/lancedb": "^0.22.3",
42
+ "@modelcontextprotocol/sdk": "^1.0.0",
43
+ "glob": "^13.0.0"
44
+ },
45
+ "devDependencies": {
46
+ "@types/node": "^22.0.0",
47
+ "tsx": "^4.0.0",
48
+ "typescript": "^5.7.0"
49
+ },
50
+ "engines": {
51
+ "node": ">=20.0.0"
52
+ }
53
+ }