source dump of claude code
at main 76 lines 2.2 kB view raw
1import { createHash } from 'crypto' 2import type { AssistantMessage, UserMessage } from '../types/message.js' 3 4/** 5 * Hardcoded salt from backend validation. 6 * Must match exactly for fingerprint validation to pass. 7 */ 8export const FINGERPRINT_SALT = '59cf53e54c78' 9 10/** 11 * Extracts text content from the first user message. 12 * 13 * @param messages - Array of internal message types 14 * @returns First text content, or empty string if not found 15 */ 16export function extractFirstMessageText( 17 messages: (UserMessage | AssistantMessage)[], 18): string { 19 const firstUserMessage = messages.find(msg => msg.type === 'user') 20 if (!firstUserMessage) { 21 return '' 22 } 23 24 const content = firstUserMessage.message.content 25 26 if (typeof content === 'string') { 27 return content 28 } 29 30 if (Array.isArray(content)) { 31 const textBlock = content.find(block => block.type === 'text') 32 if (textBlock && textBlock.type === 'text') { 33 return textBlock.text 34 } 35 } 36 37 return '' 38} 39 40/** 41 * Computes 3-character fingerprint for Claude Code attribution. 42 * Algorithm: SHA256(SALT + msg[4] + msg[7] + msg[20] + version)[:3] 43 * IMPORTANT: Do not change this method without careful coordination with 44 * 1P and 3P (Bedrock, Vertex, Azure) APIs. 45 * 46 * @param messageText - First user message text content 47 * @param version - Version string (from MACRO.VERSION) 48 * @returns 3-character hex fingerprint 49 */ 50export function computeFingerprint( 51 messageText: string, 52 version: string, 53): string { 54 // Extract chars at indices [4, 7, 20], use "0" if index not found 55 const indices = [4, 7, 20] 56 const chars = indices.map(i => messageText[i] || '0').join('') 57 58 const fingerprintInput = `${FINGERPRINT_SALT}${chars}${version}` 59 60 // SHA256 hash, return first 3 hex chars 61 const hash = createHash('sha256').update(fingerprintInput).digest('hex') 62 return hash.slice(0, 3) 63} 64 65/** 66 * Computes fingerprint from the first user message. 67 * 68 * @param messages - Array of normalized messages 69 * @returns 3-character hex fingerprint 70 */ 71export function computeFingerprintFromMessages( 72 messages: (UserMessage | AssistantMessage)[], 73): string { 74 const firstMessageText = extractFirstMessageText(messages) 75 return computeFingerprint(firstMessageText, MACRO.VERSION) 76}