|
1 | 1 | # Release History - open AEA |
2 | 2 |
|
3 | | -## Unreleased |
| 3 | +## 2.2.6 (2026-05-14) |
4 | 4 |
|
5 | | -Plugins: |
| 5 | +Framework: |
6 | 6 |
|
7 | | -- `open-aea-ledger-ethereum`: tightens `max_gas_fast` per chain in `CHAIN_EIP1559_OVERRIDES`. Until now low-fee chains (Gnosis, Optimism, Base, Mode, Fraxtal, Arbitrum One) inherited the chain-agnostic 1500 gwei default, so a fee-oracle anomaly could authorise a tx priced 100×+ above the chain's normal range before the cap engaged. A production market-creator deployment on Gnosis submitted a routine multisend at 694 gwei (~700× the validator floor of 1 gwei) on 2026-04-22 ([tx 0x727262d9…](https://gnosisscan.io/tx/0x727262d9238881e72eeaeb01bf88b234b380c6d3d2dc9e60fcb71b07354933bd)), paying 0.637 xDAI — ~45% of the agent's 30-day spend — while the inherited 1500 gwei ceiling did not trigger the fallback. New per-chain ceilings: Gnosis 30 gwei, Optimism / Base 100 gwei, Mode / Fraxtal 50 gwei, Arbitrum One 5 gwei. Sized to preserve operability during legitimate congestion (Base's March 2024 Dencun memecoin frenzy sustained ~24 gwei averages with bursts >100 gwei in individual blocks; Gnosis Tornado-deposit waves briefly hit 5–8 gwei) while bounding fee-oracle anomalies. Polygon (10000 gwei ceiling) and Celo (default 1500 gwei) are unchanged. #909 |
| 7 | +- `aea.helpers.base.try_decorator`: enriches the swallowed-exception log line with the wrapped function's qualified name and the exception type. The previous `log(error_message.format(e))` rendered a `KeyError("maxFee")` as just `"...'maxFee'"`; the line now reads `"... [function=<qualname>, exc_type=KeyError]"` so swallowed failures are diagnosable without changing the catch semantics. The public docstring also documents the `raise_on_try=True` escape hatch. #891 #910 |
8 | 8 |
|
9 | 9 | Packages: |
10 | 10 |
|
11 | | -- `valory/ledger` connection: aligns per-chain `max_gas_fast` in `connection.yaml` with the new plugin-level ceilings — Gnosis 30, Optimism / Base 100, Mode / Fraxtal 50, Arbitrum One 5. Self-documenting and defensible if the plugin defaults ever drift. #909 |
| 11 | +- `valory/ledger` connection: caps the per-attempt retry sleep in `get_transaction_receipt` / `get_transaction` at `MAX_RETRY_DELAY = 60.0`. Without the cap, the linear backoff `retry_timeout * attempts` grew unboundedly across the retry budget; capping bounds the worst-case loop while preserving the retry count. #891 #910 |
| 12 | +- `valory/ledger` connection: owns a dedicated `ThreadPoolExecutor` sized by a new `max_thread_workers` config (default 32) and shuts it down with `cancel_futures=True` on disconnect. Previously the dispatchers passed `executor=None` and shared Python's default asyncio thread pool with every other agent component; under sustained RPC outage `RotatingHTTPProvider.make_request`'s sync sleeps accumulated abandoned threads in the shared pool. The dedicated executor isolates ledger work and surfaces the resource cost as operator-tunable config. #891 #910 |
| 13 | +- `valory/ledger` connection: lowers the shipped `retry_attempts` default in `connection.yaml` from 240 to 60 (and the in-code `MAX_ATTEMPTS` / `RequestDispatcher.retry_attempts` defaults from 120 to 60 to match). Now that `RotatingHTTPProvider` handles transport-layer rotation per call, the dispatcher budget is a layered backstop rather than the primary retry mechanism; the tighter default drops worst-case per-slot pool occupancy from ~230 minutes to ~50 minutes. Operators wanting the old budget can override in their connection config. #891 #910 |
| 14 | +- `valory/ledger` connection: improves the dispatcher's retry-loop warning log to include the exception type — `self.logger.warning(e)` previously rendered a `KeyError("maxFee")` as just `"maxFee"`. Now uses `"%s: %s", type(e).__name__, e` for both the receipt and transaction loops. #891 #910 |
| 15 | +- `valory/ledger` connection: typed `max_thread_workers` as `int` at the assignment site so a stringified YAML value cannot slip past mypy and explode at `ThreadPoolExecutor(max_workers=...)`. #891 #910 |
| 16 | + |
| 17 | +Plugins: |
| 18 | + |
| 19 | +- `open-aea-ledger-ethereum`: tightens `max_gas_fast` per chain in `CHAIN_EIP1559_OVERRIDES`. Until now low-fee chains (Gnosis, Optimism, Base, Mode, Fraxtal, Arbitrum One) inherited the chain-agnostic 1500 gwei default, so a fee-oracle anomaly could authorise a tx priced 100×+ above the chain's normal range before the cap engaged. A production market-creator deployment on Gnosis submitted a routine multisend at 694 gwei (~700× the validator floor of 1 gwei) on 2026-04-22 ([tx 0x727262d9…](https://gnosisscan.io/tx/0x727262d9238881e72eeaeb01bf88b234b380c6d3d2dc9e60fcb71b07354933bd)), paying 0.637 xDAI — ~45% of the agent's 30-day spend — while the inherited 1500 gwei ceiling did not trigger the fallback. New per-chain ceilings: Gnosis 30 gwei, Optimism / Base 100 gwei, Mode / Fraxtal 50 gwei, Arbitrum One 5 gwei. Sized to preserve operability during legitimate congestion (Base's March 2024 Dencun memecoin frenzy sustained ~24 gwei averages with bursts >100 gwei in individual blocks; Gnosis Tornado-deposit waves briefly hit 5–8 gwei) while bounding fee-oracle anomalies. Polygon (10000 gwei ceiling) and Celo (default 1500 gwei) are unchanged. `valory/ledger` `connection.yaml` mirrors the plugin-level ceilings. #909 #911 |
| 20 | +- `open-aea-ledger-ethereum`: gas-price strategies (Polygon EIP1559 and Eth Gas Station) broaden the `except` clause to cover `(requests.exceptions.RequestException, ValueError, KeyError, TypeError)` so malformed-response failure modes hit the documented fallback. `response.json()` raises `JSONDecodeError` (a `ValueError` subclass) on non-JSON 200; `[speed]` / `["maxFee"]` subscripts raise `KeyError` on schema drift; a non-dict 200 body (a JSON `null`, array, or string from a CDN serving an error page) raises `TypeError` on the raw subscript. The previous `except requests.exceptions.RequestException` only caught network-shaped errors, so the documented fallback was bypassed for everything else. Both strategies now also emit a `WARNING` carrying the exception type so transport failures and schema drift are distinguishable in operator logs. #891 #910 |
| 21 | +- `open-aea-ledger-ethereum`: `RotatingHTTPProvider` docstring documents the interaction with the ledger connection's dedicated `ThreadPoolExecutor` — `make_request` is synchronous and uses `time.sleep` between retries, so worker threads in the connection's pool can be held for the duration of a retry sequence. Operators expecting high ledger concurrency under RPC degradation should size `max_thread_workers` to exceed peak concurrent retries for their RPC topology. #891 #910 |
| 22 | +- `open-aea-cli-ipfs`: routes the success-path `json.loads` calls in `_api_post`, `add`, and `add_bytes` through a single `_safe_json_loads` helper that raises a typed `StatusError` (with a printable, length-capped body preview) on non-JSON 200 responses. Previously a 200 carrying a non-JSON body (CDN HTML error page, truncated payload, gzipped body) raised an unhandled `ValueError` to the caller. The body preview replaces non-printable bytes with `.` and truncates at 80 chars so an arbitrary remote response cannot inject terminal-control sequences into operator logs. #891 #910 |
| 23 | + |
| 24 | +Documentation: |
| 25 | + |
| 26 | +- New `docs/connection-resilience.md` framework-developer guidance for choosing retry and timeout behaviour. Covers where work happens in an agent (skills / connections / protocols), the distinction between within-agent and agent-to-external failures, per-component overview (HTTP client, HTTP server, ledger read-side / write-side / thread pool, `RotatingHTTPProvider`, IPFS, P2P libp2p variants, cosmos / fetchai / solana plugins), and a "picking a policy for a new component" checklist. Indexed in `mkdocs.yml` under Development – Advanced → Topic Guides. #891 #910 |
12 | 27 |
|
13 | 28 | ## 2.2.5 (2026-05-08) |
14 | 29 |
|
|
0 commit comments