llm_cost_tracker 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/CODE_OF_CONDUCT.md +23 -0
- data/README.md +86 -8
- data/SECURITY.md +36 -0
- data/app/assets/llm_cost_tracker/application.css +1 -4
- data/app/controllers/llm_cost_tracker/assets_controller.rb +0 -2
- data/app/controllers/llm_cost_tracker/calls_controller.rb +9 -13
- data/app/controllers/llm_cost_tracker/dashboard_controller.rb +8 -19
- data/app/controllers/llm_cost_tracker/data_quality_controller.rb +1 -2
- data/app/controllers/llm_cost_tracker/models_controller.rb +5 -2
- data/app/controllers/llm_cost_tracker/tags_controller.rb +2 -4
- data/app/helpers/llm_cost_tracker/dashboard_filter_options_helper.rb +1 -7
- data/app/helpers/llm_cost_tracker/dashboard_query_helper.rb +5 -9
- data/app/services/llm_cost_tracker/dashboard/data_quality.rb +10 -10
- data/app/services/llm_cost_tracker/dashboard/filter.rb +6 -26
- data/app/services/llm_cost_tracker/dashboard/provider_breakdown.rb +0 -3
- data/app/services/llm_cost_tracker/dashboard/tag_breakdown.rb +0 -2
- data/app/services/llm_cost_tracker/pagination.rb +1 -9
- data/app/views/layouts/llm_cost_tracker/application.html.erb +1 -16
- data/app/views/llm_cost_tracker/calls/index.html.erb +13 -13
- data/app/views/llm_cost_tracker/calls/show.html.erb +8 -3
- data/app/views/llm_cost_tracker/dashboard/index.html.erb +1 -1
- data/app/views/llm_cost_tracker/data_quality/index.html.erb +36 -14
- data/app/views/llm_cost_tracker/models/index.html.erb +10 -9
- data/app/views/llm_cost_tracker/shared/_spend_chart.html.erb +0 -1
- data/app/views/llm_cost_tracker/shared/_tag_chips.html.erb +0 -1
- data/app/views/llm_cost_tracker/tags/index.html.erb +1 -1
- data/app/views/llm_cost_tracker/tags/show.html.erb +1 -1
- data/lib/llm_cost_tracker/configuration.rb +0 -1
- data/lib/llm_cost_tracker/event.rb +1 -0
- data/lib/llm_cost_tracker/event_metadata.rb +1 -0
- data/lib/llm_cost_tracker/generators/llm_cost_tracker/add_provider_response_id_generator.rb +29 -0
- data/lib/llm_cost_tracker/generators/llm_cost_tracker/templates/add_provider_response_id_to_llm_api_calls.rb.erb +15 -0
- data/lib/llm_cost_tracker/generators/llm_cost_tracker/templates/create_llm_api_calls.rb.erb +2 -0
- data/lib/llm_cost_tracker/llm_api_call.rb +6 -2
- data/lib/llm_cost_tracker/middleware/faraday.rb +1 -0
- data/lib/llm_cost_tracker/parameter_hash.rb +33 -0
- data/lib/llm_cost_tracker/parsed_usage.rb +14 -3
- data/lib/llm_cost_tracker/parsers/anthropic.rb +47 -28
- data/lib/llm_cost_tracker/parsers/gemini.rb +28 -4
- data/lib/llm_cost_tracker/parsers/openai_compatible.rb +5 -6
- data/lib/llm_cost_tracker/parsers/openai_usage.rb +14 -0
- data/lib/llm_cost_tracker/price_registry.rb +22 -7
- data/lib/llm_cost_tracker/price_sync/refresh_plan_builder.rb +162 -0
- data/lib/llm_cost_tracker/price_sync/registry_loader.rb +55 -0
- data/lib/llm_cost_tracker/price_sync/registry_writer.rb +25 -0
- data/lib/llm_cost_tracker/price_sync.rb +16 -184
- data/lib/llm_cost_tracker/pricing.rb +0 -11
- data/lib/llm_cost_tracker/railtie.rb +2 -1
- data/lib/llm_cost_tracker/report.rb +0 -5
- data/lib/llm_cost_tracker/storage/active_record_store.rb +10 -11
- data/lib/llm_cost_tracker/stream_collector.rb +17 -13
- data/lib/llm_cost_tracker/tags_column.rb +4 -0
- data/lib/llm_cost_tracker/tracker.rb +10 -2
- data/lib/llm_cost_tracker/version.rb +1 -1
- data/lib/llm_cost_tracker.rb +6 -14
- data/llm_cost_tracker.gemspec +3 -1
- metadata +37 -1
|
@@ -3,21 +3,11 @@
|
|
|
3
3
|
require "monitor"
|
|
4
4
|
|
|
5
5
|
module LlmCostTracker
|
|
6
|
-
# Calculates costs from price entries expressed in USD per 1M tokens.
|
|
7
6
|
module Pricing
|
|
8
7
|
PRICES = PriceRegistry.builtin_prices
|
|
9
8
|
MUTEX = Monitor.new
|
|
10
9
|
|
|
11
10
|
class << self
|
|
12
|
-
# Estimate model cost from token counts.
|
|
13
|
-
#
|
|
14
|
-
# @param model [String] Provider model identifier.
|
|
15
|
-
# @param input_tokens [Integer] Input token count, including cached tokens if reported that way.
|
|
16
|
-
# @param output_tokens [Integer] Output token count.
|
|
17
|
-
# @param cached_input_tokens [Integer] OpenAI-style cached input tokens.
|
|
18
|
-
# @param cache_read_input_tokens [Integer] Anthropic-style cache read tokens.
|
|
19
|
-
# @param cache_creation_input_tokens [Integer] Anthropic-style cache creation tokens.
|
|
20
|
-
# @return [LlmCostTracker::Cost, nil] nil when no price is configured for the model.
|
|
21
11
|
def cost_for(model:, input_tokens:, output_tokens:, cached_input_tokens: 0,
|
|
22
12
|
cache_read_input_tokens: 0, cache_creation_input_tokens: 0)
|
|
23
13
|
prices = lookup(model)
|
|
@@ -111,7 +101,6 @@ module LlmCostTracker
|
|
|
111
101
|
model.to_s.split("/").last
|
|
112
102
|
end
|
|
113
103
|
|
|
114
|
-
# Try to match model names like "gpt-4o-2024-08-06" to "gpt-4o".
|
|
115
104
|
def fuzzy_match(model, normalized_model, table)
|
|
116
105
|
sorted_price_keys(table).each do |key|
|
|
117
106
|
return table[key] if model.start_with?(key) || normalized_model.start_with?(key)
|
|
@@ -4,6 +4,8 @@ module LlmCostTracker
|
|
|
4
4
|
class Railtie < Rails::Railtie
|
|
5
5
|
generators do
|
|
6
6
|
require_relative "generators/llm_cost_tracker/add_latency_ms_generator"
|
|
7
|
+
require_relative "generators/llm_cost_tracker/add_provider_response_id_generator"
|
|
8
|
+
require_relative "generators/llm_cost_tracker/add_streaming_generator"
|
|
7
9
|
require_relative "generators/llm_cost_tracker/install_generator"
|
|
8
10
|
require_relative "generators/llm_cost_tracker/prices_generator"
|
|
9
11
|
require_relative "generators/llm_cost_tracker/upgrade_cost_precision_generator"
|
|
@@ -15,7 +17,6 @@ module LlmCostTracker
|
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
initializer "llm_cost_tracker.configure" do
|
|
18
|
-
# Auto-require ActiveRecord storage if configured
|
|
19
20
|
ActiveSupport.on_load(:active_record) do
|
|
20
21
|
if LlmCostTracker.configuration.active_record?
|
|
21
22
|
require_relative "llm_api_call"
|
|
@@ -8,11 +8,6 @@ module LlmCostTracker
|
|
|
8
8
|
DEFAULT_DAYS = ReportData::DEFAULT_DAYS
|
|
9
9
|
|
|
10
10
|
class << self
|
|
11
|
-
# Render a terminal-friendly cost report from ActiveRecord storage.
|
|
12
|
-
#
|
|
13
|
-
# @param days [Integer] Number of trailing days to include.
|
|
14
|
-
# @param now [Time] Report end time.
|
|
15
|
-
# @return [String]
|
|
16
11
|
def generate(days: DEFAULT_DAYS, now: Time.now.utc, tag_breakdowns: nil)
|
|
17
12
|
ReportFormatter.new(data(days: days, now: now, tag_breakdowns: tag_breakdowns)).to_s
|
|
18
13
|
rescue LoadError => e
|
|
@@ -19,24 +19,23 @@ module LlmCostTracker
|
|
|
19
19
|
tags: tags_for_storage(tags),
|
|
20
20
|
tracked_at: event.tracked_at
|
|
21
21
|
}
|
|
22
|
-
attributes[:latency_ms]
|
|
23
|
-
attributes[:stream]
|
|
24
|
-
attributes[:usage_source] = event.usage_source if
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
attributes[:latency_ms] = event.latency_ms if LlmCostTracker::LlmApiCall.latency_column?
|
|
23
|
+
attributes[:stream] = event.stream if LlmCostTracker::LlmApiCall.stream_column?
|
|
24
|
+
attributes[:usage_source] = event.usage_source if LlmCostTracker::LlmApiCall.usage_source_column?
|
|
25
|
+
if LlmCostTracker::LlmApiCall.provider_response_id_column?
|
|
26
|
+
attributes[:provider_response_id] = event.provider_response_id
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
LlmCostTracker::LlmApiCall.create!(attributes)
|
|
27
30
|
end
|
|
28
31
|
|
|
29
32
|
def monthly_total(time: Time.now.utc)
|
|
30
|
-
|
|
33
|
+
LlmCostTracker::LlmApiCall
|
|
31
34
|
.where(tracked_at: time.beginning_of_month..time)
|
|
32
35
|
.sum(:total_cost)
|
|
33
36
|
.to_f
|
|
34
37
|
end
|
|
35
38
|
|
|
36
|
-
def model_class
|
|
37
|
-
LlmCostTracker::LlmApiCall
|
|
38
|
-
end
|
|
39
|
-
|
|
40
39
|
private
|
|
41
40
|
|
|
42
41
|
def stringify_tags(tags)
|
|
@@ -44,7 +43,7 @@ module LlmCostTracker
|
|
|
44
43
|
end
|
|
45
44
|
|
|
46
45
|
def tags_for_storage(tags)
|
|
47
|
-
|
|
46
|
+
LlmCostTracker::LlmApiCall.tags_json_column? ? tags : tags.to_json
|
|
48
47
|
end
|
|
49
48
|
|
|
50
49
|
def stringify_tag_value(value)
|
|
@@ -8,10 +8,11 @@ module LlmCostTracker
|
|
|
8
8
|
class StreamCollector
|
|
9
9
|
attr_reader :provider
|
|
10
10
|
|
|
11
|
-
def initialize(provider:, model:, latency_ms: nil, metadata: {})
|
|
11
|
+
def initialize(provider:, model:, latency_ms: nil, provider_response_id: nil, metadata: {})
|
|
12
12
|
@provider = provider.to_s
|
|
13
13
|
@model = model
|
|
14
14
|
@latency_ms = latency_ms
|
|
15
|
+
@provider_response_id = provider_response_id
|
|
15
16
|
@metadata = ValueHelpers.deep_dup(metadata || {})
|
|
16
17
|
@events = []
|
|
17
18
|
@explicit_usage = nil
|
|
@@ -20,13 +21,11 @@ module LlmCostTracker
|
|
|
20
21
|
@monitor = Monitor.new
|
|
21
22
|
end
|
|
22
23
|
|
|
23
|
-
def model
|
|
24
|
-
@monitor.synchronize { @model }
|
|
25
|
-
end
|
|
24
|
+
def model = @monitor.synchronize { @model }
|
|
26
25
|
|
|
27
|
-
def metadata
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
def metadata = @monitor.synchronize { ValueHelpers.deep_dup(@metadata) }
|
|
27
|
+
|
|
28
|
+
def provider_response_id = @monitor.synchronize { @provider_response_id }
|
|
30
29
|
|
|
31
30
|
def model=(value)
|
|
32
31
|
@monitor.synchronize do
|
|
@@ -35,6 +34,13 @@ module LlmCostTracker
|
|
|
35
34
|
end
|
|
36
35
|
end
|
|
37
36
|
|
|
37
|
+
def provider_response_id=(value)
|
|
38
|
+
@monitor.synchronize do
|
|
39
|
+
ensure_open!
|
|
40
|
+
@provider_response_id = value
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
38
44
|
def event(data, type: nil)
|
|
39
45
|
@monitor.synchronize do
|
|
40
46
|
ensure_open!
|
|
@@ -67,6 +73,7 @@ module LlmCostTracker
|
|
|
67
73
|
explicit_usage: ValueHelpers.deep_dup(@explicit_usage),
|
|
68
74
|
model: @model,
|
|
69
75
|
latency_ms: @latency_ms,
|
|
76
|
+
provider_response_id: @provider_response_id,
|
|
70
77
|
metadata: ValueHelpers.deep_dup(@metadata)
|
|
71
78
|
}
|
|
72
79
|
end
|
|
@@ -80,6 +87,7 @@ module LlmCostTracker
|
|
|
80
87
|
latency_ms: snapshot[:latency_ms] || elapsed_ms,
|
|
81
88
|
stream: true,
|
|
82
89
|
usage_source: parsed.usage_source,
|
|
90
|
+
provider_response_id: parsed.provider_response_id || snapshot[:provider_response_id],
|
|
83
91
|
metadata: error_metadata(errored).merge(snapshot[:metadata]).merge(parsed.metadata)
|
|
84
92
|
)
|
|
85
93
|
end
|
|
@@ -147,12 +155,8 @@ module LlmCostTracker
|
|
|
147
155
|
)
|
|
148
156
|
end
|
|
149
157
|
|
|
150
|
-
def error_metadata(errored)
|
|
151
|
-
errored ? { stream_errored: true } : {}
|
|
152
|
-
end
|
|
158
|
+
def error_metadata(errored) = errored ? { stream_errored: true } : {}
|
|
153
159
|
|
|
154
|
-
def elapsed_ms
|
|
155
|
-
((Process.clock_gettime(Process::CLOCK_MONOTONIC) - @started_at) * 1000).round
|
|
156
|
-
end
|
|
160
|
+
def elapsed_ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - @started_at) * 1000).round
|
|
157
161
|
end
|
|
158
162
|
end
|
|
@@ -13,8 +13,8 @@ module LlmCostTracker
|
|
|
13
13
|
Budget.enforce!
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def record(provider:, model:, input_tokens:, output_tokens:,
|
|
17
|
-
|
|
16
|
+
def record(provider:, model:, input_tokens:, output_tokens:, latency_ms: nil, stream: false,
|
|
17
|
+
usage_source: nil, provider_response_id: nil, metadata: {})
|
|
18
18
|
usage = EventMetadata.usage_data(input_tokens, output_tokens, metadata)
|
|
19
19
|
|
|
20
20
|
cost_data = Pricing.cost_for(
|
|
@@ -39,6 +39,7 @@ module LlmCostTracker
|
|
|
39
39
|
latency_ms: normalized_latency_ms(latency_ms),
|
|
40
40
|
stream: stream ? true : false,
|
|
41
41
|
usage_source: normalized_usage_source(usage_source),
|
|
42
|
+
provider_response_id: normalized_provider_response_id(provider_response_id),
|
|
42
43
|
tracked_at: Time.now.utc
|
|
43
44
|
)
|
|
44
45
|
|
|
@@ -122,6 +123,13 @@ module LlmCostTracker
|
|
|
122
123
|
symbol = value.to_sym
|
|
123
124
|
USAGE_SOURCES.include?(symbol) ? symbol.to_s : nil
|
|
124
125
|
end
|
|
126
|
+
|
|
127
|
+
def normalized_provider_response_id(value)
|
|
128
|
+
return nil if value.nil?
|
|
129
|
+
|
|
130
|
+
string = value.to_s
|
|
131
|
+
string.empty? ? nil : string
|
|
132
|
+
end
|
|
125
133
|
end
|
|
126
134
|
end
|
|
127
135
|
end
|
data/lib/llm_cost_tracker.rb
CHANGED
|
@@ -8,6 +8,7 @@ require_relative "llm_cost_tracker/version"
|
|
|
8
8
|
require_relative "llm_cost_tracker/configuration"
|
|
9
9
|
require_relative "llm_cost_tracker/errors"
|
|
10
10
|
require_relative "llm_cost_tracker/logging"
|
|
11
|
+
require_relative "llm_cost_tracker/parameter_hash"
|
|
11
12
|
require_relative "llm_cost_tracker/cost"
|
|
12
13
|
require_relative "llm_cost_tracker/event"
|
|
13
14
|
require_relative "llm_cost_tracker/parsed_usage"
|
|
@@ -44,10 +45,6 @@ module LlmCostTracker
|
|
|
44
45
|
CONFIGURATION_MUTEX.synchronize { @configuration ||= Configuration.new }
|
|
45
46
|
end
|
|
46
47
|
|
|
47
|
-
# Configure the gem once during application boot.
|
|
48
|
-
#
|
|
49
|
-
# @yieldparam configuration [LlmCostTracker::Configuration]
|
|
50
|
-
# @return [void]
|
|
51
48
|
def configure
|
|
52
49
|
config = CONFIGURATION_MUTEX.synchronize do
|
|
53
50
|
current = @configuration || Configuration.new
|
|
@@ -69,13 +66,8 @@ module LlmCostTracker
|
|
|
69
66
|
Tracker.enforce_budget!
|
|
70
67
|
end
|
|
71
68
|
|
|
72
|
-
def track(provider:, model:, input_tokens:, output_tokens:,
|
|
73
|
-
|
|
74
|
-
stream = options.key?(:stream) ? options.delete(:stream) : false
|
|
75
|
-
usage_source = options.key?(:usage_source) ? options.delete(:usage_source) : :manual
|
|
76
|
-
enforce_budget = options.key?(:enforce_budget) ? options.delete(:enforce_budget) : false
|
|
77
|
-
metadata = options
|
|
78
|
-
|
|
69
|
+
def track(provider:, model:, input_tokens:, output_tokens:, latency_ms: nil, stream: false, usage_source: :manual,
|
|
70
|
+
enforce_budget: false, provider_response_id: nil, **metadata)
|
|
79
71
|
enforce_budget! if enforce_budget
|
|
80
72
|
Tracker.record(
|
|
81
73
|
provider: provider.to_s,
|
|
@@ -85,17 +77,19 @@ module LlmCostTracker
|
|
|
85
77
|
latency_ms: latency_ms,
|
|
86
78
|
stream: stream,
|
|
87
79
|
usage_source: usage_source,
|
|
80
|
+
provider_response_id: provider_response_id,
|
|
88
81
|
metadata: metadata
|
|
89
82
|
)
|
|
90
83
|
end
|
|
91
84
|
|
|
92
|
-
def track_stream(provider:, model:, latency_ms: nil, enforce_budget: false, **metadata)
|
|
85
|
+
def track_stream(provider:, model:, latency_ms: nil, enforce_budget: false, provider_response_id: nil, **metadata)
|
|
93
86
|
require_relative "llm_cost_tracker/stream_collector"
|
|
94
87
|
enforce_budget! if enforce_budget
|
|
95
88
|
collector = StreamCollector.new(
|
|
96
89
|
provider: provider.to_s,
|
|
97
90
|
model: model,
|
|
98
91
|
latency_ms: latency_ms,
|
|
92
|
+
provider_response_id: provider_response_id,
|
|
99
93
|
metadata: metadata
|
|
100
94
|
)
|
|
101
95
|
yield collector
|
|
@@ -116,10 +110,8 @@ module LlmCostTracker
|
|
|
116
110
|
end
|
|
117
111
|
end
|
|
118
112
|
|
|
119
|
-
# Load Railtie if Rails is present
|
|
120
113
|
require_relative "llm_cost_tracker/railtie" if defined?(Rails::Railtie)
|
|
121
114
|
|
|
122
|
-
# Auto-register Faraday middleware
|
|
123
115
|
if defined?(Faraday)
|
|
124
116
|
Faraday::Middleware.register_middleware(
|
|
125
117
|
llm_cost_tracker: LlmCostTracker::Middleware::Faraday
|
data/llm_cost_tracker.gemspec
CHANGED
|
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
|
|
|
28
28
|
spec.files = Dir.chdir(__dir__) do
|
|
29
29
|
`git ls-files -z`.split("\x0").reject do |f|
|
|
30
30
|
(File.expand_path(f) == __FILE__) ||
|
|
31
|
-
f.start_with?("bin/", "test/", "spec/", ".git", ".github", "gemfiles/", ".rubocop", "Gemfile")
|
|
31
|
+
f.start_with?("bin/", "docs/", "test/", "spec/", ".git", ".github", "gemfiles/", ".rubocop", "Gemfile")
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -43,6 +43,8 @@ Gem::Specification.new do |spec|
|
|
|
43
43
|
spec.add_development_dependency "rake", "~> 13.0"
|
|
44
44
|
spec.add_development_dependency "rspec", "~> 3.0"
|
|
45
45
|
spec.add_development_dependency "rubocop", "~> 1.0"
|
|
46
|
+
spec.add_development_dependency "simplecov", "~> 0.22"
|
|
47
|
+
spec.add_development_dependency "simplecov-lcov", "~> 0.8"
|
|
46
48
|
spec.add_development_dependency "sqlite3", ">= 1.4", "< 3.0"
|
|
47
49
|
spec.add_development_dependency "webmock", "~> 3.0"
|
|
48
50
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: llm_cost_tracker
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sergii Khomenko
|
|
@@ -146,6 +146,34 @@ dependencies:
|
|
|
146
146
|
- - "~>"
|
|
147
147
|
- !ruby/object:Gem::Version
|
|
148
148
|
version: '1.0'
|
|
149
|
+
- !ruby/object:Gem::Dependency
|
|
150
|
+
name: simplecov
|
|
151
|
+
requirement: !ruby/object:Gem::Requirement
|
|
152
|
+
requirements:
|
|
153
|
+
- - "~>"
|
|
154
|
+
- !ruby/object:Gem::Version
|
|
155
|
+
version: '0.22'
|
|
156
|
+
type: :development
|
|
157
|
+
prerelease: false
|
|
158
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
159
|
+
requirements:
|
|
160
|
+
- - "~>"
|
|
161
|
+
- !ruby/object:Gem::Version
|
|
162
|
+
version: '0.22'
|
|
163
|
+
- !ruby/object:Gem::Dependency
|
|
164
|
+
name: simplecov-lcov
|
|
165
|
+
requirement: !ruby/object:Gem::Requirement
|
|
166
|
+
requirements:
|
|
167
|
+
- - "~>"
|
|
168
|
+
- !ruby/object:Gem::Version
|
|
169
|
+
version: '0.8'
|
|
170
|
+
type: :development
|
|
171
|
+
prerelease: false
|
|
172
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
173
|
+
requirements:
|
|
174
|
+
- - "~>"
|
|
175
|
+
- !ruby/object:Gem::Version
|
|
176
|
+
version: '0.8'
|
|
149
177
|
- !ruby/object:Gem::Dependency
|
|
150
178
|
name: sqlite3
|
|
151
179
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -192,9 +220,11 @@ extra_rdoc_files: []
|
|
|
192
220
|
files:
|
|
193
221
|
- ".rspec"
|
|
194
222
|
- CHANGELOG.md
|
|
223
|
+
- CODE_OF_CONDUCT.md
|
|
195
224
|
- LICENSE.txt
|
|
196
225
|
- README.md
|
|
197
226
|
- Rakefile
|
|
227
|
+
- SECURITY.md
|
|
198
228
|
- app/assets/llm_cost_tracker/application.css
|
|
199
229
|
- app/controllers/llm_cost_tracker/application_controller.rb
|
|
200
230
|
- app/controllers/llm_cost_tracker/assets_controller.rb
|
|
@@ -248,10 +278,12 @@ files:
|
|
|
248
278
|
- lib/llm_cost_tracker/event.rb
|
|
249
279
|
- lib/llm_cost_tracker/event_metadata.rb
|
|
250
280
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/add_latency_ms_generator.rb
|
|
281
|
+
- lib/llm_cost_tracker/generators/llm_cost_tracker/add_provider_response_id_generator.rb
|
|
251
282
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/add_streaming_generator.rb
|
|
252
283
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/install_generator.rb
|
|
253
284
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/prices_generator.rb
|
|
254
285
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/templates/add_latency_ms_to_llm_api_calls.rb.erb
|
|
286
|
+
- lib/llm_cost_tracker/generators/llm_cost_tracker/templates/add_provider_response_id_to_llm_api_calls.rb.erb
|
|
255
287
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/templates/add_streaming_to_llm_api_calls.rb.erb
|
|
256
288
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/templates/create_llm_api_calls.rb.erb
|
|
257
289
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/templates/initializer.rb.erb
|
|
@@ -263,6 +295,7 @@ files:
|
|
|
263
295
|
- lib/llm_cost_tracker/llm_api_call.rb
|
|
264
296
|
- lib/llm_cost_tracker/logging.rb
|
|
265
297
|
- lib/llm_cost_tracker/middleware/faraday.rb
|
|
298
|
+
- lib/llm_cost_tracker/parameter_hash.rb
|
|
266
299
|
- lib/llm_cost_tracker/parsed_usage.rb
|
|
267
300
|
- lib/llm_cost_tracker/parsers/anthropic.rb
|
|
268
301
|
- lib/llm_cost_tracker/parsers/base.rb
|
|
@@ -279,6 +312,9 @@ files:
|
|
|
279
312
|
- lib/llm_cost_tracker/price_sync/merger.rb
|
|
280
313
|
- lib/llm_cost_tracker/price_sync/model_catalog.rb
|
|
281
314
|
- lib/llm_cost_tracker/price_sync/raw_price.rb
|
|
315
|
+
- lib/llm_cost_tracker/price_sync/refresh_plan_builder.rb
|
|
316
|
+
- lib/llm_cost_tracker/price_sync/registry_loader.rb
|
|
317
|
+
- lib/llm_cost_tracker/price_sync/registry_writer.rb
|
|
282
318
|
- lib/llm_cost_tracker/price_sync/source.rb
|
|
283
319
|
- lib/llm_cost_tracker/price_sync/source_result.rb
|
|
284
320
|
- lib/llm_cost_tracker/price_sync/sources/litellm.rb
|