feat(frontend): negotiate agent stream→batch fallback on /invoke#4875
Conversation
The agent playground sent a fixed Accept from the kebab toggle and trusted it, with no fallback if the backend could not stream. Add the negotiation the 'stream' default implies, aligned to the SDK /invoke contract: - createNegotiatingFetch (new, @agenta/playground): a fetch middleware that requests the SSE stream, falls back to a batch re-request on a 406 (handler can't stream), and passes any other non-OK response through so useChat surfaces the real error inline. - AgentChatTransport now owns its fetch via the negotiator and parses the body by the channel that actually resolved, not the requested one — fixing the latent case where a stream request that fell back to batch was fed to the SSE parser. - channelMode doc + barrel exports updated; the Stream/Batch toggle is now a preference (Stream = negotiate with fallback, Batch = force batch). - Adds 5 unit tests covering stream, 406 fallback, error pass-through, explicit batch, and Content-Type trust.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 213b6551-526e-4ec5-89c7-b81896c722bf
📒 Files selected for processing (7)
web/oss/src/components/AgentChatSlice/assets/AgentChatTransport.tsweb/packages/agenta-playground/src/index.tsweb/packages/agenta-playground/src/state/execution/agentNegotiation.tsweb/packages/agenta-playground/src/state/execution/channelMode.tsweb/packages/agenta-playground/src/state/execution/index.tsweb/packages/agenta-playground/src/state/index.tsweb/packages/agenta-playground/tests/unit/agentNegotiation.test.ts
The negotiating fetch tracked the resolved channel (stream vs. batch) in a shared mutable variable that AgentChatTransport read back later in processResponseStream. That read-back across the fetch->parse boundary is only safe while requests on a transport never overlap; it is a latent race if they ever do (the parse could pick up a sibling request's mode). Key the mode off the response body ReadableStream via a WeakMap instead, so the parse decision is bound to the exact body being parsed. resolvedMode now takes the stream (with a no-arg fallback to the last negotiation for callers without it). Behaviour is unchanged for the existing single-request paths; the 5 negotiation unit tests stay green.
|
@coderabbitai review |
✅ Action performedReview finished.
|
Context
The agent playground's run lane talks to
/invokewith content negotiation:Accept: text/event-streamasks for the v6 SSE UI-message stream,application/jsonfor a singleWorkflowBatchResponse. The SDK route answers a stream request it can't satisfy with 406 Not Acceptable, and surfaces handler errors as JSON with the real status code.The first cut wired this as a fixed
Acceptdriven by the kebab Stream/Batch toggle and trusted it — there was no negotiation. If the backend couldn't stream, the toggle'sstreamdefault had no fallback, and a stream request that came back as batch JSON would have been handed to the SSE parser.Changes
Implements the negotiation the
streamdefault implies — try stream → fall back to batch → error gracefully — aligned to the backend/invokecontract.createNegotiatingFetch(new,@agenta/playground) — afetchmiddleware that:406(handler can only batch), re-issues the same request asapplication/jsonso the run isn't lost;useChat'sonErrorrenders the real error inline.It also trusts the response
Content-Typeover the request intent, and skips the stream attempt when batch is chosen explicitly.AgentChatTransportnow owns itsfetchthrough the negotiator and parses the body by the channel that actually resolved (resolvedMode()), not the requested one — fixing the latent SSE-parser-fed-batch case.channelModedoc + barrel exports updated; the Stream/Batch toggle is now a preference (Stream = negotiate with fallback, Batch = force batch).Tests / notes
406→ batch re-request (Accept flips toapplication/json), real error pass-through (no second request), explicit batch skips the stream attempt, and Content-Type trust.@agenta/playgroundbuild (tsc) clean; full package suite green (139 tests). OSS tsc clean for the touched files.big-agents(after PR [feat] /invoke absorbs /messages + align agent env var names #4868 —/invokeabsorbs/messages— merged into it).What to QA