agent-harness 0.5.0 → 0.5.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 +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +10 -0
- data/README.md +30 -0
- data/json-2.18.1.gem +0 -0
- data/lib/agent_harness/configuration.rb +2 -1
- data/lib/agent_harness/provider_health_check.rb +289 -0
- data/lib/agent_harness/providers/anthropic.rb +1 -1
- data/lib/agent_harness/providers/codex.rb +2 -2
- data/lib/agent_harness/providers/kilocode.rb +3 -3
- data/lib/agent_harness/version.rb +1 -1
- data/lib/agent_harness.rb +20 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 16862141d853f2e8817d000a9e4813162f0544cda2c30343de2efc1ffd7e9e73
|
|
4
|
+
data.tar.gz: ee57bd3611abb7566560675c65c1feb04faee531cd182f8a8812881a73701aae
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f5145b28d2c92bef3c8ba6f8a0e8ffe2217f8eb9462c672f28d25e0f6bd6a1bb17f1fa14ae2dcf2e57d35c4fa82a6233fdf51acf7778d399c89c4412ee9c9695
|
|
7
|
+
data.tar.gz: f6f9e464d3f5f84a87f98b98dd3d0687157a1b69249a3a0731ba162653aabf6cc517430f31b0f9e9b1d3e5d67d0b767c4c5a12c4e88425bd8b24f578343a87e9
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.5.1](https://github.com/viamin/agent-harness/compare/agent-harness/v0.5.0...agent-harness/v0.5.1) (2026-03-24)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* 30: fix(codex): use 'codex exec' subcommand instead of --prompt ([#35](https://github.com/viamin/agent-harness/issues/35)) ([1093a23](https://github.com/viamin/agent-harness/commit/1093a23dd001a7ea3caf13306d284fe3b5b976c5))
|
|
9
|
+
* **anthropic:** use positional argument instead of --prompt for Claude CLI ([4ba59bd](https://github.com/viamin/agent-harness/commit/4ba59bd55394cf9ff1d1994ce787e0e285725b93)), closes [#29](https://github.com/viamin/agent-harness/issues/29)
|
|
10
|
+
* **kilocode:** use 'kilo run' subcommand instead of --prompt flag ([f850f54](https://github.com/viamin/agent-harness/commit/f850f54cfac595fe910298303beb373c7bc68376))
|
|
11
|
+
* **test:** use correct RSpec matcher `end_with` instead of `ending_with` ([3a9d68b](https://github.com/viamin/agent-harness/commit/3a9d68b90a0e788683a382303108ebe28cc24e63))
|
|
12
|
+
|
|
3
13
|
## [0.5.0](https://github.com/viamin/agent-harness/compare/agent-harness/v0.4.0...agent-harness/v0.5.0) (2026-03-03)
|
|
4
14
|
|
|
5
15
|
|
data/README.md
CHANGED
|
@@ -326,6 +326,36 @@ Any existing expiry metadata in the credentials file is cleared on refresh so th
|
|
|
326
326
|
|
|
327
327
|
This raises `NotImplementedError` for `:api_key` providers. Credential file paths respect the `CLAUDE_CONFIG_DIR` environment variable.
|
|
328
328
|
|
|
329
|
+
## Provider Health Checks
|
|
330
|
+
|
|
331
|
+
Pre-flight check that configured providers are registered and authenticated. Reachability and configuration validation depend on provider-specific `health_status` and `validate_config` overrides; providers that don't implement these use safe defaults (healthy / valid).
|
|
332
|
+
|
|
333
|
+
> **Note:** These methods provide the library-level API. CLI flag (`--check-providers`) and HTTP endpoint (`GET /providers/status`) integration are not yet implemented and are tracked separately.
|
|
334
|
+
|
|
335
|
+
```ruby
|
|
336
|
+
# Check all enabled providers
|
|
337
|
+
results = AgentHarness.check_providers
|
|
338
|
+
results.each do |r|
|
|
339
|
+
puts "#{r[:name]}: #{r[:status]} - #{r[:message]} (#{r[:latency_ms]}ms)"
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# Check a single provider
|
|
343
|
+
result = AgentHarness.check_provider(:claude)
|
|
344
|
+
puts result[:status] # => "ok", "degraded", or "error"
|
|
345
|
+
|
|
346
|
+
# Formatted CLI output
|
|
347
|
+
puts AgentHarness::ProviderHealthCheck.format_results(results)
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
Each result is a hash with keys:
|
|
351
|
+
|
|
352
|
+
- `:name` — provider name (Symbol)
|
|
353
|
+
- `:status` — `"ok"` (all checks passed), `"degraded"` (partial issues such as unimplemented auth status), or `"error"` (provider unavailable or authentication failed)
|
|
354
|
+
- `:message` — human-readable description
|
|
355
|
+
- `:latency_ms` — time taken for the check in milliseconds
|
|
356
|
+
|
|
357
|
+
Health checks run five steps per provider: registration, CLI availability, authentication, provider health status, and configuration validation. The default timeout per provider is configurable via `orchestration.health_check.timeout` (default: 5 seconds).
|
|
358
|
+
|
|
329
359
|
## Development
|
|
330
360
|
|
|
331
361
|
```bash
|
data/json-2.18.1.gem
ADDED
|
Binary file
|
|
@@ -221,12 +221,13 @@ module AgentHarness
|
|
|
221
221
|
|
|
222
222
|
# Health check configuration
|
|
223
223
|
class HealthCheckConfig
|
|
224
|
-
attr_accessor :enabled, :interval, :failure_threshold
|
|
224
|
+
attr_accessor :enabled, :interval, :failure_threshold, :timeout
|
|
225
225
|
|
|
226
226
|
def initialize
|
|
227
227
|
@enabled = true
|
|
228
228
|
@interval = 60 # 1 minute
|
|
229
229
|
@failure_threshold = 3
|
|
230
|
+
@timeout = 5 # seconds per provider check
|
|
230
231
|
end
|
|
231
232
|
end
|
|
232
233
|
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "timeout"
|
|
4
|
+
|
|
5
|
+
module AgentHarness
|
|
6
|
+
# Performs health checks on configured providers
|
|
7
|
+
#
|
|
8
|
+
# Validates provider setup, authentication status, and reachability.
|
|
9
|
+
# Returns per-provider status objects with name, status, message, and latency.
|
|
10
|
+
#
|
|
11
|
+
# @example Check all providers
|
|
12
|
+
# results = AgentHarness::ProviderHealthCheck.check_all
|
|
13
|
+
# results.each { |r| puts "#{r[:name]}: #{r[:status]}" }
|
|
14
|
+
#
|
|
15
|
+
# @example Check a single provider
|
|
16
|
+
# result = AgentHarness::ProviderHealthCheck.check(:claude)
|
|
17
|
+
# puts result[:status] # => "ok", "error", or "degraded"
|
|
18
|
+
class ProviderHealthCheck
|
|
19
|
+
# Single source of truth: derive the fallback from HealthCheckConfig's default
|
|
20
|
+
# so that the timeout isn't duplicated here and in configuration.rb.
|
|
21
|
+
DEFAULT_TIMEOUT = HealthCheckConfig.new.timeout
|
|
22
|
+
|
|
23
|
+
class << self
|
|
24
|
+
# Check health of all configured providers
|
|
25
|
+
#
|
|
26
|
+
# @param timeout [Integer] timeout in seconds for each check
|
|
27
|
+
# @return [Array<Hash>] health status for each provider
|
|
28
|
+
def check_all(timeout: configured_timeout)
|
|
29
|
+
provider_names = if AgentHarness.configuration.providers.empty?
|
|
30
|
+
Providers::Registry.instance.all
|
|
31
|
+
else
|
|
32
|
+
enabled_provider_names
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
provider_names.map { |name| check(name, timeout: timeout) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Check health of a single provider
|
|
39
|
+
#
|
|
40
|
+
# @param provider_name [Symbol, String] the provider name
|
|
41
|
+
# @param timeout [Integer] timeout in seconds
|
|
42
|
+
# @return [Hash] health status with :name, :status, :message, :latency_ms keys
|
|
43
|
+
def check(provider_name, timeout: configured_timeout)
|
|
44
|
+
name = normalize_name(provider_name)
|
|
45
|
+
start_time = monotonic_now
|
|
46
|
+
timeout = validate_timeout(timeout)
|
|
47
|
+
|
|
48
|
+
Timeout.timeout(timeout) do
|
|
49
|
+
perform_check(name, start_time)
|
|
50
|
+
end
|
|
51
|
+
rescue Timeout::Error
|
|
52
|
+
build_result(
|
|
53
|
+
name: name,
|
|
54
|
+
status: "error",
|
|
55
|
+
message: "Health check timed out after #{timeout}s",
|
|
56
|
+
start_time: start_time || monotonic_now
|
|
57
|
+
)
|
|
58
|
+
rescue NotImplementedError => e
|
|
59
|
+
# NotImplementedError inherits from ScriptError, not StandardError,
|
|
60
|
+
# so it must be rescued explicitly. Its messages are safe internal
|
|
61
|
+
# setup errors (e.g., missing provider methods) that help users
|
|
62
|
+
# diagnose configuration problems.
|
|
63
|
+
AgentHarness.logger&.error("ProviderHealthCheck error for #{name}: #{e.class}")
|
|
64
|
+
build_result(
|
|
65
|
+
name: name,
|
|
66
|
+
status: "error",
|
|
67
|
+
message: "Health check failed: #{e.class}: #{e.message}",
|
|
68
|
+
start_time: start_time || monotonic_now
|
|
69
|
+
)
|
|
70
|
+
rescue => e
|
|
71
|
+
# Return a generic message to avoid leaking sensitive details
|
|
72
|
+
# (e.g., tokens embedded in exception messages). Log only the
|
|
73
|
+
# exception class (not the message) to avoid leaking secrets.
|
|
74
|
+
AgentHarness.logger&.error("ProviderHealthCheck error for #{name}: #{e.class}")
|
|
75
|
+
build_result(
|
|
76
|
+
name: name,
|
|
77
|
+
status: "error",
|
|
78
|
+
message: "Health check failed: #{e.class}",
|
|
79
|
+
start_time: start_time || monotonic_now
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Format health check results for CLI output
|
|
84
|
+
#
|
|
85
|
+
# @param results [Array<Hash>] health check results
|
|
86
|
+
# @return [String] formatted output
|
|
87
|
+
def format_results(results)
|
|
88
|
+
lines = ["Checking providers..."]
|
|
89
|
+
|
|
90
|
+
if results.empty?
|
|
91
|
+
lines << ""
|
|
92
|
+
lines << "No providers checked."
|
|
93
|
+
return lines.join("\n")
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
results.each do |result|
|
|
97
|
+
name = result[:name].to_s.ljust(16)
|
|
98
|
+
case result[:status]
|
|
99
|
+
when "ok"
|
|
100
|
+
latency = result[:latency_ms] ? "(#{result[:latency_ms]}ms)" : ""
|
|
101
|
+
lines << " ✓ #{name} OK #{latency}".rstrip
|
|
102
|
+
when "degraded"
|
|
103
|
+
lines << " ~ #{name} #{result[:message]}"
|
|
104
|
+
else
|
|
105
|
+
lines << " ✗ #{name} #{result[:message]}"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
failed = results.count { |r| r[:status] == "error" }
|
|
110
|
+
degraded = results.count { |r| r[:status] == "degraded" }
|
|
111
|
+
total = results.size
|
|
112
|
+
|
|
113
|
+
lines << ""
|
|
114
|
+
summary_parts = []
|
|
115
|
+
summary_parts << "#{failed} failed" if failed > 0
|
|
116
|
+
summary_parts << "#{degraded} degraded" if degraded > 0
|
|
117
|
+
|
|
118
|
+
provider_word = (total == 1) ? "provider" : "providers"
|
|
119
|
+
lines << if summary_parts.any?
|
|
120
|
+
"#{total} #{provider_word} checked: #{summary_parts.join(", ")}."
|
|
121
|
+
else
|
|
122
|
+
"All #{total} #{provider_word} healthy."
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
lines.join("\n")
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
private
|
|
129
|
+
|
|
130
|
+
def enabled_provider_names
|
|
131
|
+
AgentHarness.configuration.providers.select { |_name, config| config.enabled }.keys
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def validate_timeout(timeout)
|
|
135
|
+
(timeout.is_a?(Numeric) && timeout.positive?) ? timeout : configured_timeout
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def configured_timeout
|
|
139
|
+
timeout = AgentHarness.configuration.orchestration_config.health_check_config.timeout
|
|
140
|
+
(timeout.is_a?(Numeric) && timeout.positive?) ? timeout : DEFAULT_TIMEOUT
|
|
141
|
+
rescue NoMethodError
|
|
142
|
+
DEFAULT_TIMEOUT
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def normalize_name(provider_name)
|
|
146
|
+
provider_name.to_sym
|
|
147
|
+
rescue NoMethodError, ArgumentError, TypeError
|
|
148
|
+
:unknown
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def perform_check(provider_name, start_time)
|
|
152
|
+
# Step 1: Check provider is registered
|
|
153
|
+
registry = Providers::Registry.instance
|
|
154
|
+
unless registry.registered?(provider_name)
|
|
155
|
+
return build_result(
|
|
156
|
+
name: provider_name,
|
|
157
|
+
status: "error",
|
|
158
|
+
message: "Provider not registered",
|
|
159
|
+
start_time: start_time
|
|
160
|
+
)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Step 2: Check CLI availability
|
|
164
|
+
klass = registry.get(provider_name)
|
|
165
|
+
unless klass.available?
|
|
166
|
+
return build_result(
|
|
167
|
+
name: provider_name,
|
|
168
|
+
status: "error",
|
|
169
|
+
message: "CLI '#{klass.binary_name}' not found in PATH",
|
|
170
|
+
start_time: start_time
|
|
171
|
+
)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Step 3: Check authentication
|
|
175
|
+
# Treat "not implemented" auth status as degraded rather than error,
|
|
176
|
+
# since most built-in providers don't implement auth_status hooks.
|
|
177
|
+
# In either case, continue to steps 4/5 so health and config issues
|
|
178
|
+
# are still surfaced for providers that lack an auth_status hook.
|
|
179
|
+
auth = Authentication.auth_status(provider_name)
|
|
180
|
+
auth_degraded = false
|
|
181
|
+
unless auth[:valid]
|
|
182
|
+
unless auth_not_implemented?(auth)
|
|
183
|
+
return build_result(
|
|
184
|
+
name: provider_name,
|
|
185
|
+
status: "error",
|
|
186
|
+
message: auth[:error] || "Authentication failed",
|
|
187
|
+
start_time: start_time
|
|
188
|
+
)
|
|
189
|
+
end
|
|
190
|
+
auth_degraded = true
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Step 4: Check provider-level health (e.g., endpoint reachability)
|
|
194
|
+
# The Adapter default always returns {healthy: true}, so providers
|
|
195
|
+
# that haven't implemented a real health check are reported as ok
|
|
196
|
+
# with a note that the check is not implemented.
|
|
197
|
+
provider_instance = build_provider(provider_name, klass)
|
|
198
|
+
health = provider_instance.health_status
|
|
199
|
+
unless health[:healthy]
|
|
200
|
+
return build_result(
|
|
201
|
+
name: provider_name,
|
|
202
|
+
status: "degraded",
|
|
203
|
+
message: health[:message] || "Provider health check failed",
|
|
204
|
+
start_time: start_time
|
|
205
|
+
)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Step 5: Validate provider config
|
|
209
|
+
# The Adapter default always returns {valid: true}, so providers
|
|
210
|
+
# that haven't implemented real config validation pass by default.
|
|
211
|
+
validation = provider_instance.validate_config
|
|
212
|
+
unless validation[:valid]
|
|
213
|
+
errors_msg = Array(validation[:errors]).join(", ")
|
|
214
|
+
errors_msg = "check provider configuration" if errors_msg.empty?
|
|
215
|
+
return build_result(
|
|
216
|
+
name: provider_name,
|
|
217
|
+
status: "degraded",
|
|
218
|
+
message: "Configuration issues: #{errors_msg}",
|
|
219
|
+
start_time: start_time
|
|
220
|
+
)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# If auth was not implemented but health/config passed, report degraded
|
|
224
|
+
if auth_degraded
|
|
225
|
+
return build_result(
|
|
226
|
+
name: provider_name,
|
|
227
|
+
status: "degraded",
|
|
228
|
+
message: "Auth status check not implemented; health and config checks passed",
|
|
229
|
+
start_time: start_time
|
|
230
|
+
)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
message = if provider_overrides_method?(provider_instance, :health_status) ||
|
|
234
|
+
provider_overrides_method?(provider_instance, :validate_config)
|
|
235
|
+
"All checks passed"
|
|
236
|
+
else
|
|
237
|
+
"Registered and authenticated (health/config checks use defaults)"
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
build_result(
|
|
241
|
+
name: provider_name,
|
|
242
|
+
status: "ok",
|
|
243
|
+
message: message,
|
|
244
|
+
start_time: start_time
|
|
245
|
+
)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def auth_not_implemented?(auth)
|
|
249
|
+
# Prefer explicit flags over brittle string matching on error messages.
|
|
250
|
+
# This keeps backward compatibility with existing callers that only set :error,
|
|
251
|
+
# while allowing newer callers to pass structured reasons.
|
|
252
|
+
if auth.respond_to?(:[])
|
|
253
|
+
return true if auth.key?(:implemented) && auth[:implemented] == false
|
|
254
|
+
return true if auth.key?(:reason) && auth[:reason] == :not_implemented
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
error = auth[:error].to_s
|
|
258
|
+
error.include?("not implemented")
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def provider_overrides_method?(provider_instance, method_name)
|
|
262
|
+
provider_instance.method(method_name).owner != Providers::Adapter
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def build_result(name:, status:, message:, start_time:)
|
|
266
|
+
latency = ((monotonic_now - start_time) * 1000).round
|
|
267
|
+
{
|
|
268
|
+
name: name,
|
|
269
|
+
status: status,
|
|
270
|
+
message: message,
|
|
271
|
+
latency_ms: latency
|
|
272
|
+
}
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def build_provider(provider_name, klass)
|
|
276
|
+
config = AgentHarness.configuration.providers[provider_name]
|
|
277
|
+
klass.new(
|
|
278
|
+
config: config,
|
|
279
|
+
executor: AgentHarness.configuration.command_executor,
|
|
280
|
+
logger: AgentHarness.logger
|
|
281
|
+
)
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def monotonic_now
|
|
285
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
@@ -81,13 +81,13 @@ module AgentHarness
|
|
|
81
81
|
protected
|
|
82
82
|
|
|
83
83
|
def build_command(prompt, options)
|
|
84
|
-
cmd = [self.class.binary_name]
|
|
84
|
+
cmd = [self.class.binary_name, "exec"]
|
|
85
85
|
|
|
86
86
|
if options[:session]
|
|
87
87
|
cmd += session_flags(options[:session])
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
-
cmd
|
|
90
|
+
cmd << prompt
|
|
91
91
|
|
|
92
92
|
cmd
|
|
93
93
|
end
|
|
@@ -12,7 +12,7 @@ module AgentHarness
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def binary_name
|
|
15
|
-
"
|
|
15
|
+
"kilo"
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def available?
|
|
@@ -60,8 +60,8 @@ module AgentHarness
|
|
|
60
60
|
protected
|
|
61
61
|
|
|
62
62
|
def build_command(prompt, options)
|
|
63
|
-
cmd = [self.class.binary_name]
|
|
64
|
-
cmd
|
|
63
|
+
cmd = [self.class.binary_name, "run"]
|
|
64
|
+
cmd << prompt
|
|
65
65
|
cmd
|
|
66
66
|
end
|
|
67
67
|
|
data/lib/agent_harness.rb
CHANGED
|
@@ -113,6 +113,25 @@ module AgentHarness
|
|
|
113
113
|
def refresh_auth(provider_name, token: nil)
|
|
114
114
|
Authentication.refresh_auth(provider_name, token: token)
|
|
115
115
|
end
|
|
116
|
+
|
|
117
|
+
# Check health of all configured providers.
|
|
118
|
+
#
|
|
119
|
+
# Validates each enabled provider through registration, CLI availability,
|
|
120
|
+
# authentication, provider health status, and config validation checks.
|
|
121
|
+
#
|
|
122
|
+
# @param timeout [Integer] timeout in seconds for each check (defaults to configured value)
|
|
123
|
+
# @return [Array<Hash>] health status for each provider
|
|
124
|
+
def check_providers(timeout: nil)
|
|
125
|
+
timeout ? ProviderHealthCheck.check_all(timeout: timeout) : ProviderHealthCheck.check_all
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Check health of a single provider
|
|
129
|
+
# @param provider_name [Symbol] the provider name
|
|
130
|
+
# @param timeout [Integer, nil] timeout in seconds (nil lets ProviderHealthCheck apply its validated default)
|
|
131
|
+
# @return [Hash] health status with :name, :status, :message, :latency_ms
|
|
132
|
+
def check_provider(provider_name, timeout: nil)
|
|
133
|
+
timeout ? ProviderHealthCheck.check(provider_name, timeout: timeout) : ProviderHealthCheck.check(provider_name)
|
|
134
|
+
end
|
|
116
135
|
end
|
|
117
136
|
end
|
|
118
137
|
|
|
@@ -125,6 +144,7 @@ require_relative "agent_harness/response"
|
|
|
125
144
|
require_relative "agent_harness/token_tracker"
|
|
126
145
|
require_relative "agent_harness/error_taxonomy"
|
|
127
146
|
require_relative "agent_harness/authentication"
|
|
147
|
+
require_relative "agent_harness/provider_health_check"
|
|
128
148
|
|
|
129
149
|
# Provider layer
|
|
130
150
|
require_relative "agent_harness/providers/registry"
|
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.5.
|
|
4
|
+
version: 0.5.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bart Agapinan
|
|
@@ -76,6 +76,7 @@ files:
|
|
|
76
76
|
- Rakefile
|
|
77
77
|
- bin/console
|
|
78
78
|
- bin/setup
|
|
79
|
+
- json-2.18.1.gem
|
|
79
80
|
- lib/agent_harness.rb
|
|
80
81
|
- lib/agent_harness/authentication.rb
|
|
81
82
|
- lib/agent_harness/command_executor.rb
|
|
@@ -89,6 +90,7 @@ files:
|
|
|
89
90
|
- lib/agent_harness/orchestration/metrics.rb
|
|
90
91
|
- lib/agent_harness/orchestration/provider_manager.rb
|
|
91
92
|
- lib/agent_harness/orchestration/rate_limiter.rb
|
|
93
|
+
- lib/agent_harness/provider_health_check.rb
|
|
92
94
|
- lib/agent_harness/providers/adapter.rb
|
|
93
95
|
- lib/agent_harness/providers/aider.rb
|
|
94
96
|
- lib/agent_harness/providers/anthropic.rb
|
|
@@ -126,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
126
128
|
- !ruby/object:Gem::Version
|
|
127
129
|
version: '0'
|
|
128
130
|
requirements: []
|
|
129
|
-
rubygems_version: 4.0.
|
|
131
|
+
rubygems_version: 4.0.6
|
|
130
132
|
specification_version: 4
|
|
131
133
|
summary: Unified interface for CLI-based AI coding agents
|
|
132
134
|
test_files: []
|