Commit be45cf9
authored
fix(sdk): preserve partial assistant message on chat stream failure (#4348)
## Summary
When a `chat.agent` (or `chat.createSession`) turn's model stream fails
mid-response (e.g. a transport timeout like `UND_ERR_BODY_TIMEOUT`), the
assistant output that already streamed was dropped: `onTurnComplete`
fired with `responseMessage: undefined`, and the manual loop's
`turn.complete()` rethrew without keeping the partial. Apps that
register `hydrateMessages` are hit hardest, since boot-time tail-replay
recovery is off by design.
This preserves the streamed-so-far assistant output while still
reporting the turn as errored, so persistence and recovery keep it.
## Scope of behavior change
Only the **error path** changes. Successful turns are unaffected: the
same chunks stream to the client in the same order, and
backpressure/cancel behave as before. Everything here is a correctness
improvement on a turn that hit a source-stream failure.
## What it does
Follow-up to #4304 (`chat.pipeAndCapture`), extending the same
partial-recovery to the two loops that lacked it:
- **`chat.agent`**: taps the response stream (via a `TransformStream`,
so pass-through backpressure and cancel are preserved) to buffer chunks,
and on a source-stream failure reconstructs the partial (preferring the
`onFinish` message). It's surfaced on the error-path `onTurnComplete`
(`responseMessage`, `rawResponseMessage`, `uiMessages`, `newUIMessages`,
`newMessages`) and committed to the accumulator so the next turn and the
reboot snapshot keep it.
- **`chat.createSession` / `turn.complete()`**: the reconstructed
partial is accumulated (so `turn.uiMessages` reflects it and the caller
can persist after catching) before `turn.complete()` rethrows.
`onBeforeTurnComplete` stays skipped on the error path (it hands out a
writer for a stream that has already broken).
## Correctness properties (each covered by a regression test)
Each test below was confirmed to fail without its fix:
- The recovered partial reaches `onTurnComplete` and the next turn's
accumulated messages.
- An already-committed (possibly enriched) response is not overwritten
if a post-response hook then throws.
- Incomplete tool parts are cleaned from the recovered partial (text
kept), so the UI and model views agree and the next turn isn't poisoned.
- A prior turn's model-only compaction survives an errored turn (append
only the new tail, don't reconvert the full history).
- A reconstructed fragment that reuses an existing message id does not
clobber the complete message.
- Queued `chat.response` data parts are folded into the recovered
partial, matching the success path.
- `newMessages` (model delta) stays symmetric with `newUIMessages`.
## Tests
New `chat-agent-source-stream-error.test.ts` covers the cases above. The
full `@trigger.dev/sdk` unit suite passes and the package build is green
across all supported runtimes (Node 20 to 26, Bun, Deno, Cloudflare
Workers).1 parent 109e245 commit be45cf9
3 files changed
Lines changed: 551 additions & 26 deletions
File tree
- .changeset
- packages/trigger-sdk
- src/v3
- test
Lines changed: 5 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6389 | 6389 | | |
6390 | 6390 | | |
6391 | 6391 | | |
| 6392 | + | |
| 6393 | + | |
| 6394 | + | |
6392 | 6395 | | |
6393 | 6396 | | |
6394 | 6397 | | |
| |||
7175 | 7178 | | |
7176 | 7179 | | |
7177 | 7180 | | |
| 7181 | + | |
7178 | 7182 | | |
7179 | 7183 | | |
7180 | 7184 | | |
7181 | 7185 | | |
7182 | | - | |
| 7186 | + | |
7183 | 7187 | | |
7184 | 7188 | | |
7185 | 7189 | | |
| |||
7390 | 7394 | | |
7391 | 7395 | | |
7392 | 7396 | | |
| 7397 | + | |
| 7398 | + | |
| 7399 | + | |
| 7400 | + | |
| 7401 | + | |
| 7402 | + | |
7393 | 7403 | | |
7394 | 7404 | | |
7395 | 7405 | | |
| |||
7611 | 7621 | | |
7612 | 7622 | | |
7613 | 7623 | | |
| 7624 | + | |
7614 | 7625 | | |
7615 | 7626 | | |
7616 | 7627 | | |
| |||
7904 | 7915 | | |
7905 | 7916 | | |
7906 | 7917 | | |
7907 | | - | |
7908 | | - | |
7909 | | - | |
7910 | | - | |
| 7918 | + | |
| 7919 | + | |
| 7920 | + | |
| 7921 | + | |
| 7922 | + | |
| 7923 | + | |
| 7924 | + | |
| 7925 | + | |
| 7926 | + | |
| 7927 | + | |
| 7928 | + | |
| 7929 | + | |
| 7930 | + | |
| 7931 | + | |
| 7932 | + | |
| 7933 | + | |
| 7934 | + | |
| 7935 | + | |
| 7936 | + | |
| 7937 | + | |
| 7938 | + | |
| 7939 | + | |
| 7940 | + | |
| 7941 | + | |
| 7942 | + | |
| 7943 | + | |
| 7944 | + | |
| 7945 | + | |
| 7946 | + | |
| 7947 | + | |
| 7948 | + | |
| 7949 | + | |
| 7950 | + | |
| 7951 | + | |
| 7952 | + | |
| 7953 | + | |
| 7954 | + | |
| 7955 | + | |
| 7956 | + | |
| 7957 | + | |
| 7958 | + | |
| 7959 | + | |
| 7960 | + | |
| 7961 | + | |
| 7962 | + | |
| 7963 | + | |
| 7964 | + | |
| 7965 | + | |
| 7966 | + | |
| 7967 | + | |
| 7968 | + | |
| 7969 | + | |
| 7970 | + | |
| 7971 | + | |
| 7972 | + | |
| 7973 | + | |
| 7974 | + | |
| 7975 | + | |
| 7976 | + | |
| 7977 | + | |
| 7978 | + | |
| 7979 | + | |
| 7980 | + | |
| 7981 | + | |
| 7982 | + | |
| 7983 | + | |
| 7984 | + | |
| 7985 | + | |
| 7986 | + | |
| 7987 | + | |
| 7988 | + | |
7911 | 7989 | | |
7912 | 7990 | | |
7913 | 7991 | | |
| |||
7917 | 7995 | | |
7918 | 7996 | | |
7919 | 7997 | | |
7920 | | - | |
7921 | | - | |
7922 | | - | |
7923 | | - | |
7924 | | - | |
| 7998 | + | |
| 7999 | + | |
| 8000 | + | |
| 8001 | + | |
| 8002 | + | |
7925 | 8003 | | |
7926 | 8004 | | |
7927 | 8005 | | |
| |||
7967 | 8045 | | |
7968 | 8046 | | |
7969 | 8047 | | |
7970 | | - | |
| 8048 | + | |
7971 | 8049 | | |
7972 | 8050 | | |
7973 | 8051 | | |
| |||
8887 | 8965 | | |
8888 | 8966 | | |
8889 | 8967 | | |
8890 | | - | |
| 8968 | + | |
8891 | 8969 | | |
8892 | 8970 | | |
8893 | | - | |
| 8971 | + | |
8894 | 8972 | | |
8895 | | - | |
8896 | | - | |
8897 | | - | |
8898 | | - | |
8899 | | - | |
8900 | | - | |
8901 | | - | |
8902 | | - | |
8903 | | - | |
8904 | | - | |
8905 | | - | |
8906 | | - | |
| 8973 | + | |
| 8974 | + | |
| 8975 | + | |
| 8976 | + | |
| 8977 | + | |
| 8978 | + | |
| 8979 | + | |
| 8980 | + | |
| 8981 | + | |
| 8982 | + | |
8907 | 8983 | | |
8908 | 8984 | | |
8909 | 8985 | | |
8910 | 8986 | | |
8911 | | - | |
| 8987 | + | |
8912 | 8988 | | |
8913 | 8989 | | |
8914 | 8990 | | |
| |||
9744 | 9820 | | |
9745 | 9821 | | |
9746 | 9822 | | |
| 9823 | + | |
| 9824 | + | |
| 9825 | + | |
| 9826 | + | |
| 9827 | + | |
| 9828 | + | |
| 9829 | + | |
| 9830 | + | |
| 9831 | + | |
9747 | 9832 | | |
9748 | 9833 | | |
9749 | 9834 | | |
| |||
0 commit comments