source dump of claude code
at main 71 lines 2.8 kB view raw
1/** 2 * Preconnect to the Anthropic API to overlap TCP+TLS handshake with startup. 3 * 4 * The TCP+TLS handshake is ~100-200ms that normally blocks inside the first 5 * API call. Kicking a fire-and-forget fetch during init lets the handshake 6 * happen in parallel with action-handler work (~100ms of setup/commands/mcp 7 * before the API request in -p mode; unbounded "user is typing" window in 8 * interactive mode). 9 * 10 * Bun's fetch shares a keep-alive connection pool globally, so the real API 11 * request reuses the warmed connection. 12 * 13 * Called from init.ts AFTER applyExtraCACertsFromConfig() + configureGlobalAgents() 14 * so settings.json env vars are applied and the TLS cert store is finalized. 15 * The early cli.tsx call site was removed — it ran before settings.json loaded, 16 * so ANTHROPIC_BASE_URL/proxy/mTLS in settings would be invisible and preconnect 17 * would warm the wrong pool (or worse, lock BoringSSL's cert store before 18 * NODE_EXTRA_CA_CERTS was applied). 19 * 20 * Skipped when: 21 * - proxy/mTLS/unix socket configured (preconnect would use wrong transport — 22 * the SDK passes a custom dispatcher/agent that doesn't share the global pool) 23 * - Bedrock/Vertex/Foundry (different endpoints, different auth) 24 */ 25 26import { getOauthConfig } from '../constants/oauth.js' 27import { isEnvTruthy } from './envUtils.js' 28 29let fired = false 30 31export function preconnectAnthropicApi(): void { 32 if (fired) return 33 fired = true 34 35 // Skip if using a cloud provider — different endpoint + auth 36 if ( 37 isEnvTruthy(process.env.CLAUDE_CODE_USE_BEDROCK) || 38 isEnvTruthy(process.env.CLAUDE_CODE_USE_VERTEX) || 39 isEnvTruthy(process.env.CLAUDE_CODE_USE_FOUNDRY) 40 ) { 41 return 42 } 43 // Skip if proxy/mTLS/unix — SDK's custom dispatcher won't reuse this pool 44 if ( 45 process.env.HTTPS_PROXY || 46 process.env.https_proxy || 47 process.env.HTTP_PROXY || 48 process.env.http_proxy || 49 process.env.ANTHROPIC_UNIX_SOCKET || 50 process.env.CLAUDE_CODE_CLIENT_CERT || 51 process.env.CLAUDE_CODE_CLIENT_KEY 52 ) { 53 return 54 } 55 56 // Use configured base URL (staging, local, or custom gateway). Covers 57 // ANTHROPIC_BASE_URL env + USE_STAGING_OAUTH + USE_LOCAL_OAUTH in one lookup. 58 // NODE_EXTRA_CA_CERTS no longer a skip — init.ts applied it before this fires. 59 const baseUrl = 60 process.env.ANTHROPIC_BASE_URL || getOauthConfig().BASE_API_URL 61 62 // Fire and forget. HEAD means no response body — the connection is eligible 63 // for keep-alive pool reuse immediately after headers arrive. 10s timeout 64 // so a slow network doesn't hang the process; abort is fine since the real 65 // request will handshake fresh if needed. 66 // eslint-disable-next-line eslint-plugin-n/no-unsupported-features/node-builtins 67 void fetch(baseUrl, { 68 method: 'HEAD', 69 signal: AbortSignal.timeout(10_000), 70 }).catch(() => {}) 71}