codebaxing 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.
- package/LICENSE +21 -0
- package/README.md +402 -0
- package/README.vi.md +402 -0
- package/dist/core/exceptions.d.ts +25 -0
- package/dist/core/exceptions.d.ts.map +1 -0
- package/dist/core/exceptions.js +46 -0
- package/dist/core/exceptions.js.map +1 -0
- package/dist/core/interfaces.d.ts +13 -0
- package/dist/core/interfaces.d.ts.map +1 -0
- package/dist/core/interfaces.js +5 -0
- package/dist/core/interfaces.js.map +1 -0
- package/dist/core/models.d.ts +132 -0
- package/dist/core/models.d.ts.map +1 -0
- package/dist/core/models.js +303 -0
- package/dist/core/models.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/indexing/embedding-service.d.ts +66 -0
- package/dist/indexing/embedding-service.d.ts.map +1 -0
- package/dist/indexing/embedding-service.js +271 -0
- package/dist/indexing/embedding-service.js.map +1 -0
- package/dist/indexing/memory-retriever.d.ts +58 -0
- package/dist/indexing/memory-retriever.d.ts.map +1 -0
- package/dist/indexing/memory-retriever.js +327 -0
- package/dist/indexing/memory-retriever.js.map +1 -0
- package/dist/indexing/parallel-indexer.d.ts +36 -0
- package/dist/indexing/parallel-indexer.d.ts.map +1 -0
- package/dist/indexing/parallel-indexer.js +67 -0
- package/dist/indexing/parallel-indexer.js.map +1 -0
- package/dist/indexing/source-retriever.d.ts +66 -0
- package/dist/indexing/source-retriever.d.ts.map +1 -0
- package/dist/indexing/source-retriever.js +420 -0
- package/dist/indexing/source-retriever.js.map +1 -0
- package/dist/mcp/server.d.ts +16 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +370 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/state.d.ts +26 -0
- package/dist/mcp/state.d.ts.map +1 -0
- package/dist/mcp/state.js +154 -0
- package/dist/mcp/state.js.map +1 -0
- package/dist/parsers/language-configs.d.ts +26 -0
- package/dist/parsers/language-configs.d.ts.map +1 -0
- package/dist/parsers/language-configs.js +422 -0
- package/dist/parsers/language-configs.js.map +1 -0
- package/dist/parsers/treesitter-parser.d.ts +37 -0
- package/dist/parsers/treesitter-parser.d.ts.map +1 -0
- package/dist/parsers/treesitter-parser.js +602 -0
- package/dist/parsers/treesitter-parser.js.map +1 -0
- package/package.json +91 -0
package/README.vi.md
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
# Codebaxing
|
|
2
|
+
|
|
3
|
+
MCP server cho **semantic code search**. Index codebase và tìm kiếm bằng ngôn ngữ tự nhiên.
|
|
4
|
+
|
|
5
|
+
## Ý tưởng
|
|
6
|
+
|
|
7
|
+
Tìm kiếm code truyền thống (grep, ripgrep) chỉ match exact text. Nhưng lập trình viên suy nghĩ theo khái niệm:
|
|
8
|
+
|
|
9
|
+
- *"Logic xác thực người dùng ở đâu?"* - không phải `grep "authentication"`
|
|
10
|
+
- *"Tìm code kết nối database"* - không phải `grep "database"`
|
|
11
|
+
- *"Xử lý lỗi hoạt động như thế nào?"* - không phải `grep "error"`
|
|
12
|
+
|
|
13
|
+
**Codebaxing** giải quyết vấn đề này bằng **semantic search**:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
Query: "user authentication"
|
|
17
|
+
↓
|
|
18
|
+
Tìm được: login(), validateCredentials(), checkPassword(), authMiddleware()
|
|
19
|
+
(dù chúng không chứa từ "authentication")
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Cơ chế hoạt động
|
|
23
|
+
|
|
24
|
+
### Kiến trúc tổng quan
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
28
|
+
│ INDEXING │
|
|
29
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
30
|
+
│ │
|
|
31
|
+
│ Source Files (.py, .ts, .js, .go, .rs, ...) │
|
|
32
|
+
│ │ │
|
|
33
|
+
│ ▼ │
|
|
34
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
35
|
+
│ │ Tree-sitter │───▶│ Symbols │───▶│ Embedding │ │
|
|
36
|
+
│ │ Parser │ │ Extraction │ │ Model │ │
|
|
37
|
+
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
38
|
+
│ │ │ │ │
|
|
39
|
+
│ Parse AST Functions, Text → Vector │
|
|
40
|
+
│ Classes, etc. (384 chiều) │
|
|
41
|
+
│ │ │
|
|
42
|
+
│ ▼ │
|
|
43
|
+
│ ┌──────────────┐ │
|
|
44
|
+
│ │ ChromaDB │ │
|
|
45
|
+
│ │ (vectors) │ │
|
|
46
|
+
│ └──────────────┘ │
|
|
47
|
+
│ │
|
|
48
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
49
|
+
|
|
50
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
51
|
+
│ SEARCH │
|
|
52
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
53
|
+
│ │
|
|
54
|
+
│ "find auth code" │
|
|
55
|
+
│ │ │
|
|
56
|
+
│ ▼ │
|
|
57
|
+
│ ┌──────────────┐ ┌──────────────┐ │
|
|
58
|
+
│ │ Embedding │────────▶│ ChromaDB │ │
|
|
59
|
+
│ │ Model │ query │ Query │ │
|
|
60
|
+
│ └──────────────┘ vector └──────────────┘ │
|
|
61
|
+
│ │ │
|
|
62
|
+
│ ▼ │
|
|
63
|
+
│ Cosine Similarity │
|
|
64
|
+
│ │ │
|
|
65
|
+
│ ▼ │
|
|
66
|
+
│ Top-k Results │
|
|
67
|
+
│ (login.py, auth.ts, ...) │
|
|
68
|
+
│ │
|
|
69
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Quy trình chi tiết
|
|
73
|
+
|
|
74
|
+
#### 1. Parsing (Tree-sitter)
|
|
75
|
+
|
|
76
|
+
Tree-sitter parse source code thành Abstract Syntax Tree (AST), trích xuất các symbols có ý nghĩa:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
# Input: auth.py
|
|
80
|
+
def login(username, password):
|
|
81
|
+
"""Authenticate user credentials"""
|
|
82
|
+
if validate(username, password):
|
|
83
|
+
return create_session(username)
|
|
84
|
+
raise AuthError("Invalid credentials")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
# Output: Symbol
|
|
89
|
+
{
|
|
90
|
+
name: "login",
|
|
91
|
+
type: "function",
|
|
92
|
+
signature: "def login(username, password)",
|
|
93
|
+
code: "def login(username, password):...",
|
|
94
|
+
filepath: "auth.py",
|
|
95
|
+
lineStart: 1,
|
|
96
|
+
lineEnd: 6
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### 2. Embedding (all-MiniLM-L6-v2)
|
|
101
|
+
|
|
102
|
+
Mỗi code chunk được chuyển thành vector 384 chiều bằng neural network:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
"def login(username, password): authenticate user..."
|
|
106
|
+
↓
|
|
107
|
+
Embedding Model (chạy local, ONNX)
|
|
108
|
+
↓
|
|
109
|
+
[0.12, -0.34, 0.56, 0.08, ..., -0.22] (384 số)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Model hiểu được quan hệ ngữ nghĩa:
|
|
113
|
+
- `"authentication"` ≈ `"login"` ≈ `"credentials"` (vectors gần nhau)
|
|
114
|
+
- `"database"` ≈ `"query"` ≈ `"SQL"` (vectors gần nhau)
|
|
115
|
+
- `"authentication"` ≠ `"database"` (vectors xa nhau)
|
|
116
|
+
|
|
117
|
+
#### 3. Lưu trữ (ChromaDB)
|
|
118
|
+
|
|
119
|
+
Vectors được lưu trong ChromaDB, database tối ưu cho similarity search:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
ChromaDB Collection:
|
|
123
|
+
┌─────────────────────────────────────────────────────┐
|
|
124
|
+
│ ID │ Vector (384d) │ Metadata │
|
|
125
|
+
├─────────────────────────────────────────────────────┤
|
|
126
|
+
│ chunk_001 │ [0.12, -0.34, ...] │ {file: auth.py} │
|
|
127
|
+
│ chunk_002 │ [0.45, 0.23, ...] │ {file: db.py} │
|
|
128
|
+
│ chunk_003 │ [-0.11, 0.67, ...] │ {file: api.ts} │
|
|
129
|
+
│ ... │ ... │ ... │
|
|
130
|
+
└─────────────────────────────────────────────────────┘
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
#### 4. Tìm kiếm (Cosine Similarity)
|
|
134
|
+
|
|
135
|
+
Khi bạn search, query được embed và so sánh với tất cả vectors đã lưu:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
Query: "user authentication"
|
|
139
|
+
↓
|
|
140
|
+
Query Vector: [0.15, -0.31, 0.52, ...]
|
|
141
|
+
↓
|
|
142
|
+
So sánh với tất cả vectors bằng cosine similarity:
|
|
143
|
+
- chunk_001 (login): similarity = 0.89 ← CAO
|
|
144
|
+
- chunk_002 (db): similarity = 0.23 ← THẤP
|
|
145
|
+
- chunk_003 (auth): similarity = 0.85 ← CAO
|
|
146
|
+
↓
|
|
147
|
+
Trả về top-k chunks tương tự nhất
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Tại sao Semantic Search hoạt động
|
|
151
|
+
|
|
152
|
+
Embedding model được train trên hàng triệu cặp text, học được rằng:
|
|
153
|
+
|
|
154
|
+
| Khái niệm A | ≈ Tương tự với | Khoảng cách |
|
|
155
|
+
|-------------|----------------|-------------|
|
|
156
|
+
| authentication | login, credentials, auth, signin | Gần |
|
|
157
|
+
| database | query, SQL, connection, ORM | Gần |
|
|
158
|
+
| error | exception, failure, catch, throw | Gần |
|
|
159
|
+
| parse | tokenize, lexer, AST, syntax | Gần |
|
|
160
|
+
|
|
161
|
+
Điều này cho phép tìm code theo **ý nghĩa**, không chỉ từ khóa.
|
|
162
|
+
|
|
163
|
+
## Tính năng
|
|
164
|
+
|
|
165
|
+
- **Semantic Code Search**: Tìm code bằng cách mô tả những gì bạn cần
|
|
166
|
+
- **24+ Ngôn ngữ**: Python, TypeScript, JavaScript, Go, Rust, Java, C/C++, và nhiều hơn nữa
|
|
167
|
+
- **Memory Layer**: Lưu trữ và truy xuất context dự án qua các session
|
|
168
|
+
- **Incremental Indexing**: Chỉ re-index các file đã thay đổi
|
|
169
|
+
- **100% Local**: Không gọi API, không cloud, hoạt động offline
|
|
170
|
+
- **GPU Acceleration**: Hỗ trợ WebGPU/CUDA tùy chọn
|
|
171
|
+
|
|
172
|
+
## Yêu cầu
|
|
173
|
+
|
|
174
|
+
- Node.js >= 20.0.0
|
|
175
|
+
- ~500MB dung lượng đĩa cho embedding model (tải xuống lần chạy đầu tiên)
|
|
176
|
+
|
|
177
|
+
## Cài đặt
|
|
178
|
+
|
|
179
|
+
### Cách 1: Qua npx (Khuyến nghị)
|
|
180
|
+
|
|
181
|
+
Không cần cài đặt! Chỉ cần cấu hình Claude Desktop trực tiếp.
|
|
182
|
+
|
|
183
|
+
### Cách 2: Qua npm (Cài global)
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
npm install -g codebaxing
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Cách 3: Clone từ source
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
git clone https://github.com/duysolo/codebaxing.git
|
|
193
|
+
cd codebaxing
|
|
194
|
+
npm install
|
|
195
|
+
npm run build
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### (Tùy chọn) Cài đặt persistent storage
|
|
199
|
+
|
|
200
|
+
Mặc định, index được lưu trong memory và mất khi server restart.
|
|
201
|
+
|
|
202
|
+
Để lưu trữ vĩnh viễn, chạy ChromaDB:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
# Dùng Docker (khuyến nghị)
|
|
206
|
+
docker run -d -p 8000:8000 chromadb/chroma
|
|
207
|
+
|
|
208
|
+
# Set biến môi trường
|
|
209
|
+
export CHROMADB_URL=http://localhost:8000
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Cấu hình Claude Desktop
|
|
213
|
+
|
|
214
|
+
Thêm vào file config của Claude Desktop:
|
|
215
|
+
|
|
216
|
+
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
217
|
+
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
218
|
+
|
|
219
|
+
#### Qua npx (không cần cài):
|
|
220
|
+
|
|
221
|
+
```json
|
|
222
|
+
{
|
|
223
|
+
"mcpServers": {
|
|
224
|
+
"codebaxing": {
|
|
225
|
+
"command": "npx",
|
|
226
|
+
"args": ["-y", "codebaxing"]
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### Qua global install:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
npm install -g codebaxing
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"mcpServers": {
|
|
241
|
+
"codebaxing": {
|
|
242
|
+
"command": "codebaxing"
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### Với persistent storage (ChromaDB):
|
|
249
|
+
|
|
250
|
+
```json
|
|
251
|
+
{
|
|
252
|
+
"mcpServers": {
|
|
253
|
+
"codebaxing": {
|
|
254
|
+
"command": "npx",
|
|
255
|
+
"args": ["-y", "codebaxing"],
|
|
256
|
+
"env": {
|
|
257
|
+
"CHROMADB_URL": "http://localhost:8000"
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### Từ source (development):
|
|
265
|
+
|
|
266
|
+
```json
|
|
267
|
+
{
|
|
268
|
+
"mcpServers": {
|
|
269
|
+
"codebaxing": {
|
|
270
|
+
"command": "node",
|
|
271
|
+
"args": ["/path/to/codebaxing/dist/mcp/server.js"]
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Khởi động lại Claude Desktop
|
|
278
|
+
|
|
279
|
+
Các tool Codebaxing sẽ có sẵn trong Claude.
|
|
280
|
+
|
|
281
|
+
## Sử dụng
|
|
282
|
+
|
|
283
|
+
### MCP Tools
|
|
284
|
+
|
|
285
|
+
| Tool | Mô tả |
|
|
286
|
+
|------|-------|
|
|
287
|
+
| `index` | Index codebase. Modes: `auto` (incremental), `full`, `load-only` |
|
|
288
|
+
| `search` | Semantic search. Trả về ranked code chunks |
|
|
289
|
+
| `stats` | Thống kê index (files, symbols, chunks) |
|
|
290
|
+
| `languages` | Liệt kê các file extensions được hỗ trợ |
|
|
291
|
+
| `remember` | Lưu memories (conversation, status, decision, preference, doc, note) |
|
|
292
|
+
| `recall` | Semantic search trên memories |
|
|
293
|
+
| `forget` | Xóa memories theo ID, type, tags, hoặc tuổi |
|
|
294
|
+
| `memory-stats` | Thống kê memory theo type |
|
|
295
|
+
|
|
296
|
+
### Ví dụ Workflow
|
|
297
|
+
|
|
298
|
+
1. **Index codebase:**
|
|
299
|
+
```
|
|
300
|
+
index(path="/path/to/your/project")
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
2. **Tìm kiếm code:**
|
|
304
|
+
```
|
|
305
|
+
search(question="authentication middleware")
|
|
306
|
+
search(question="database connection", language="typescript")
|
|
307
|
+
search(question="error handling", symbol_type="function")
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
3. **Lưu context:**
|
|
311
|
+
```
|
|
312
|
+
remember(content="Sử dụng PostgreSQL với Prisma ORM", memory_type="decision")
|
|
313
|
+
remember(content="Auth dùng JWT tokens", memory_type="doc", tags=["auth", "security"])
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
4. **Truy xuất context:**
|
|
317
|
+
```
|
|
318
|
+
recall(query="database setup")
|
|
319
|
+
recall(query="authentication", memory_type="decision")
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Ngôn ngữ được hỗ trợ
|
|
323
|
+
|
|
324
|
+
Python, JavaScript, TypeScript, C, C++, Bash, Go, Java, Kotlin, Rust, Ruby, C#, PHP, Scala, Swift, Lua, Dart, Elixir, Haskell, OCaml, Zig, Perl, CSS, HTML, Vue, JSON, YAML, TOML, Makefile
|
|
325
|
+
|
|
326
|
+
## Cấu hình
|
|
327
|
+
|
|
328
|
+
### Biến môi trường
|
|
329
|
+
|
|
330
|
+
| Biến | Mô tả | Mặc định |
|
|
331
|
+
|------|-------|----------|
|
|
332
|
+
| `CHROMADB_URL` | URL ChromaDB server để lưu trữ vĩnh viễn | (in-memory) |
|
|
333
|
+
| `CODEBAXING_DEVICE` | Thiết bị tính toán cho embeddings | `cpu` |
|
|
334
|
+
|
|
335
|
+
### Tăng tốc GPU
|
|
336
|
+
|
|
337
|
+
Bật GPU để tạo embedding nhanh hơn:
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
# WebGPU (thử nghiệm, dùng Metal trên macOS)
|
|
341
|
+
export CODEBAXING_DEVICE=webgpu
|
|
342
|
+
|
|
343
|
+
# Tự động chọn thiết bị tốt nhất
|
|
344
|
+
export CODEBAXING_DEVICE=auto
|
|
345
|
+
|
|
346
|
+
# NVIDIA GPU (chỉ Linux/Windows, cần CUDA)
|
|
347
|
+
export CODEBAXING_DEVICE=cuda
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
Mặc định là `cpu`, hoạt động mọi nơi.
|
|
351
|
+
|
|
352
|
+
**Lưu ý:** macOS không hỗ trợ CUDA (không có NVIDIA drivers). Dùng `webgpu` để tăng tốc trên Mac.
|
|
353
|
+
|
|
354
|
+
### Lưu trữ
|
|
355
|
+
|
|
356
|
+
Metadata được lưu trong thư mục `.codebaxing/` trong project:
|
|
357
|
+
- `metadata.json` - Index metadata và file timestamps
|
|
358
|
+
|
|
359
|
+
## Development
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
npm run dev # Chạy với tsx (không cần build)
|
|
363
|
+
npm run build # Compile TypeScript
|
|
364
|
+
npm start # Chạy bản đã compile
|
|
365
|
+
npm test # Chạy tests
|
|
366
|
+
npm run typecheck # Type check không emit
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Testing
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
# Chạy unit tests
|
|
373
|
+
npm test
|
|
374
|
+
|
|
375
|
+
# Test indexing thủ công
|
|
376
|
+
CHROMADB_URL=http://localhost:8000 npx tsx test-indexing.ts
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## So sánh: Grep vs Semantic Search
|
|
380
|
+
|
|
381
|
+
| Khía cạnh | Grep | Semantic Search |
|
|
382
|
+
|-----------|------|-----------------|
|
|
383
|
+
| Query | Match exact text | Ngôn ngữ tự nhiên |
|
|
384
|
+
| "authentication" | Chỉ tìm "authentication" | Tìm login, auth, credentials, v.v. |
|
|
385
|
+
| Hiểu context | Không | Có |
|
|
386
|
+
| Tìm từ đồng nghĩa | Không | Có |
|
|
387
|
+
| Tốc độ | Rất nhanh | Nhanh (sau khi index) |
|
|
388
|
+
| Setup | Không cần | Cần indexing |
|
|
389
|
+
|
|
390
|
+
## Chi tiết kỹ thuật
|
|
391
|
+
|
|
392
|
+
| Component | Công nghệ |
|
|
393
|
+
|-----------|-----------|
|
|
394
|
+
| Embedding Model | `all-MiniLM-L6-v2` (384 chiều) |
|
|
395
|
+
| Model Runtime | `@huggingface/transformers` (ONNX) |
|
|
396
|
+
| Vector Database | ChromaDB |
|
|
397
|
+
| Code Parser | Tree-sitter |
|
|
398
|
+
| MCP SDK | `@modelcontextprotocol/sdk` |
|
|
399
|
+
|
|
400
|
+
## License
|
|
401
|
+
|
|
402
|
+
MIT
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom exceptions for Codebaxing.
|
|
3
|
+
*/
|
|
4
|
+
export declare class CodebaxingError extends Error {
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class ParseError extends CodebaxingError {
|
|
8
|
+
filepath: string;
|
|
9
|
+
language: string;
|
|
10
|
+
details: string;
|
|
11
|
+
constructor(filepath: string, language: string, details: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class IndexingError extends CodebaxingError {
|
|
14
|
+
constructor(message: string);
|
|
15
|
+
}
|
|
16
|
+
export declare class EmbeddingError extends CodebaxingError {
|
|
17
|
+
constructor(message: string);
|
|
18
|
+
}
|
|
19
|
+
export declare class SearchError extends CodebaxingError {
|
|
20
|
+
constructor(message: string);
|
|
21
|
+
}
|
|
22
|
+
export declare class ConfigurationError extends CodebaxingError {
|
|
23
|
+
constructor(message: string);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=exceptions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exceptions.d.ts","sourceRoot":"","sources":["../../src/core/exceptions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,UAAW,SAAQ,eAAe;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;gBAEJ,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAOhE;AAED,qBAAa,aAAc,SAAQ,eAAe;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,cAAe,SAAQ,eAAe;gBACrC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,WAAY,SAAQ,eAAe;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,eAAe;gBACzC,OAAO,EAAE,MAAM;CAI5B"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom exceptions for Codebaxing.
|
|
3
|
+
*/
|
|
4
|
+
export class CodebaxingError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'CodebaxingError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export class ParseError extends CodebaxingError {
|
|
11
|
+
filepath;
|
|
12
|
+
language;
|
|
13
|
+
details;
|
|
14
|
+
constructor(filepath, language, details) {
|
|
15
|
+
super(`Failed to parse ${filepath} (${language}): ${details}`);
|
|
16
|
+
this.name = 'ParseError';
|
|
17
|
+
this.filepath = filepath;
|
|
18
|
+
this.language = language;
|
|
19
|
+
this.details = details;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export class IndexingError extends CodebaxingError {
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = 'IndexingError';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export class EmbeddingError extends CodebaxingError {
|
|
29
|
+
constructor(message) {
|
|
30
|
+
super(message);
|
|
31
|
+
this.name = 'EmbeddingError';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export class SearchError extends CodebaxingError {
|
|
35
|
+
constructor(message) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = 'SearchError';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export class ConfigurationError extends CodebaxingError {
|
|
41
|
+
constructor(message) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.name = 'ConfigurationError';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=exceptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exceptions.js","sourceRoot":"","sources":["../../src/core/exceptions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,UAAW,SAAQ,eAAe;IAC7C,QAAQ,CAAS;IACjB,QAAQ,CAAS;IACjB,OAAO,CAAS;IAEhB,YAAY,QAAgB,EAAE,QAAgB,EAAE,OAAe;QAC7D,KAAK,CAAC,mBAAmB,QAAQ,KAAK,QAAQ,MAAM,OAAO,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,eAAe;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,eAAe;IACjD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,eAAe;IAC9C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,eAAe;IACrD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract interfaces for Codebaxing components.
|
|
3
|
+
*/
|
|
4
|
+
import type { ParsedFile } from './models.js';
|
|
5
|
+
export interface IParser {
|
|
6
|
+
/** Determine if this parser can handle the given file. */
|
|
7
|
+
canParse(filepath: string): boolean;
|
|
8
|
+
/** Parse a source file and extract all symbols. */
|
|
9
|
+
parseFile(filepath: string): ParsedFile;
|
|
10
|
+
/** Return list of file extensions this parser supports. */
|
|
11
|
+
getSupportedExtensions(): string[];
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=interfaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/core/interfaces.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,OAAO;IACtB,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAEpC,mDAAmD;IACnD,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAAC;IAExC,2DAA2D;IAC3D,sBAAsB,IAAI,MAAM,EAAE,CAAC;CACpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/core/interfaces.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core data models for Codebaxing.
|
|
3
|
+
*
|
|
4
|
+
* Defines the fundamental data structures used throughout the system
|
|
5
|
+
* for representing code symbols, parsed files, and codebase indices.
|
|
6
|
+
*/
|
|
7
|
+
export declare enum SymbolType {
|
|
8
|
+
FUNCTION = "function",
|
|
9
|
+
CLASS = "class",
|
|
10
|
+
METHOD = "method",
|
|
11
|
+
VARIABLE = "variable"
|
|
12
|
+
}
|
|
13
|
+
export declare function symbolTypeFromString(value: string): SymbolType;
|
|
14
|
+
export interface SymbolData {
|
|
15
|
+
name: string;
|
|
16
|
+
type: SymbolType;
|
|
17
|
+
filepath: string;
|
|
18
|
+
lineStart: number;
|
|
19
|
+
lineEnd: number;
|
|
20
|
+
language: string;
|
|
21
|
+
signature: string;
|
|
22
|
+
docstring?: string;
|
|
23
|
+
parent?: string;
|
|
24
|
+
codeSnippet?: string;
|
|
25
|
+
imports?: string[];
|
|
26
|
+
calls?: string[];
|
|
27
|
+
metadata?: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
export declare class Symbol {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly type: SymbolType;
|
|
32
|
+
readonly filepath: string;
|
|
33
|
+
readonly lineStart: number;
|
|
34
|
+
readonly lineEnd: number;
|
|
35
|
+
readonly language: string;
|
|
36
|
+
readonly signature: string;
|
|
37
|
+
readonly docstring: string;
|
|
38
|
+
readonly parent: string | undefined;
|
|
39
|
+
readonly codeSnippet: string;
|
|
40
|
+
readonly imports: string[];
|
|
41
|
+
readonly calls: string[];
|
|
42
|
+
readonly metadata: Record<string, unknown>;
|
|
43
|
+
constructor(data: SymbolData);
|
|
44
|
+
get qualifiedName(): string;
|
|
45
|
+
get lineCount(): number;
|
|
46
|
+
toDict(): Record<string, unknown>;
|
|
47
|
+
static fromDict(data: Record<string, unknown>): Symbol;
|
|
48
|
+
}
|
|
49
|
+
export interface ParsedFileData {
|
|
50
|
+
filepath: string;
|
|
51
|
+
language: string;
|
|
52
|
+
symbols?: Symbol[];
|
|
53
|
+
imports?: string[];
|
|
54
|
+
parseTime?: number;
|
|
55
|
+
error?: string;
|
|
56
|
+
}
|
|
57
|
+
export declare class ParsedFile {
|
|
58
|
+
readonly filepath: string;
|
|
59
|
+
readonly language: string;
|
|
60
|
+
readonly symbols: Symbol[];
|
|
61
|
+
readonly imports: string[];
|
|
62
|
+
readonly parseTime: number;
|
|
63
|
+
readonly error: string | undefined;
|
|
64
|
+
constructor(data: ParsedFileData);
|
|
65
|
+
get isSuccessful(): boolean;
|
|
66
|
+
get symbolCount(): number;
|
|
67
|
+
getSymbolsByType(symbolType: SymbolType): Symbol[];
|
|
68
|
+
toDict(): Record<string, unknown>;
|
|
69
|
+
static fromDict(data: Record<string, unknown>): ParsedFile;
|
|
70
|
+
}
|
|
71
|
+
export interface CodebaseIndexData {
|
|
72
|
+
rootPath: string;
|
|
73
|
+
files?: Record<string, ParsedFile>;
|
|
74
|
+
totalFiles?: number;
|
|
75
|
+
totalSymbols?: number;
|
|
76
|
+
indexedAt?: string;
|
|
77
|
+
}
|
|
78
|
+
export declare class CodebaseIndex {
|
|
79
|
+
readonly rootPath: string;
|
|
80
|
+
readonly files: Record<string, ParsedFile>;
|
|
81
|
+
readonly totalFiles: number;
|
|
82
|
+
readonly totalSymbols: number;
|
|
83
|
+
readonly indexedAt: string;
|
|
84
|
+
constructor(data: CodebaseIndexData);
|
|
85
|
+
get successfulParses(): number;
|
|
86
|
+
get failedParses(): number;
|
|
87
|
+
getSymbolsByName(name: string): Symbol[];
|
|
88
|
+
getSymbolsByType(symbolType: SymbolType): Symbol[];
|
|
89
|
+
toDict(): Record<string, unknown>;
|
|
90
|
+
static fromDict(data: Record<string, unknown>): CodebaseIndex;
|
|
91
|
+
}
|
|
92
|
+
export declare enum MemoryType {
|
|
93
|
+
CONVERSATION = "conversation",
|
|
94
|
+
STATUS = "status",
|
|
95
|
+
DECISION = "decision",
|
|
96
|
+
PREFERENCE = "preference",
|
|
97
|
+
DOC = "doc",
|
|
98
|
+
NOTE = "note"
|
|
99
|
+
}
|
|
100
|
+
export declare function memoryTypeFromString(value: string): MemoryType;
|
|
101
|
+
declare const VALID_TTLS: readonly ["session", "day", "week", "month", "permanent"];
|
|
102
|
+
export type TTL = typeof VALID_TTLS[number];
|
|
103
|
+
export interface MemoryData {
|
|
104
|
+
id: string;
|
|
105
|
+
content: string;
|
|
106
|
+
memoryType: MemoryType;
|
|
107
|
+
project: string;
|
|
108
|
+
tags?: string[];
|
|
109
|
+
createdAt?: string;
|
|
110
|
+
accessedAt?: string;
|
|
111
|
+
ttl?: TTL;
|
|
112
|
+
source?: string;
|
|
113
|
+
metadata?: Record<string, unknown>;
|
|
114
|
+
}
|
|
115
|
+
export declare class Memory {
|
|
116
|
+
id: string;
|
|
117
|
+
content: string;
|
|
118
|
+
memoryType: MemoryType;
|
|
119
|
+
project: string;
|
|
120
|
+
tags: string[];
|
|
121
|
+
createdAt: string;
|
|
122
|
+
accessedAt: string;
|
|
123
|
+
ttl: TTL;
|
|
124
|
+
source: string;
|
|
125
|
+
metadata: Record<string, unknown>;
|
|
126
|
+
constructor(data: MemoryData);
|
|
127
|
+
toDict(): Record<string, unknown>;
|
|
128
|
+
static fromDict(data: Record<string, unknown>): Memory;
|
|
129
|
+
touch(): void;
|
|
130
|
+
}
|
|
131
|
+
export {};
|
|
132
|
+
//# sourceMappingURL=models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/core/models.ts"],"names":[],"mappings":"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"}
|