MCPcopy Create free account
hub / github.com/anomalyco/opencode / getUsage

Function getUsage

packages/opencode/src/session/session.ts:338–407  ·  view source on GitHub ↗
(input: { model: Provider.Model; usage: Usage; metadata?: ProviderMetadata })

Source from the content-addressed store, hash-verified

336}
337
338export const getUsage = (input: { model: Provider.Model; usage: Usage; metadata?: ProviderMetadata }) => {
339 const safe = (value: number) => {
340 if (!Number.isFinite(value)) return 0
341 return Math.max(0, value)
342 }
343 const inputTokens = safe(input.usage.inputTokens ?? 0)
344 const outputTokens = safe(input.usage.outputTokens ?? 0)
345 const reasoningTokens = safe(input.usage.reasoningTokens ?? 0)
346
347 const cacheReadInputTokens = safe(input.usage.cacheReadInputTokens ?? 0)
348 const cacheWriteInputTokens = safe(
349 Number(
350 input.usage.cacheWriteInputTokens ??
351 input.metadata?.["anthropic"]?.["cacheCreationInputTokens"] ??
352 // google-vertex-anthropic returns metadata under "vertex" key
353 // (AnthropicMessagesLanguageModel custom provider key from 'vertex.anthropic.messages')
354 input.metadata?.["vertex"]?.["cacheCreationInputTokens"] ??
355 // @ts-expect-error
356 input.metadata?.["bedrock"]?.["usage"]?.["cacheWriteInputTokens"] ??
357 // @ts-expect-error
358 input.metadata?.["venice"]?.["usage"]?.["cacheCreationInputTokens"] ??
359 0,
360 ),
361 )
362
363 // AI SDK v6 normalized inputTokens to include cached tokens across all providers
364 // (including Anthropic/Bedrock which previously excluded them). Always subtract cache
365 // tokens to get the non-cached input count for separate cost calculation.
366 const adjustedInputTokens = safe(inputTokens - cacheReadInputTokens - cacheWriteInputTokens)
367
368 const total = input.usage.totalTokens
369
370 const tokens = {
371 total,
372 input: adjustedInputTokens,
373 output: safe(outputTokens - reasoningTokens),
374 reasoning: reasoningTokens,
375 cache: {
376 write: cacheWriteInputTokens,
377 read: cacheReadInputTokens,
378 },
379 }
380
381 const contextTokens = inputTokens
382 const costInfo =
383 input.model.cost?.tiers
384 ?.filter((item) => item.tier.type === "context" && contextTokens > item.tier.size)
385 .sort((a, b) => b.tier.size - a.tier.size)[0] ??
386 (input.model.cost?.experimentalOver200K && contextTokens > 200_000
387 ? input.model.cost.experimentalOver200K
388 : input.model.cost)
389 const totalNanoAiu = input.metadata?.["copilot"]?.["totalNanoAiu"]
390 return {
391 cost:
392 typeof totalNanoAiu === "number" && Number.isFinite(totalNanoAiu) && totalNanoAiu >= 0
393 ? new Decimal(totalNanoAiu).div(100_000_000_000).toNumber()
394 : safe(
395 new Decimal(0)

Callers

nothing calls this directly

Calls 2

safeFunction · 0.70
addMethod · 0.65

Tested by

no test coverage detected