Skip to content

Add Chat SDK state adapter and messenger admin UI#1570

Merged
threepointone merged 7 commits into
mainfrom
chat-sdk-messenger-admin-ui
May 21, 2026
Merged

Add Chat SDK state adapter and messenger admin UI#1570
threepointone merged 7 commits into
mainfrom
chat-sdk-messenger-admin-ui

Conversation

@threepointone
Copy link
Copy Markdown
Contributor

@threepointone threepointone commented May 21, 2026

Summary

This PR turns the chat-sdk-messenger example into a fuller, reviewable messenger app and extracts its reusable Chat SDK state layer into the agents package.

Chat SDK state adapter

  • Adds a new agents/chat-sdk package entrypoint with createChatSdkState(), ChatSdkStateAdapter, ChatSdkStateAgent, defaultThreadShard(), and defaultKeyShard().
  • Stores Chat SDK subscriptions, locks, queues, generic cache values, callback metadata, thread/channel state, persisted thread history, and transcript lists in Durable Object SQLite.
  • Uses Agents sub-agents for state shards, so a messenger ingress Agent can keep Chat SDK infrastructure state under the parent Agent instead of requiring a separate top-level Durable Object binding for each shard.
  • Defaults createChatSdkState() to the built-in ChatSdkStateAgent and defaults parent from getCurrentAgent() in normal Agent lifecycle/request contexts.
  • Adds chat as an optional peer dependency for agents and includes the new chat-sdk entry in the build and package exports.
  • Adds a detailed changeset for the new public API.

Messenger example

  • Updates examples/chat-sdk-messenger to consume agents/chat-sdk rather than carrying its own local state adapter implementation.
  • Adds a full admin UI with conversation/reply-job visibility, setup status, and useful controls for operating the Telegram bot example.
  • Expands the Worker-side admin directory helpers and reply-job inspection data so the UI can show recent conversations and managed reply jobs.
  • Keeps the example’s ingress Agent focused on Chat SDK webhook handling, menu/demo flows, and Think-backed AI replies.
  • Simplifies the example config by relying on the built agents package exports instead of local agents/chat-sdk aliases in Vite, Vitest, and TypeScript config.

Sub-agent configuration and test harness docs

  • Updates sub-agent documentation and examples to clarify that facet-only child classes should be exported but do not belong in production new_sqlite_classes unless also used as top-level Durable Objects.
  • Keeps facet classes out of new_sqlite_classes across the reviewed test/example configs.
  • Adds comments around test-only Durable Object bindings where @cloudflare/vitest-pool-workers currently needs facet classes listed as bindings for ctx.exports compatibility.
  • Documents the Vitest-only workaround separately from production Worker configuration.

Repro / notes

  • Updates the issue 1410 repro notes and WIP design notes to match the production-vs-test distinction for facet classes.
  • Leaves the minimal runtime repro outside this repo; this PR only updates in-repo docs, tests, examples, and package code.

Test plan

Ran the focused verification for the package and example:

  • npm run build -w agents
  • npm run typecheck -w @cloudflare/agents-chat-sdk-messenger
  • npm run test:workers -w agents -- src/tests/chat-sdk.test.ts
  • npm test -w @cloudflare/agents-chat-sdk-messenger

Notes:

  • The messenger example now resolves agents/chat-sdk through the built package export, so agents must be built before running the example tests locally. This matches the expected CI ordering.
  • npm run build -w agents still emits the existing rolldown-plugin-dts warning about enabling dts.eager, but the build exits successfully.

Made with Cursor


Open in Devin Review

threepointone and others added 4 commits May 20, 2026 17:58
Build out the chat-sdk-messenger example into a fuller admin-oriented app while keeping the core architecture centered on Chat SDK ingress, an Agents-backed state adapter, and Think-owned conversation intelligence.

The example now serves a Vite/React admin dashboard, exposes parent-owned admin APIs for setup/conversation/job inspection, gates browser access to known ConversationAgent subagents, and adds a one-click Telegram webhook setup flow for local quick tunnels and deployed Workers. This makes the example easier to run, inspect, and operate without turning the admin Think pane into an implicit messenger sender.

Harden the AI reply delivery path for Telegram by introducing a bounded visible stream bridge. Think still receives and persists the full model response, while Telegram gets a conservative first streaming message and any overflow is posted as provider-safe follow-up chunks. Expected Telegram final-edit no-op errors after the visible stream reaches the soft limit are treated as delivery completion instead of model interruption, while real first-stream failures and overflow chunk failures remain delivery errors so managed fibers are not incorrectly completed.

