UNPKG

unbound-claude-code

Version:

Claude Code with Unbound integration - Drop-in replacement for Claude Code with multi-provider routing and cost optimization

121 lines • 4.49 kB
"use strict"; /** * Unbound Code Interceptor * * Intercepts and logs requests. Used for debugging. * Uses environment variables to redirect Claude to Unbound gateway. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.UnboundInterceptor = void 0; exports.initializeUnboundInterceptor = initializeUnboundInterceptor; exports.getUnboundInterceptor = getUnboundInterceptor; exports.setUnboundApiKey = setUnboundApiKey; const global_1 = require("./global"); class UnboundInterceptor { constructor(config = {}) { this.config = { baseUrl: `${global_1.UNBOUND_BASE_URL}/v1`, logLevel: "info", ...config, }; } setApiKey(apiKey) { // No-op: API key is now handled via environment variables console.log("API key set via environment variables"); } logRequest(url, method, headers, body) { console.log('\nšŸ” REQUEST INTERCEPTED'); console.log('═'.repeat(50)); console.log(`šŸ“ URL: ${url}`); console.log(`šŸ”§ Method: ${method}`); console.log('\nšŸ“‹ Headers:'); if (headers) { if (headers instanceof Headers) { headers.forEach((value, key) => { // Mask sensitive headers const maskedValue = key.toLowerCase().includes('authorization') || key.toLowerCase().includes('key') ? `${value.substring(0, 10)}...` : value; console.log(` ${key}: ${maskedValue}`); }); } else { Object.entries(headers).forEach(([key, value]) => { const maskedValue = key.toLowerCase().includes('authorization') || key.toLowerCase().includes('key') ? `${String(value).substring(0, 10)}...` : value; console.log(` ${key}: ${maskedValue}`); }); } } console.log('\nšŸ“¦ Body:'); if (body) { try { const bodyStr = typeof body === 'string' ? body : body.toString(); const parsedBody = JSON.parse(bodyStr); console.log('šŸ“¦ Request Payload:'); console.log(JSON.stringify(parsedBody, null, 2)); // Specifically log messages if they exist if (parsedBody.messages) { console.log('\nšŸ’¬ Messages being sent:'); parsedBody.messages.forEach((msg, index) => { console.log(` Message ${index + 1} (${msg.role}):`); console.log(` ${msg.content}`); }); } } catch (e) { console.log('šŸ“¦ Request Body (raw):'); console.log(body); } } else { console.log('[No body]'); } console.log('═'.repeat(50)); } instrumentFetch() { if (!global.fetch) { return; } // Check if already instrumented if (global.fetch.__unboundIntercepted) { return; } const originalFetch = global.fetch; const interceptor = this; global.fetch = async function (input, init = {}) { const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url; const method = init.method || 'GET'; // Enable this to log all outgoing requests for debugging // interceptor.logRequest(url, method, init.headers, init.body); // Pass through to original fetch return originalFetch(input, init); }; // Mark fetch as instrumented global.fetch.__unboundIntercepted = true; } instrumentAll() { this.instrumentFetch(); } } exports.UnboundInterceptor = UnboundInterceptor; // Global interceptor instance let globalInterceptor = null; function initializeUnboundInterceptor(config) { if (globalInterceptor) { return globalInterceptor; } globalInterceptor = new UnboundInterceptor(config); globalInterceptor.instrumentAll(); return globalInterceptor; } function getUnboundInterceptor() { return globalInterceptor; } function setUnboundApiKey(apiKey) { if (globalInterceptor) { globalInterceptor.setApiKey(apiKey); } } //# sourceMappingURL=interceptor.js.map