Skip to content

fix(tinyoffice): connect SSE directly to API, bypass Next.js rewrite#232

Open
crisdias wants to merge 1 commit intoTinyAGI:mainfrom
crisdias:fix/tinyoffice-sse-and-console-select
Open

fix(tinyoffice): connect SSE directly to API, bypass Next.js rewrite#232
crisdias wants to merge 1 commit intoTinyAGI:mainfrom
crisdias:fix/tinyoffice-sse-and-console-select

Conversation

@crisdias
Copy link

Summary

  • Next.js rewrites buffer SSE responses, causing the office view to always show "Disconnected"
  • Makes EventSource connect directly to the API server (port 3777) instead of going through the Next.js rewrite proxy
  • Supports NEXT_PUBLIC_SSE_URL env var for custom deployments

Fixes #231

Test plan

  • Open TinyOffice office view
  • Verify SSE connects directly to port 3777 (check DevTools Network tab)
  • Send a message and confirm status changes to "Live"
  • Speech bubbles appear on agent sprites

🤖 Generated with Claude Code

Next.js rewrites buffer SSE responses, causing the TinyOffice office
view to always show "Disconnected". This makes the EventSource connect
directly to the API server on port 3777 instead of going through the
Next.js rewrite proxy.

Fixes TinyAGI#231

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@greptile-apps
Copy link

greptile-apps bot commented Mar 16, 2026

Greptile Summary

This PR fixes a real-time SSE connectivity issue where the Next.js rewrite proxy was buffering EventSource responses, keeping the TinyOffice view perpetually in "Disconnected" state. The fix makes subscribeToEvents construct a URL that points directly to the API server on port 3777, bypassing the proxy entirely, and introduces a NEXT_PUBLIC_SSE_URL env var for custom deployments.

Key changes:

  • EventSource no longer uses the shared API_BASE constant; instead it builds its own URL from NEXT_PUBLIC_SSE_URL, or falls back to ${window.location.protocol}//${window.location.hostname}:3777

Issue found:

  • The fallback URL is built from window.location.hostname and hardcoded port 3777, which ignores NEXT_PUBLIC_API_URL. Any deployment that configured a custom API host via NEXT_PUBLIC_API_URL will have SSE silently connect to the wrong host. Adding process.env.NEXT_PUBLIC_API_URL as a middle step in the fallback chain (between NEXT_PUBLIC_SSE_URL and the window.location guess) would fix this regression with minimal code change.

Confidence Score: 3/5

  • Safe to merge for default local-dev setups, but introduces a regression for custom deployments that rely on NEXT_PUBLIC_API_URL.
  • The core fix (bypassing Next.js SSE buffering) is correct and the NEXT_PUBLIC_SSE_URL override exists for power users. However, dropping NEXT_PUBLIC_API_URL from the fallback chain silently breaks SSE for existing deployments that configured a non-default API host without needing to set an extra env var before this change. The fix is a one-liner, so the score reflects a real but easily-addressed bug rather than a fundamental design problem.
  • tinyoffice/src/lib/api.ts — the SSE URL fallback logic on lines 383-385

Important Files Changed

Filename Overview
tinyoffice/src/lib/api.ts SSE EventSource now bypasses the Next.js rewrite proxy by constructing a direct URL; the fallback ignores NEXT_PUBLIC_API_URL, which can silently break SSE in custom deployments where the API is on a different host.

Sequence Diagram

sequenceDiagram
    participant Browser
    participant NextJS as Next.js (port 3000)
    participant API as API Server (port 3777)

    Note over Browser,API: Before fix — SSE via Next.js rewrite (buffered)
    Browser->>NextJS: EventSource /api/events/stream
    NextJS-->>API: proxied request (buffers SSE)
    API-->>NextJS: SSE events (held in buffer)
    NextJS--xBrowser: events never flushed → "Disconnected"

    Note over Browser,API: After fix — SSE direct to API
    Browser->>API: EventSource http://hostname:3777/api/events/stream
    API-->>Browser: SSE events streamed in real-time → "Live"
Loading

Last reviewed commit: d9d018e

Comment on lines +383 to +385
const sseBase = typeof window !== "undefined"
? (process.env.NEXT_PUBLIC_SSE_URL ?? `${window.location.protocol}//${window.location.hostname}:3777`)
: "";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fallback URL ignores NEXT_PUBLIC_API_URL

The fallback constructs the SSE URL from window.location.hostname hardcoded to port 3777. However, API_BASE at the top of the file already respects NEXT_PUBLIC_API_URL, which users may have configured to point to an API server on a different hostname (e.g., http://my-api-server:3777). In that case, the new fallback will silently connect SSE to the wrong host (${window.location.hostname}:3777), breaking SSE for any deployment where the API is not co-located with the frontend server — even though all other API calls route correctly via API_BASE.

Using NEXT_PUBLIC_API_URL in the fallback chain (before the window.location guess) would preserve consistency and avoid surprises:

Suggested change
const sseBase = typeof window !== "undefined"
? (process.env.NEXT_PUBLIC_SSE_URL ?? `${window.location.protocol}//${window.location.hostname}:3777`)
: "";
const sseBase = typeof window !== "undefined"
? (process.env.NEXT_PUBLIC_SSE_URL ?? process.env.NEXT_PUBLIC_API_URL ?? `${window.location.protocol}//${window.location.hostname}:3777`)
: "";

This way:

  1. NEXT_PUBLIC_SSE_URL – explicit SSE override (current behaviour)
  2. NEXT_PUBLIC_API_URL – reuse the already-configured API host (fixes the regression)
  3. window.location.hostname:3777 – last-resort guess for plain local-dev setups

@crisdias
Copy link
Author

Note: this can also be solved by setting NEXT_PUBLIC_API_URL=http://<host>:3777 in .env.local and rebuilding, since the original code already used API_BASE for the EventSource. This PR is still useful as an auto-detection fallback for deployments without that env var set.

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.

TinyOffice SSE always shows Disconnected - Next.js rewrite buffers event stream

1 participant