Module: AgentCliRuntime::UsageExtractors

Defined in:
lib/agent_cli_runtime/usage_extractors.rb

Constant Summary collapse

CLAUDE =
lambda do |event|
  next nil unless event.is_a?(Hash)

  usage = usage_hash(event)
  if event["type"] == "result" && usage
    usage_result(event, usage, model_from(event))
  elsif event["type"] == "stream_event" && usage
    usage_result(event, usage, model_from(event))
  end
end
CODEX =
lambda do |event|
  next nil unless event.is_a?(Hash)

  usage = usage_hash(event)
  usage_result(event, usage, model_from(event)) if usage
end
PI =
lambda do |event|
  next nil unless event.is_a?(Hash)

  usage = usage_hash(event)
  usage_result(event, usage, model_from(event)) if usage
end
GROK =
lambda do |event|
  next nil unless event.is_a?(Hash)

  usage = usage_hash(event)
  usage_result(event, usage, model_from(event)) if usage
end

Class Method Summary collapse

Class Method Details

.cached_tokens(usage) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/agent_cli_runtime/usage_extractors.rb', line 65

def cached_tokens(usage)
  direct = token_count(
    usage, "cached", "cached_tokens", "cachedTokens",
    "cached_input_tokens", "cachedInputTokens"
  )
  return direct if direct.positive?

  token_count(usage, "cache_read_input_tokens", "cacheReadInputTokens") +
    token_count(usage, "cache_creation_input_tokens", "cacheCreationInputTokens") +
    token_count(
      nested_hash(usage, "prompt_tokens_details"), "cached_tokens", "cachedTokens"
    ) +
    token_count(
      nested_hash(usage, "input_tokens_details"), "cached_tokens", "cachedTokens"
    )
end

.model_from(event) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/agent_cli_runtime/usage_extractors.rb', line 94

def model_from(event)
  model_usage = event["modelUsage"]
  if model_usage.is_a?(Hash) && !model_usage.empty?
    return model_usage.keys.first.to_s
  end

  candidates = [
    event["model"],
    event.dig("message", "model"),
    event.dig("event", "message", "model"),
    event.dig("response", "model"),
    event.dig("item", "model")
  ]
  candidates.find { |value| !value.to_s.empty? }&.to_s
end

.model_from_usage(usage) ⇒ Object



110
111
112
113
# File 'lib/agent_cli_runtime/usage_extractors.rb', line 110

def model_from_usage(usage)
  value = usage["model"] || usage["model_name"] || usage["modelName"]
  value.to_s.empty? ? nil : value.to_s
end

.nested_hash(hash, key) ⇒ Object



89
90
91
92
# File 'lib/agent_cli_runtime/usage_extractors.rb', line 89

def nested_hash(hash, key)
  value = hash[key]
  value.is_a?(Hash) ? value : {}
end

.token_count(hash, *keys) ⇒ Object



82
83
84
85
86
87
# File 'lib/agent_cli_runtime/usage_extractors.rb', line 82

def token_count(hash, *keys)
  return 0 unless hash.is_a?(Hash)

  key = keys.find { |candidate| hash.key?(candidate) }
  key ? hash[key].to_i : 0
end

.usage_hash(event) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/agent_cli_runtime/usage_extractors.rb', line 37

def usage_hash(event)
  candidates = [
    event["usage"],
    event["token_usage"],
    event.dig("event", "usage"),
    event.dig("event", "message", "usage"),
    event.dig("info", "usage"),
    event.dig("info", "total_token_usage"),
    event.dig("response", "usage"),
    event.dig("item", "usage")
  ]
  candidates.find { |value| value.is_a?(Hash) }
end

.usage_result(event, usage, model) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/agent_cli_runtime/usage_extractors.rb', line 51

def usage_result(event, usage, model)
  {
    input: token_count(
      usage, "input_tokens", "inputTokens", "prompt_tokens", "promptTokens"
    ),
    output: token_count(
      usage, "output_tokens", "outputTokens", "completion_tokens",
      "completionTokens"
    ),
    cached: cached_tokens(usage),
    model: model || model_from_usage(usage) || model_from(event)
  }
end