(Alleged) Leaked source of Claude Code
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 141 lines 4.6 kB view raw
1import axios from 'axios' 2import isEqual from 'lodash-es/isEqual.js' 3import { 4 getAnthropicApiKey, 5 getClaudeAIOAuthTokens, 6 hasProfileScope, 7} from 'src/utils/auth.js' 8import { z } from 'zod' 9import { getOauthConfig, OAUTH_BETA_HEADER } from '../../constants/oauth.js' 10import { getGlobalConfig, saveGlobalConfig } from '../../utils/config.js' 11import { logForDebugging } from '../../utils/debug.js' 12import { withOAuth401Retry } from '../../utils/http.js' 13import { lazySchema } from '../../utils/lazySchema.js' 14import { logError } from '../../utils/log.js' 15import { getAPIProvider } from '../../utils/model/providers.js' 16import { isEssentialTrafficOnly } from '../../utils/privacyLevel.js' 17import { getClaudeCodeUserAgent } from '../../utils/userAgent.js' 18 19const bootstrapResponseSchema = lazySchema(() => 20 z.object({ 21 client_data: z.record(z.unknown()).nullish(), 22 additional_model_options: z 23 .array( 24 z 25 .object({ 26 model: z.string(), 27 name: z.string(), 28 description: z.string(), 29 }) 30 .transform(({ model, name, description }) => ({ 31 value: model, 32 label: name, 33 description, 34 })), 35 ) 36 .nullish(), 37 }), 38) 39 40type BootstrapResponse = z.infer<ReturnType<typeof bootstrapResponseSchema>> 41 42async function fetchBootstrapAPI(): Promise<BootstrapResponse | null> { 43 if (isEssentialTrafficOnly()) { 44 logForDebugging('[Bootstrap] Skipped: Nonessential traffic disabled') 45 return null 46 } 47 48 if (getAPIProvider() !== 'firstParty') { 49 logForDebugging('[Bootstrap] Skipped: 3P provider') 50 return null 51 } 52 53 // OAuth preferred (requires user:profile scope — service-key OAuth tokens 54 // lack it and would 403). Fall back to API key auth for console users. 55 const apiKey = getAnthropicApiKey() 56 const hasUsableOAuth = 57 getClaudeAIOAuthTokens()?.accessToken && hasProfileScope() 58 if (!hasUsableOAuth && !apiKey) { 59 logForDebugging('[Bootstrap] Skipped: no usable OAuth or API key') 60 return null 61 } 62 63 const endpoint = `${getOauthConfig().BASE_API_URL}/api/claude_cli/bootstrap` 64 65 // withOAuth401Retry handles the refresh-and-retry. API key users fail 66 // through on 401 (no refresh mechanism — no OAuth token to pass). 67 try { 68 return await withOAuth401Retry(async () => { 69 // Re-read OAuth each call so the retry picks up the refreshed token. 70 const token = getClaudeAIOAuthTokens()?.accessToken 71 let authHeaders: Record<string, string> 72 if (token && hasProfileScope()) { 73 authHeaders = { 74 Authorization: `Bearer ${token}`, 75 'anthropic-beta': OAUTH_BETA_HEADER, 76 } 77 } else if (apiKey) { 78 authHeaders = { 'x-api-key': apiKey } 79 } else { 80 logForDebugging('[Bootstrap] No auth available on retry, aborting') 81 return null 82 } 83 84 logForDebugging('[Bootstrap] Fetching') 85 const response = await axios.get<unknown>(endpoint, { 86 headers: { 87 'Content-Type': 'application/json', 88 'User-Agent': getClaudeCodeUserAgent(), 89 ...authHeaders, 90 }, 91 timeout: 5000, 92 }) 93 const parsed = bootstrapResponseSchema().safeParse(response.data) 94 if (!parsed.success) { 95 logForDebugging( 96 `[Bootstrap] Response failed validation: ${parsed.error.message}`, 97 ) 98 return null 99 } 100 logForDebugging('[Bootstrap] Fetch ok') 101 return parsed.data 102 }) 103 } catch (error) { 104 logForDebugging( 105 `[Bootstrap] Fetch failed: ${axios.isAxiosError(error) ? (error.response?.status ?? error.code) : 'unknown'}`, 106 ) 107 throw error 108 } 109} 110 111/** 112 * Fetch bootstrap data from the API and persist to disk cache. 113 */ 114export async function fetchBootstrapData(): Promise<void> { 115 try { 116 const response = await fetchBootstrapAPI() 117 if (!response) return 118 119 const clientData = response.client_data ?? null 120 const additionalModelOptions = response.additional_model_options ?? [] 121 122 // Only persist if data actually changed — avoids a config write on every startup. 123 const config = getGlobalConfig() 124 if ( 125 isEqual(config.clientDataCache, clientData) && 126 isEqual(config.additionalModelOptionsCache, additionalModelOptions) 127 ) { 128 logForDebugging('[Bootstrap] Cache unchanged, skipping write') 129 return 130 } 131 132 logForDebugging('[Bootstrap] Cache updated, persisting to disk') 133 saveGlobalConfig(current => ({ 134 ...current, 135 clientDataCache: clientData, 136 additionalModelOptionsCache: additionalModelOptions, 137 })) 138 } catch (error) { 139 logError(error) 140 } 141}