refactor: rename class name from indexer to context

Signed-off-by: ChengZi <chen.zhang@zilliz.com>
This commit is contained in:
ChengZi
2025-07-21 15:37:21 +08:00
committed by Cheney Zhang
parent be04eaf9cc
commit 965ff86761
21 changed files with 226 additions and 198 deletions

View File

@@ -2,9 +2,9 @@ name: CI
on:
push:
branches: [ master, main, refactor_name ]
branches: [ master, main, refactor_class_name ]
pull_request:
branches: [ master, main, refactor_name ]
branches: [ master, main, refactor_class_name ]
jobs:
lint_and_build:

View File

@@ -374,7 +374,7 @@ While MCP is the recommended way to use Code Context with AI assistants, you can
The `@zilliz/code-context-core` package provides the fundamental functionality for code indexing and semantic search.
```typescript
import { CodeIndexer, MilvusVectorDatabase, OpenAIEmbedding } from '@zilliz/code-context-core';
import { CodeContext, MilvusVectorDatabase, OpenAIEmbedding } from '@zilliz/code-context-core';
// Initialize embedding provider
const embedding = new OpenAIEmbedding({
@@ -388,20 +388,20 @@ const vectorDatabase = new MilvusVectorDatabase({
token: process.env.MILVUS_TOKEN || 'your-zilliz-cloud-api-key'
});
// Create indexer instance
const indexer = new CodeIndexer({
// Create context instance
const context = new CodeContext({
embedding,
vectorDatabase
});
// Index your codebase with progress tracking
const stats = await indexer.indexCodebase('./your-project', (progress) => {
const stats = await context.indexCodebase('./your-project', (progress) => {
console.log(`${progress.phase} - ${progress.percentage}%`);
});
console.log(`Indexed ${stats.indexedFiles} files, ${stats.totalChunks} chunks`);
// Perform semantic search
const results = await indexer.semanticSearch('./your-project', 'vector database operations', 5);
const results = await context.semanticSearch('./your-project', 'vector database operations', 5);
results.forEach(result => {
console.log(`File: ${result.relativePath}:${result.startLine}-${result.endLine}`);
console.log(`Score: ${(result.score * 100).toFixed(2)}%`);

View File

@@ -1,4 +1,4 @@
import { CodeIndexer, MilvusVectorDatabase, MilvusRestfulVectorDatabase, AstCodeSplitter, LangChainCodeSplitter } from '@zilliz/code-context-core';
import { CodeContext, MilvusVectorDatabase, MilvusRestfulVectorDatabase, AstCodeSplitter, LangChainCodeSplitter } from '@zilliz/code-context-core';
import * as path from 'path';
// Try to load .env file
@@ -9,7 +9,7 @@ try {
}
async function main() {
console.log('🚀 CodeIndexer Real Usage Example');
console.log('🚀 CodeContext Real Usage Example');
console.log('===============================');
try {
@@ -39,14 +39,14 @@ async function main() {
});
}
// 2. Create CodeIndexer instance
// 2. Create CodeContext instance
let codeSplitter;
if (splitterType === 'langchain') {
codeSplitter = new LangChainCodeSplitter(1000, 200);
} else {
codeSplitter = new AstCodeSplitter(2500, 300);
}
const indexer = new CodeIndexer({
const context = new CodeContext({
vectorDatabase,
codeSplitter,
supportedExtensions: ['.ts', '.js', '.py', '.java', '.cpp', '.go', '.rs']
@@ -57,14 +57,14 @@ async function main() {
const codebasePath = path.join(__dirname, '../..'); // Index entire project
// Check if index already exists
const hasExistingIndex = await indexer.hasIndex(codebasePath);
const hasExistingIndex = await context.hasIndex(codebasePath);
if (hasExistingIndex) {
console.log('🗑️ Existing index found, clearing it first...');
await indexer.clearIndex(codebasePath);
await context.clearIndex(codebasePath);
}
// Index with progress tracking
const indexStats = await indexer.indexCodebase(codebasePath);
const indexStats = await context.indexCodebase(codebasePath);
// 4. Show indexing statistics
console.log(`\n📊 Indexing stats: ${indexStats.indexedFiles} files, ${indexStats.totalChunks} code chunks`);
@@ -81,7 +81,7 @@ async function main() {
for (const query of queries) {
console.log(`\n🔎 Search: "${query}"`);
const results = await indexer.semanticSearch(codebasePath, query, 3, 0.3);
const results = await context.semanticSearch(codebasePath, query, 3, 0.3);
if (results.length > 0) {
results.forEach((result, index) => {

View File

@@ -27,7 +27,7 @@ pnpm dev:core
## Project Structure
- `src/indexer.ts` - Main CodeIndexer class
- `src/context.ts` - Main CodeContext class
- `src/embedding/` - Embedding providers (OpenAI, VoyageAI, Ollama)
- `src/vectordb/` - Vector database implementations (Milvus)
- `src/splitter/` - Code splitting logic

View File

@@ -45,7 +45,7 @@ MILVUS_TOKEN=your-zilliz-cloud-api-key
```typescript
import {
CodeIndexer,
CodeContext,
OpenAIEmbedding,
MilvusVectorDatabase
} from '@zilliz/code-context-core';
@@ -62,21 +62,21 @@ const vectorDatabase = new MilvusVectorDatabase({
token: process.env.MILVUS_TOKEN || ''
});
// Create indexer instance
const indexer = new CodeIndexer({
// Create context instance
const context = new CodeContext({
embedding,
vectorDatabase
});
// Index a codebase
const stats = await indexer.indexCodebase('./my-project', (progress) => {
const stats = await context.indexCodebase('./my-project', (progress) => {
console.log(`${progress.phase} - ${progress.percentage}%`);
});
console.log(`Indexed ${stats.indexedFiles} files with ${stats.totalChunks} chunks`);
// Search the codebase
const results = await indexer.semanticSearch(
const results = await context.semanticSearch(
'./my-project',
'function that handles user authentication',
5
@@ -115,10 +115,10 @@ results.forEach(result => {
## Configuration
### CodeIndexerConfig
### CodeContextConfig
```typescript
interface CodeIndexerConfig {
interface CodeContextConfig {
embedding?: Embedding; // Embedding provider
vectorDatabase?: VectorDatabase; // Vector database instance (required)
codeSplitter?: Splitter; // Code splitting strategy
@@ -148,7 +148,7 @@ interface CodeIndexerConfig {
## API Reference
### CodeIndexer
### CodeContext
#### Methods
@@ -180,7 +180,7 @@ interface SemanticSearchResult {
### Using VoyageAI Embeddings
```typescript
import { CodeIndexer, MilvusVectorDatabase, VoyageAIEmbedding } from '@zilliz/code-context-core';
import { CodeContext, MilvusVectorDatabase, VoyageAIEmbedding } from '@zilliz/code-context-core';
// Initialize with VoyageAI embedding provider
const embedding = new VoyageAIEmbedding({
@@ -193,7 +193,7 @@ const vectorDatabase = new MilvusVectorDatabase({
token: process.env.MILVUS_TOKEN || ''
});
const indexer = new CodeIndexer({
const context = new CodeContext({
embedding,
vectorDatabase
});
@@ -202,7 +202,7 @@ const indexer = new CodeIndexer({
### Custom File Filtering
```typescript
const indexer = new CodeIndexer({
const context = new CodeContext({
embedding,
vectorDatabase,
supportedExtensions: ['.ts', '.js', '.py', '.java'],
@@ -257,13 +257,13 @@ The file synchronization system uses a **Merkle tree-based approach** combined w
## Contributing
This package is part of the CodeIndexer monorepo. Please see:
This package is part of the CodeContext monorepo. Please see:
- [Main Contributing Guide](../../CONTRIBUTING.md) - General contribution guidelines
- [Core Package Contributing](CONTRIBUTING.md) - Specific development guide for this package
## Related Packages
- **[@code-indexer/mcp](../mcp)** - MCP server that uses this core engine
- **[@code-context/mcp](../mcp)** - MCP server that uses this core engine
- **[VSCode Extension](../vscode-extension)** - VSCode extension built on this core

View File

@@ -79,7 +79,7 @@ const DEFAULT_IGNORE_PATTERNS = [
'*.map', // source map files
];
export interface CodeIndexerConfig {
export interface CodeContextConfig {
embedding?: Embedding;
vectorDatabase?: VectorDatabase;
codeSplitter?: Splitter;
@@ -87,7 +87,7 @@ export interface CodeIndexerConfig {
ignorePatterns?: string[];
}
export class CodeIndexer {
export class CodeContext {
private embedding: Embedding;
private vectorDatabase: VectorDatabase;
private codeSplitter: Splitter;
@@ -95,7 +95,7 @@ export class CodeIndexer {
private ignorePatterns: string[];
private synchronizers = new Map<string, FileSynchronizer>();
constructor(config: CodeIndexerConfig = {}) {
constructor(config: CodeContextConfig = {}) {
// Initialize services
this.embedding = config.embedding || new OpenAIEmbedding({
apiKey: process.env.OPENAI_API_KEY || 'your-openai-api-key',

View File

@@ -2,5 +2,5 @@ export * from './splitter';
export * from './embedding';
export * from './vectordb';
export * from './types';
export * from './indexer';
export * from './context';
export * from './sync/synchronizer';

View File

@@ -21,7 +21,7 @@ export class FileSynchronizer {
private getSnapshotPath(codebasePath: string): string {
const homeDir = os.homedir();
const merkleDir = path.join(homeDir, '.codeindexer', 'merkle');
const merkleDir = path.join(homeDir, '.codecontext', 'merkle');
const normalizedPath = path.resolve(codebasePath);
const hash = crypto.createHash('md5').update(normalizedPath).digest('hex');
@@ -287,7 +287,7 @@ export class FileSynchronizer {
*/
static async deleteSnapshot(codebasePath: string): Promise<void> {
const homeDir = os.homedir();
const merkleDir = path.join(homeDir, '.codeindexer', 'merkle');
const merkleDir = path.join(homeDir, '.codecontext', 'merkle');
const normalizedPath = path.resolve(codebasePath);
const hash = crypto.createHash('md5').update(normalizedPath).digest('hex');
const snapshotPath = path.join(merkleDir, `${hash}.json`);

View File

@@ -86,7 +86,7 @@ export class MilvusVectorDatabase implements VectorDatabase {
const createCollectionParams = {
collection_name: collectionName,
description: description || `Code indexer collection: ${collectionName}`,
description: description || `Code context collection: ${collectionName}`,
fields: schema,
};

View File

@@ -21,7 +21,7 @@ import {
ListToolsRequestSchema,
CallToolRequestSchema
} from "@modelcontextprotocol/sdk/types.js";
import { CodeIndexer, SemanticSearchResult } from "@zilliz/code-context-core";
import { CodeContext, SemanticSearchResult } from "@zilliz/code-context-core";
import { OpenAIEmbedding, VoyageAIEmbedding, GeminiEmbedding, OllamaEmbedding } from "@zilliz/code-context-core";
import { MilvusVectorDatabase } from "@zilliz/code-context-core";
import * as path from "path";
@@ -63,7 +63,7 @@ function getEmbeddingModelForProvider(provider: string): string {
}
// Helper function to create embedding instance based on provider
function createEmbeddingInstance(config: CodeIndexerMcpConfig): OpenAIEmbedding | VoyageAIEmbedding | GeminiEmbedding | OllamaEmbedding {
function createEmbeddingInstance(config: CodeContextMcpConfig): OpenAIEmbedding | VoyageAIEmbedding | GeminiEmbedding | OllamaEmbedding {
console.log(`[EMBEDDING] Creating ${config.embeddingProvider} embedding instance...`);
switch (config.embeddingProvider) {
@@ -123,7 +123,7 @@ function createEmbeddingInstance(config: CodeIndexerMcpConfig): OpenAIEmbedding
}
}
interface CodeIndexerMcpConfig {
interface CodeContextMcpConfig {
name: string;
version: string;
// Embedding provider configuration
@@ -147,9 +147,9 @@ interface CodebaseSnapshot {
lastUpdated: string;
}
class CodeIndexerMcpServer {
class CodeContextMcpServer {
private server: Server;
private codeIndexer: CodeIndexer;
private codeContext: CodeContext;
private activeCodebasePath: string | null = null;
private indexedCodebases: string[] = [];
private indexingStats: { indexedFiles: number; totalChunks: number } | null = null;
@@ -157,13 +157,13 @@ class CodeIndexerMcpServer {
private snapshotFilePath: string;
private currentWorkspace: string;
constructor(config: CodeIndexerMcpConfig) {
constructor(config: CodeContextMcpConfig) {
// Get current workspace
this.currentWorkspace = process.cwd();
console.log(`[WORKSPACE] Current workspace: ${this.currentWorkspace}`);
// Initialize snapshot file path
this.snapshotFilePath = path.join(os.homedir(), '.code-indexer-mcp', 'codebase-snapshot.json');
this.snapshotFilePath = path.join(os.homedir(), '.code-context-mcp', 'codebase-snapshot.json');
// Initialize MCP server
this.server = new Server(
@@ -178,7 +178,7 @@ class CodeIndexerMcpServer {
}
);
// Initialize code indexer with proper configuration
// Initialize code context with proper configuration
console.log(`[EMBEDDING] Initializing embedding provider: ${config.embeddingProvider}`);
console.log(`[EMBEDDING] Using model: ${config.embeddingModel}`);
@@ -208,7 +208,7 @@ class CodeIndexerMcpServer {
...(config.milvusToken && { token: config.milvusToken })
});
this.codeIndexer = new CodeIndexer({
this.codeContext = new CodeContext({
embedding,
vectorDatabase
});
@@ -419,11 +419,11 @@ class CodeIndexerMcpServer {
// Clear index if force is true
if (forceReindex) {
await this.codeIndexer.clearIndex(absolutePath);
await this.codeContext.clearIndex(absolutePath);
}
// Use the existing CodeIndexer instance for indexing.
let indexerForThisTask = this.codeIndexer;
// Use the existing CodeContext instance for indexing.
let contextForThisTask = this.codeContext;
if (splitterType !== 'ast') {
console.warn(`[INDEX] Non-AST splitter '${splitterType}' requested; falling back to AST splitter`);
@@ -431,30 +431,30 @@ class CodeIndexerMcpServer {
// Initialize file synchronizer with proper ignore patterns
const { FileSynchronizer } = await import("@zilliz/code-context-core");
const ignorePatterns = this.codeIndexer['ignorePatterns'] || [];
const ignorePatterns = this.codeContext['ignorePatterns'] || [];
console.log(`[INDEX] Using ignore patterns: ${ignorePatterns.join(', ')}`);
const synchronizer = new FileSynchronizer(absolutePath, ignorePatterns);
await synchronizer.initialize();
// Store synchronizer in the indexer's internal map using the same collection name generation logic
// Store synchronizer in the context's internal map using the same collection name generation logic
const normalizedPath = path.resolve(absolutePath);
const hash = crypto.createHash('md5').update(normalizedPath).digest('hex');
const collectionName = `code_chunks_${hash.substring(0, 8)}`;
// Store synchronizer in both indexers if using a custom one
this.codeIndexer['synchronizers'].set(collectionName, synchronizer);
if (indexerForThisTask !== this.codeIndexer) {
indexerForThisTask['synchronizers'].set(collectionName, synchronizer);
// Store synchronizer in both contexts if using a custom one
this.codeContext['synchronizers'].set(collectionName, synchronizer);
if (contextForThisTask !== this.codeContext) {
contextForThisTask['synchronizers'].set(collectionName, synchronizer);
}
console.log(`[INDEX] Starting indexing with ${splitterType} splitter for: ${absolutePath}`);
// Log embedding provider information before indexing
const embeddingProvider = this.codeIndexer['embedding'];
const embeddingProvider = this.codeContext['embedding'];
console.log(`[INDEX] 🧠 Using embedding provider: ${embeddingProvider.getProvider()} with dimension: ${embeddingProvider.getDimension()}`);
// Start indexing with the appropriate indexer
// Start indexing with the appropriate context
console.log(`[INDEX] 🚀 Beginning codebase indexing process...`);
const stats = await indexerForThisTask.indexCodebase(absolutePath);
const stats = await contextForThisTask.indexCodebase(absolutePath);
console.log(`[INDEX] ✅ Indexing completed successfully! Files: ${stats.indexedFiles}, Chunks: ${stats.totalChunks}`);
// Store current codebase path and stats
@@ -533,8 +533,8 @@ class CodeIndexerMcpServer {
}
try {
console.log(`[SYNC-DEBUG] Calling codeIndexer.reindexByChange() for '${codebasePath}'`);
const stats = await this.codeIndexer.reindexByChange(codebasePath);
console.log(`[SYNC-DEBUG] Calling codeContext.reindexByChange() for '${codebasePath}'`);
const stats = await this.codeContext.reindexByChange(codebasePath);
const codebaseElapsed = Date.now() - codebaseStartTime;
console.log(`[SYNC-DEBUG] Reindex stats for '${codebasePath}':`, stats);
@@ -628,12 +628,12 @@ class CodeIndexerMcpServer {
console.log(`[SEARCH] Query: "${query}"`);
// Log embedding provider information before search
const embeddingProvider = this.codeIndexer['embedding'];
const embeddingProvider = this.codeContext['embedding'];
console.log(`[SEARCH] 🧠 Using embedding provider: ${embeddingProvider.getProvider()} for semantic search`);
console.log(`[SEARCH] 🔍 Generating embeddings for query using ${embeddingProvider.getProvider()}...`);
// Search in the specified codebase
const searchResults = await this.codeIndexer.semanticSearch(
const searchResults = await this.codeContext.semanticSearch(
absolutePath,
query,
Math.min(resultLimit, 50),
@@ -734,7 +734,7 @@ class CodeIndexerMcpServer {
console.log(`[CLEAR] Clearing codebase: ${absolutePath}`);
try {
await this.codeIndexer.clearIndex(absolutePath);
await this.codeContext.clearIndex(absolutePath);
console.log(`[CLEAR] Successfully cleared index for: ${absolutePath}`);
} catch (error: any) {
const errorMsg = `Failed to clear ${absolutePath}: ${error.message}`;
@@ -818,7 +818,7 @@ class CodeIndexerMcpServer {
async start() {
console.log('[SYNC-DEBUG] MCP server start() method called');
console.log('Starting CodeIndexer MCP server...');
console.log('Starting CodeContext MCP server...');
const transport = new StdioServerTransport();
console.log('[SYNC-DEBUG] StdioServerTransport created, attempting server connection...');
@@ -866,7 +866,7 @@ async function main() {
const args = process.argv.slice(2);
const embeddingProvider = (process.env.EMBEDDING_PROVIDER?.toLowerCase() === 'ollama' ? 'ollama' : 'openai') as 'openai' | 'ollama';
// Debug: Print all environment variables related to CodeIndexer
// Debug: Print all environment variables related to CodeContext
console.log(`[DEBUG] 🔍 Environment Variables Debug:`);
console.log(`[DEBUG] EMBEDDING_PROVIDER: ${process.env.EMBEDDING_PROVIDER || 'NOT SET'}`);
console.log(`[DEBUG] EMBEDDING_MODEL: ${process.env.EMBEDDING_MODEL || 'NOT SET'}`);
@@ -876,8 +876,8 @@ async function main() {
console.log(`[DEBUG] MILVUS_ADDRESS: ${process.env.MILVUS_ADDRESS || 'NOT SET'}`);
console.log(`[DEBUG] NODE_ENV: ${process.env.NODE_ENV || 'NOT SET'}`);
const config: CodeIndexerMcpConfig = {
name: process.env.MCP_SERVER_NAME || "CodeIndexer MCP Server",
const config: CodeContextMcpConfig = {
name: process.env.MCP_SERVER_NAME || "CodeContext MCP Server",
version: process.env.MCP_SERVER_VERSION || "1.0.0",
// Embedding provider configuration
embeddingProvider: (process.env.EMBEDDING_PROVIDER as 'OpenAI' | 'VoyageAI' | 'Gemini' | 'Ollama') || 'OpenAI',
@@ -898,9 +898,9 @@ async function main() {
// Show help if requested
if (args.includes('--help') || args.includes('-h')) {
console.log(`
CodeIndexer MCP Server
CodeContext MCP Server
Usage: npx @code-indexer/mcp@latest [options]
Usage: npx @zilliz/code-context-mcp@latest [options]
Options:
--help, -h Show this help message
@@ -929,22 +929,22 @@ Environment Variables:
Examples:
# Start MCP server with OpenAI (default)
OPENAI_API_KEY=sk-xxx npx @code-indexer/mcp@latest
OPENAI_API_KEY=sk-xxx npx @zilliz/code-context-mcp@latest
# Start MCP server with VoyageAI
EMBEDDING_PROVIDER=VoyageAI VOYAGEAI_API_KEY=pa-xxx npx @code-indexer/mcp@latest
EMBEDDING_PROVIDER=VoyageAI VOYAGEAI_API_KEY=pa-xxx npx @zilliz/code-context-mcp@latest
# Start MCP server with Gemini
EMBEDDING_PROVIDER=Gemini GEMINI_API_KEY=xxx npx @code-indexer/mcp@latest
EMBEDDING_PROVIDER=Gemini GEMINI_API_KEY=xxx npx @zilliz/code-context-mcp@latest
# Start MCP server with Ollama
EMBEDDING_PROVIDER=Ollama EMBEDDING_MODEL=nomic-embed-text npx @code-indexer/mcp@latest
EMBEDDING_PROVIDER=Ollama EMBEDDING_MODEL=nomic-embed-text npx @zilliz/code-context-mcp@latest
`);
process.exit(0);
}
// Log configuration summary before starting server
console.log(`[MCP] 🚀 Starting CodeIndexer MCP Server`);
console.log(`[MCP] 🚀 Starting CodeContext MCP Server`);
console.log(`[MCP] Configuration Summary:`);
console.log(`[MCP] Server: ${config.name} v${config.version}`);
console.log(`[MCP] Embedding Provider: ${config.embeddingProvider}`);
@@ -973,7 +973,7 @@ Examples:
console.log(`[MCP] 🔧 Initializing server components...`);
const server = new CodeIndexerMcpServer(config);
const server = new CodeContextMcpServer(config);
await server.start();
}

View File

@@ -2,7 +2,7 @@
[![Visual Studio Marketplace](https://img.shields.io/visual-studio-marketplace/v/zilliz.semanticcodesearch?label=VS%20Code%20Marketplace&logo=visual-studio-code)](https://marketplace.visualstudio.com/items?itemName=zilliz.semanticcodesearch)
A code indexing and semantic search VSCode extension powered by Code Context.
A code indexing and semantic search VSCode extension powered by [Code Context](https://github.com/zilliztech/code-context).
> 📖 **New to Code Context?** Check out the [main project README](../../README.md) for an overview and setup instructions.

View File

@@ -1,21 +1,21 @@
import * as vscode from 'vscode';
import { CodeIndexer } from '@zilliz/code-context-core';
import { CodeContext } from '@zilliz/code-context-core';
import * as path from 'path';
import * as fs from 'fs';
import * as crypto from 'crypto';
export class IndexCommand {
private codeIndexer: CodeIndexer;
private codeContext: CodeContext;
constructor(codeIndexer: CodeIndexer) {
this.codeIndexer = codeIndexer;
constructor(codeContext: CodeContext) {
this.codeContext = codeContext;
}
/**
* Update the CodeIndexer instance (used when configuration changes)
* Update the CodeContext instance (used when configuration changes)
*/
updateCodeIndexer(codeIndexer: CodeIndexer): void {
this.codeIndexer = codeIndexer;
updateCodeContext(codeContext: CodeContext): void {
this.codeContext = codeContext;
}
/**
@@ -30,12 +30,12 @@ export class IndexCommand {
if (fs.existsSync(gitignorePath)) {
console.log(`📄 Found .gitignore file at: ${gitignorePath}`);
// Use the static method from CodeIndexer to read ignore patterns
const ignorePatterns = await CodeIndexer.getIgnorePatternsFromFile(gitignorePath);
// Use the static method from CodeContext to read ignore patterns
const ignorePatterns = await CodeContext.getIgnorePatternsFromFile(gitignorePath);
if (ignorePatterns.length > 0) {
// Update the CodeIndexer instance with new patterns
this.codeIndexer.updateIgnorePatterns(ignorePatterns);
// Update the CodeContext instance with new patterns
this.codeContext.updateIgnorePatterns(ignorePatterns);
console.log(`🚫 Loaded ${ignorePatterns.length} ignore patterns from .gitignore`);
vscode.window.showInformationMessage(
@@ -46,13 +46,13 @@ export class IndexCommand {
}
} else {
console.log('📄 No .gitignore file found, using default ignore patterns only');
// No need to update patterns - CodeIndexer will use defaults
// No need to update patterns - CodeContext will use defaults
}
} catch (error) {
console.warn(`⚠️ Failed to load .gitignore patterns: ${error}`);
vscode.window.showWarningMessage(`⚠️ Failed to load .gitignore: ${error}`);
// Continue with default patterns on error
this.codeIndexer.updateIgnorePatterns([]);
this.codeContext.updateIgnorePatterns([]);
}
}
@@ -108,7 +108,7 @@ export class IndexCommand {
await this.loadGitignorePatterns(selectedFolder.uri.fsPath);
// Clear existing index first
await this.codeIndexer.clearIndex(
await this.codeContext.clearIndex(
selectedFolder.uri.fsPath,
(progressInfo) => {
// Clear index progress is usually fast, just show the message
@@ -119,16 +119,16 @@ export class IndexCommand {
// Initialize file synchronizer
progress.report({ increment: 0, message: 'Initializing file synchronizer...' });
const { FileSynchronizer } = await import("@zilliz/code-context-core");
const synchronizer = new FileSynchronizer(selectedFolder.uri.fsPath, this.codeIndexer['ignorePatterns'] || []);
const synchronizer = new FileSynchronizer(selectedFolder.uri.fsPath, this.codeContext['ignorePatterns'] || []);
await synchronizer.initialize();
// Store synchronizer in the indexer's internal map using the same collection name generation logic
// Store synchronizer in the context's internal map using the same collection name generation logic
const normalizedPath = path.resolve(selectedFolder.uri.fsPath);
const hash = crypto.createHash('md5').update(normalizedPath).digest('hex');
const collectionName = `code_chunks_${hash.substring(0, 8)}`;
this.codeIndexer['synchronizers'].set(collectionName, synchronizer);
this.codeContext['synchronizers'].set(collectionName, synchronizer);
// Start indexing with progress callback
indexStats = await this.codeIndexer.indexCodebase(
indexStats = await this.codeContext.indexCodebase(
selectedFolder.uri.fsPath,
(progressInfo) => {
// Calculate increment from last reported percentage
@@ -178,7 +178,7 @@ export class IndexCommand {
title: 'Clearing Index',
cancellable: false
}, async (progress) => {
await this.codeIndexer.clearIndex(
await this.codeContext.clearIndex(
workspaceFolders[0].uri.fsPath,
(progressInfo) => {
progress.report({

View File

@@ -1,19 +1,19 @@
import * as vscode from 'vscode';
import { CodeIndexer, SearchQuery, SemanticSearchResult } from '@zilliz/code-context-core';
import { CodeContext, SearchQuery, SemanticSearchResult } from '@zilliz/code-context-core';
import * as path from 'path';
export class SearchCommand {
private codeIndexer: CodeIndexer;
private codeContext: CodeContext;
constructor(codeIndexer: CodeIndexer) {
this.codeIndexer = codeIndexer;
constructor(codeContext: CodeContext) {
this.codeContext = codeContext;
}
/**
* Update the CodeIndexer instance (used when configuration changes)
* Update the CodeContext instance (used when configuration changes)
*/
updateCodeIndexer(codeIndexer: CodeIndexer): void {
this.codeIndexer = codeIndexer;
updateCodeContext(codeContext: CodeContext): void {
this.codeContext = codeContext;
}
async execute(preSelectedText?: string): Promise<void> {
@@ -59,7 +59,7 @@ export class SearchCommand {
limit: 20
};
const results = await this.codeIndexer.semanticSearch(
const results = await this.codeContext.semanticSearch(
codebasePath,
query.term,
query.limit || 20,
@@ -136,7 +136,7 @@ export class SearchCommand {
const codebasePath = workspaceFolders[0].uri.fsPath;
// Use the semantic search service
return await this.codeIndexer.semanticSearch(
return await this.codeContext.semanticSearch(
codebasePath,
searchTerm,
limit,
@@ -148,7 +148,7 @@ export class SearchCommand {
* Check if index exists for the given codebase path
*/
async hasIndex(codebasePath: string): Promise<boolean> {
return await this.codeIndexer.hasIndex(codebasePath);
return await this.codeContext.hasIndex(codebasePath);
}
/**

View File

@@ -1,20 +1,20 @@
import * as vscode from 'vscode';
import { CodeIndexer } from '@zilliz/code-context-core';
import { CodeContext } from '@zilliz/code-context-core';
import * as fs from 'fs';
export class SyncCommand {
private codeIndexer: CodeIndexer;
private codeContext: CodeContext;
private isSyncing: boolean = false;
constructor(codeIndexer: CodeIndexer) {
this.codeIndexer = codeIndexer;
constructor(codeContext: CodeContext) {
this.codeContext = codeContext;
}
/**
* Update the CodeIndexer instance (used when configuration changes)
* Update the CodeContext instance (used when configuration changes)
*/
updateCodeIndexer(codeIndexer: CodeIndexer): void {
this.codeIndexer = codeIndexer;
updateCodeContext(codeContext: CodeContext): void {
this.codeContext = codeContext;
}
/**
@@ -57,7 +57,7 @@ export class SyncCommand {
progress.report({ increment: 0, message: 'Checking for file changes...' });
try {
syncStats = await this.codeIndexer.reindexByChange(
syncStats = await this.codeContext.reindexByChange(
codebasePath,
(progressInfo) => {
const increment = progressInfo.percentage;
@@ -148,7 +148,7 @@ export class SyncCommand {
this.isSyncing = true;
try {
const syncStats = await this.codeIndexer.reindexByChange(codebasePath);
const syncStats = await this.codeContext.reindexByChange(codebasePath);
const totalChanges = syncStats.added + syncStats.removed + syncStats.modified;

View File

@@ -5,29 +5,29 @@ import { SearchCommand } from './commands/searchCommand';
import { IndexCommand } from './commands/indexCommand';
import { SyncCommand } from './commands/syncCommand';
import { ConfigManager } from './config/configManager';
import { CodeIndexer, OpenAIEmbedding, VoyageAIEmbedding, GeminiEmbedding, MilvusRestfulVectorDatabase, AstCodeSplitter, LangChainCodeSplitter, SplitterType } from '@zilliz/code-context-core';
import { CodeContext, OpenAIEmbedding, VoyageAIEmbedding, GeminiEmbedding, MilvusRestfulVectorDatabase, AstCodeSplitter, LangChainCodeSplitter, SplitterType } from '@zilliz/code-context-core';
let semanticSearchProvider: SemanticSearchViewProvider;
let searchCommand: SearchCommand;
let indexCommand: IndexCommand;
let syncCommand: SyncCommand;
let configManager: ConfigManager;
let codeIndexer: CodeIndexer;
let codeContext: CodeContext;
let autoSyncDisposable: vscode.Disposable | null = null;
export async function activate(context: vscode.ExtensionContext) {
console.log('CodeIndexer extension is now active!');
console.log('CodeContext extension is now active!');
// Initialize config manager
configManager = new ConfigManager(context);
// Initialize shared codeIndexer instance with embedding configuration
codeIndexer = createCodeIndexerWithConfig(configManager);
// Initialize shared codeContext instance with embedding configuration
codeContext = createCodeContextWithConfig(configManager);
// Initialize providers and commands
searchCommand = new SearchCommand(codeIndexer);
indexCommand = new IndexCommand(codeIndexer);
syncCommand = new SyncCommand(codeIndexer);
searchCommand = new SearchCommand(codeContext);
indexCommand = new IndexCommand(codeContext);
syncCommand = new SyncCommand(codeContext);
semanticSearchProvider = new SemanticSearchViewProvider(context.extensionUri, searchCommand, indexCommand, syncCommand, configManager);
// Register command handlers
@@ -45,8 +45,8 @@ export async function activate(context: vscode.ExtensionContext) {
event.affectsConfiguration('semanticCodeSearch.milvus') ||
event.affectsConfiguration('semanticCodeSearch.splitter') ||
event.affectsConfiguration('semanticCodeSearch.autoSync')) {
console.log('CodeIndexer configuration changed, reloading...');
reloadCodeIndexerConfiguration();
console.log('CodeContext configuration changed, reloading...');
reloadCodeContextConfiguration();
}
}),
@@ -59,7 +59,7 @@ export async function activate(context: vscode.ExtensionContext) {
}),
vscode.commands.registerCommand('semanticCodeSearch.indexCodebase', () => indexCommand.execute()),
vscode.commands.registerCommand('semanticCodeSearch.clearIndex', () => indexCommand.clearIndex()),
vscode.commands.registerCommand('semanticCodeSearch.reloadConfiguration', () => reloadCodeIndexerConfiguration())
vscode.commands.registerCommand('semanticCodeSearch.reloadConfiguration', () => reloadCodeContextConfiguration())
];
context.subscriptions.push(...disposables);
@@ -72,7 +72,7 @@ export async function activate(context: vscode.ExtensionContext) {
// Show status bar item
const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
statusBarItem.text = `$(search) CodeIndexer`;
statusBarItem.text = `$(search) CodeContext`;
statusBarItem.tooltip = 'Click to open semantic search';
statusBarItem.command = 'semanticCodeSearch.semanticSearch';
statusBarItem.show();
@@ -117,7 +117,7 @@ function setupAutoSync() {
}
}
function createCodeIndexerWithConfig(configManager: ConfigManager): CodeIndexer {
function createCodeContextWithConfig(configManager: ConfigManager): CodeContext {
const embeddingConfig = configManager.getEmbeddingProviderConfig();
const milvusConfig = configManager.getMilvusFullConfig();
const splitterConfig = configManager.getSplitterConfig();
@@ -126,13 +126,13 @@ function createCodeIndexerWithConfig(configManager: ConfigManager): CodeIndexer
let embedding;
let vectorDatabase;
const codeIndexerConfig: any = {};
const codeContextConfig: any = {};
// Create embedding instance
if (embeddingConfig) {
embedding = ConfigManager.createEmbeddingInstance(embeddingConfig.provider, embeddingConfig.config);
console.log(`Embedding initialized with ${embeddingConfig.provider} (model: ${embeddingConfig.config.model})`);
codeIndexerConfig.embedding = embedding;
codeContextConfig.embedding = embedding;
} else {
console.log('No embedding configuration found');
}
@@ -141,14 +141,14 @@ function createCodeIndexerWithConfig(configManager: ConfigManager): CodeIndexer
if (milvusConfig) {
vectorDatabase = new MilvusRestfulVectorDatabase(milvusConfig);
console.log(`Vector database initialized with Milvus REST API (address: ${milvusConfig.address})`);
codeIndexerConfig.vectorDatabase = vectorDatabase;
codeContextConfig.vectorDatabase = vectorDatabase;
} else {
vectorDatabase = new MilvusRestfulVectorDatabase({
address: process.env.MILVUS_ADDRESS || 'http://localhost:19530',
token: process.env.MILVUS_TOKEN || ''
});
console.log('No Milvus configuration found, using default REST API configuration');
codeIndexerConfig.vectorDatabase = vectorDatabase;
codeContextConfig.vectorDatabase = vectorDatabase;
}
// Create splitter instance
@@ -165,23 +165,23 @@ function createCodeIndexerWithConfig(configManager: ConfigManager): CodeIndexer
splitterConfig.chunkOverlap ?? 300
);
}
codeIndexerConfig.codeSplitter = codeSplitter;
codeContextConfig.codeSplitter = codeSplitter;
console.log(`Splitter configured: ${splitterConfig.type} (chunkSize: ${splitterConfig.chunkSize}, overlap: ${splitterConfig.chunkOverlap})`);
} else {
codeSplitter = new AstCodeSplitter(2500, 300);
codeIndexerConfig.codeSplitter = codeSplitter;
codeContextConfig.codeSplitter = codeSplitter;
console.log('No splitter configuration found, using default AST splitter (chunkSize: 2500, overlap: 300)');
}
return new CodeIndexer(codeIndexerConfig);
return new CodeContext(codeContextConfig);
} catch (error) {
console.error('Failed to create CodeIndexer with user config:', error);
vscode.window.showErrorMessage(`Failed to initialize CodeIndexer: ${error instanceof Error ? error.message : 'Unknown error'}`);
console.error('Failed to create CodeContext with user config:', error);
vscode.window.showErrorMessage(`Failed to initialize CodeContext: ${error instanceof Error ? error.message : 'Unknown error'}`);
throw error;
}
}
function reloadCodeIndexerConfiguration() {
console.log('Reloading CodeIndexer configuration...');
function reloadCodeContextConfiguration() {
console.log('Reloading CodeContext configuration...');
const embeddingConfig = configManager.getEmbeddingProviderConfig();
const milvusConfig = configManager.getMilvusFullConfig();
@@ -191,14 +191,14 @@ function reloadCodeIndexerConfiguration() {
// Update embedding if configuration exists
if (embeddingConfig) {
const embedding = ConfigManager.createEmbeddingInstance(embeddingConfig.provider, embeddingConfig.config);
codeIndexer.updateEmbedding(embedding);
codeContext.updateEmbedding(embedding);
console.log(`Embedding updated with ${embeddingConfig.provider} (model: ${embeddingConfig.config.model})`);
}
// Update vector database if configuration exists
if (milvusConfig) {
const vectorDatabase = new MilvusRestfulVectorDatabase(milvusConfig);
codeIndexer.updateVectorDatabase(vectorDatabase);
codeContext.updateVectorDatabase(vectorDatabase);
console.log(`Vector database updated with Milvus REST API (address: ${milvusConfig.address})`);
}
@@ -216,32 +216,32 @@ function reloadCodeIndexerConfiguration() {
splitterConfig.chunkOverlap ?? 300
);
}
codeIndexer.updateSplitter(newSplitter);
codeContext.updateSplitter(newSplitter);
console.log(`Splitter updated: ${splitterConfig.type} (chunkSize: ${splitterConfig.chunkSize}, overlap: ${splitterConfig.chunkOverlap})`);
} else {
const defaultSplitter = new AstCodeSplitter(2500, 300);
codeIndexer.updateSplitter(defaultSplitter);
codeContext.updateSplitter(defaultSplitter);
console.log('No splitter configuration found, using default AST splitter (chunkSize: 2500, overlap: 300)');
}
// Update command instances with new codeIndexer
searchCommand.updateCodeIndexer(codeIndexer);
indexCommand.updateCodeIndexer(codeIndexer);
syncCommand.updateCodeIndexer(codeIndexer);
// Update command instances with new codeContext
searchCommand.updateCodeContext(codeContext);
indexCommand.updateCodeContext(codeContext);
syncCommand.updateCodeContext(codeContext);
// Restart auto-sync if it was enabled
setupAutoSync();
console.log('CodeIndexer configuration reloaded successfully');
console.log('CodeContext configuration reloaded successfully');
vscode.window.showInformationMessage('Configuration reloaded successfully!');
} catch (error) {
console.error('Failed to reload CodeIndexer configuration:', error);
console.error('Failed to reload CodeContext configuration:', error);
vscode.window.showErrorMessage(`Failed to reload configuration: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
export function deactivate() {
console.log('CodeIndexer extension is now deactivated');
console.log('CodeContext extension is now deactivated');
// Stop auto-sync if running
if (autoSyncDisposable) {

View File

@@ -259,7 +259,7 @@ export class SemanticSearchViewProvider implements vscode.WebviewViewProvider {
// Add a small delay to ensure configuration is fully saved
await new Promise(resolve => setTimeout(resolve, 100));
// Notify extension to recreate CodeIndexer with new config
// Notify extension to recreate CodeContext with new config
vscode.commands.executeCommand('semanticCodeSearch.reloadConfiguration');
webview.postMessage({
@@ -268,7 +268,7 @@ export class SemanticSearchViewProvider implements vscode.WebviewViewProvider {
message: 'Configuration saved successfully!'
});
vscode.window.showInformationMessage('CodeIndexer configuration saved successfully!');
vscode.window.showInformationMessage('CodeContext configuration saved successfully!');
} catch (error) {
webview.postMessage({
command: 'saveResult',

View File

@@ -17,7 +17,8 @@
<div class="header-section">
<div class="title-section">
<h3>🔍 Semantic Code Search</h3>
<p class="subtitle">built by CodeIndexer</p>
<p class="subtitle">built by <a href="https://github.com/zilliztech/code-context"
target="_blank">Code Context</a></p>
</div>
<button id="settingsButton" class="settings-button" title="Settings">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor"

View File

@@ -47,7 +47,7 @@ from ts_executor import TypeScriptExecutor
executor = TypeScriptExecutor()
result = executor.call_method(
'./test_codecontext.ts',
'testCodeIndexerEndToEnd',
'testCodeContextEndToEnd',
{
'openaiApiKey': 'sk-your-key',
'milvusAddress': 'localhost:19530',

View File

@@ -1,20 +1,20 @@
import { CodeIndexer } from '../packages/core/src/indexer';
import { CodeContext } from '../packages/core/src/context';
import { OpenAIEmbedding } from '../packages/core/src/embedding/openai-embedding';
import { MilvusVectorDatabase } from '../packages/core/src/vectordb/milvus-vectordb';
import { AstCodeSplitter } from '../packages/core/src/splitter/ast-splitter';
/**
* CodeIndexer End-to-End Test - Complete Workflow
* Includes: Configure Embedding → Configure Vector Database → Create Indexer → Index Codebase → Semantic Search
* CodeContext End-to-End Test - Complete Workflow
* Includes: Configure Embedding → Configure Vector Database → Create Context → Index Codebase → Semantic Search
*/
export async function testCodeIndexerEndToEnd(config: {
export async function testCodeContextEndToEnd(config: {
openaiApiKey: string;
milvusAddress: string;
codebasePath: string;
searchQuery: string;
}) {
try {
console.log('🚀 Starting CodeIndexer end-to-end test...');
console.log('🚀 Starting CodeContext end-to-end test...');
// 1. Create embedding instance
console.log('📝 Creating OpenAI embedding instance...');
@@ -29,10 +29,10 @@ export async function testCodeIndexerEndToEnd(config: {
address: config.milvusAddress
});
// 3. Create CodeIndexer instance
console.log('🔧 Creating CodeIndexer instance...');
// 3. Create CodeContext instance
console.log('🔧 Creating CodeContext instance...');
const codeSplitter = new AstCodeSplitter(1000, 200);
const indexer = new CodeIndexer({
const context = new CodeContext({
embedding: embedding,
vectorDatabase: vectorDB,
codeSplitter: codeSplitter
@@ -40,14 +40,14 @@ export async function testCodeIndexerEndToEnd(config: {
// 4. Check if index already exists
console.log('🔍 Checking existing index...');
const hasIndex = await indexer.hasIndex(config.codebasePath);
const hasIndex = await context.hasIndex(config.codebasePath);
console.log(`Existing index status: ${hasIndex}`);
// 5. Index codebase
let indexStats;
if (!hasIndex) {
console.log('📚 Starting codebase indexing...');
indexStats = await indexer.indexCodebase(config.codebasePath, (progress) => {
indexStats = await context.indexCodebase(config.codebasePath, (progress) => {
console.log(`Indexing progress: ${progress.phase} - ${progress.percentage}%`);
});
console.log('✅ Indexing completed');
@@ -58,7 +58,7 @@ export async function testCodeIndexerEndToEnd(config: {
// 6. Execute semantic search
console.log('🔎 Executing semantic search...');
const searchResults = await indexer.semanticSearch(
const searchResults = await context.semanticSearch(
config.codebasePath,
config.searchQuery,
5, // topK

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python3
"""
CodeIndexer End-to-End Test
Use TypeScriptExecutor to call complete CodeIndexer workflow
CodeContext End-to-End Test
Use TypeScriptExecutor to call complete CodeContext workflow
"""
import os
@@ -14,18 +14,20 @@ sys.path.append(str(Path(__file__).parent))
from ts_executor import TypeScriptExecutor
def run_codeindexer_endtoend_test():
"""Run CodeIndexer end-to-end test"""
def run_codecontext_endtoend_test():
"""Run CodeContext end-to-end test"""
# Configuration parameters
config = {
"openaiApiKey": os.environ.get("OPENAI_API_KEY", "your-openai-api-key"),
"milvusAddress": os.environ.get("MILVUS_ADDRESS", "localhost:19530"),
"codebasePath": "../packages/core/src", # Index core source code
"codebasePath": str(
Path(__file__).parent.parent / "packages" / "core" / "src"
), # Index core source code
"searchQuery": "embedding creation and vector database configuration",
}
print("🚀 Starting CodeIndexer end-to-end test")
print("🚀 Starting CodeContext end-to-end test")
print(f"📊 Configuration:")
print(f" - Codebase path: {config['codebasePath']}")
print(f" - Vector database: {config['milvusAddress']}")
@@ -40,7 +42,7 @@ def run_codeindexer_endtoend_test():
# Call end-to-end test
result = executor.call_method(
"./test_codecontext.ts", "testCodeIndexerEndToEnd", config
"./test_codecontext.ts", "testCodeContextEndToEnd", config
)
# Output results
@@ -102,19 +104,19 @@ def run_codeindexer_endtoend_test():
def main():
"""Main function"""
print("=" * 60)
print("🧪 CodeIndexer End-to-End Test")
print("🧪 CodeContext End-to-End Test")
print("=" * 60)
print()
success = run_codeindexer_endtoend_test()
success = run_codecontext_endtoend_test()
print()
print("=" * 60)
if success:
print("🎉 Test completed! CodeIndexer end-to-end workflow runs successfully!")
print("🎉 Test completed! CodeContext end-to-end workflow runs successfully!")
print()
print("💡 This proves:")
print(" ✅ Can call TypeScript CodeIndexer from Python")
print(" ✅ Can call TypeScript CodeContext from Python")
print(" ✅ Supports complete indexing and search workflow")
print(" ✅ Supports complex configuration and parameter passing")
print(" ✅ Can get detailed execution results and statistics")

View File

@@ -61,39 +61,64 @@ class TypeScriptExecutor:
f.write(wrapper_code)
# Execute TypeScript code using ts-node
result = subprocess.run(
# Use subprocess.Popen to capture output in real-time
process = subprocess.Popen(
["npx", "ts-node", temp_file],
capture_output=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=True,
cwd=self.working_dir,
bufsize=1, # Line buffering
universal_newlines=True,
)
# Parse results
if result.stdout.strip():
# Try to extract JSON part from output
import re
stdout_lines = []
stderr_lines = []
output = result.stdout.strip()
# Find the last complete JSON object - improved regex
json_match = re.search(
r"\{.*\}(?=\s*$)", output, re.DOTALL | re.MULTILINE
)
if json_match:
# Read output line by line and display console.log in real-time
while True:
output = process.stdout.readline()
if output == "" and process.poll() is not None:
break
if output:
line = output.strip()
stdout_lines.append(line)
# Try to parse as JSON to see if it's the final result
try:
return json.loads(json_match.group())
json.loads(line)
# If it parses as JSON, it might be the final result, don't print it yet
except json.JSONDecodeError:
pass
# If no JSON found, try direct parsing
# If it's not JSON, it's likely a console.log, so print it
print(line)
# Get any remaining stderr
stderr_output = process.stderr.read()
if stderr_output:
stderr_lines.append(stderr_output.strip())
return_code = process.poll()
if return_code != 0:
error_msg = "\n".join(stderr_lines) if stderr_lines else "Unknown error"
raise RuntimeError(f"TypeScript execution failed: {error_msg}")
# Parse results from the last line that looks like JSON
for line in reversed(stdout_lines):
if line.strip():
try:
return json.loads(output)
# Try to parse as JSON
return json.loads(line)
except json.JSONDecodeError:
return output # Return raw output
else:
continue
# If no JSON found, return the last non-empty line
for line in reversed(stdout_lines):
if line.strip():
return line
return None
except subprocess.CalledProcessError as e:
raise RuntimeError(f"TypeScript execution failed: {e.stderr}")
except Exception as e:
raise RuntimeError(f"Execution error: {str(e)}")
finally: