* improve error logging; tool loop defaults
* version bump
* enhance logging
* x_search option
* improve SSE handling
* style: apply ruff format across the repo
The CI "format check" job ran `scripts/format.py`, which invokes the writing
form of `ruff format` rather than `--check`. It rewrote files in the ephemeral
checkout and always exited 0, so formatting drifted while the job stayed green.
This commit is the resulting sweep, with no functional change: every file here
parses to an identical AST before and after (173/173 verified with ast.dump).
Files that also carry hand edits are formatted in their own commits.
* feat(llm): stream diagnostics on the chat-completions path
Stream timing was collected for every provider using the idle-timeout wrapper
but only consumed by the Responses transport, so chat-completions models
(HuggingFace routes included) produced none of it. A GLM-5.2 benchmark run hit a
mid-stream TransferEncodingError and the retry telemetry could only report
`stream_events_received: null`, which hides whether a truncated stream died
early or nearly complete.
- move `stream_timing_payload` into streaming_timeouts so both transports share
one formatter, replacing the private copy in responses.py
- report extended inter-event gaps and include stream timing in the idle-timeout
error on the chat-completions path
- record how far a failed stream got for any mid-stream failure, not just idle
timeouts, and surface it through the existing fast-agent-retry channel; the
count is reset per attempt so it cannot leak between retries
- wire the same recording into the Responses SSE and websocket transports
- fix the retry notice, which showed "Attempt 1/2" while the telemetry for the
same event said `max_attempts: 3`; retry_count counts retries, so total
attempts is retry_count + 1, as the webdebug line already had it
* fix(llm): recover empty Responses payloads and report iteration limits
Work in progress that was already in the tree, committed as its own change.
- rebuild `output` from completed stream items when a terminal Responses payload
arrives empty, shared across the SSE, OpenResponses and websocket transports
- add an explicit MAX_ITERATIONS stop reason so an exhausted tool loop is warned
about and displayed rather than ending silently, mapped to the ACP
`max_turn_requests` stop reason
- raise the default streaming idle timeout from 90s to 120s
- extract `flatten_event_data` so the console, file and HTTP log sinks all lift a
nested `data=` payload consistently
* ci: make the format check actually check
`scripts/format.py` only had the writing form of `ruff format`, so the CI job
named "Run ruff format check" rewrote files in its checkout and could never fail.
Add `--check` and use it in CI.
Also drop `from rich import print` from the lint, format and typecheck scripts.
They used it to print a single unmarked-up error line, and pulling rich in
transitively via typer meant an unrelated rich problem could take out the whole
lint and typecheck gate.
* test: bound tool loop construction smoke test