Skip to content

feat: ship chats.streamChat() with SSE support#7

Merged
rodnnnney merged 2 commits into
mainfrom
rod/stream-chat-sse
Jul 21, 2026
Merged

feat: ship chats.streamChat() with SSE support#7
rodnnnney merged 2 commits into
mainfrom
rod/stream-chat-sse

Conversation

@rodnnnney

@rodnnnney rodnnnney commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

streamChat was documented on docs.textql.com but missing from the generated SDK. Root cause: the registry spec labels the stream response application/x-ndjson, and Speakeasy gates JSONL/NDJSON stream generation (jsonlResponses) behind its enterprise tier — so codegen silently skipped the operation. SSE generation works on the current tier.

The endpoint is served by demo2's platform v2 SSE handler (TextQLLabs/demo2#13014), which streams {result: Cell} / {error: Status} envelopes as data: frames.

Changes

  • Overlay (.speakeasy/speakeasy-modifications-overlay.yaml): normalizes the stream operation to the SSE envelope contract — 200 is text/event-stream with typed data.result: Cell / data.error: Status, errors are application/json. Written to be robust against any registry snapshot state; becomes a harmless no-op once demo2 publishes the SSE spec at the source.
  • Regenerated SDK: ships textql.chats.streamChat() returning EventStream<StreamChatEvent>. Version 1.1.1.

Usage

const result = await textql.chats.streamChat({ chatId, body: { latestCompleteCellId } });
if (result instanceof EventStream) {
  for await (const event of result) {
    if (event.data.result) { /* next cell */ }
    if (event.data.error)  { /* stream ended with an error */ }
  }
}

Cross-repo context & merge order

This PR can merge independently, but the generated method only works once demo2#13014 deploys (the endpoint doesn't exist in production until then). On merge, the Publish workflow releases to npm and auto-opens the docs-sync PR in demo2.

Follow-ups

  • Drop the overlay normalization actions once a prod deploy republishes the spec (they'll be no-ops).
  • examples/chat-demo still uses a raw-fetch NDJSON parser; switch it to chats.streamChat() once this is on npm.

The registry spec declares the stream endpoint as application/x-ndjson (the
grpc-gateway generator shape), which Speakeasy silently skips during codegen -
the method was documented but never generated. The server actually emits
Server-Sent Events (data: {...} frames, Content-Type: text/event-stream).

Add overlay actions rewriting the operation to the served contract (200 ->
text/event-stream with the discriminated stream-event payload; errors ->
application/json) and regenerate. streamChat() now returns
EventStream<StreamChatEvent>.

Once TextQLLabs/demo2#13014 ships through a prod deploy the registry spec is
SSE at the source and these overlay actions become redundant no-ops.
@socket-security

Copy link
Copy Markdown

@socket-security

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm @emnapi/runtime is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: examples/chat-demo/package-lock.jsonnpm/vite@8.1.5npm/@emnapi/runtime@1.11.1

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@emnapi/runtime@1.11.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@rodnnnney
rodnnnney merged commit f02a7bf into main Jul 21, 2026
7 checks passed
rodnnnney added a commit that referenced this pull request Jul 22, 2026
* bear bones

* feat: ship chats.streamChat() with SSE support

The registry spec declares the stream endpoint as application/x-ndjson (the
grpc-gateway generator shape), which Speakeasy silently skips during codegen -
the method was documented but never generated. The server actually emits
Server-Sent Events (data: {...} frames, Content-Type: text/event-stream).

Add overlay actions rewriting the operation to the served contract (200 ->
text/event-stream with the discriminated stream-event payload; errors ->
application/json) and regenerate. streamChat() now returns
EventStream<StreamChatEvent>.

Once TextQLLabs/demo2#13014 ships through a prod deploy the registry spec is
SSE at the source and these overlay actions become redundant no-ops.

---------

Co-authored-by: textql-sdk-dispatch-bot[bot] <307206229+textql-sdk-dispatch-bot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant