chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:49:10 +08:00
commit b7e7f5f487
178 changed files with 39171 additions and 0 deletions
+68
View File
@@ -0,0 +1,68 @@
# Python → TypeScript Claude Context Bridge
A simple utility to call TypeScript Claude Context methods from Python.
## What's This?
This directory contains a basic bridge that allows you to run Claude Context TypeScript functions from Python scripts. It's not a full SDK - just a simple way to test and use the TypeScript codebase from Python.
## Files
- `ts_executor.py` - Executes TypeScript methods from Python
- `test_context.ts` - TypeScript test script with Claude Context workflow
- `test_endtoend.py` - Python script that calls the TypeScript test
## Prerequisites
```bash
# Make sure you have Node.js dependencies installed
cd .. && pnpm install
# Set your OpenAI API key (required for actual indexing)
export OPENAI_API_KEY="your-openai-api-key"
# Optional: Set Milvus address (defaults to localhost:19530)
export MILVUS_ADDRESS="localhost:19530"
```
## Quick Usage
```bash
# Run the end-to-end test
python test_endtoend.py
```
This will:
1. Create embeddings using OpenAI
2. Connect to Milvus vector database
3. Index the `packages/core/src` codebase
4. Perform a semantic search
5. Show results
## Manual Usage
```python
from ts_executor import TypeScriptExecutor
executor = TypeScriptExecutor()
result = executor.call_method(
'./test_context.ts',
'testContextEndToEnd',
{
'openaiApiKey': 'sk-your-key',
'milvusAddress': 'localhost:19530',
'codebasePath': '../packages/core/src',
'searchQuery': 'vector database configuration'
}
)
print(result)
```
## How It Works
1. `ts_executor.py` creates temporary TypeScript wrapper files
2. Runs them with `ts-node`
3. Captures JSON output and returns to Python
4. Supports async functions and complex parameters
That's it! This is just a simple bridge for testing purposes.
+112
View File
@@ -0,0 +1,112 @@
import { Context } 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';
/**
* Context End-to-End Test - Complete Workflow
* Includes: Configure Embedding → Configure Vector Database → Create Context → Index Codebase → Semantic Search
*/
export async function testContextEndToEnd(config: {
openaiApiKey: string;
milvusAddress: string;
codebasePath: string;
searchQuery: string;
}) {
try {
console.log('🚀 Starting Context end-to-end test...');
// 1. Create embedding instance
console.log('📝 Creating OpenAI embedding instance...');
const embedding = new OpenAIEmbedding({
apiKey: config.openaiApiKey,
model: 'text-embedding-3-small'
});
// 2. Create vector database instance
console.log('🗄️ Creating Milvus vector database instance...');
const vectorDB = new MilvusVectorDatabase({
address: config.milvusAddress
});
// 3. Create Context instance
console.log('🔧 Creating Context instance...');
const codeSplitter = new AstCodeSplitter(1000, 200);
const context = new Context({
embedding: embedding,
vectorDatabase: vectorDB,
codeSplitter: codeSplitter
});
// 4. Check if index already exists
console.log('🔍 Checking existing index...');
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 context.indexCodebase(config.codebasePath, (progress) => {
console.log(`Indexing progress: ${progress.phase} - ${progress.percentage}%`);
});
console.log('✅ Indexing completed');
} else {
console.log('📖 Using existing index');
indexStats = { indexedFiles: 0, totalChunks: 0, message: "Using existing index" };
}
// 6. Execute semantic search
console.log('🔎 Executing semantic search...');
const searchResults = await context.semanticSearch(
config.codebasePath,
config.searchQuery,
5, // topK
0.5 // threshold
);
// 7. Return complete results
const result = {
success: true,
timestamp: new Date().toISOString(),
config: {
embeddingProvider: embedding.getProvider(),
embeddingModel: 'text-embedding-3-small',
embeddingDimension: embedding.getDimension(),
vectorDatabase: 'Milvus',
chunkSize: 1000,
chunkOverlap: 200
},
indexStats: indexStats,
searchQuery: config.searchQuery,
searchResults: searchResults.map(result => ({
relativePath: result.relativePath,
startLine: result.startLine,
endLine: result.endLine,
language: result.language,
score: result.score,
contentPreview: result.content.substring(0, 200) + '...'
})),
summary: {
indexedFiles: indexStats.indexedFiles || 0,
totalChunks: indexStats.totalChunks || 0,
foundResults: searchResults.length,
avgScore: searchResults.length > 0 ?
searchResults.reduce((sum, r) => sum + r.score, 0) / searchResults.length : 0
}
};
console.log('🎉 End-to-end test completed!');
return result;
} catch (error: any) {
console.error('❌ End-to-end test failed:', error);
return {
success: false,
timestamp: new Date().toISOString(),
error: error.message,
stack: error.stack
};
}
}
+132
View File
@@ -0,0 +1,132 @@
#!/usr/bin/env python3
"""
Claude Context End-to-End Test
Use TypeScriptExecutor to call complete Claude Context workflow
"""
import os
import sys
from pathlib import Path
# Add python directory to path
sys.path.append(str(Path(__file__).parent))
from ts_executor import TypeScriptExecutor
def run_context_endtoend_test():
"""Run Claude Context 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": str(
Path(__file__).parent.parent / "packages" / "core" / "src"
), # Index core source code
"searchQuery": "embedding creation and vector database configuration",
}
print("🚀 Starting Claude Context end-to-end test")
print(f"📊 Configuration:")
print(f" - Codebase path: {config['codebasePath']}")
print(f" - Vector database: {config['milvusAddress']}")
print(f" - Search query: {config['searchQuery']}")
print(
f" - OpenAI API: {'✅ Configured' if config['openaiApiKey'] != 'your-openai-api-key' else '❌ Need to set OPENAI_API_KEY environment variable'}"
)
print()
try:
executor = TypeScriptExecutor()
# Call end-to-end test
result = executor.call_method(
"./test_context.ts", "testContextEndToEnd", config
)
# Output results
if result.get("success"):
print("✅ End-to-end test successful!")
print(f"📅 Timestamp: {result.get('timestamp')}")
# Display configuration info
config_info = result.get("config", {})
print(f"🔧 Configuration:")
print(f" - Embedding provider: {config_info.get('embeddingProvider')}")
print(f" - Embedding model: {config_info.get('embeddingModel')}")
print(f" - Embedding dimension: {config_info.get('embeddingDimension')}")
print(f" - Vector database: {config_info.get('vectorDatabase')}")
print(f" - Chunk size: {config_info.get('chunkSize')}")
print(f" - Chunk overlap: {config_info.get('chunkOverlap')}")
# Display indexing statistics
index_stats = result.get("indexStats", {})
print(f"📚 Indexing statistics:")
print(f" - Indexed files: {index_stats.get('indexedFiles', 0)}")
print(f" - Total chunks: {index_stats.get('totalChunks', 0)}")
# Display search results
summary = result.get("summary", {})
search_results = result.get("searchResults", [])
print(f"🔍 Search results:")
print(f" - Query: '{result.get('searchQuery')}'")
print(f" - Results found: {summary.get('foundResults', 0)} items")
print(f" - Average relevance: {summary.get('avgScore', 0):.3f}")
# Display top 3 search results
if search_results:
print(f"📋 Top {min(3, len(search_results))} most relevant results:")
for i, item in enumerate(search_results[:3]):
print(
f" {i+1}. {item['relativePath']} (lines {item['startLine']}-{item['endLine']})"
)
print(
f" Language: {item['language']}, Relevance: {item['score']:.3f}"
)
print(f" Preview: {item['contentPreview'][:100]}...")
print()
return True
else:
print("❌ End-to-end test failed")
print(f"Error: {result.get('error')}")
if result.get("stack"):
print(f"Stack trace: {result.get('stack')}")
return False
except Exception as e:
print(f"❌ Execution failed: {e}")
return False
def main():
"""Main function"""
print("=" * 60)
print("🧪 Claude Context End-to-End Test")
print("=" * 60)
print()
success = run_context_endtoend_test()
print()
print("=" * 60)
if success:
print("🎉 Test completed! Claude Context end-to-end workflow runs successfully!")
print()
print("💡 This proves:")
print(" ✅ Can call TypeScript Claude Context from Python")
print(" ✅ Supports complete indexing and search workflow")
print(" ✅ Supports complex configuration and parameter passing")
print(" ✅ Can get detailed execution results and statistics")
else:
print("❌ Test failed. Please check:")
print(" - OPENAI_API_KEY environment variable is correctly set")
print(" - Milvus vector database is running properly")
print(" - packages/core code is accessible")
print("=" * 60)
if __name__ == "__main__":
main()
+308
View File
@@ -0,0 +1,308 @@
#!/usr/bin/env python3
"""
TypeScript Executor - Execute TypeScript methods from Python
Supports calling TypeScript functions with complex parameters and async/await
"""
import json
import os
import subprocess
import tempfile
from pathlib import Path
from typing import Any, Dict, List, Optional
class TypeScriptExecutor:
"""TypeScript method executor"""
def __init__(self, working_dir: Optional[str] = None):
"""Initialize TypeScript executor
Args:
working_dir: Working directory, defaults to current directory
"""
self.working_dir = working_dir or os.getcwd()
def call_method(self, ts_file_path: str, method_name: str, *args, **kwargs) -> Any:
"""Call TypeScript method
Args:
ts_file_path: TypeScript file path
method_name: Method name
*args: Positional arguments
**kwargs: Keyword arguments
Returns:
Execution result
"""
# Convert relative path to absolute path
if not os.path.isabs(ts_file_path):
ts_file_path = os.path.join(self.working_dir, ts_file_path)
# Ensure the target file exists
if not os.path.exists(ts_file_path):
raise FileNotFoundError(f"TypeScript file not found: {ts_file_path}")
# Get the directory of the target file
target_dir = os.path.dirname(ts_file_path)
# Create wrapper script
wrapper_code = self._create_wrapper_script(
ts_file_path, method_name, list(args), kwargs
)
# Create temporary file in the same directory as the target file
temp_fd, temp_file = tempfile.mkstemp(suffix=".ts", dir=target_dir)
try:
# Write wrapper script
with os.fdopen(temp_fd, "w", encoding="utf-8") as f:
f.write(wrapper_code)
# Execute TypeScript code using ts-node
# Use subprocess.Popen to capture output in real-time
process = subprocess.Popen(
["npx", "ts-node", temp_file],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
cwd=self.working_dir,
bufsize=1, # Line buffering
universal_newlines=True,
)
stdout_lines = []
stderr_lines = []
# 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:
json.loads(line)
# If it parses as JSON, it might be the final result, don't print it yet
except json.JSONDecodeError:
# 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:
# Try to parse as JSON
return json.loads(line)
except json.JSONDecodeError:
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 Exception as e:
raise RuntimeError(f"Execution error: {str(e)}")
finally:
# Clean up temporary file
os.unlink(temp_file)
def _create_wrapper_script(
self,
ts_file_path: str,
method_name: str,
args: List[Any],
kwargs: Dict[str, Any],
) -> str:
"""Create wrapper script
Args:
ts_file_path: TypeScript file path
method_name: Method name
args: Positional arguments
kwargs: Keyword arguments
Returns:
Wrapper script code
"""
# Use relative path for import, since temp file is in the same directory
ts_filename = os.path.basename(ts_file_path)
# Remove .ts extension, since import doesn't need it
if ts_filename.endswith(".ts"):
import_path = "./" + ts_filename[:-3]
else:
import_path = "./" + ts_filename
args_json = json.dumps(args)
kwargs_json = json.dumps(kwargs)
wrapper_code = f"""
import * as targetModule from '{import_path}';
async function executeMethod() {{
try {{
// Prepare arguments
const args: any[] = {args_json};
const kwargs: any = {kwargs_json};
// Get method
const method = (targetModule as any).{method_name};
if (typeof method !== 'function') {{
throw new Error(`Method '{method_name}' does not exist or is not a function`);
}}
// Call method
let result: any;
if (Object.keys(kwargs).length > 0) {{
// If there are keyword arguments, pass them as the last parameter
result = await method(...args, kwargs);
}} else {{
// Only positional arguments
result = await method(...args);
}}
// Output result
console.log(JSON.stringify(result));
}} catch (error: any) {{
console.error(JSON.stringify({{
error: (error as Error).message,
stack: (error as Error).stack
}}));
process.exit(1);
}}
}}
executeMethod();
"""
return wrapper_code
# Convenience function
def call_ts_method(
ts_file: str, method_name: str, *args, working_dir: Optional[str] = None, **kwargs
) -> Any:
"""Convenience function: Call TypeScript method
Args:
ts_file: TypeScript file path
method_name: Method name
*args: Positional arguments
working_dir: Working directory
**kwargs: Keyword arguments
Returns:
Execution result
"""
executor = TypeScriptExecutor(working_dir)
return executor.call_method(ts_file, method_name, *args, **kwargs)
# Usage example
if __name__ == "__main__":
# Create test TypeScript file
test_ts_content = """
export function add(a: number, b: number): number {
return a + b;
}
export function greet(name: string, options?: { formal?: boolean }): string {
const greeting = options?.formal ? "Hello" : "Hi";
return `${greeting}, ${name}!`;
}
export async function processData(data: any[]): Promise<{ count: number; items: any[] }> {
// Simulate async processing
await new Promise(resolve => setTimeout(resolve, 100));
return {
count: data.length,
items: data.map(item => ({ processed: true, original: item }))
};
}
export function complexFunction(
numbers: number[],
config: { multiplier: number; offset: number }
): { result: number[]; sum: number } {
const result = numbers.map(n => n * config.multiplier + config.offset);
const sum = result.reduce((a, b) => a + b, 0);
return { result, sum };
}
"""
# Write test file
with open("test_methods.ts", "w") as f:
f.write(test_ts_content)
try:
# Create executor
executor = TypeScriptExecutor()
print("=== TypeScript Method Execution Test ===")
# Test 1: Simple function
print("\n1. Testing simple addition function:")
result = executor.call_method("test_methods.ts", "add", 10, 20)
print(f" add(10, 20) = {result}")
# Test 2: Function with optional parameters
print("\n2. Testing greeting function:")
result1 = executor.call_method("test_methods.ts", "greet", "Alice")
print(f" greet('Alice') = {result1}")
result2 = executor.call_method(
"test_methods.ts", "greet", "Bob", {"formal": True}
)
print(f" greet('Bob', {{formal: true}}) = {result2}")
# Test 3: Async function
print("\n3. Testing async function:")
result = executor.call_method(
"test_methods.ts", "processData", [1, 2, 3, "hello"]
)
print(f" processData([1, 2, 3, 'hello']) = {result}")
# Test 4: Complex function
print("\n4. Testing complex function:")
result = executor.call_method(
"test_methods.ts",
"complexFunction",
[1, 2, 3, 4, 5],
{"multiplier": 2, "offset": 1},
)
print(f" complexFunction([1,2,3,4,5], {{multiplier:2, offset:1}}) = {result}")
# Test 5: Using convenience function
print("\n5. Testing convenience function:")
result = call_ts_method("test_methods.ts", "add", 100, 200)
print(f" call_ts_method('test_methods.ts', 'add', 100, 200) = {result}")
except Exception as e:
print(f"Error: {e}")
finally:
# Clean up test file
if os.path.exists("test_methods.ts"):
os.remove("test_methods.ts")