Lightning.Tesla.Adapter.Finch (Lightning v2.19.0-pre)

View Source

Enough of Tesla's Finch adapter for the Apollo client, with the failure reason preserved on a streamed response.

Not a faithful copy: it drops upstream's build/4 clauses for multipart, stream and function request bodies, and hands the body to Finch.build/4 as it stands. Anything but a plain body therefore fails further down, in Mint, rather than here. Apollo sends JSON.

Upstream's streaming path returns nil from its Stream.unfold for a mid-stream error, a mid-stream timeout, and a clean end alike, discarding the reason. Every AI chat therefore ended up reporting "Stream ended without complete response" whatever had actually happened - a hung Apollo, a severed connection, and a genuinely short answer were indistinguishable.

A sentinel inside the stream is not an option: Tesla.Middleware.SSE concatenates elements as binaries and would fail on anything else. But the Stream.unfold body runs in the calling process, so the reason is left in that process's dictionary and read back with take_stream_error/0 once the stream has been consumed.

Also passes :request_timeout through to Finch, which the 1.18.3 we pin drops.

Both are fixed upstream, in separate releases: the option pass-through in 1.19.0 (tesla#879), the stream reason in 1.21.1 (tesla#912). This module exists only because we pin ~> 1.18.2; bumping to 1.21.1 deletes it, and the reason then arrives as a raised Tesla.Error rather than through take_stream_error/0, so the caller in Lightning.AiAssistant changes with it. Tracked in #5080.

Summary

Functions

Why the last streamed response stopped, if it stopped badly.

Functions

take_stream_error()

@spec take_stream_error() :: term() | nil

Why the last streamed response stopped, if it stopped badly.

Returns nil when the stream ended cleanly. Reading clears it, so a later request cannot pick up an earlier one's failure.