UNPKG

@tehreet/conduit

Version:

LLM API gateway with intelligent routing, robust process management, and health monitoring

199 lines (196 loc) 7.43 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.wrapperCommand = wrapperCommand; exports.installWrapperCommand = installWrapperCommand; const claude_wrapper_1 = require("../core/claude-wrapper"); const metadata_handler_1 = require("../core/metadata-handler"); const synapse_features_1 = require("../features/synapse-features"); const utils_1 = require("../utils"); const log_1 = require("../utils/log"); const fs = __importStar(require("fs")); const path = __importStar(require("path")); async function wrapperCommand(args) { try { // Find Claude binary const claudeBinary = await findClaudeBinary(); if (!claudeBinary) { console.error('Error: Claude CLI not found. Please install Claude Code first.'); process.exit(1); } // Load Conduit configuration const config = await (0, utils_1.initConfig)(); // Initialize Synapse features if enabled let synapseFeatures; if (process.env.SYNAPSE_PROJECT_ID || process.env.SYNAPSE_AGENT_ID) { synapseFeatures = new synapse_features_1.SynapseFeatures({ telemetryEndpoint: process.env.SYNAPSE_TELEMETRY_ENDPOINT, }); } // Create wrapper instance const wrapper = new claude_wrapper_1.ClaudeWrapper({ claudeBinaryPath: claudeBinary, config, loggingEnabled: config.LOG || process.env.LOG === 'true', metricsEnabled: true, }); // Handle routing decision events wrapper.on('routing-decision', decision => { if (config.LOG) { (0, log_1.log)('Routing decision:', decision); } }); // Handle usage tracking if (synapseFeatures) { wrapper.on('usage', async (usage) => { await synapseFeatures.trackUsage({ projectId: usage.projectId || 'unknown', agentId: usage.agentId || 'unknown', model: usage.model, inputTokens: usage.tokenCount || 0, outputTokens: 0, // Will be updated when response completes }); }); } // Wrap the Claude command const claudeProcess = await wrapper.wrapCommand(args, process.env); // Set up stream handling with metadata injection if (claudeProcess.stdout) { const processor = metadata_handler_1.MetadataHandler.createStreamProcessor(metadata => { // Metadata is already injected, just log if needed if (config.LOG) { (0, log_1.log)('Metadata injected:', metadata); } }); claudeProcess.stdout.pipe(processor).pipe(process.stdout); } // Pass through stderr if (claudeProcess.stderr) { claudeProcess.stderr.pipe(process.stderr); } // Pass through stdin if (claudeProcess.stdin) { process.stdin.pipe(claudeProcess.stdin); } // Handle process exit claudeProcess.on('exit', code => { process.exit(code || 0); }); // Handle errors claudeProcess.on('error', error => { console.error('Claude process error:', error); process.exit(1); }); } catch (error) { console.error('Wrapper error:', error); process.exit(1); } } async function findClaudeBinary() { // Common locations for Claude CLI const possiblePaths = [ // Global npm install '/usr/local/bin/claude', '/usr/bin/claude', // Local npm install path.join(process.env.HOME || '', '.npm-global/bin/claude'), path.join(process.env.HOME || '', 'node_modules/.bin/claude'), // Homebrew '/opt/homebrew/bin/claude', '/usr/local/opt/claude/bin/claude', // Direct from PATH 'claude', ]; // Check if CLAUDE_BINARY is set if (process.env.CLAUDE_BINARY) { possiblePaths.unshift(process.env.CLAUDE_BINARY); } // Try to find Claude in PATH first try { const { execSync } = require('child_process'); const which = execSync('which claude', { encoding: 'utf-8' }).trim(); if (which) { return which; } } catch (error) { // which command failed, try other paths } // Check each possible path for (const claudePath of possiblePaths) { try { if (fs.existsSync(claudePath)) { // Verify it's executable fs.accessSync(claudePath, fs.constants.X_OK); return claudePath; } } catch (error) { // Continue to next path } } return null; } async function installWrapperCommand() { console.log('🔧 Setting up Conduit wrapper mode...\n'); // Create wrapper script const wrapperScript = `#!/usr/bin/env node // Conduit wrapper for Claude CLI const { spawn } = require('child_process'); const path = require('path'); // Path to Conduit CLI const conduitPath = '${process.argv[1]}'; // Run Conduit in wrapper mode const conduit = spawn('node', [conduitPath, 'wrap', ...process.argv.slice(2)], { stdio: 'inherit', env: process.env }); conduit.on('exit', (code) => process.exit(code || 0)); `; // Save wrapper script const wrapperPath = path.join(process.env.HOME || '', '.conduit', 'bin', 'conduit-claude'); const binDir = path.dirname(wrapperPath); // Create directory fs.mkdirSync(binDir, { recursive: true }); // Write wrapper script fs.writeFileSync(wrapperPath, wrapperScript); fs.chmodSync(wrapperPath, '755'); console.log('✅ Wrapper script created at:', wrapperPath); console.log('\nTo use Conduit as a Claude wrapper, set:'); console.log(`export CLAUDE_BINARY="${wrapperPath}"`); console.log('\nOr add to your shell configuration file.'); } //# sourceMappingURL=wrapper-command.js.map