agent-harness 0.29.0 → 0.31.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 +21 -0
- data/lib/agent_harness/providers/omp.rb +160 -3
- data/lib/agent_harness/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1e4fa0ebff9c67559f7294ebe65550e75629b9c21d95f2e04155f944f9d4e5de
|
|
4
|
+
data.tar.gz: bed581986f9471514de4488702b8c120c830887835c393cb0c6ad2f5d42b974b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 480a0bffe3625ea4c7e43bdcb1cfb8857798156be26a69f23d88e38443e8b75682aa0125b5ca2af6e94e967839129482c1607779a01e7bf76d5bb673bebb8888
|
|
7
|
+
data.tar.gz: dc36eb56d5b62dd7956cf311cd0d9635dbab456f02550ea3cc14fdb304488e38aeda33a5a36234aae7fd31b3e47783fcf69698850131cb6e08ced1326e0b2d2f
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,27 @@
|
|
|
5
5
|
* add runner model compatibility contract (`AgentHarness.model_compatibility`) with structured `ModelCompatibility::Result` outcomes. Codex exposes static facts for CLI-gated models (e.g. `gpt-5.5` requires Codex CLI `>= 0.116.0`), a baseline supported-model list, supported auth modes, and a `DEFAULT_COMPATIBLE_MODEL_ID` fallback so downstream orchestrators can validate tier/model assignments before scheduling agent runs ([#259](https://github.com/viamin/agent-harness/issues/259)).
|
|
6
6
|
* **auth:** add provider-owned PKCE code-exchange API for Claude OAuth (`AgentHarness::Authentication.exchange_code`). Takes an authorization code plus PKCE verifier (and `redirect_uri`/`client_id`), posts an `authorization_code` grant to the Claude token endpoint, and persists the resulting access/refresh tokens in the native `claudeAiOauth` shape. Adds `exchange_code_supported?` and a `code_exchange` key to `auth_capabilities` ([#266](https://github.com/viamin/agent-harness/issues/266)).
|
|
7
7
|
|
|
8
|
+
## [0.31.0](https://github.com/viamin/agent-harness/compare/agent-harness/v0.30.0...agent-harness/v0.31.0) (2026-07-16)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* release agent-harness 0.31.0 with omp support ([#302](https://github.com/viamin/agent-harness/issues/302)) ([7a82fbc](https://github.com/viamin/agent-harness/commit/7a82fbc5cc627eaa10c678e3e2b998fc0ce100f2))
|
|
14
|
+
|
|
15
|
+
## [0.31.0](https://github.com/viamin/agent-harness/compare/agent-harness/v0.30.0...agent-harness/v0.31.0) (2026-07-16)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* release a single `agent-harness` gem version that consolidates the full `:omp` provider contract for downstream consumers: distinct `:omp` provider metadata separate from `:pi`, the install/runtime contract for `@oh-my-pi/pi-coding-agent` `17.0.1`, the Bun runtime floor `>= 1.3.14` (pinned install target `1.3.14`), the smoke-test contract, and regression coverage for the public `AgentHarness` APIs ([#297](https://github.com/viamin/agent-harness/issues/297))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## [0.30.0](https://github.com/viamin/agent-harness/compare/agent-harness/v0.29.0...agent-harness/v0.30.0) (2026-07-16)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Features
|
|
27
|
+
|
|
28
|
+
* Implement Oh My Pi execution, auth, and smoke-test contract ([#300](https://github.com/viamin/agent-harness/issues/300)) ([dc3f5ec](https://github.com/viamin/agent-harness/commit/dc3f5ecce4508f103a8b769727e31aaa3d694c7e))
|
|
8
29
|
|
|
9
30
|
## [0.29.0](https://github.com/viamin/agent-harness/compare/agent-harness/v0.28.6...agent-harness/v0.29.0) (2026-07-16)
|
|
10
31
|
|
|
@@ -31,6 +31,71 @@ module AgentHarness
|
|
|
31
31
|
SUPPORTED_BUN_VERSION = "1.3.14"
|
|
32
32
|
BUN_REQUIREMENT_STRING = ">= #{SUPPORTED_BUN_VERSION}".freeze
|
|
33
33
|
|
|
34
|
+
# Smoke-test contract suitable for container health probes.
|
|
35
|
+
#
|
|
36
|
+
# Oh My Pi runs non-interactively via `-p` with `--no-session`, so the
|
|
37
|
+
# probe is a single deterministic round trip. The contract is tuned for
|
|
38
|
+
# a tight probe budget: a short prompt that elicits a predictable reply
|
|
39
|
+
# and a bounded timeout that accommodates a cold Bun runtime start.
|
|
40
|
+
SMOKE_TEST_CONTRACT = {
|
|
41
|
+
prompt: "Reply with exactly OK.",
|
|
42
|
+
expected_output: "OK",
|
|
43
|
+
timeout: 30,
|
|
44
|
+
require_output: true,
|
|
45
|
+
success_message: "Oh My Pi smoke test passed"
|
|
46
|
+
}.freeze
|
|
47
|
+
|
|
48
|
+
# Oh My Pi is a multi-provider CLI: it routes to a backend through
|
|
49
|
+
# `--provider` and surfaces that backend's error vocabulary. The
|
|
50
|
+
# patterns below extend the shared HTTP-style set with Oh My Pi /
|
|
51
|
+
# upstream-Pi specific phrasing observed for auth expiry, quota and
|
|
52
|
+
# rate-limit surfaces, model resolution failures, and transient
|
|
53
|
+
# network faults.
|
|
54
|
+
ERROR_PATTERNS = {
|
|
55
|
+
rate_limited: COMMON_ERROR_PATTERNS[:rate_limited],
|
|
56
|
+
auth_expired: COMMON_ERROR_PATTERNS[:auth_expired] + [
|
|
57
|
+
/\b401\b/,
|
|
58
|
+
/session.*(?:expired|invalid)/i,
|
|
59
|
+
/log(?:ged)?.?in.*required/i,
|
|
60
|
+
/api.?key.*(?:invalid|missing|expired|revoked)/i,
|
|
61
|
+
/token.*(?:expired|invalid|revoked)/i,
|
|
62
|
+
/credentials.*(?:expired|invalid|missing)/i
|
|
63
|
+
],
|
|
64
|
+
quota_exceeded: COMMON_ERROR_PATTERNS[:quota_exceeded],
|
|
65
|
+
# Model resolution is surfaced by both the omp CLI (unknown
|
|
66
|
+
# `--model`/`--provider` combination) and the upstream backend.
|
|
67
|
+
# Treat it as a distinct, non-retryable category so callers can
|
|
68
|
+
# fall back to a known-good model instead of retrying the same id.
|
|
69
|
+
model_not_found: [
|
|
70
|
+
/model.*not.*found/i,
|
|
71
|
+
/no.*such.*model/i,
|
|
72
|
+
/unknown.*model/i,
|
|
73
|
+
/model.*does.*not.*exist/i,
|
|
74
|
+
/invalid.*model/i,
|
|
75
|
+
/model.*unavailable/i,
|
|
76
|
+
/provider.*does.*not.*support.*model/i
|
|
77
|
+
],
|
|
78
|
+
transient: COMMON_ERROR_PATTERNS[:transient] + [
|
|
79
|
+
/connection.*reset/i,
|
|
80
|
+
/econnreset/i,
|
|
81
|
+
/socket.*hang.*up/i,
|
|
82
|
+
/network.*error/i
|
|
83
|
+
]
|
|
84
|
+
}.tap { |patterns| patterns.each_value(&:freeze) }.freeze
|
|
85
|
+
|
|
86
|
+
# Non-actionable output that Oh My Pi writes while the Bun runtime and
|
|
87
|
+
# the agent bootstrap. Downstream consumers use these to filter probe
|
|
88
|
+
# and run output so startup banners do not masquerade as failures.
|
|
89
|
+
NOISY_OUTPUT_PATTERNS = [
|
|
90
|
+
/oh.?my.?pi\b/i,
|
|
91
|
+
/pi(?:-coding.?agent)?\s+v?\d+\.\d+/i,
|
|
92
|
+
/\bbun\s+v?\d+\.\d+/i,
|
|
93
|
+
/\bloading/i,
|
|
94
|
+
/\binitializing/i,
|
|
95
|
+
/\bwarming.?up/i,
|
|
96
|
+
/fetching.*model/i
|
|
97
|
+
].freeze
|
|
98
|
+
|
|
34
99
|
class << self
|
|
35
100
|
def provider_name
|
|
36
101
|
:omp
|
|
@@ -49,7 +114,22 @@ module AgentHarness
|
|
|
49
114
|
{
|
|
50
115
|
auth: {
|
|
51
116
|
service: :omp,
|
|
52
|
-
api_family: :multi_provider
|
|
117
|
+
api_family: :multi_provider,
|
|
118
|
+
# Oh My Pi routes to a backend through `--provider` and reads
|
|
119
|
+
# that backend's API key from its conventional env var. The
|
|
120
|
+
# harness never reuses the upstream Pi credential store
|
|
121
|
+
# (paid_pi_auth_entry); callers pass backend keys per request
|
|
122
|
+
# through ProviderRuntime#env, which build_env materializes into
|
|
123
|
+
# the subprocess environment. This keeps the omp runner an
|
|
124
|
+
# independent entity from :pi.
|
|
125
|
+
#
|
|
126
|
+
# Deliberately do NOT advertise a harness-managed credential
|
|
127
|
+
# store here. Authentication has no omp read/write/validate path,
|
|
128
|
+
# so auth_status(:omp) reports "not implemented"; exposing
|
|
129
|
+
# credential_store would imply a session store that does not
|
|
130
|
+
# exist and let callers infer harness-managed session auth.
|
|
131
|
+
# Surface the implemented per-request env model instead.
|
|
132
|
+
api_key_source: :provider_runtime_env
|
|
53
133
|
}
|
|
54
134
|
}
|
|
55
135
|
end
|
|
@@ -158,7 +238,7 @@ module AgentHarness
|
|
|
158
238
|
end
|
|
159
239
|
|
|
160
240
|
def smoke_test_contract
|
|
161
|
-
|
|
241
|
+
SMOKE_TEST_CONTRACT
|
|
162
242
|
end
|
|
163
243
|
end
|
|
164
244
|
|
|
@@ -202,13 +282,60 @@ module AgentHarness
|
|
|
202
282
|
# Oh My Pi's non-interactive CLI currently exposes only text print mode.
|
|
203
283
|
# Keep JSON mode disabled until the CLI ships a structured output flag.
|
|
204
284
|
json_mode: false,
|
|
285
|
+
# MCP capability decision: the omp non-interactive print-mode path
|
|
286
|
+
# (`omp --no-session -p`) does not accept an MCP server config flag
|
|
287
|
+
# in the harness's supported CLI version. Keep MCP disabled here so
|
|
288
|
+
# callers do not attempt to attach servers that the runtime would
|
|
289
|
+
# reject. Revisit once omp ships a stable `--mcp-config` flag.
|
|
205
290
|
mcp: false,
|
|
206
291
|
dangerous_mode: false
|
|
207
292
|
}
|
|
208
293
|
end
|
|
209
294
|
|
|
210
295
|
def error_patterns
|
|
211
|
-
|
|
296
|
+
ERROR_PATTERNS
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
# Downstream-facing error classification. Augments the shared quota set
|
|
300
|
+
# with auth-expiry, model-resolution, and authentication-specific
|
|
301
|
+
# phrasing so consumers can route omp failures without re-deriving the
|
|
302
|
+
# CLI vocabulary. The inherited `:quota` set is deliberately preserved
|
|
303
|
+
# (not overridden) so omp's multi-provider backends surface their full
|
|
304
|
+
# credit/balance vocabulary (requires more credits, insufficient
|
|
305
|
+
# balance, spend limit reached, billing limit, etc.).
|
|
306
|
+
def error_classification_patterns
|
|
307
|
+
super.merge(
|
|
308
|
+
auth_expired: ERROR_PATTERNS[:auth_expired],
|
|
309
|
+
authentication: [
|
|
310
|
+
/api.?key.*not.*(?:set|configured)/i,
|
|
311
|
+
/no.*api.?key/i,
|
|
312
|
+
/missing.*credentials/i,
|
|
313
|
+
/log(?:ged)?.?in.*required/i
|
|
314
|
+
],
|
|
315
|
+
model_not_found: ERROR_PATTERNS[:model_not_found]
|
|
316
|
+
)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# Oh My Pi emits a startup banner (version, Bun runtime, model fetch)
|
|
320
|
+
# that is not actionable. Expose it so callers can strip probe noise.
|
|
321
|
+
def noisy_error_patterns
|
|
322
|
+
NOISY_OUTPUT_PATTERNS
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def translate_error(message)
|
|
326
|
+
if ERROR_PATTERNS[:model_not_found].any? { |p| message.match?(p) }
|
|
327
|
+
"Oh My Pi could not resolve the requested model. Check --model/--provider."
|
|
328
|
+
elsif /api.?key.*not.*(?:set|configured)/i.match?(message) || /no.*api.?key/i.match?(message)
|
|
329
|
+
"Oh My Pi API key not set for the selected provider."
|
|
330
|
+
else
|
|
331
|
+
message
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# Oh My Pi runs stateless through `--no-session`; the harness does not
|
|
336
|
+
# expose session persistence, so callers cannot resume a session.
|
|
337
|
+
def supports_sessions?
|
|
338
|
+
false
|
|
212
339
|
end
|
|
213
340
|
|
|
214
341
|
def supports_tool_control?
|
|
@@ -219,6 +346,36 @@ module AgentHarness
|
|
|
219
346
|
:oauth
|
|
220
347
|
end
|
|
221
348
|
|
|
349
|
+
# Conventional backend API-key env vars the omp CLI reads. Oh My Pi is
|
|
350
|
+
# multi-provider: the effective var is the one matching the selected
|
|
351
|
+
# `--provider`, supplied per request through ProviderRuntime#env.
|
|
352
|
+
def api_key_env_var_names
|
|
353
|
+
[
|
|
354
|
+
"ANTHROPIC_API_KEY",
|
|
355
|
+
"OPENAI_API_KEY",
|
|
356
|
+
"GEMINI_API_KEY",
|
|
357
|
+
"GOOGLE_API_KEY",
|
|
358
|
+
"XAI_API_KEY",
|
|
359
|
+
"DEEPSEEK_API_KEY",
|
|
360
|
+
"OPENROUTER_API_KEY",
|
|
361
|
+
"GROQ_API_KEY",
|
|
362
|
+
"MISTRAL_API_KEY"
|
|
363
|
+
]
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
# omp routes through `--provider` rather than an env-driven proxy/base
|
|
367
|
+
# URL, so there are no known proxy header vars to scrub when a caller
|
|
368
|
+
# supplies its own key.
|
|
369
|
+
def api_key_unset_vars
|
|
370
|
+
[]
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# When running against an OAuth/subscription session, drop backend
|
|
374
|
+
# API-key env vars so the CLI prefers the stored session credentials.
|
|
375
|
+
def subscription_unset_vars
|
|
376
|
+
api_key_env_var_names
|
|
377
|
+
end
|
|
378
|
+
|
|
222
379
|
def execution_semantics
|
|
223
380
|
{
|
|
224
381
|
prompt_delivery: :flag,
|