Skip to content

fix(channels): Web client resume and TUI Access refresh - #2493

Draft
cjol wants to merge 6 commits into
mainfrom
fix/web-client-resume
Draft

cjol wants to merge 6 commits into
mainfrom
fix/web-client-resume

Conversation

@cjol

@cjol cjol commented Oct 5, 2026

Copy link
Copy Markdown
Member

This PR fixes four follow-ups from the Channels stack: two Web client reconnect gaps, an AI SDK transport stream that never finishes, and a TUI stranded by an expired Cloudflare Access token. Stacked on #2479.

Why

  • After a reconnect, WebChannelClient dropped any response whose turn was no longer running. A response can keep streaming after its turn settles, so listeners such as the AI SDK transport lost its remaining chunks and its end.
  • The snapshot after a reconnect updated the client's turns without telling activity listeners. A turn restarted under a new responseId while offline was invisible to the transport, which kept waiting on the old response.
  • The transport ignored a settled status that arrived while it was sending tool results, so a continuation that settled before answer() returned left the stream open.
  • agents tui fetched the Access token from feat(channels): agents tui logs in to Cloudflare Access by itself #2462 once at startup. Once it expired, every reconnect sent the stale token. A WebSocket constructor is synchronous, so a fresh token must be read synchronously at upgrade time: the TUI now runs cloudflared access token (non-interactive, reading cloudflared's cache) for each reconnect. Refreshing in the background on close was the alternative, but it races the 1 s reconnect timer.

Public API Surface

Symbol Kind Notes
WebChannelClient.onActivity behaviour Also reports each turn in a reconnect snapshot as a turn activity
sendHeadersOnUpgrade TUI internal Accepts a header function, read for each upgrade
accessHeaders TUI internal Resolves to a header function instead of a header record

Code Changes

  • web/client.ts: #resume resubscribes to every unended response from where it left off, and hides the ones whose turn moved on rather than deleting them. The snapshot handler updates state first, then emits its turns, so listeners read the new transcript.
  • web/ai-sdk.ts: answer() calls settle() once it finishes sending.
  • web/tui/access.ts: the returned function uses the startup token for the first upgrade and asks cloudflared again for later ones, keeping the last token if that fails. It never opens a browser login after startup; if the Access session itself expired, the upgrade is rejected and restarting the TUI logs in again.
  • web/tui/socket.ts, main.ts, app.ts: pass the header function through to the patched WebSocket.

cjol added 6 commits October 5, 2026 09:43
… pending reconnects

send() and listConversations() reject once the client is closed, rather
than leaving their promises pending. follow() and close() clear a reconnect
scheduled after a dropped socket, so it can no longer replace the followed
socket or reconnect a closed client.
Resubscribe to every unended response after a reconnect, not only those of
running turns, and report snapshot turns to activity listeners so a turn
restarted under a new response while offline is followed.
@changeset-bot

changeset-bot Bot commented Oct 5, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 456af28

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
agents Patch
@cloudflare/agent-think Patch

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

@agent-think

agent-think Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

✅ agents import sizes: no significant changes (ad5275b1 → 456af28f, workflow run)

Base automatically changed from fix/web-client-closed-reconnect to main October 5, 2026 16:30
@pkg-pr-new

pkg-pr-new Bot commented Oct 5, 2026

Copy link
Copy Markdown

Open in StackBlitz

agents

npm i https://pkg.pr.new/agents@2493

@cloudflare/ai-chat

npm i https://pkg.pr.new/@cloudflare/ai-chat@2493

@cloudflare/codemode

npm i https://pkg.pr.new/@cloudflare/codemode@2493

hono-agents

npm i https://pkg.pr.new/hono-agents@2493

@cloudflare/shell

npm i https://pkg.pr.new/@cloudflare/shell@2493

@cloudflare/think

npm i https://pkg.pr.new/@cloudflare/think@2493

@cloudflare/voice

npm i https://pkg.pr.new/@cloudflare/voice@2493

@cloudflare/worker-bundler

npm i https://pkg.pr.new/@cloudflare/worker-bundler@2493

commit: 456af28

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