Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/getting-started/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Claude Context supports a global configuration file at `~/.context/.env` to simp
| `SPLITTER_TYPE` | Code splitter type: `ast`, `langchain` | `ast` |
| `CUSTOM_EXTENSIONS` | Additional file extensions to include (comma-separated, e.g., `.vue,.svelte,.astro`) | None |
| `CUSTOM_IGNORE_PATTERNS` | Additional ignore patterns (comma-separated, e.g., `temp/**,*.backup,private/**`) | None |
| `CONTEXT_ENCRYPTION_KEY` | Encryption key for content encryption. Can be a 64-character hex string or any string (will be hashed). **Note: Only works in semantic search mode (`HYBRID_MODE=false`). Automatically disabled in hybrid mode as BM25 requires plain text.** | None (encryption disabled) |

## 🚀 Quick Setup

Expand Down
85 changes: 66 additions & 19 deletions examples/basic-usage/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Context, MilvusVectorDatabase, MilvusRestfulVectorDatabase, AstCodeSplitter, LangChainCodeSplitter } from '@zilliz/claude-context-core';
import { Context, MilvusVectorDatabase, MilvusRestfulVectorDatabase, PostgresVectorDatabase, AstCodeSplitter, LangChainCodeSplitter, OllamaEmbedding, OpenAIEmbedding } from '@zilliz/claude-context-core';
import { envManager } from '@zilliz/claude-context-core';
import * as path from 'path';

