agent-harness 0.43.0 → 0.44.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 +7 -0
- data/docs/provider-neutral-api-execution-contract.md +114 -9
- 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: 4908f5b12da6f2ae8bc0a93ebf3f682e99fbe017146a9bce9f0727ca397a3f72
|
|
4
|
+
data.tar.gz: 571c10e6f65f9a2a9c03e7b3ee83c8c13b461e66e27d3ff40ddd3dc7b2d883f7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 77c952417ea0b5f2dbf2a9c646350d3b2154f864cab17639d56abbd2ad95d13757244a2c6680c8b071ce938087acb68fdf5c0ca41d5156c01c0791106efaf4f4
|
|
7
|
+
data.tar.gz: 2164b3afcbb40f241417950b9d126e0c82b5df261a544f9e5e11255b487a374bd401ef632fd9ed9b75fe1b42e778732b6092d5e215f61ab30e53ff84e14fca7e
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,13 @@
|
|
|
6
6
|
* 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)).
|
|
7
7
|
* **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)).
|
|
8
8
|
|
|
9
|
+
## [0.44.0](https://github.com/viamin/agent-harness/compare/agent-harness/v0.43.0...agent-harness/v0.44.0) (2026-09-25)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
* Evaluate resumable loop delegation and implement only if simpler (RDR-072) ([#448](https://github.com/viamin/agent-harness/issues/448)) ([02dedfb](https://github.com/viamin/agent-harness/commit/02dedfb08096631e59f326333df61feb57eba395))
|
|
15
|
+
|
|
9
16
|
## [0.43.0](https://github.com/viamin/agent-harness/compare/agent-harness/v0.42.0...agent-harness/v0.43.0) (2026-09-25)
|
|
10
17
|
|
|
11
18
|
|
|
@@ -9,9 +9,12 @@ usage, and optional conversation-persistence work.
|
|
|
9
9
|
|
|
10
10
|
RDR-072's rollout guard was **docs-only** for the design phase. The normalized
|
|
11
11
|
chat, attempt-accounting, schema, and embedding capabilities described below
|
|
12
|
-
are now implemented.
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
are now implemented. The resumable-loop delegation evaluation is also
|
|
13
|
+
complete: it closed with a **retained-loop outcome** (see "Resumable-loop
|
|
14
|
+
delegation evaluation"), so no loop runtime was added. Other capabilities
|
|
15
|
+
remain design contracts and each still needs its own failing-first contract
|
|
16
|
+
tests, implementation, release evidence, and downstream adoption evidence
|
|
17
|
+
before a caller enables it.
|
|
15
18
|
|
|
16
19
|
Existing CLI and subscription behavior remains the default. Existing
|
|
17
20
|
`TextTransport`, `OpenAICompatibleTransport`, `Conversation`, and `Response`
|
|
@@ -553,6 +556,7 @@ records.
|
|
|
553
556
|
| Attempt usage | `usage.ruby_llm` per physical attempt | Useful facts, but the public payload has no stable attempt ID; harness must add one |
|
|
554
557
|
| Plain Ruby resume | transcript can be reconstructed manually | No documented state export/import API; implement normalized export/import outside RubyLLM |
|
|
555
558
|
| Rails resume | `acts_as_chat` transcript plus supporting records | Technically restart-safe at checkpoints; at-least-once side effects remain |
|
|
559
|
+
| Loop controls | `Chat#step`, `#complete`, `#run_tools`, `#approve`, `#deny`, `Tool.requires_approval`, `#cancel` | Evaluated for delegation; retained-loop outcome (see below) |
|
|
556
560
|
|
|
557
561
|
### Optional Rails supporting tables
|
|
558
562
|
|
|
@@ -591,14 +595,96 @@ historical/pending-conversation tests. Reverting the gem is not a data rollback.
|
|
|
591
595
|
2. **Use RubyLLM tool-call and usage tables selectively.** Potentially removes
|
|
592
596
|
bookkeeping, but only after stable-attempt mapping, tenant-scoped access,
|
|
593
597
|
audit, and migration tests are complete.
|
|
594
|
-
3. **Delegate the full loop and all supporting tables.**
|
|
595
|
-
|
|
596
|
-
|
|
598
|
+
3. **Delegate the full loop and all supporting tables.** Evaluated and
|
|
599
|
+
rejected for now: the delegation review below found maintenance increases
|
|
600
|
+
across both repositories. Retaining Paid's loop over the normalized
|
|
601
|
+
transport is the completed outcome and creates no future delegation
|
|
602
|
+
obligation.
|
|
597
603
|
|
|
598
604
|
The state investigation is therefore positive for checkpoint-based Rails
|
|
599
605
|
restoration and normalized plain Ruby reconstruction, and negative for
|
|
600
606
|
exactly-once recovery or an off-the-shelf plain Ruby export/import mechanism.
|
|
601
607
|
|
|
608
|
+
## Resumable-loop delegation evaluation
|
|
609
|
+
|
|
610
|
+
RDR-072 permits delegating the chat loop only when behavior is preserved and
|
|
611
|
+
maintenance decreases across both repositories, counting adapters,
|
|
612
|
+
persistence, and recovery code. Retaining Paid's loop over the normalized
|
|
613
|
+
transport is an acceptable completed outcome. This section records the
|
|
614
|
+
evaluation against RubyLLM 2.0.0's public loop controls
|
|
615
|
+
(`Chat#step`, `#complete`, `#run_tools`, `#complete?`, `#awaiting_approval?`,
|
|
616
|
+
`#pending_approvals`, `#approve`, `#deny`, `#cancel`, and
|
|
617
|
+
`Tool.requires_approval`) and its conclusion.
|
|
618
|
+
|
|
619
|
+
### Verified behaviors
|
|
620
|
+
|
|
621
|
+
`spec/ruby_llm_loop_delegation_evaluation_spec.rb` drives a real
|
|
622
|
+
`RubyLLM::Chat` through the public API with stubbed Anthropic Messages
|
|
623
|
+
responses and pins each fact with a contract test:
|
|
624
|
+
|
|
625
|
+
| Required behavior | Result | Evidence |
|
|
626
|
+
| --- | --- | --- |
|
|
627
|
+
| Single-step execution | Verified | `#step` advances one move; `#complete?` flips only on a final answer |
|
|
628
|
+
| Mixed read/write batches | Verified | Reads without approval execute; `requires_approval` writes stay pending (`#awaiting_approval?`) |
|
|
629
|
+
| Multiple pending decisions | Verified | `#pending_approvals` lists every undecided write; `#approve`/`#deny` resolve them independently |
|
|
630
|
+
| Denial | Verified | A denied call receives a structured denial result and the model continues |
|
|
631
|
+
| Completion | Verified | `#complete?` reports the terminal state |
|
|
632
|
+
| Cancellation | Verified | `#cancel` raises `CancelledError` at the next loop checkpoint, then clears |
|
|
633
|
+
| Completed tool results preserved | Verified | `#run_tools` skips calls that already carry results, so a resumed round executes only the remainder |
|
|
634
|
+
|
|
635
|
+
### Gaps that fail the delegation criteria
|
|
636
|
+
|
|
637
|
+
| Criterion | Finding | Evidence |
|
|
638
|
+
| --- | --- | --- |
|
|
639
|
+
| Stable tool IDs | `ToolCall#id` is the provider wire id verbatim; no caller-stable identity is generated, so the contract's "provider_id is not a durable application identifier" rule needs a new mapping adapter | provider-id example |
|
|
640
|
+
| Iteration limits | The loop has no bound: `#complete` steps until `#complete?` or `#awaiting_approval?`, and `tool_options` exposes only choice/calls/concurrency; bounding stays caller-owned | unbounded-iteration example |
|
|
641
|
+
| Restart restoration without Rails | Decisions recorded with `#approve` live in per-chat in-memory state; a plain Ruby chat rebuilt from the same messages is awaiting approval again. Durable decisions require `acts_as_chat` (Active Record), which plain Ruby consumers must not require | reconstruction example |
|
|
642
|
+
| Crash recovery | Same as above: checkpoint restoration is Rails-only, so a plain Ruby consumer re-implements decision and transcript persistence | reconstruction example |
|
|
643
|
+
| Runner-isolated tool execution | `Tool#execute` runs in the calling process; the loop has no dispatch boundary. Paid executes tools in runner processes under caller-owned authorization and atomic claims, so delegation needs new dispatch adapters rather than removing code | in-process execution throughout |
|
|
644
|
+
| Bounded, non-nested retries | Each loop `#generate` retries beneath the caller through Faraday middleware by default (`max_retries` defaults to three), violating the single-retry-owner and shared `max_attempts` budget rules; even with retries disabled, per-step budget/fallback sequencing is absent | hidden-retry example |
|
|
645
|
+
| Attempt accounting | `usage.ruby_llm` payloads carry only operation/provider/model/status/tokens/cost — no attempt or request identity — so the harness `AttemptReport` ledger with stable `attempt_id` would be bypassed | usage-payload example |
|
|
646
|
+
|
|
647
|
+
### Maintenance comparison
|
|
648
|
+
|
|
649
|
+
Delegating the loop would remove Paid's turn-taking mechanics (step dispatch
|
|
650
|
+
and approve/deny plumbing) while keeping Paid's authorization, atomic claims,
|
|
651
|
+
runner dispatch, iteration bounds, workflow recovery, durable accounting, and
|
|
652
|
+
cross-process cancellation. It would add, across the two repositories:
|
|
653
|
+
|
|
654
|
+
- a provider-id to stable-id mapping adapter;
|
|
655
|
+
- in-process `Tool#execute` to runner-process dispatch adapters;
|
|
656
|
+
- a per-step retry, shared-budget, and fallback sequencing wrapper;
|
|
657
|
+
- a caller-side iteration-limit driver replacing `#complete`;
|
|
658
|
+
- plain Ruby decision/transcript persistence and export/import (Rails
|
|
659
|
+
`acts_as_chat` cannot be a dependency); and
|
|
660
|
+
- attempt-accounting extraction with harness-side attempt identity.
|
|
661
|
+
|
|
662
|
+
The additions exceed the removals, so maintenance increases across both
|
|
663
|
+
repositories and the criteria fail.
|
|
664
|
+
|
|
665
|
+
### Outcome
|
|
666
|
+
|
|
667
|
+
**Retained loop.** Paid keeps its conversation loop over
|
|
668
|
+
`Api::ChatTransport`; the harness keeps one normalized response per call
|
|
669
|
+
with bounded retries, fallback, cancellation, and the attempt ledger. Tool
|
|
670
|
+
execution, approval decisions, authorization, atomic claims, iteration
|
|
671
|
+
limits, and crash recovery remain caller responsibilities under the existing
|
|
672
|
+
ownership boundary. No loop runtime, adapter, persistence, or release was
|
|
673
|
+
added, so there is no migration cost and no consumer activation step. This
|
|
674
|
+
closes the evaluation without creating a future delegation obligation.
|
|
675
|
+
|
|
676
|
+
Re-evaluate only if RubyLLM later documents a public, plain-Ruby-resumable
|
|
677
|
+
loop with caller-stable tool identity, an external tool-dispatch boundary, a
|
|
678
|
+
bounded `#complete`, and per-attempt accounting identity; the evaluation
|
|
679
|
+
spec's examples are the tripwire that detects such changes on upgrade.
|
|
680
|
+
|
|
681
|
+
### Communication
|
|
682
|
+
|
|
683
|
+
The retained-loop outcome, the behavior-test evidence above, and the zero
|
|
684
|
+
migration cost are the message for the Paid adoption and closeout tracking
|
|
685
|
+
(viamin/paid#4014 and the parent viamin/agent-harness#430). No scope beyond
|
|
686
|
+
the accepted RDR-072 alternatives is requested or implied.
|
|
687
|
+
|
|
602
688
|
## Current harness gaps and incremental delivery
|
|
603
689
|
|
|
604
690
|
The current transports already normalize basic text, tool calls, token totals,
|
|
@@ -615,7 +701,8 @@ Ship capabilities independently in this order:
|
|
|
615
701
|
3. normalized non-streaming and streaming chat transport;
|
|
616
702
|
4. structured output for verified model/protocol combinations;
|
|
617
703
|
5. plain Ruby state round trips; and
|
|
618
|
-
6. optional Rails persistence evaluation, then loop evaluation
|
|
704
|
+
6. optional Rails persistence evaluation, then loop evaluation (closed with
|
|
705
|
+
the retained-loop outcome recorded above; no runtime change).
|
|
619
706
|
|
|
620
707
|
Each implementation issue starts with failing contract tests for request-local
|
|
621
708
|
credential isolation, custom endpoints/headers, unsupported outcomes,
|
|
@@ -660,6 +747,23 @@ types stay behind the harness boundary.
|
|
|
660
747
|
interfaces. JSON-only mode and model-specific capability discovery are not
|
|
661
748
|
migrated.
|
|
662
749
|
|
|
750
|
+
### Loop-delegation evaluation evidence (retained loop)
|
|
751
|
+
|
|
752
|
+
- Publication: none required. The evaluation changed documentation and tests
|
|
753
|
+
only; no runtime path, adapter, table, or public API was added or altered,
|
|
754
|
+
so every released agent-harness version already carries the outcome.
|
|
755
|
+
- Verification: `spec/ruby_llm_loop_delegation_evaluation_spec.rb` exercises
|
|
756
|
+
only the public RubyLLM 2.0 API (pinned `ruby_llm = 2.0.0`) against stubbed
|
|
757
|
+
Anthropic Messages responses and runs with the upstream suite and lint on
|
|
758
|
+
the repository's supported Ruby environment. It records the verified loop
|
|
759
|
+
behaviors and the gaps that failed the delegation criteria.
|
|
760
|
+
- Migration: none. Paid and other consumers keep their existing loops over
|
|
761
|
+
`Api::ChatTransport`; no consumer activation, feature flag, or rollout step
|
|
762
|
+
applies.
|
|
763
|
+
- Retained responsibilities: documented in "Resumable-loop delegation
|
|
764
|
+
evaluation" above; loop ownership stays with Paid under RDR-072's accepted
|
|
765
|
+
alternatives.
|
|
766
|
+
|
|
663
767
|
AgentHarness currently supports Ruby 3.2 and later and must remain usable as a
|
|
664
768
|
plain Ruby gem. RubyLLM 2.0.0 itself supports Ruby 3.1.3 and later and adds
|
|
665
769
|
Faraday, event-stream parsing, Schematist, Marcel, and Zeitwerk runtime
|
|
@@ -683,6 +787,7 @@ For every capability, release evidence must name:
|
|
|
683
787
|
- retained paths and follow-up issues for combinations not migrated.
|
|
684
788
|
|
|
685
789
|
Paid issue `viamin/paid#4014` should receive this compatibility result, the
|
|
686
|
-
state-restoration conclusion, the stable-ID gap,
|
|
687
|
-
evidence
|
|
790
|
+
state-restoration conclusion, the stable-ID gap, the per-capability release
|
|
791
|
+
evidence, and the retained-loop outcome of the delegation evaluation.
|
|
792
|
+
Downstream adoption cannot proceed from this design issue closing or
|
|
688
793
|
from a Git tag alone.
|