Update @cloudflare/think so programmatic chat() and clearMessages() calls broadcast message updates to connected clients. This keeps the admin Think pane live when messenger-originated turns arrive through RPC rather than WebSocket input.

Refresh the example docs and TODOs around quick tunnels, admin dashboard behavior, long Telegram replies, managed reply job inspection, and future SDK extraction candidates. Standardize remaining repo docs and sample env files on .env/.env.example while keeping local secret files ignored.

Add focused coverage for the admin APIs, subagent gating, Think broadcast behavior, bounded streaming, Telegram chunk splitting, and delivery-error classification.

Co-authored-by: Cursor <cursoragent@cursor.com>
Tighten the chat-sdk-messenger local development flow around Quick Tunnels by making the Vite plugin start a tunnel by default, removing the separate tunnel script, and updating the setup UI to avoid invalid Telegram webhook attempts from localhost. The admin dashboard now surfaces a prominent localhost warning that points users to the printed trycloudflare.com URL while still allowing local-only inspection when needed.

Keep Telegram webhook setup safer by rejecting non-HTTPS setup requests before calling the Telegram API. This prevents the confusing Telegram error where localhost-derived webhook URLs are rejected as non-HTTPS, and gives the example a clearer failure mode when opened from the wrong origin.

Improve the Think admin pane as a debugging surface. It now renders all UI message parts instead of collapsing messages to text only: text remains inline, while reasoning traces, tool calls/results, and unknown message parts appear as collapsible JSON sections. Telegram delivery remains text-only, so internal reasoning/tool data stays confined to the admin UI.

Update Think so RPC-driven chat() turns broadcast live chat response chunks to connected WebSocket clients. Messenger-originated turns still stream through the RPC callback to Telegram, but connected admin clients now receive the same live cf_agent_use_chat_response frames instead of seeing the assistant message only after final persistence.

Add regression coverage for HTTPS-only webhook setup and RPC chat stream broadcasting to connected Think clients.

Co-authored-by: Cursor <cursoragent@cursor.com>
Split the chat-sdk-messenger example along the boundaries we expect to matter for a future SDK extraction. Keep ChatIngressAgent focused on orchestration while moving provider policy, admin directory mapping, and AI reply delivery helpers into smaller modules.

The Telegram provider module now owns webhook setup, HTTPS validation, message delivery limits, long-message chunking, final-edit no-op classification, and Telegram-specific state key sharding. This removes Telegram-specific dedupe key handling from the generic Agents-backed Chat SDK state adapter.

The intelligence delivery module now owns managed AI reply fiber names, snapshots, recovery mode, and failure mode policy. The admin directory module owns conversation/job DTOs and row-to-view mapping helpers. These files make the example a better staging ground for deciding what eventually belongs in agents/src/chat-sdk without prematurely extracting Telegram or admin UI product code.

Replace the ChatStateAgent recurring cleanup interval with lazy one-shot cleanup scheduling. Expiring writes now schedule the next cleanup only when needed, update the scheduled cleanup when an earlier expiry appears, and reschedule after cleanup only if expiring rows remain. Cleanup metadata tracks the next expiry and schedule id so state shards without expiring records do not pay for a forever schedule, which is a better shape for SDK-owned state infrastructure.

Update README/TODO notes to document the module layout and extraction candidates, and adjust tests to cover provider-owned Telegram key sharding instead of baking Telegram behavior into the generic state adapter.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 21, 2026

🦋 Changeset detected

Latest commit: 7c9d8a5

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/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

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 2 potential issues.

View 6 additional findings in Devin Review.

Open in Devin Review

Comment thread examples/chat-sdk-messenger/src/intelligence/delivery.ts
Comment thread examples/chat-sdk-messenger/index.html
Include a favicon for the chat-sdk-messenger example by adding public/favicon.ico and adding a <link rel="icon" href="/favicon.ico" /> in the head of index.html so browsers display the site icon.
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 21, 2026

Open in StackBlitz

agents

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

@cloudflare/ai-chat

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

@cloudflare/codemode

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

hono-agents

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

@cloudflare/shell

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

@cloudflare/think

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

@cloudflare/voice

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

@cloudflare/worker-bundler

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

commit: 7c9d8a5

threepointone and others added 2 commits May 21, 2026 09:41
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@threepointone threepointone merged commit 4f14b9c into main May 21, 2026
4 checks passed
@threepointone threepointone deleted the chat-sdk-messenger-admin-ui branch May 21, 2026 09:29
@github-actions github-actions Bot mentioned this pull request May 21, 2026
threepointone added a commit that referenced this pull request May 21, 2026
* Expand chat SDK messenger admin and delivery flows

