feat: pure SSE transport driver with reconnect + stop conditions (#46) - #51
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #46
Adds a pure, VS Code-free SSE transport driver on top of the existing frame parser and
@sse-untilgate. Complements #46 without pulling in the response-viewer UI in the same PR.What changed
src/core/sse/transport.ts— new module:runSseTransport({ input, onEvent, ... })drives an async iterable of decoded string chunks throughSseParser, callingonEventper dispatched event with{ index, elapsedMs, reconnect }meta.AbortSignal,@sse-untilmatch,maxEvents,maxDurationMs,idleMs— all enforced between events so a multi-frame chunk can't blast past a cap.SseReconnectStatetrackslastEventIdand server-suggestedretryMsacross attempts.reconnectHeaders(state)produces theLast-Event-IDheader per spec (omitted when unset/empty).clampRetryMs(...)bounds absurd server values into 100 ms – 30 s by default.formatSseTranscriptLine(...)emits one JSON record per line for the.sse.jsonltranscript format.SseTransportUserOptionsSchema(zod,.strict()) validates directive-sourced options before they touch the driver.src/core/sse/index.ts— re-exports.test/sse.transport.test.ts— 22 vitest cases covering happy paths, chunk-boundary framing, every stop condition (with injected clocks +AbortController),@sse-untilerrors, transcript formatting, header omission, retry clamping, and schema validation.README.md— Streaming responses (SSE) section with an OpenAI-style example and links to [feature] Server-Sent Events (SSE) request support #46 for the UI follow-up.Acceptance criteria progress (#46)
src/core/sse/with vitest coverage — already existed; kept intact.SseEventSchema(parser) +SseTransportUserOptionsSchema(driver options).# @sse-until <expr>directive parsed + evaluated in sandboxed context — parsed generically today; now wired through the transport driver.Last-Event-IDbehavior — implemented as pure state; integration test against a real HTTP server lands with the undici wiring PR.formatSseTranscriptLineonly reflects event fields.What's left
Follow-up PR: wire
runSseTransportinto the undici request path (text/event-streamdetection, response-viewer streaming mode, Stop button, transcript save command, reconnect loop honoringclampRetryMs).Checks
npm run lint✅npm run typecheck✅npm run test:unit— 480 tests pass (was 458).