MCPcopy Create free account
hub / github.com/AnukarOP/claude-code-leaked / normalizeMessagesForAPI

Function normalizeMessagesForAPI

source code/utils/messages.ts:1991–2372  ·  view source on GitHub ↗
(
  messages: Message[],
  tools: Tools = [],
)

Source from the content-addressed store, hash-verified

1989}
1990
1991export function normalizeMessagesForAPI(
1992 messages: Message[],
1993 tools: Tools = [],
1994): (UserMessage | AssistantMessage)[] {
1995 // Build set of available tool names for filtering unavailable tool references
1996 const availableToolNames = new Set(tools.map(t => t.name))
1997
1998 // First, reorder attachments to bubble up until they hit a tool result or assistant message
1999 // Then strip virtual messages — they're display-only (e.g. REPL inner tool
2000 // calls) and must never reach the API.
2001 const reorderedMessages = reorderAttachmentsForAPI(messages).filter(
2002 m => !((m.type === 'user' || m.type === 'assistant') && m.isVirtual),
2003 )
2004
2005 // Build a map from error text → which block types to strip from the preceding user message.
2006 const errorToBlockTypes: Record<string, Set<string>> = {
2007 [getPdfTooLargeErrorMessage()]: new Set(['document']),
2008 [getPdfPasswordProtectedErrorMessage()]: new Set(['document']),
2009 [getPdfInvalidErrorMessage()]: new Set(['document']),
2010 [getImageTooLargeErrorMessage()]: new Set(['image']),
2011 [getRequestTooLargeErrorMessage()]: new Set(['document', 'image']),
2012 }
2013
2014 // Walk the reordered messages to build a targeted strip map:
2015 // userMessageUUID → set of block types to strip from that message.
2016 const stripTargets = new Map<string, Set<string>>()
2017 for (let i = 0; i < reorderedMessages.length; i++) {
2018 const msg = reorderedMessages[i]!
2019 if (!isSyntheticApiErrorMessage(msg)) {
2020 continue
2021 }
2022 // Determine which error this is
2023 const errorText =
2024 Array.isArray(msg.message.content) &&
2025 msg.message.content[0]?.type === 'text'
2026 ? msg.message.content[0].text
2027 : undefined
2028 if (!errorText) {
2029 continue
2030 }
2031 const blockTypesToStrip = errorToBlockTypes[errorText]
2032 if (!blockTypesToStrip) {
2033 continue
2034 }
2035 // Walk backward to find the nearest preceding isMeta user message
2036 for (let j = i - 1; j >= 0; j--) {
2037 const candidate = reorderedMessages[j]!
2038 if (candidate.type === 'user' && candidate.isMeta) {
2039 const existing = stripTargets.get(candidate.uuid)
2040 if (existing) {
2041 for (const t of blockTypesToStrip) {
2042 existing.add(t)
2043 }
2044 } else {
2045 stripTargets.set(candidate.uuid, new Set(blockTypesToStrip))
2046 }
2047 break
2048 }

Callers 9

queryLoopFunction · 0.85
FeedbackFunction · 0.85
submitTranscriptShareFunction · 0.85
generateAgentFunction · 0.85
analyzeContextFunction · 0.85
approximateMessageTokensFunction · 0.85
withVCRFunction · 0.85
streamCompactSummaryFunction · 0.85
queryModelFunction · 0.85

Tested by

no test coverage detected