Expand All @@ -15,29 +15,48 @@ async function main() {

try {
// 1. Choose Vector Database implementation
// Set to true to use RESTful API (for environments without gRPC support)
// Set to false to use gRPC (default, more efficient)
const useRestfulApi = false;
const milvusAddress = envManager.get('MILVUS_ADDRESS') || 'localhost:19530';
const milvusToken = envManager.get('MILVUS_TOKEN');
const vectorDbProvider = envManager.get('VECTOR_DATABASE_PROVIDER')?.toLowerCase() || 'milvus';
const useRestfulApi = envManager.get('MILVUS_USE_RESTFUL') === 'true';
const splitterType = envManager.get('SPLITTER_TYPE')?.toLowerCase() || 'ast';

console.log(`🔧 Using ${useRestfulApi ? 'RESTful API' : 'gRPC'} implementation`);
console.log(`🔌 Connecting to Milvus at: ${milvusAddress}`);
console.log(`🔧 Using vector database provider: ${vectorDbProvider}`);

let vectorDatabase;
if (useRestfulApi) {
// Use RESTful implementation (for environments without gRPC support)
vectorDatabase = new MilvusRestfulVectorDatabase({
address: milvusAddress,
...(milvusToken && { token: milvusToken })
});
if (vectorDbProvider === 'postgres') {
// Use PostgreSQL with pgvector
const postgresConfig = {
connectionString: envManager.get('POSTGRES_CONNECTION_STRING'),
host: envManager.get('POSTGRES_HOST') || 'localhost',
port: envManager.get('POSTGRES_PORT') ? parseInt(envManager.get('POSTGRES_PORT')!) : 5432,
database: envManager.get('POSTGRES_DATABASE') || 'postgres',
username: envManager.get('POSTGRES_USERNAME') || 'postgres',
password: envManager.get('POSTGRES_PASSWORD'),
ssl: envManager.get('POSTGRES_SSL') === 'true'
};

console.log(`🔌 Connecting to PostgreSQL at: ${postgresConfig.connectionString || `${postgresConfig.host}:${postgresConfig.port}/${postgresConfig.database}`}`);
vectorDatabase = new PostgresVectorDatabase(postgresConfig);
} else {
// Use gRPC implementation (default, more efficient)
vectorDatabase = new MilvusVectorDatabase({
address: milvusAddress,
...(milvusToken && { token: milvusToken })
});
// Use Milvus (default)
const milvusAddress = envManager.get('MILVUS_ADDRESS') || 'localhost:19530';
const milvusToken = envManager.get('MILVUS_TOKEN');

console.log(`🔧 Using ${useRestfulApi ? 'RESTful API' : 'gRPC'} implementation`);
console.log(`🔌 Connecting to Milvus at: ${milvusAddress}`);

if (useRestfulApi) {
// Use RESTful implementation (for environments without gRPC support)
vectorDatabase = new MilvusRestfulVectorDatabase({
address: milvusAddress,
...(milvusToken && { token: milvusToken })
});
} else {
// Use gRPC implementation (default, more efficient)
vectorDatabase = new MilvusVectorDatabase({
address: milvusAddress,
...(milvusToken && { token: milvusToken })
});
}
}

// 2. Create Context instance
Expand All @@ -47,7 +66,26 @@ async function main() {
} else {
codeSplitter = new AstCodeSplitter(2500, 300);
}

console.log('🔧 Using embedding provider: ', envManager.get('EMBEDDING_PROVIDER'));
let embedding;
const embeddingProvider = envManager.get('EMBEDDING_PROVIDER')?.toLowerCase() || 'openai';
if (embeddingProvider === 'ollama') {
console.log('🔧 Using Ollama embedding provider');
embedding = new OllamaEmbedding({
host: envManager.get('OLLAMA_HOST') || 'http://127.0.0.1:11434',
model: envManager.get('EMBEDDING_MODEL') || 'all-minilm'
});
} else {
embedding = new OpenAIEmbedding({
model: 'text-embedding-3-small',
apiKey: envManager.get('OPENAI_API_KEY') || 'your-openai-api-key',
baseURL: envManager.get('OPENAI_BASE_URL') || 'https://api.openai.com/v1'
});
}

const context = new Context({
embedding,
vectorDatabase,
codeSplitter,
supportedExtensions: ['.ts', '.js', '.py', '.java', '.cpp', '.go', '.rs']
Expand Down Expand Up @@ -119,8 +157,17 @@ async function main() {
console.log('\n💡 Environment Variables:');
console.log(' - OPENAI_API_KEY: Your OpenAI API key (required)');
console.log(' - OPENAI_BASE_URL: Custom OpenAI API endpoint (optional)');
console.log(' - VECTOR_DATABASE_PROVIDER: Vector database provider - "milvus" or "postgres" (default: milvus)');
console.log(' - MILVUS_ADDRESS: Milvus server address (default: localhost:19530)');
console.log(' - MILVUS_TOKEN: Milvus authentication token (optional)');
console.log(' - MILVUS_USE_RESTFUL: Use Milvus REST API instead of gRPC (true/false, default: false)');
console.log(' - POSTGRES_CONNECTION_STRING: PostgreSQL connection string (e.g., postgresql://user:pass@localhost:5432/db)');
console.log(' - POSTGRES_HOST: PostgreSQL host (default: localhost)');
console.log(' - POSTGRES_PORT: PostgreSQL port (default: 5432)');
console.log(' - POSTGRES_DATABASE: PostgreSQL database name (default: postgres)');
console.log(' - POSTGRES_USERNAME: PostgreSQL username (default: postgres)');
console.log(' - POSTGRES_PASSWORD: PostgreSQL password');
console.log(' - POSTGRES_SSL: Enable SSL connection (true/false, default: false)');
console.log(' - SPLITTER_TYPE: Code splitter type - "ast" or "langchain" (default: ast)');
}

Expand Down
4 changes: 3 additions & 1 deletion examples/basic-usage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
"dev": "tsx --watch index.ts"
},
"dependencies": {
"@zilliz/claude-context-core": "workspace:*"
"@zilliz/claude-context-core": "workspace:*",
"pg": "^8.11.3"
},
"devDependencies": {
"tsx": "^4.0.0",
"typescript": "^5.0.0",
"@types/node": "^20.0.0",
"@types/pg": "^8.10.9",
"dotenv": "^16.0.0"
},
"private": true
Expand Down
2 changes: 2 additions & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"langchain": "^0.3.27",
"ollama": "^0.5.16",
"openai": "^5.1.1",
"pg": "^8.11.3",
"tree-sitter": "^0.21.1",
"tree-sitter-cpp": "^0.22.0",
"tree-sitter-go": "^0.21.0",
Expand All @@ -38,6 +39,7 @@
"@types/fs-extra": "^11.0.0",
"@types/jest": "^30.0.0",
"@types/mock-fs": "^4.13.4",
"@types/pg": "^8.10.9",
"jest": "^30.0.0",
"mock-fs": "^5.5.0",
"ts-jest": "^29.4.0"
Expand Down
23 changes: 18 additions & 5 deletions packages/core/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from './vectordb';
import { SemanticSearchResult } from './types';
import { envManager } from './utils/env-manager';
import { EncryptionManager } from './utils/encryption';
import * as fs from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';
Expand Down Expand Up @@ -103,12 +104,13 @@ export class Context {
private supportedExtensions: string[];
private ignorePatterns: string[];
private synchronizers = new Map<string, FileSynchronizer>();
private encryptionManager: EncryptionManager;

constructor(config: ContextConfig = {}) {
// Initialize services
this.embedding = config.embedding || new OpenAIEmbedding({
apiKey: envManager.get('OPENAI_API_KEY') || 'your-openai-api-key',
model: 'text-embedding-3-small',
model: envManager.get('EMBEDDING_MODEL') || 'text-embedding-3-small',
...(envManager.get('OPENAI_BASE_URL') && { baseURL: envManager.get('OPENAI_BASE_URL') })
});

Expand All @@ -119,6 +121,15 @@ export class Context {

this.codeSplitter = config.codeSplitter || new AstCodeSplitter(2500, 300);

// Initialize encryption manager based on hybrid mode
const isHybrid = this.getIsHybrid();
const enableEncryption = !isHybrid; // Disable encryption if hybrid mode is enabled
this.encryptionManager = new EncryptionManager(enableEncryption);

if (isHybrid && envManager.get('CONTEXT_ENCRYPTION_KEY')) {
console.log('[Context] ⚠️ Content encryption disabled because hybrid mode is enabled (BM25 requires plain text)');
}

// Load custom extensions from environment variables
const envCustomExtensions = this.getCustomExtensionsFromEnv();

Expand Down Expand Up @@ -474,7 +485,7 @@ export class Context {

// 4. Convert to semantic search result format
const results: SemanticSearchResult[] = searchResults.map(result => ({
content: result.document.content,
content: this.encryptionManager.decrypt(result.document.content), // Decrypt content after retrieval
relativePath: result.document.relativePath,
startLine: result.document.startLine,
endLine: result.document.endLine,
Expand Down Expand Up @@ -502,7 +513,7 @@ export class Context {

// 3. Convert to semantic search result format
const results: SemanticSearchResult[] = searchResults.map(result => ({
content: result.document.content,
content: this.encryptionManager.decrypt(result.document.content), // Decrypt content after retrieval
relativePath: result.document.relativePath,
startLine: result.document.startLine,
endLine: result.document.endLine,
Expand Down Expand Up @@ -828,7 +839,7 @@ export class Context {

return {
id: this.generateId(relativePath, chunk.metadata.startLine || 0, chunk.metadata.endLine || 0, chunk.content),
content: chunk.content, // Full text content for BM25 and storage
content: this.encryptionManager.encrypt(chunk.content), // Encrypt content before storage
vector: embeddings[index].vector, // Dense vector
relativePath,
startLine: chunk.metadata.startLine || 0,
Expand Down Expand Up @@ -859,7 +870,7 @@ export class Context {
return {
id: this.generateId(relativePath, chunk.metadata.startLine || 0, chunk.metadata.endLine || 0, chunk.content),
vector: embeddings[index].vector,
content: chunk.content,
content: this.encryptionManager.encrypt(chunk.content), // Encrypt content before storage
relativePath,
startLine: chunk.metadata.startLine || 0,
endLine: chunk.metadata.endLine || 0,
Expand Down Expand Up @@ -967,6 +978,8 @@ export class Context {
} else {
console.log('📄 No ignore files found, keeping existing patterns');
}

console.log(`[Context] 🔍 Ignore patterns: ${this.ignorePatterns.join(', ')}`);
} catch (error) {
console.warn(`[Context] ⚠️ Failed to load ignore patterns: ${error}`);
// Continue with existing patterns on error - don't reset them
Expand Down
Loading