(
block: ContentBlockParam | ContentBlock | BetaContentBlock,
message: UserMessage | AssistantMessage,
stats: TokenStats,
toolIds: Map<string, string>,
readToolPaths: Map<string, string>,
fileReads: Map<string, { count: number; totalTokens: number }>,
)
| 99 | } |
| 100 | |
| 101 | function processBlock( |
| 102 | block: ContentBlockParam | ContentBlock | BetaContentBlock, |
| 103 | message: UserMessage | AssistantMessage, |
| 104 | stats: TokenStats, |
| 105 | toolIds: Map<string, string>, |
| 106 | readToolPaths: Map<string, string>, |
| 107 | fileReads: Map<string, { count: number; totalTokens: number }>, |
| 108 | ): void { |
| 109 | const tokens = countTokens(jsonStringify(block)) |
| 110 | stats.total += tokens |
| 111 | |
| 112 | switch (block.type) { |
| 113 | case 'text': |
| 114 | // Check if this is a local command output |
| 115 | if ( |
| 116 | message.type === 'user' && |
| 117 | 'text' in block && |
| 118 | block.text.includes('local-command-stdout') |
| 119 | ) { |
| 120 | stats.localCommandOutputs += tokens |
| 121 | } else { |
| 122 | stats[ |
| 123 | message.type === 'user' ? 'humanMessages' : 'assistantMessages' |
| 124 | ] += tokens |
| 125 | } |
| 126 | break |
| 127 | |
| 128 | case 'tool_use': { |
| 129 | if ('name' in block && 'id' in block) { |
| 130 | const toolName = block.name || 'unknown' |
| 131 | increment(stats.toolRequests, toolName, tokens) |
| 132 | toolIds.set(block.id, toolName) |
| 133 | |
| 134 | // Track Read tool file paths |
| 135 | if ( |
| 136 | toolName === 'Read' && |
| 137 | 'input' in block && |
| 138 | block.input && |
| 139 | typeof block.input === 'object' && |
| 140 | 'file_path' in block.input |
| 141 | ) { |
| 142 | const path = String( |
| 143 | (block.input as Record<string, unknown>).file_path, |
| 144 | ) |
| 145 | readToolPaths.set(block.id, path) |
| 146 | } |
| 147 | } |
| 148 | break |
| 149 | } |
| 150 | |
| 151 | case 'tool_result': { |
| 152 | if ('tool_use_id' in block) { |
| 153 | const toolName = toolIds.get(block.tool_use_id) || 'unknown' |
| 154 | increment(stats.toolResults, toolName, tokens) |
| 155 | |
| 156 | // Track file read tokens |
| 157 | if (toolName === 'Read') { |
| 158 | const path = readToolPaths.get(block.tool_use_id) |
no test coverage detected