mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-12 02:37:45 +08:00
feat: Enhance LiteLLM integration and CLI management
- Added token estimation and batching functionality in LiteLLMEmbedder to handle large text inputs efficiently. - Updated embed method to support max_tokens_per_batch parameter for better API call management. - Introduced new API routes for managing custom CLI endpoints, including GET, POST, PUT, and DELETE methods. - Enhanced CLI history component to support source directory context for native session content. - Improved error handling and logging in various components for better debugging and user feedback. - Added internationalization support for new API endpoint features in the i18n module. - Updated CodexLens CLI commands to allow for concurrent API calls with a max_workers option. - Enhanced embedding manager to track model information and handle embeddings generation more robustly. - Added entry points for CLI commands in the package configuration.
This commit is contained in:
@@ -38,7 +38,9 @@ import {
|
||||
saveClaudeCliTools,
|
||||
updateClaudeToolEnabled,
|
||||
updateClaudeCacheSettings,
|
||||
getClaudeCliToolsInfo
|
||||
getClaudeCliToolsInfo,
|
||||
addClaudeCustomEndpoint,
|
||||
removeClaudeCustomEndpoint
|
||||
} from '../../tools/claude-cli-tools.js';
|
||||
|
||||
export interface RouteContext {
|
||||
@@ -211,6 +213,93 @@ export async function handleCliRoutes(ctx: RouteContext): Promise<boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
// API: Get all custom endpoints
|
||||
if (pathname === '/api/cli/endpoints' && req.method === 'GET') {
|
||||
try {
|
||||
const config = loadClaudeCliTools(initialPath);
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ endpoints: config.customEndpoints || [] }));
|
||||
} catch (err) {
|
||||
res.writeHead(500, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ error: (err as Error).message }));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// API: Add/Update custom endpoint
|
||||
if (pathname === '/api/cli/endpoints' && req.method === 'POST') {
|
||||
handlePostRequest(req, res, async (body: unknown) => {
|
||||
try {
|
||||
const { id, name, enabled } = body as { id: string; name: string; enabled: boolean };
|
||||
if (!id || !name) {
|
||||
return { error: 'id and name are required', status: 400 };
|
||||
}
|
||||
const config = addClaudeCustomEndpoint(initialPath, { id, name, enabled: enabled !== false });
|
||||
|
||||
broadcastToClients({
|
||||
type: 'CLI_ENDPOINT_UPDATED',
|
||||
payload: { endpoint: { id, name, enabled }, timestamp: new Date().toISOString() }
|
||||
});
|
||||
|
||||
return { success: true, endpoints: config.customEndpoints };
|
||||
} catch (err) {
|
||||
return { error: (err as Error).message, status: 500 };
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
// API: Update custom endpoint enabled status
|
||||
if (pathname.match(/^\/api\/cli\/endpoints\/[^/]+$/) && req.method === 'PUT') {
|
||||
const endpointId = pathname.split('/').pop() || '';
|
||||
handlePostRequest(req, res, async (body: unknown) => {
|
||||
try {
|
||||
const { enabled, name } = body as { enabled?: boolean; name?: string };
|
||||
const config = loadClaudeCliTools(initialPath);
|
||||
const endpoint = config.customEndpoints.find(e => e.id === endpointId);
|
||||
|
||||
if (!endpoint) {
|
||||
return { error: 'Endpoint not found', status: 404 };
|
||||
}
|
||||
|
||||
if (typeof enabled === 'boolean') endpoint.enabled = enabled;
|
||||
if (name) endpoint.name = name;
|
||||
|
||||
saveClaudeCliTools(initialPath, config);
|
||||
|
||||
broadcastToClients({
|
||||
type: 'CLI_ENDPOINT_UPDATED',
|
||||
payload: { endpoint, timestamp: new Date().toISOString() }
|
||||
});
|
||||
|
||||
return { success: true, endpoint };
|
||||
} catch (err) {
|
||||
return { error: (err as Error).message, status: 500 };
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
// API: Delete custom endpoint
|
||||
if (pathname.match(/^\/api\/cli\/endpoints\/[^/]+$/) && req.method === 'DELETE') {
|
||||
const endpointId = pathname.split('/').pop() || '';
|
||||
try {
|
||||
const config = removeClaudeCustomEndpoint(initialPath, endpointId);
|
||||
|
||||
broadcastToClients({
|
||||
type: 'CLI_ENDPOINT_DELETED',
|
||||
payload: { endpointId, timestamp: new Date().toISOString() }
|
||||
});
|
||||
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ success: true, endpoints: config.customEndpoints }));
|
||||
} catch (err) {
|
||||
res.writeHead(500, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ error: (err as Error).message }));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// API: CLI Execution History
|
||||
if (pathname === '/api/cli/history') {
|
||||
const projectPath = url.searchParams.get('path') || initialPath;
|
||||
|
||||
@@ -529,27 +529,38 @@ export async function handleLiteLLMApiRoutes(ctx: RouteContext): Promise<boolean
|
||||
// GET /api/litellm-api/ccw-litellm/status - Check ccw-litellm installation status
|
||||
if (pathname === '/api/litellm-api/ccw-litellm/status' && req.method === 'GET') {
|
||||
try {
|
||||
const { spawn } = await import('child_process');
|
||||
const result = await new Promise<{ installed: boolean; version?: string }>((resolve) => {
|
||||
const proc = spawn('python', ['-c', 'import ccw_litellm; print(ccw_litellm.__version__ if hasattr(ccw_litellm, "__version__") else "installed")'], {
|
||||
shell: true,
|
||||
timeout: 10000
|
||||
});
|
||||
const { execSync } = await import('child_process');
|
||||
|
||||
let output = '';
|
||||
proc.stdout?.on('data', (data) => { output += data.toString(); });
|
||||
proc.on('close', (code) => {
|
||||
if (code === 0) {
|
||||
resolve({ installed: true, version: output.trim() || 'unknown' });
|
||||
} else {
|
||||
resolve({ installed: false });
|
||||
// Try multiple Python executables
|
||||
const pythonExecutables = ['python', 'python3', 'py'];
|
||||
// Use single quotes inside Python code for Windows compatibility
|
||||
const pythonCode = "import ccw_litellm; print(getattr(ccw_litellm, '__version__', 'installed'))";
|
||||
|
||||
let installed = false;
|
||||
let version = '';
|
||||
let lastError = '';
|
||||
|
||||
for (const pythonExe of pythonExecutables) {
|
||||
try {
|
||||
const output = execSync(`${pythonExe} -c "${pythonCode}"`, {
|
||||
encoding: 'utf-8',
|
||||
timeout: 10000,
|
||||
windowsHide: true
|
||||
});
|
||||
version = output.trim();
|
||||
if (version) {
|
||||
installed = true;
|
||||
console.log(`[ccw-litellm status] Found with ${pythonExe}: ${version}`);
|
||||
break;
|
||||
}
|
||||
});
|
||||
proc.on('error', () => resolve({ installed: false }));
|
||||
});
|
||||
} catch (err) {
|
||||
lastError = (err as Error).message;
|
||||
console.log(`[ccw-litellm status] ${pythonExe} failed:`, lastError.substring(0, 100));
|
||||
}
|
||||
}
|
||||
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify(result));
|
||||
res.end(JSON.stringify(installed ? { installed: true, version } : { installed: false, error: lastError }));
|
||||
} catch (err) {
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ installed: false, error: (err as Error).message }));
|
||||
|
||||
Reference in New Issue
Block a user