Skip to content

Commit 4f329d4

Browse files
committed
feat: multi projects
1 parent 8f27c8d commit 4f329d4

27 files changed

Lines changed: 311 additions & 57 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Edit your `claude_mcp_settings.json` file:
2323
"mcpServers": {
2424
"h-codex": {
2525
"command": "npx",
26-
"args": ["@h-codex/mcp"],
26+
"args": ["@hpbyte/h-codex-mcp"],
2727
"env": {
2828
"OPENAI_API_KEY": "your_openai_api_key_here",
2929
"DB_CONNECTION_STRING": "postgresql://postgres:password@localhost:5432/h-codex"

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
22
"name": "h-codex",
3-
"version": "0.1.0",
3+
"version": "0.1.1",
44
"description": "A semantic code search tool for intelligent, cross-repo context retrieval.",
55
"author": "Htoo Pyae Lwin",
66
"license": "MIT",
77
"type": "module",
88
"scripts": {
99
"build": "pnpm -r run build",
10-
"dev": "pnpm --filter @h-codex/core run dev",
11-
"db:generate": "pnpm --filter @h-codex/core run db:generate",
12-
"db:migrate": "pnpm --filter @h-codex/core run db:migrate",
10+
"dev": "pnpm --filter @hpbyte/h-codex-core run dev",
11+
"db:generate": "pnpm --filter @hpbyte/h-codex-core run db:generate",
12+
"db:migrate": "pnpm --filter @hpbyte/h-codex-core run db:migrate",
1313
"lint:fix": "eslint packages --ext .ts --fix",
1414
"format": "prettier --write \"packages/**/*.ts\""
1515
},

packages/core/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# @h-codex/core
1+
# @hpbyte/h-codex-core
22

33
Core package for h-codex semantic code indexing and search.
44

@@ -14,7 +14,7 @@ Core package for h-codex semantic code indexing and search.
1414
### Installation
1515

1616
```bash
17-
pnpm add @h-codex/core
17+
pnpm add @hpbyte/h-codex-core
1818
```
1919

2020
### Environment Setup
@@ -30,7 +30,7 @@ DB_CONNECTION_STRING=postgresql://postgres:password@localhost:5432/h-codex
3030
### Usage Example
3131

3232
```typescript
33-
import { indexer, semanticSearch } from '@h-codex/core'
33+
import { indexer, semanticSearch } from '@hpbyte/h-codex-core'
3434

3535
// Index a codebase
3636
const indexResult = await indexer.index('./path/to/codebase')

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@hpbyte/h-codex-core",
3-
"version": "0.1.0",
3+
"version": "0.1.1",
44
"description": "Core indexing and search functionality for h-codex",
55
"author": "Htoo Pyae Lwin",
66
"license": "MIT",

packages/core/src/config/database.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getEnvVar } from './helper'
1+
import { getEnvVar } from '../utils'
22

33
export const dbConnectionString = getEnvVar(
44
'DB_CONNECTION_STRING',

packages/core/src/config/embedding.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getEnvVar, getEnvNumber } from './helper'
1+
import { getEnvVar, getEnvNumber } from '../utils'
22

33
interface EmbeddingsConfig {
44
apiKey: string

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './ingestion'
22
export * from './search'
3+
export * from './types'

packages/core/src/ingestion/chunker/index.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,18 @@ export class CSTChunker {
1111
private coalesce = 50
1212
private filePath = ''
1313
private fileContent = ''
14+
private projectId = ''
1415
private language: SupportedLanguage | null = null
1516

16-
async processFile(filePath: string): Promise<CodeChunkInsert[]> {
17+
async processFile(filePath: string, projectId: string): Promise<CodeChunkInsert[]> {
1718
try {
1819
const language = this.detectLanguage(filePath)
1920
const cstRootNode = await treeSitterParser.parseFile(filePath, language)
2021

2122
this.filePath = filePath
2223
this.language = language
2324
this.fileContent = cstRootNode.text
25+
this.projectId = projectId
2426

2527
const chunks = this.chunkNode(cstRootNode)
2628
const processedChunks = this.processChunks(chunks)
@@ -123,7 +125,8 @@ export class CSTChunker {
123125
return {
124126
content,
125127
filePath: this.filePath,
126-
startLine: chunk.start + 1, // tree-sitter index starts from 0, make it human-readable
128+
projectId: this.projectId,
129+
startLine: chunk.start + 1, // tree-sitter index starts from 0
127130
endLine: chunk.end + 1,
128131
nodeType: chunk.nodeType,
129132
language: this.language!,

packages/core/src/ingestion/chunker/tree-sitter-parser.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ export class TreeSitterParser {
1818
const content = await fs.readFile(filePath, 'utf-8')
1919
const tree = this.parser.parse(content)
2020

21-
console.log('total content length: ', content.length)
22-
2321
return tree.rootNode
2422
}
2523

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
import { chunker } from '../chunker'
22
import { embedder } from '../embedder'
33
import { fileExplorer } from '../explorer'
4-
import { repository } from '../../storage/repository'
4+
import { chunkEmbeddingsRepository } from '../../storage/chunk-embeddings.repository'
5+
import { projectsRepository } from '../../storage/projects.repository'
56

67
export class Indexer {
7-
async index(path: string): Promise<{
8-
totalFiles: number
9-
processedFiles: number
10-
failedFiles: number
11-
errors: Array<{ file: string; error: string }>
12-
}> {
13-
console.log(`Starting indexing of folder: ${path}`)
14-
8+
async index(path: string) {
159
try {
1610
const files = await fileExplorer.discover(path)
17-
console.log(`Found ${files.length} files to process`)
11+
12+
const projectName = path.split('/').pop() || 'untitled-project'
13+
14+
const project = await projectsRepository.getOrCreate(projectName, path)
1815

1916
if (files.length === 0) {
2017
return {
@@ -26,16 +23,12 @@ export class Indexer {
2623
}
2724

2825
const { results, errors } = await fileExplorer.processInBatches(files, (filePath: string) =>
29-
this.indexFile(filePath)
26+
this.indexFile(filePath, project.id)
3027
)
3128

3229
const processedFiles = results.filter(result => result !== null).length
3330
const failedFiles = errors.length
3431

35-
console.log(
36-
`Indexing completed: ${processedFiles} files processed, ${failedFiles} files failed`
37-
)
38-
3932
return {
4033
totalFiles: files.length,
4134
processedFiles,
@@ -46,25 +39,27 @@ export class Indexer {
4639
})),
4740
}
4841
} catch (error) {
49-
console.error('Error during folder indexing:', error)
5042
throw new Error(`Failed to index folder ${path}: ${error}`)
5143
}
5244
}
5345

54-
async indexFile(filePath: string) {
46+
async indexFile(filePath: string, projectId: string) {
5547
try {
56-
const chunks = await chunker.processFile(filePath)
57-
const newCodeChunks = await repository.insertCodeChunks(chunks)
48+
const chunks = await chunker.processFile(filePath, projectId)
49+
const newCodeChunks = await chunkEmbeddingsRepository.insertCodeChunks(chunks)
5850

5951
const embeddings = await embedder.generate(newCodeChunks)
60-
const newEmbeddings = await repository.insertEmbeddings(newCodeChunks, embeddings)
52+
const newEmbeddings = await chunkEmbeddingsRepository.insertEmbeddings(
53+
newCodeChunks,
54+
embeddings
55+
)
6156

6257
return { newCodeChunks, newEmbeddings }
6358
} catch (error) {
64-
console.error('Error indexing file:', error)
6559
throw new Error(`Failed to index file ${filePath}: ${error}`)
6660
}
6761
}
6862
}
6963

7064
export const indexer = new Indexer()
65+

0 commit comments

Comments
 (0)