( messages: Anthropic.Beta.Messages.BetaMessageParam[], tools: Anthropic.Beta.Messages.BetaToolUnion[], )
| 145 | } |
| 146 | |
| 147 | export async function countMessagesTokensWithAPI( |
| 148 | messages: Anthropic.Beta.Messages.BetaMessageParam[], |
| 149 | tools: Anthropic.Beta.Messages.BetaToolUnion[], |
| 150 | ): Promise<number | null> { |
| 151 | return withTokenCountVCR(messages, tools, async () => { |
| 152 | try { |
| 153 | const provider = getAPIProvider() |
| 154 | if (provider === 'gemini') { |
| 155 | return roughTokenCountEstimationForAPIRequest(messages, tools) |
| 156 | } |
| 157 | |
| 158 | const model = getMainLoopModel() |
| 159 | const betas = getModelBetas(model) |
| 160 | const containsThinking = hasThinkingBlocks(messages) |
| 161 | |
| 162 | if (provider === 'bedrock') { |
| 163 | // @anthropic-sdk/bedrock-sdk doesn't support countTokens currently |
| 164 | return countTokensWithBedrock({ |
| 165 | model: normalizeModelStringForAPI(model), |
| 166 | messages, |
| 167 | tools, |
| 168 | betas, |
| 169 | containsThinking, |
| 170 | }) |
| 171 | } |
| 172 | |
| 173 | const anthropic = await getAnthropicClient({ |
| 174 | maxRetries: 1, |
| 175 | model, |
| 176 | source: 'count_tokens', |
| 177 | }) |
| 178 | |
| 179 | const filteredBetas = |
| 180 | getAPIProvider() === 'vertex' |
| 181 | ? betas.filter(b => VERTEX_COUNT_TOKENS_ALLOWED_BETAS.has(b)) |
| 182 | : betas |
| 183 | |
| 184 | const response = await anthropic.beta.messages.countTokens({ |
| 185 | model: normalizeModelStringForAPI(model), |
| 186 | messages: |
| 187 | // When we pass tools and no messages, we need to pass a dummy message |
| 188 | // to get an accurate tool token count. |
| 189 | messages.length > 0 ? messages : [{ role: 'user', content: 'foo' }], |
| 190 | tools, |
| 191 | ...(filteredBetas.length > 0 && { betas: filteredBetas }), |
| 192 | // Enable thinking if messages contain thinking blocks |
| 193 | ...(containsThinking && { |
| 194 | thinking: { |
| 195 | type: 'enabled', |
| 196 | budget_tokens: TOKEN_COUNT_THINKING_BUDGET, |
| 197 | }, |
| 198 | }), |
| 199 | }) |
| 200 | |
| 201 | if (typeof response.input_tokens !== 'number') { |
| 202 | // Vertex client throws |
| 203 | // Bedrock client succeeds with { Output: { __type: 'com.amazon.coral.service#UnknownOperationException' }, Version: '1.0' } |
| 204 | return null |
no test coverage detected