agent-harness 0.18.1 → 0.19.0
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/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +16 -0
- data/lib/agent_harness/error_taxonomy.rb +1 -1
- data/lib/agent_harness/errors.rb +3 -2
- data/lib/agent_harness/providers/adapter.rb +10 -3
- data/lib/agent_harness/providers/base.rb +10 -7
- data/lib/agent_harness/providers/kilocode.rb +1 -1
- data/lib/agent_harness/providers/opencode.rb +4 -1
- data/lib/agent_harness/providers/rate_limit_reset_parsing.rb +11 -0
- data/lib/agent_harness/version.rb +1 -1
- data/lib/agent_harness.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 35805e09786006c623325c10d579dc95c8be7863536ae52b0440332403f108da
|
|
4
|
+
data.tar.gz: 162638a405a7b1cfadbd5d03396cd898142ecf4fa57a9d811726644c0329e485
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b624b8380ae5d7e0759be8ef02b1affafff2180773172e4cd7d9d715678570d6e04d1090ffad50461c5d9a8500f756191a0c7705df042603d02d359dc45ac8e6
|
|
7
|
+
data.tar.gz: 8c8de046b361f532a701d5121550fe41ce47b4f9bab3799b5754dfb7db01803a42e3f898782af8dfdf2e7b5d783f9981e42ddd95db7d3ccf3775a70e74272cf6
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.19.0](https://github.com/viamin/agent-harness/compare/agent-harness/v0.18.2...agent-harness/v0.19.0) (2026-05-29)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* opencode-ai install contract should support postinstall (native binary download) ([b3eed97](https://github.com/viamin/agent-harness/commit/b3eed971b9bc46ce2bb2976b70dfd65b15ae5e9b))
|
|
9
|
+
* **opencode:** add requires_postinstall and postinstall_command to install contract ([d6808fd](https://github.com/viamin/agent-harness/commit/d6808fd62476289b199202b0c20c65fc4966bfcc)), closes [#223](https://github.com/viamin/agent-harness/issues/223)
|
|
10
|
+
|
|
11
|
+
## [0.18.2](https://github.com/viamin/agent-harness/compare/agent-harness/v0.18.1...agent-harness/v0.18.2) (2026-05-17)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* **release:** require conventional PR titles for release-please ([4f0054f](https://github.com/viamin/agent-harness/commit/4f0054f4c9f35251c3185fa8bbf645fcace130b5))
|
|
17
|
+
* **release:** require conventional PR titles for release-please ([fd6633d](https://github.com/viamin/agent-harness/commit/fd6633dff3710ad1575af9bd172f047a93a8f647))
|
|
18
|
+
|
|
3
19
|
## [0.18.1](https://github.com/viamin/agent-harness/compare/agent-harness/v0.18.0...agent-harness/v0.18.1) (2026-05-12)
|
|
4
20
|
|
|
5
21
|
|
|
@@ -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
|
data/lib/agent_harness/errors.rb
CHANGED
|
@@ -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
|
|
@@ -22,7 +22,7 @@ module AgentHarness
|
|
|
22
22
|
source = contract[:source]
|
|
23
23
|
install_command = contract[:install_command]&.dup
|
|
24
24
|
|
|
25
|
-
{
|
|
25
|
+
normalized = {
|
|
26
26
|
provider: provider_name.to_sym,
|
|
27
27
|
source_type: normalize_metadata_source_type(contract[:source_type] || source),
|
|
28
28
|
package_name: metadata_package_name(contract, source),
|
|
@@ -35,6 +35,11 @@ module AgentHarness
|
|
|
35
35
|
install_command: install_command,
|
|
36
36
|
install_command_string: contract[:install_command_string] || install_command&.join(" ")
|
|
37
37
|
}
|
|
38
|
+
|
|
39
|
+
normalized[:requires_postinstall] = contract[:requires_postinstall] if contract.key?(:requires_postinstall)
|
|
40
|
+
normalized[:postinstall_command] = contract[:postinstall_command] if contract.key?(:postinstall_command)
|
|
41
|
+
|
|
42
|
+
normalized
|
|
38
43
|
end
|
|
39
44
|
|
|
40
45
|
def self.normalize_metadata_source_type(source)
|
|
@@ -838,9 +843,11 @@ module AgentHarness
|
|
|
838
843
|
quota: [
|
|
839
844
|
/requires more credits/i,
|
|
840
845
|
/insufficient credits/i,
|
|
846
|
+
/insufficient balance/i,
|
|
841
847
|
/credit.*exceeded/i,
|
|
842
848
|
/spend limit.*reached/i,
|
|
843
|
-
/billing.*limit/i
|
|
849
|
+
/billing.*limit/i,
|
|
850
|
+
/(?:weekly|monthly)(?:\/(?:weekly|monthly))?\s+limit\s+exhausted/i
|
|
844
851
|
]
|
|
845
852
|
}
|
|
846
853
|
end
|
|
@@ -1130,7 +1137,7 @@ module AgentHarness
|
|
|
1130
1137
|
rescue AuthenticationError => e
|
|
1131
1138
|
failure_smoke_test_result(e.message, :auth_expired)
|
|
1132
1139
|
rescue RateLimitError => e
|
|
1133
|
-
failure_smoke_test_result(e.message, :rate_limited)
|
|
1140
|
+
failure_smoke_test_result(e.message, e.error_category || :rate_limited)
|
|
1134
1141
|
rescue ProviderError => e
|
|
1135
1142
|
failure_smoke_test_result(e.message, classify_smoke_test_message(e.message))
|
|
1136
1143
|
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(
|
|
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,
|
|
@@ -14,6 +14,7 @@ module AgentHarness
|
|
|
14
14
|
SUPPORTED_CLI_REQUIREMENT = Gem::Requirement.new(">= #{SUPPORTED_CLI_VERSION}", "< 1.4.0").freeze
|
|
15
15
|
INSTALL_COMMAND_PREFIX = ["npm", "install", "-g", "--ignore-scripts"].freeze
|
|
16
16
|
SUPPORTED_CLI_VERSIONS = [SUPPORTED_CLI_VERSION].freeze
|
|
17
|
+
POSTINSTALL_COMMAND = "node $(npm root -g)/opencode-ai/postinstall.mjs"
|
|
17
18
|
VERSION_REQUIREMENT_STRINGS = SUPPORTED_CLI_REQUIREMENT.requirements
|
|
18
19
|
.map { |op, ver| "#{op} #{ver}".freeze }
|
|
19
20
|
.freeze
|
|
@@ -89,6 +90,8 @@ module AgentHarness
|
|
|
89
90
|
binary_name: binary_name,
|
|
90
91
|
install_command_prefix: INSTALL_COMMAND_PREFIX,
|
|
91
92
|
install_command: install_command,
|
|
93
|
+
requires_postinstall: true,
|
|
94
|
+
postinstall_command: POSTINSTALL_COMMAND,
|
|
92
95
|
supported_versions: SUPPORTED_CLI_VERSIONS
|
|
93
96
|
}
|
|
94
97
|
|
|
@@ -194,7 +197,7 @@ module AgentHarness
|
|
|
194
197
|
non_interactive_flag: nil,
|
|
195
198
|
legitimate_exit_codes: [0],
|
|
196
199
|
stderr_is_diagnostic: true,
|
|
197
|
-
parses_rate_limit_reset:
|
|
200
|
+
parses_rate_limit_reset: true
|
|
198
201
|
}
|
|
199
202
|
end
|
|
200
203
|
|
|
@@ -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)
|
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.
|
|
4
|
+
version: 0.19.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bart Agapinan
|
|
@@ -169,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
169
169
|
- !ruby/object:Gem::Version
|
|
170
170
|
version: '0'
|
|
171
171
|
requirements: []
|
|
172
|
-
rubygems_version: 4.0.
|
|
172
|
+
rubygems_version: 4.0.10
|
|
173
173
|
specification_version: 4
|
|
174
174
|
summary: Unified interface for CLI-based AI coding agents
|
|
175
175
|
test_files: []
|