Provider exceptions may expose numeric error_type or error_code values. Convert those fields at the response boundary before fallback consumers apply string operations, and cover the behavior with a regression test.
Plain tool values (grep patterns, web_search/x_search queries, find_files
globs) were never truncated by format_tool_hints(), so long arguments
overflowed tool_hint_max_length and were pushed to chat/UI verbatim.
Add a hard-truncation fallback for the plain branch, mirroring the existing
truncation used by abbreviate_path / _abbreviate_command. This completes the
same class of fix started in 99209a80 for is_path tools.
Adds 4 regression tests to tests/agent/test_tool_hint.py.
`_listener_is_serving()` probes `SO_ACCEPTCONN` to decide whether a bound
socket is still accepting connections. That option is not portable: macOS
and the BSDs raise `OSError` with `ENOPROTOOPT` ("Protocol not available")
for it even on a perfectly healthy listening socket.
The surrounding `except OSError: return False` swallows that error, so the
listener is reported as degraded on every check. `_serve_forever()` then
raises `_ListenerUnavailableError("WebSocket listener did not enter a
serving state")`, and because `_is_recoverable_listener_error()` classifies
that exception as recoverable, the channel retries forever (4s -> 8s -> 16s
-> 30s backoff) and never becomes ready. On macOS this leaves the gateway
permanently at `ready: false` with the WebUI unreachable, since the
WebSocket channel is enabled by default.
Reproduced on macOS 26.5.1 / Python 3.14.3:
>>> s = socket.socket(); s.bind(("127.0.0.1", 0)); s.listen(1)
>>> s.getsockopt(socket.SOL_SOCKET, socket.SO_ACCEPTCONN)
OSError: [Errno 42] Protocol not available
Extract `_socket_is_accepting()` and treat `ENOPROTOOPT` / `EOPNOTSUPP` /
`EINVAL` as "this platform cannot answer the question", falling back to the
file-descriptor liveness check that already guarded the expression. Other
`OSError`s still propagate, and a closed socket is still rejected via the
`fileno() < 0` short circuit, so Linux behaviour is unchanged.
Address review feedback on the rich edit error classification:
- Transport, rate-limit, and unexpected errors now propagate instead of
returning False. Returning False made send_delta fall through to an
immediate legacy edit_message_text, which under connection-pool
exhaustion doubled demand and discarded the buffered retry state that
ChannelManager relies on.
- 'Message is not modified' is treated as success: when the rich edit is
applied server-side but its response times out, the retry inside
_call_with_retry reports the edit as already applied, and the previous
BadRequest branch would have let the legacy edit overwrite the
successful rich result.
- False is now returned only for capability errors (pre-10.1 servers,
which still trip the rich latch) and content-shaped rejections, where
the legacy HTML path is the intended fallback.
Adds regression coverage for a direct NetworkError (propagates, buffer
kept for manager retry) and TimedOut followed by Message-is-not-modified
(treated as success, no legacy overwrite).
The rich branch in send_delta(stream_end=True) was unreachable: it was
guarded by 'not buf.message_id' after an earlier return had already
ensured buf.message_id is set, so sendRichMessage never fired with
streaming enabled and the final message always went through the legacy
HTML editMessageText path.
Bot API 10.1 added a rich_message parameter to editMessageText, which
upgrades an existing message to rich in place. Use it at stream end via
do_api_request so the streaming preview keeps its identity — no
delete-and-resend, so none of the flickering or dropped line breaks
that made rich-at-stream-end fail in #4470.
Capability errors (server older than 10.1) trip the existing
_rich_send_disabled latch and fall back to the legacy HTML path, which
is unchanged.
Fixes#5516
* refactor(agent): unify runner request fitting
* fix(agent): fit every runner model request
* fix(agent): count resumed state during request fitting
* refactor(agent): consolidate request fitting state