Build out the chat-sdk-messenger example into a fuller admin-oriented app while keeping the core architecture centered on Chat SDK ingress, an Agents-backed state adapter, and Think-owned conversation intelligence.

The example now serves a Vite/React admin dashboard, exposes parent-owned admin APIs for setup/conversation/job inspection, gates browser access to known ConversationAgent subagents, and adds a one-click Telegram webhook setup flow for local quick tunnels and deployed Workers. This makes the example easier to run, inspect, and operate without turning the admin Think pane into an implicit messenger sender.

Harden the AI reply delivery path for Telegram by introducing a bounded visible stream bridge. Think still receives and persists the full model response, while Telegram gets a conservative first streaming message and any overflow is posted as provider-safe follow-up chunks. Expected Telegram final-edit no-op errors after the visible stream reaches the soft limit are treated as delivery completion instead of model interruption, while real first-stream failures and overflow chunk failures remain delivery errors so managed fibers are not incorrectly completed.

Update @cloudflare/think so programmatic chat() and clearMessages() calls broadcast message updates to connected clients. This keeps the admin Think pane live when messenger-originated turns arrive through RPC rather than WebSocket input.

Refresh the example docs and TODOs around quick tunnels, admin dashboard behavior, long Telegram replies, managed reply job inspection, and future SDK extraction candidates. Standardize remaining repo docs and sample env files on .env/.env.example while keeping local secret files ignored.

Add focused coverage for the admin APIs, subagent gating, Think broadcast behavior, bounded streaming, Telegram chunk splitting, and delivery-error classification.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Polish messenger admin streaming and tunnel workflow

Tighten the chat-sdk-messenger local development flow around Quick Tunnels by making the Vite plugin start a tunnel by default, removing the separate tunnel script, and updating the setup UI to avoid invalid Telegram webhook attempts from localhost. The admin dashboard now surfaces a prominent localhost warning that points users to the printed trycloudflare.com URL while still allowing local-only inspection when needed.

Keep Telegram webhook setup safer by rejecting non-HTTPS setup requests before calling the Telegram API. This prevents the confusing Telegram error where localhost-derived webhook URLs are rejected as non-HTTPS, and gives the example a clearer failure mode when opened from the wrong origin.

Improve the Think admin pane as a debugging surface. It now renders all UI message parts instead of collapsing messages to text only: text remains inline, while reasoning traces, tool calls/results, and unknown message parts appear as collapsible JSON sections. Telegram delivery remains text-only, so internal reasoning/tool data stays confined to the admin UI.

Update Think so RPC-driven chat() turns broadcast live chat response chunks to connected WebSocket clients. Messenger-originated turns still stream through the RPC callback to Telegram, but connected admin clients now receive the same live cf_agent_use_chat_response frames instead of seeing the assistant message only after final persistence.

Add regression coverage for HTTPS-only webhook setup and RPC chat stream broadcasting to connected Think clients.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Modularize chat SDK messenger example boundaries

Split the chat-sdk-messenger example along the boundaries we expect to matter for a future SDK extraction. Keep ChatIngressAgent focused on orchestration while moving provider policy, admin directory mapping, and AI reply delivery helpers into smaller modules.

The Telegram provider module now owns webhook setup, HTTPS validation, message delivery limits, long-message chunking, final-edit no-op classification, and Telegram-specific state key sharding. This removes Telegram-specific dedupe key handling from the generic Agents-backed Chat SDK state adapter.

The intelligence delivery module now owns managed AI reply fiber names, snapshots, recovery mode, and failure mode policy. The admin directory module owns conversation/job DTOs and row-to-view mapping helpers. These files make the example a better staging ground for deciding what eventually belongs in agents/src/chat-sdk without prematurely extracting Telegram or admin UI product code.

Replace the ChatStateAgent recurring cleanup interval with lazy one-shot cleanup scheduling. Expiring writes now schedule the next cleanup only when needed, update the scheduled cleanup when an earlier expiry appears, and reschedule after cleanup only if expiring rows remain. Cleanup metadata tracks the next expiry and schedule id so state shards without expiring records do not pay for a forever schedule, which is a better shape for SDK-owned state infrastructure.

Update README/TODO notes to document the module layout and extraction candidates, and adjust tests to cover provider-owned Telegram key sharding instead of baking Telegram behavior into the generic state adapter.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add Chat SDK state adapter

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add favicon to chat-sdk-messenger example

Include a favicon for the chat-sdk-messenger example by adding public/favicon.ico and adding a <link rel="icon" href="/favicon.ico" /> in the head of index.html so browsers display the site icon.

* Handle post-limit model failures

Co-authored-by: Cursor <cursoragent@cursor.com>

* Bind conversation facet in messenger tests

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.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