brute 5.0.0 → 5.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b9b592266887d7f4099f89d132ae3fb0af1b7b360f8b4a819c10b300b8e0484e
4
- data.tar.gz: d761c4ab24c37596acf52235e5e640177ec4b4d6ba528c5c9c0936452fdffc88
3
+ metadata.gz: 2e01ccfbca88337e90f041dc548bb2ced64a83bcffc1f76e302bd8fa4825b902
4
+ data.tar.gz: 6bd8054dacdf68ac5d3f773d53fd6a4093be59985350ba51cc78c10227fe38ef
5
5
  SHA512:
6
- metadata.gz: 98083c184fcea3e2213fe6b244a151aabdb4d136ef11bd130d35ecf4a07881925b961df267e75de5574927b5e8cf18c2fda9f9fea1ec10e57740c76e8c0a2c23
7
- data.tar.gz: 41f4df4d86383fb6eb3cddaeb4d64e27dd37f3bccd09e5e80d2f5b98eaac7f1b7df886c16cb77a714b8d1888becf3cca5495723d8a6e9539771b36623bb413c0
6
+ metadata.gz: 4eae8566ab16b8f48ab62db551efe0878569727a4a5a5069e8a7c8de533858a84707538dd6015f4651f2ef276b9c17fc9b6ef615535e76301a425039fbf8deb0
7
+ data.tar.gz: fb6bf08902d2917ec98089403a64f1424216ac8f2d81374a426b372ff24e2a90e32adf4c52571d24cce166ddcbd2f1f13c34180c1fee01302f9cc69753c38c87
data/lib/brute/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Brute
4
- VERSION = "5.0.0"
4
+ VERSION = "5.0.1"
5
5
  end
data/lib/brute.rb CHANGED
@@ -119,7 +119,6 @@ require_relative "brute/message_transport/ruby_open_ai"
119
119
  require_relative "brute/message_transport/lang_chain"
120
120
  require_relative "brute/middleware/002_session_log"
121
121
  require_relative "brute/middleware/004_summarize"
122
- require_relative "brute/middleware/005_tracing"
123
122
  require_relative "brute/middleware/006_loop"
124
123
  require_relative "brute/middleware/008_checkpoint"
125
124
  require_relative "brute/middleware/010_max_iterations"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brute
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0
4
+ version: 5.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brute Contributors
@@ -305,7 +305,6 @@ files:
305
305
  - lib/brute/middleware/000_base.rb
306
306
  - lib/brute/middleware/002_session_log.rb
307
307
  - lib/brute/middleware/004_summarize.rb
308
- - lib/brute/middleware/005_tracing.rb
309
308
  - lib/brute/middleware/006_loop.rb
310
309
  - lib/brute/middleware/008_checkpoint.rb
311
310
  - lib/brute/middleware/010_max_iterations.rb
@@ -1,94 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/setup"
4
- require "brute"
5
-
6
- module Brute
7
- module Middleware
8
- # Logs timing and token usage for every LLM call, and tracks cumulative
9
- # timing data in env[:metadata][:timing].
10
- #
11
- # As the outermost middleware, it sees the full pipeline elapsed time per
12
- # call. It also tracks total wall-clock time across all calls in a turn
13
- # (including tool execution gaps between LLM calls).
14
- #
15
- # A new turn is detected when env[:current_iteration] == 1 (the agent
16
- # loop resets this at the start of each turn).
17
- #
18
- # Stores in env[:metadata][:timing]:
19
- # total_elapsed: wall-clock since the turn began (includes tool gaps)
20
- # total_llm_elapsed: cumulative time spent inside LLM calls only
21
- # llm_call_count: number of LLM calls so far
22
- # last_call_elapsed: duration of the most recent LLM call
23
- #
24
- class Tracing < Brute::Middleware::Base
25
- def initialize(app, logger:)
26
- @app = app
27
-
28
- @logger = logger
29
- @call_count = 0
30
- @total_llm_elapsed = 0.0
31
- @turn_start = nil
32
- end
33
-
34
- def call(env)
35
- @call_count += 1
36
-
37
- # Detect new turn via iteration counter
38
- if env[:current_iteration] <= 1
39
- @turn_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
40
- @total_llm_elapsed = 0.0
41
- end
42
-
43
- messages = env[:messages]
44
- provider_name = env[:provider]&.respond_to?(:name) ? env[:provider].name : env[:provider].class.name
45
- model_name = env[:model] || (env[:provider].default_model rescue "unknown")
46
- @logger.debug("[brute] LLM call ##{@call_count} [#{provider_name}/#{model_name}] (#{messages.size} messages in context)")
47
-
48
- start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
49
- response = @app.call(env)
50
- now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
51
- elapsed = now - start
52
-
53
- @total_llm_elapsed += elapsed
54
-
55
- tokens = if response.respond_to?(:usage) && (usage = response.usage)
56
- read_token(usage, :total_tokens)
57
- else
58
- '?'
59
- end
60
- @logger.debug("[brute] LLM response ##{@call_count} [#{provider_name}/#{model_name}]: #{tokens} tokens, #{elapsed.round(2)}s")
61
- env[:events] << { type: :log, data: "LLM response ##{@call_count}: #{tokens} tokens, #{elapsed.round(2)}s" } if response
62
-
63
- env[:metadata][:timing] = {
64
- total_elapsed: now - (@turn_start || start),
65
- total_llm_elapsed: @total_llm_elapsed,
66
- llm_call_count: @call_count,
67
- last_call_elapsed: elapsed
68
- }
69
-
70
- if response.respond_to?(:usage) && (u = response.usage)
71
- env[:metadata][:tokens] = {
72
- total: read_token(u, :total_tokens),
73
- total_input: read_token(u, :input_tokens),
74
- total_output: read_token(u, :output_tokens),
75
- }
76
- end
77
-
78
- response
79
- end
80
-
81
- private
82
-
83
- def read_token(usage, method)
84
- if usage.respond_to?(method)
85
- usage.send(method).to_i
86
- elsif usage.respond_to?(:[])
87
- (usage[method] || usage[method.to_s]).to_i
88
- else
89
- 0
90
- end
91
- end
92
- end
93
- end
94
- end