Class: AgentHarness::QuotaStatus

Inherits:
Struct
  • Object
show all
Defined in:
lib/agent_harness/quota_status.rb

Overview

Serializable snapshot of a provider's remaining quota for the current billing period.

QuotaStatus is the unified return type for Providers::Base#check_quota and TokenUsageTracker#estimated_usage. It lets the orchestration layer compare runners on the same axis (remaining/limit/unit) so Paid can auto-balance weights and let multiple runners exhaust their quotas at roughly the same rate.

All instances are frozen so callers can safely cache, share, and persist them (for example, to a database column) without worrying about mutation.

Examples:

A real API-backed status

AgentHarness::QuotaStatus.new(
  available: true,
  remaining: 1_500_000,
  limit: 2_000_000,
  reset_at: Time.utc(2026, 8, 1),
  unit: :tokens
)

Sentinel returned by providers that do not expose a quota API

AgentHarness::QuotaStatus.unavailable

Constant Summary collapse

UNITS =

Units recognized by the harness. Providers may return other Symbols, but the documented set is enumerated here so callers can switch on it without typos. New units should be added here when a provider exposes one that does not fit an existing bucket.

%i[
  tokens
  requests
  credits
  cost_cents
].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(available: false, remaining: nil, limit: nil, reset_at: nil, unit: nil, checked_at: nil) ⇒ QuotaStatus

Returns a new instance of QuotaStatus.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/agent_harness/quota_status.rb', line 49

def initialize(available: false, remaining: nil, limit: nil, reset_at: nil, unit: nil, checked_at: nil)
  unless reset_at.nil? || reset_at.is_a?(Time)
    raise ArgumentError, "reset_at must be a Time or nil (got #{reset_at.class})"
  end
  unless unit.nil? || unit.is_a?(Symbol)
    raise ArgumentError, "unit must be a Symbol or nil (got #{unit.class})"
  end
  unless available == true || available == false
    raise ArgumentError, "available must be a boolean (got #{available.class})"
  end

  # Snap the check time when an available status is built without one so
  # cached/stored statuses always record when the underlying lookup ran.
  resolved_checked_at = checked_at || (available ? Time.now.utc : nil)

  super(
    available: available,
    remaining: remaining,
    limit: limit,
    reset_at: reset_at,
    unit: unit,
    checked_at: resolved_checked_at
  )
  freeze
end

Instance Attribute Details

#availableObject

Returns the value of attribute available

Returns:

  • (Object)

    the current value of available



30
31
32
# File 'lib/agent_harness/quota_status.rb', line 30

def available
  @available
end

#checked_atObject

Returns the value of attribute checked_at

Returns:

  • (Object)

    the current value of checked_at



30
31
32
# File 'lib/agent_harness/quota_status.rb', line 30

def checked_at
  @checked_at
end

#limitObject

Returns the value of attribute limit

Returns:

  • (Object)

    the current value of limit



30
31
32
# File 'lib/agent_harness/quota_status.rb', line 30

def limit
  @limit
end

#remainingObject

Returns the value of attribute remaining

Returns:

  • (Object)

    the current value of remaining



30
31
32
# File 'lib/agent_harness/quota_status.rb', line 30

def remaining
  @remaining
end

#reset_atObject

Returns the value of attribute reset_at

Returns:

  • (Object)

    the current value of reset_at



30
31
32
# File 'lib/agent_harness/quota_status.rb', line 30

def reset_at
  @reset_at
end

#unitObject

Returns the value of attribute unit

Returns:

  • (Object)

    the current value of unit



30
31
32
# File 'lib/agent_harness/quota_status.rb', line 30

def unit
  @unit
end

Class Method Details

.from_h(hash) ⇒ QuotaStatus

Build a QuotaStatus from a Hash produced by #to_h.

Parameters:

  • hash (Hash)

    serialized QuotaStatus

Returns:



121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/agent_harness/quota_status.rb', line 121

def self.from_h(hash)
  return unavailable if hash.nil? || hash.empty?

  new(
    available: fetch_value(hash, :available),
    remaining: fetch_value(hash, :remaining),
    limit: fetch_value(hash, :limit),
    reset_at: parse_time(fetch_value(hash, :reset_at)),
    unit: normalize_unit(fetch_value(hash, :unit)),
    checked_at: parse_time(fetch_value(hash, :checked_at))
  )
end

.unavailableQuotaStatus

Sentinel for "this provider does not expose a quota API." The default implementation of Providers::Base#check_quota returns this so callers can treat all providers uniformly.

Returns:



147
148
149
# File 'lib/agent_harness/quota_status.rb', line 147

def self.unavailable
  new(available: false)
end

Instance Method Details

#available?Boolean

Whether this provider exposes any quota information at all.

Returns:

  • (Boolean)


78
# File 'lib/agent_harness/quota_status.rb', line 78

def available? = available == true

#exhausted?Boolean

Whether the tracked quota is exhausted. Returns false when availability is unknown so callers can treat the status conservatively.

Returns:

  • (Boolean)


84
85
86
87
88
89
# File 'lib/agent_harness/quota_status.rb', line 84

def exhausted?
  return false unless available?
  return false if remaining.nil?

  remaining <= 0
end

#to_hHash{Symbol => Object}

Serializable hash suitable for database persistence.

reset_at and checked_at are serialized as ISO8601 strings in UTC so the hash round-trips through JSON without losing timezone information.

Returns:

  • (Hash{Symbol => Object})


106
107
108
109
110
111
112
113
114
115
# File 'lib/agent_harness/quota_status.rb', line 106

def to_h
  {
    available: available,
    remaining: remaining,
    limit: limit,
    reset_at: serialize_time(reset_at),
    unit: unit,
    checked_at: serialize_time(checked_at)
  }
end

#unit_labelString

Human-friendly label for the unit value, useful for logs and UIs.

Returns:

  • (String)


94
95
96
97
98
# File 'lib/agent_harness/quota_status.rb', line 94

def unit_label
  return "unknown" if unit.nil?

  unit.to_s
end