feat(sdk): return lastEventId from writeTurnComplete and typed capture result#4304
Conversation
🦋 Changeset detectedLatest commit: a6d0ddb The changes in this PR will be included in the next version bump. This PR includes changesets to release 26 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
🚧 Files skipped from review as they are similar to previous changes (6)
📜 Recent review details⏰ Context from checks skipped due to timeout. (31)
🧰 Additional context used📓 Path-based instructions (1)docs/**/*.mdx📄 CodeRabbit inference engine (docs/CLAUDE.md)
Files:
🧠 Learnings (4)📚 Learning: 2026-03-10T12:44:14.176ZApplied to files:
📚 Learning: 2026-04-30T20:30:29.458ZApplied to files:
📚 Learning: 2026-06-16T13:14:09.440ZApplied to files:
📚 Learning: 2026-06-16T13:14:14.382ZApplied to files:
🔇 Additional comments (1)
WalkthroughThe SDK updates 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…e result
chat.writeTurnComplete() now resolves to { lastEventId }, the resume cursor
for the next turn, so a custom-agent loop can persist it straight from the
task instead of round-tripping it back from the client.
chat.pipeAndCapture() no longer throws when a stream is stopped or fails. It
resolves to a PipeAndCaptureResult carrying any partial message captured
before the stop or failure, a typed status (complete | aborted | error), and
the error on failure. The internal turn.complete() path keeps its existing
contract (returns UIMessage | undefined, still throws on a genuine stream
failure and discards output on full cancel).
3343ef5 to
335c087
Compare
@trigger.dev/build
trigger.dev
@trigger.dev/core
@trigger.dev/python
@trigger.dev/react-hooks
@trigger.dev/redis-worker
@trigger.dev/rsc
@trigger.dev/schema-to-json
@trigger.dev/sdk
commit: |
…omplete lastEventId Adds unit tests for the new chat.pipeAndCapture result shape (complete / aborted-with-partial / error) and for chat.writeTurnComplete returning a resume cursor. Extends the in-memory session test harness so its .out writeControl projects a synthetic seq_num and its pipe propagates source-stream errors (mirroring production) instead of swallowing them.
…rden test pipe Address PR review: - pipeAndCapture now reconstructs the partial message from buffered chunks when a transport failure abandons the stream before onFinish fires, so the partial is preserved on the hard-error path, not just on abort. - writeTurnComplete also returns sessionInEventId (the committed .in consume cursor) alongside lastEventId, so a raw loop can correlate both turn-boundary cursors server-side. - The in-memory session test harness no longer hangs if stream setup throws before the read loop; stream setup now runs inside the guarded block. - Docs and the pipeAndCapture error-path test updated to match.
Summary
Two ergonomic additions for custom chat-agent loops that own the turn loop (
chat.customAgent,chat.createSession, and the hand-rolled primitives).chat.writeTurnComplete()now resolves to{ lastEventId }, the resume cursor for the start of the next turn. A custom loop can persist it straight from the task instead of round-tripping it back from the client after the turn ends. The value was already produced internally by the turn-complete write; the public wrapper simply discarded it.chat.pipeAndCapture()no longer throws when a stream is stopped or fails. It now resolves to aPipeAndCaptureResultcarrying any partialmessagecaptured before the stop or failure, a typedstatus("complete" | "aborted" | "error"), and theerroron failure. Previously a failed stream threw and the partial was lost, and an abort was captured only when the AI SDK happened to fireonFinishin time.Design
pipeAndCapturewraps the pipe in atry/catchand classifies the outcome from the abort signal (a stop drains the source stream cleanly rather than throwing) versus a thrown error. It also races theonFinishcapture against a timeout so a hard stop that preventsonFinishfrom firing can't hang the caller. This mirrors the capture pathchat.agentalready uses internally.The
finishReasonfromonFinishis surfaced too, since it was already captured on the built-in path.The internal
turn.complete()helper keeps its existing contract: it still returnsUIMessage | undefined, still throws on a genuine stream failure, and still discards output on a full run cancel.Breaking change
chat.pipeAndCapturepreviously resolved toUIMessage | undefined. Call sites now read.messageoff the result. This is a young, low-level API; the docs examples are updated in this PR.