agent-harness 0.18.1 → 0.18.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54a70f890647d75ff53ab3b965cd3071fdab5fa42ccf1f6aad95387a5e4b1469
4
- data.tar.gz: 34dc8a3d3725d4d8d436671818716ef340ddc712412bd86fb73aa55cce5d2dd5
3
+ metadata.gz: ac0dc1fc90803175d52bbdd01e287c26cac5e2e19b65805390b5a2339fc0937f
4
+ data.tar.gz: d892428011318adc0f716660914c03404463204f2e8d2e8bda399cc9c967c791
5
5
  SHA512:
6
- metadata.gz: 055d9ef0f856eae6105e54ab76236c8b1fa3b0e24679b0874b1ebdcf74d610d6a005862ab18ce586ce21657bb7e93042558175fc3e8df2b41f5d2aa52cc7ac44
7
- data.tar.gz: ee320df58fd1ed97c931ed079068971918890dfed3ca338b835db5ad39b204de053e19e6c100da9dfcfe199fd9271fe91944f25abb0735c34f246ddcdeb0a901
6
+ metadata.gz: fba3f02f5616bf997f2b6c8264ed02abbf26fa7a83a5db143f98c980f0fdeafe2f2cb16de0d0987476e25e137e6717e39f1e7153ca994724251e478e793a6222
7
+ data.tar.gz: cdcd6cfa27c6ad1ec3401c8dee63feabc6a3e4c15dc71cef3c54d1e063364c3791f6e49cbaef843bba15e6ee16ea1d11d465cc21600d6556e112397a0c39de56
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "0.18.1"
2
+ ".": "0.18.2"
3
3
  }
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.18.2](https://github.com/viamin/agent-harness/compare/agent-harness/v0.18.1...agent-harness/v0.18.2) (2026-05-17)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **release:** require conventional PR titles for release-please ([4f0054f](https://github.com/viamin/agent-harness/commit/4f0054f4c9f35251c3185fa8bbf645fcace130b5))
9
+ * **release:** require conventional PR titles for release-please ([fd6633d](https://github.com/viamin/agent-harness/commit/fd6633dff3710ad1575af9bd172f047a93a8f647))
10
+
3
11
  ## [0.18.1](https://github.com/viamin/agent-harness/compare/agent-harness/v0.18.0...agent-harness/v0.18.1) (2026-05-12)
4
12
 
5
13
 
@@ -124,7 +124,7 @@ module AgentHarness
124
124
  :idle_timeout
125
125
  when /rate.?limit|too many requests|\b429\b/i
126
126
  :rate_limited
127
- when /quota|usage.?limit|billing/i
127
+ when /quota|usage.?limit|billing|(?:weekly|monthly)(?:\/(?:weekly|monthly))?\s+limit\s+exhausted/i
128
128
  :quota_exceeded
129
129
  when /auth|unauthorized|forbidden|invalid.*(key|token)|\b401\b|\b403\b/i
130
130
  :auth_expired
@@ -31,11 +31,12 @@ module AgentHarness
31
31
 
32
32
  # Rate limiting and circuit breaker errors
33
33
  class RateLimitError < Error
34
- attr_reader :reset_time, :provider
34
+ attr_reader :reset_time, :provider, :error_category
35
35
 
36
- def initialize(message = nil, reset_time: nil, provider: nil, **kwargs)
36
+ def initialize(message = nil, reset_time: nil, provider: nil, error_category: :rate_limited, **kwargs)
37
37
  @reset_time = reset_time
38
38
  @provider = provider
39
+ @error_category = error_category
39
40
  super(message, **kwargs)
40
41
  end
41
42
  end
@@ -838,9 +838,11 @@ module AgentHarness
838
838
  quota: [
839
839
  /requires more credits/i,
840
840
  /insufficient credits/i,
841
+ /insufficient balance/i,
841
842
  /credit.*exceeded/i,
842
843
  /spend limit.*reached/i,
843
- /billing.*limit/i
844
+ /billing.*limit/i,
845
+ /(?:weekly|monthly)(?:\/(?:weekly|monthly))?\s+limit\s+exhausted/i
844
846
  ]
845
847
  }
846
848
  end
@@ -1130,7 +1132,7 @@ module AgentHarness
1130
1132
  rescue AuthenticationError => e
1131
1133
  failure_smoke_test_result(e.message, :auth_expired)
1132
1134
  rescue RateLimitError => e
1133
- failure_smoke_test_result(e.message, :rate_limited)
1135
+ failure_smoke_test_result(e.message, e.error_category || :rate_limited)
1134
1136
  rescue ProviderError => e
1135
1137
  failure_smoke_test_result(e.message, classify_smoke_test_message(e.message))
1136
1138
  end
@@ -26,6 +26,7 @@ module AgentHarness
26
26
  class Base
27
27
  include Adapter
28
28
  include Extensions::DeepDupable
29
+ include RateLimitResetParsing
29
30
 
30
31
  DEFAULT_SMOKE_TEST_CONTRACT = {
31
32
  prompt: "Reply with exactly OK.",
@@ -52,7 +53,8 @@ module AgentHarness
52
53
  quota_exceeded: [
53
54
  /quota.*exceeded/i,
54
55
  /insufficient.*quota/i,
55
- /billing/i
56
+ /billing/i,
57
+ /(?:weekly|monthly)(?:\/(?:weekly|monthly))?\s+limit\s+exhausted/i
56
58
  ],
57
59
  transient: [
58
60
  /timeout/i,
@@ -432,10 +434,6 @@ module AgentHarness
432
434
  #
433
435
  # @param text [String, nil] error output text
434
436
  # @return [Time, nil] UTC reset time, or nil if not parseable
435
- def parse_rate_limit_reset(text)
436
- nil
437
- end
438
-
439
437
  # Run a lightweight provider-owned preflight check before committing to a
440
438
  # full prompt execution.
441
439
  #
@@ -1038,8 +1036,13 @@ module AgentHarness
1038
1036
 
1039
1037
  def map_to_error_class(classification, original_error)
1040
1038
  case classification
1041
- when :rate_limited
1042
- RateLimitError.new(original_error.message, original_error: original_error)
1039
+ when :rate_limited, :quota_exceeded
1040
+ RateLimitError.new(
1041
+ original_error.message,
1042
+ reset_time: parse_rate_limit_reset(original_error.message),
1043
+ error_category: classification,
1044
+ original_error: original_error
1045
+ )
1043
1046
  when :auth_expired
1044
1047
  AuthenticationError.new(
1045
1048
  original_error.message,
@@ -189,7 +189,7 @@ module AgentHarness
189
189
  non_interactive_flag: nil,
190
190
  legitimate_exit_codes: [0],
191
191
  stderr_is_diagnostic: true,
192
- parses_rate_limit_reset: false
192
+ parses_rate_limit_reset: true
193
193
  }
194
194
  end
195
195
 
@@ -194,7 +194,7 @@ module AgentHarness
194
194
  non_interactive_flag: nil,
195
195
  legitimate_exit_codes: [0],
196
196
  stderr_is_diagnostic: true,
197
- parses_rate_limit_reset: false
197
+ parses_rate_limit_reset: true
198
198
  }
199
199
  end
200
200
 
@@ -24,6 +24,7 @@ module AgentHarness
24
24
 
25
25
  parse_retry_after(text) ||
26
26
  parse_reset_at(text) ||
27
+ parse_reset_at_datetime(text) ||
27
28
  parse_resets_time(text) ||
28
29
  parse_resets_date_time(text)
29
30
  end
@@ -46,6 +47,16 @@ module AgentHarness
46
47
  Time.at(match[1].to_i).utc
47
48
  end
48
49
 
50
+ # "reset at 2026-05-18 11:22:32"
51
+ def parse_reset_at_datetime(text)
52
+ match = text.match(/reset\s+at\s+(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})/i)
53
+ return unless match
54
+
55
+ Time.strptime("#{match[1]} #{match[2]} UTC", "%Y-%m-%d %H:%M:%S %Z").utc
56
+ rescue ArgumentError
57
+ nil
58
+ end
59
+
49
60
  # "resets 5am (UTC)" / "resets 5:00am (UTC)"
50
61
  def parse_resets_time(text)
51
62
  match = text.match(/resets\s+(\d{1,2})(?::(\d{2}))?\s*(am|pm)\s*\(UTC\)/i)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AgentHarness
4
- VERSION = "0.18.1"
4
+ VERSION = "0.18.2"
5
5
  end
data/lib/agent_harness.rb CHANGED
@@ -372,9 +372,9 @@ require_relative "agent_harness/provider_health_check"
372
372
  # Provider layer
373
373
  require_relative "agent_harness/providers/registry"
374
374
  require_relative "agent_harness/providers/adapter"
375
- require_relative "agent_harness/providers/base"
376
375
  require_relative "agent_harness/providers/token_usage_parsing"
377
376
  require_relative "agent_harness/providers/rate_limit_reset_parsing"
377
+ require_relative "agent_harness/providers/base"
378
378
  require_relative "agent_harness/providers/mcp_config_file_support"
379
379
  require_relative "agent_harness/providers/anthropic"
380
380
  require_relative "agent_harness/providers/aider"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: agent-harness
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.1
4
+ version: 0.18.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bart Agapinan