Class: Agentilda::Tally
- Inherits:
-
Object
- Object
- Agentilda::Tally
- Defined in:
- lib/agentilda/tally.rb
Overview
What a run cost, once it is over.
The loop reports movement โ which plan went from โญ๏ธ to ๐ก, which agent failed and why โ and says nothing about the bill. A round of five agents against a large repository spends several million tokens and the better part of an hour, and until this existed the only record of that was a directory of trace files nobody reads.
#render returns a string and prints nothing, so the caller decides where it goes, the same way Reporter works.
Defined Under Namespace
Classes: Row
Constant Summary collapse
- WIDTHS =
Cells per column, so the header, the rows and the rule cannot drift.
{name: 22, invocations: 6, subagents: 11, up: 9, down: 9, seconds: 8}.freeze
Instance Attribute Summary collapse
- #attempts ⇒ Array<Agentilda::Runner::Attempt> readonly
- #rounds ⇒ Integer readonly
-
#seconds ⇒ Float
readonly
Wall clock.
Instance Method Summary collapse
-
#busy ⇒ Float
Seconds of agent time, added up across all of them.
-
#by_agent ⇒ Array<Agentilda::Tally::Row>
One per agent, dearest first.
-
#concurrency ⇒ Float
How many agents were running at any given moment, averaged over the run: agent-seconds divided by wall-clock seconds.
-
#delegated ⇒ Integer
Sub-agent spend that arrived as one number.
-
#down ⇒ Integer
Tokens generated.
-
#initialize(attempts:, seconds:, rounds: 0) ⇒ Tally
constructor
A new instance of Tally.
-
#plans ⇒ Integer
Plans an agent was actually started against, counted once each however many rounds they took.
-
#render ⇒ String
The table and the summary line under it.
-
#subagents ⇒ Integer
Sub-agents spawned by every agent in the run.
-
#summary ⇒ String
The one-line version, for a box.
-
#up ⇒ Integer
Tokens sent, everything included.
Constructor Details
#initialize(attempts:, seconds:, rounds: 0) ⇒ Tally
Returns a new instance of Tally.
38 39 40 41 42 |
# File 'lib/agentilda/tally.rb', line 38 def initialize(attempts:, seconds:, rounds: 0) @attempts = attempts.reject { |a| a.ordinal == "?" } @seconds = seconds @rounds = rounds end |
Instance Attribute Details
#attempts ⇒ Array<Agentilda::Runner::Attempt> (readonly)
45 46 47 |
# File 'lib/agentilda/tally.rb', line 45 def attempts @attempts end |
#rounds ⇒ Integer (readonly)
51 52 53 |
# File 'lib/agentilda/tally.rb', line 51 def rounds @rounds end |
#seconds ⇒ Float (readonly)
Returns wall clock.
48 49 50 |
# File 'lib/agentilda/tally.rb', line 48 def seconds @seconds end |
Instance Method Details
#busy ⇒ Float
Returns seconds of agent time, added up across all of them.
76 |
# File 'lib/agentilda/tally.rb', line 76 def busy = attempts.sum(&:seconds) |
#by_agent ⇒ Array<Agentilda::Tally::Row>
Returns one per agent, dearest first.
86 87 88 89 90 91 |
# File 'lib/agentilda/tally.rb', line 86 def by_agent attempts.group_by(&:agent).map { |name, list| Row.new(name:, invocations: list.size, subagents: list.sum(&:subagents), up: list.sum(&:up), down: list.sum(&:down), seconds: list.sum(&:seconds)) }.sort_by { |row| -row.up } end |
#concurrency ⇒ Float
How many agents were running at any given moment, averaged over the
run: agent-seconds divided by wall-clock seconds. Below the -j ceiling
by however much the round spent waiting for its slowest member.
83 |
# File 'lib/agentilda/tally.rb', line 83 def concurrency = seconds.positive? ? busy / seconds : 0.0 |
#delegated ⇒ Integer
Sub-agent spend that arrived as one number. claude reports what a
sub-agent cost without splitting it between the two directions, so this
much of #up is really up and down together.
73 |
# File 'lib/agentilda/tally.rb', line 73 def delegated = attempts.sum(&:delegated) |
#down ⇒ Integer
Returns tokens generated.
63 |
# File 'lib/agentilda/tally.rb', line 63 def down = attempts.sum(&:down) |
#plans ⇒ Integer
Plans an agent was actually started against, counted once each however many rounds they took.
57 |
# File 'lib/agentilda/tally.rb', line 57 def plans = attempts.map(&:ordinal).uniq.size |
#render ⇒ String
Returns the table and the summary line under it.
94 95 96 97 98 |
# File 'lib/agentilda/tally.rb', line 94 def render return summary if attempts.empty? ([header, rule] + by_agent.map { |row| line(row) } + [rule, totals, "", summary]).join("\n") end |
#subagents ⇒ Integer
Returns sub-agents spawned by every agent in the run.
66 |
# File 'lib/agentilda/tally.rb', line 66 def subagents = attempts.sum(&:subagents) |
#summary ⇒ String
Returns the one-line version, for a box.
101 102 103 104 105 106 107 108 109 |
# File 'lib/agentilda/tally.rb', line 101 def summary [ "#{plans} plan#{"s" unless plans == 1} addressed", "#{rounds} round#{"s" unless rounds == 1}", duration(seconds), "#{format("%.1f", concurrency)} agents at a time", "โ #{UI.abbreviate(up)} โ #{UI.abbreviate(down)}" ].join(" ยท ") + delegation end |
#up ⇒ Integer
Returns tokens sent, everything included.
60 |
# File 'lib/agentilda/tally.rb', line 60 def up = attempts.sum(&:up) |