feat(examples): Cap'n Web 0.10 group chat + shared Claude todo list#962
Conversation
Upgrade the group chat demo to Cap'n Web 0.10 bidirectional push, modern TanStack Start/Nitro setup, and fix browser RPC by calling stubs via ref instead of React state. Co-authored-by: Cursor <cursoragent@cursor.com>
Give ts-group-chat an in-memory todo list users and Claude can manage, with passive @claude mentions vs active chat watching, plus clean persona switching. Co-authored-by: Cursor <cursoragent@cursor.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (13)
🚧 Files skipped from review as they are similar to previous changes (13)
📝 WalkthroughWalkthroughThe group chat example is migrated from polling to typed Cap’n Web push notifications, adds shared todos and Claude modes, introduces typed server/client contracts, updates Claude queue processing, and revises the UI, documentation, scripts, and Vite runtime configuration. ChangesGroup chat RPC and Claude integration
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Browser
participant ChatServer
participant ChatNotifier
participant ClaudeService
Browser->>ChatServer: joinChat(username)
ChatServer->>ChatNotifier: push room state
Browser->>ChatServer: sendMessage(message)
ChatServer->>ChatNotifier: push chat event
ChatServer->>ClaudeService: enqueue request
ClaudeService->>ChatNotifier: push Claude status and response
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Co-authored-by: Cursor <cursoragent@cursor.com>
🚀 Changeset Version PreviewNo changeset entries found. Merging this PR will not cause a version bump for any packages. |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
View your CI Pipeline Execution ↗ for commit 0e3913f
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-code-mode
@tanstack/ai-code-mode-skills
@tanstack/ai-codex
@tanstack/ai-devtools-core
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-mcp
@tanstack/ai-mistral
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-sandbox
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-vercel
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-utils
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
commit: |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
examples/ts-group-chat/chat-server/chat-api.ts (1)
21-86: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winFix widespread ESLint errors (method-signature-style, array-type).
Static analysis flags method-signature-style errors on nearly every
ChatApi/ChatNotifierApimember (Lines 72, 76-85) and array-type errors onstring[]/TodoItem[]/ChatMessage[]fields (Lines 27, 28, 41, 42, 46, 52-54, 65). Since these are configured as ESLint errors, they'll likely fail lint/CI for this shared contracts file.🔧 Example fix pattern
export interface ChatApi { - joinChat(username: string): JoinResult - leaveChat(): { message: string } + joinChat: (username: string) => JoinResult + leaveChat: () => { message: string } ... }Apply the same
Array<T>/ function-property conversion to the other flagged lines.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/ts-group-chat/chat-server/chat-api.ts` around lines 21 - 86, Update the shared interfaces in ChatNotification, ChatRoomState, ChatState, JoinResult, ClaudeQueueStatus, and ChatApi to satisfy the configured array-type and method-signature-style rules: replace flagged T[] declarations with Array<T> and express interface methods such as notify, joinChat, leaveChat, and the remaining ChatApi members as function properties. Preserve all existing types, parameters, and return contracts.Source: Linters/SAST tools
examples/ts-group-chat/chat-server/capnweb-rpc.ts (1)
334-351: 🚀 Performance & Scalability | 🔵 TrivialActive mode invokes an LLM stream for every message.
In
activemode, every non-Claude message enqueues a Claude request and runs a fullstreamResponsejust to decide whether to reply (oftenNO_REPLY). For a busy room this multiplies latency and Anthropic API cost per message. Consider a cheap pre-filter (e.g. keyword/intent gate before enqueue) or debouncing to avoid a model call on clearly-unrelated chatter.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/ts-group-chat/chat-server/capnweb-rpc.ts` around lines 334 - 351, Add a low-cost relevance gate to the active-mode path before calling enqueueClaudeRequest, so clearly unrelated messages are sent without starting an LLM stream while mentions retain the existing behavior. Update the logic around shouldAskClaude and enqueueClaudeRequest, preserving direct Claude mentions and the current chat response messages.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/ts-group-chat/chat-server/todo-logic.ts`:
- Around line 4-13: Fix the ESLint violations across the listed sites: use
Array<TodoItem> and Array<string> in todo-logic.ts and capnweb-rpc.ts; remove
the unnecessary optional chaining in chat-notifier.ts; reorder imports in
vite-plugin.ts; sort and hoist the RefObject type import in useChatMessages.ts
and useClaude.ts; remove the redundant message type assertions in both hooks.
Apply these changes at examples/ts-group-chat/chat-server/todo-logic.ts lines
4-13, examples/ts-group-chat/chat-server/capnweb-rpc.ts lines 158 and 269,
examples/ts-group-chat/src/lib/chat-notifier.ts line 19,
examples/ts-group-chat/chat-server/vite-plugin.ts line 2,
examples/ts-group-chat/src/hooks/useChatMessages.ts lines 1 and 26, and
examples/ts-group-chat/src/hooks/useClaude.ts lines 1 and 77.
---
Nitpick comments:
In `@examples/ts-group-chat/chat-server/capnweb-rpc.ts`:
- Around line 334-351: Add a low-cost relevance gate to the active-mode path
before calling enqueueClaudeRequest, so clearly unrelated messages are sent
without starting an LLM stream while mentions retain the existing behavior.
Update the logic around shouldAskClaude and enqueueClaudeRequest, preserving
direct Claude mentions and the current chat response messages.
In `@examples/ts-group-chat/chat-server/chat-api.ts`:
- Around line 21-86: Update the shared interfaces in ChatNotification,
ChatRoomState, ChatState, JoinResult, ClaudeQueueStatus, and ChatApi to satisfy
the configured array-type and method-signature-style rules: replace flagged T[]
declarations with Array<T> and express interface methods such as notify,
joinChat, leaveChat, and the remaining ChatApi members as function properties.
Preserve all existing types, parameters, and return contracts.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: ebe86302-1b94-4e32-9a0e-ca7625af50cb
⛔ Files ignored due to path filters (2)
examples/ts-group-chat/pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (22)
examples/ts-group-chat/.env.exampleexamples/ts-group-chat/README.mdexamples/ts-group-chat/chat-server/capnweb-rpc.tsexamples/ts-group-chat/chat-server/chat-api.tsexamples/ts-group-chat/chat-server/chat-logic.tsexamples/ts-group-chat/chat-server/claude-service.tsexamples/ts-group-chat/chat-server/index.tsexamples/ts-group-chat/chat-server/todo-logic.tsexamples/ts-group-chat/chat-server/vite-plugin.tsexamples/ts-group-chat/package.jsonexamples/ts-group-chat/src/components/ChatInterface.tsxexamples/ts-group-chat/src/components/OnlineUsers.tsxexamples/ts-group-chat/src/components/TodoList.tsxexamples/ts-group-chat/src/components/UsernameInput.tsxexamples/ts-group-chat/src/hooks/useChatConnection.tsexamples/ts-group-chat/src/hooks/useChatMessages.tsexamples/ts-group-chat/src/hooks/useClaude.tsexamples/ts-group-chat/src/hooks/useTodos.tsexamples/ts-group-chat/src/lib/chat-notifier.tsexamples/ts-group-chat/src/routes/__root.tsxexamples/ts-group-chat/src/routes/index.tsxexamples/ts-group-chat/vite.config.ts
💤 Files with no reviewable changes (1)
- examples/ts-group-chat/src/components/UsernameInput.tsx
Align array/method signature styles and remove always-false conditionals so the Cap'n Web example matches repo lint conventions. Co-authored-by: Cursor <cursoragent@cursor.com>
The ts-group-chat example (added in #962) kept nitro 3.0.1-alpha.2 while all other examples use 3.0.260610-beta, causing sherif's multiple-dependency-versions check to fail in CI. Bump it to match.
* chore: migrate toolchain to oxc + TypeScript 7 + vite 8 Replace ESLint/Prettier with the oxc toolchain, upgrade the type checker to TypeScript 7 (native Go compiler), and move the build stack to vite 8 (Rolldown). Framework tooling that can't run TS7/vite8 yet is pinned back via the @typescript/typescript6 shim and per-package vite pins. Formatter - Prettier -> oxfmt (.oxfmtrc.json migrated from prettier config). oxfmt formats .svelte natively, so prettier + prettier-plugin-svelte are removed. `format` -> `oxfmt .`. Linter - ESLint -> oxlint, untyped + type-aware (oxlint-tsgolint). The custom `as unknown as` ban is ported via oxlint-plugin-eslint; unused-imports and @Stylistic run through oxlint's JS-plugin layer. ESLint and @tanstack/eslint-config removed. `test:eslint` -> `test:oxlint`. TypeScript 7 - Root typescript -> 7.0.2 (tsc is the native Go compiler). types now defaults to [], so tsconfig.base sets `"types": ["node"]`. - JS-Compiler-API consumers use the @typescript/typescript6 (6.0.2) shim: vite-plugin-dts (built-in fallback), @sveltejs/package, svelte-check, vue-tsc, kiira, knip (packageExtensions); @analogjs/vite-plugin-angular pinned to 5.9.3. Framework packages (angular/vue/solid/svelte) stay on 5.9.3. - Fixes: ai-acp Uint8Array->BufferSource (TS 5.7 typed-array generics); ai-react/ai-preact rootDir "../.." (TS7 rootDir default + cross-package test fixtures); one ai-client @ts-expect-error reposition. Build (vite 8 / Rolldown) - vite -> 8.1.4, vitest -> 4.1.10. @tanstack/vite-config bumped to 0.5.2 and patched: outDir->outDirs (vite-plugin-dts 5.x) and an added rollupOptions.preserveModules mirror so multi-entry output holds on both vite 7 and 8. - ai-solid-ui stays on vite 7: Solid JSX has no vite 8/Rolldown support yet (solidjs/solid-start#2075). Also: nx 22->23, knip 5->6. sherif ignores typescript+vite (intentional multi-version). CLAUDE.md updated for the new commands/tooling. * ci: apply automated fixes * fix(examples): pin example apps to vite 7 The TanStack Start example apps (Start + nitro + framework plugins) don't build under vite 8 / Rolldown yet — ts-solid-chat and ts-react-chat fail in the Start server-fn compiler / nitro server build. Keep the library packages on vite 8 and hold the dev-only example apps on vite 7 until Start/nitro support vite 8. * fix: unblock example builds + ai-mcp CI timeout under the new toolchain - ai/realtime: drop the literal `createServerFn()` from the JSDoc example. The vite 8/Rolldown build preserves JSDoc in the emitted .js (vite 7 stripped it), and TanStack Start's server-fn plugin string-matches `createServerFn`, so it tried to compile @tanstack/ai's realtime dist and resolve the framework runtime (@tanstack/solid-start) from ai's package, failing ts-solid-chat's build. The example still shows realtimeToken usage. - ai-mcp: raise vitest testTimeout to 30s. The client/server handshake tests absorb ~20s+ cold module-import cost on CI, tipping the first test over the 5s default (flaky timeout). * chore(examples): upgrade nitro to latest - nitro (v3): sandbox-web + ts-react-media 3.0.1-alpha.2 -> 3.0.260610-beta; ts-react-search pinned off the floating `latest` tag to the same version. Consolidates to a single nitro v3 in the lockfile (drops the stale alpha). - @tanstack/nitro-v2-vite-plugin: ^1.154.7 -> ^1.155.0 across the Start examples + testing/panel + testing/e2e. Verified: all six examples build and testing/panel + testing/e2e typecheck. Examples stay on vite 7 for now (Start/nitro vite 8 support is a separate follow-up). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(examples): move React Start examples to nitro 3 + vite 8 Un-pins the React Start examples from vite 7 and standardizes them on nitro 3 (`nitro/vite`), dropping @tanstack/nitro-v2-vite-plugin. - sandbox-web, ts-react-media, ts-react-search: already nitro 3 — flipped vite ^7.3.3 -> ^8.1.4. - ts-react-chat, ts-code-mode-web: migrated nitroV2Plugin() -> nitro(), vite -> ^8.1.4. nitro 3's server build (rolldown) externalizes node_modules but must resolve each external at build time. Under pnpm, server-only deps reached only via a workspace adapter's nested store dir don't resolve from the example, so the native/wasm/binary ones are declared as direct deps: - ts-react-chat: @anthropic-ai/sdk, @elevenlabs/elevenlabs-js, dockerode - ts-code-mode-web: isolated-vm, quickjs-emscripten(+core) and the four @jitl/quickjs-wasmfile-* variants The pure-JS server deps the old nitro-v2 externals list named (google-auth-library, gaxios, jws, gcp-metadata, google-logging-utils, ws, node-fetch, openai) are now bundled normally and dropped from ssr.external. ts-solid-chat stays on vite 7 (Solid JSX has no vite 8/Rolldown support yet); its nitroV2Plugin was already disabled. Verified: all five migrated examples build and test:types clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(examples): drop stray route-dir test in ts-react-chat `src/routes/api.sandbox-triage.test.ts` sat under the router's route directory, so TanStack Router picked it up as a route candidate and warned it exports no Route. Delete it; equivalent coverage already lives at `src/sandbox-triage.test.ts`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(examples): use vite 8 native tsconfig paths, drop vite-tsconfig-paths Vite 8 resolves tsconfig `paths` natively via `resolve.tsconfigPaths`, so the `vite-tsconfig-paths` plugin is redundant (and now emits a deprecation warning). Replace `viteTsConfigPaths({ projects: ['./tsconfig.json'] })` with `resolve: { tsconfigPaths: true }` and remove the dep in the six vite-8 projects (ts-react-chat, ts-code-mode-web, ts-react-media, ts-react-search, testing/panel, testing/e2e). ts-solid-chat and ts-group-chat stay on vite 7, so they keep the plugin. Verified: all six build and test:types clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: apply automated fixes * feat(examples): move ts-solid-chat to vite 8 Both blockers the vite-7 pin cited are resolved upstream: vitejs/vite#22057 (Rolldown JSX scanner) and solidjs/solid-start#2075 (vite 8 compat) are now closed. The example builds on vite 8 because it applies `vite-plugin-solid` itself, which handles Solid's JSX transform under Rolldown. - vite ^7.3.3 -> ^8.1.4; also switch to vite 8 native `resolve.tsconfigPaths` and drop the vite-tsconfig-paths plugin (merged into the existing resolve). - @tanstack/ai-solid-ui stays on vite 7: its @tanstack/vite-config library build runs no Solid JSX transform, and Rolldown's parser rejects raw JSX ("JSX syntax is disabled") where vite 7's esbuild parsed it implicitly. That needs a build-pipeline fix (or vite-plugin-solid@3 / Solid 2), not a version bump. Verified: ts-solid-chat builds and test:types clean on vite 8. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(ai-solid-ui): build on vite 8 via vite-plugin-solid ai-solid-ui was the last Solid holdout on vite 7. Its @tanstack/vite-config build had no Solid JSX transform — vite 7's esbuild parsed the `.tsx` (jsxImportSource: solid-js) implicitly, but vite 8's Rolldown parser rejects raw JSX ("JSX syntax is disabled"). Fix it in the package's own config (not the shared vite-config patch, which is framework-agnostic): add vite-plugin-solid, mirroring what solid-ai-devtools already does on vite 8. - vite ^7.3.3 -> ^8.1.4; add vite-plugin-solid + `plugins: [solid()]`. - Test env node -> happy-dom: once solid() transforms the components into the test graph they import solid-js/web (references `document`), so the suite needs a DOM. Adds happy-dom devDep. Verified: build, test:types, test:lib (7/7), and publint all pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: align dep ranges to satisfy sherif (happy-dom, dockerode, isolated-vm) The vite-8/nitro-3 work pinned three newly-direct deps to their resolved versions, which mismatched the ranges the workspace already declares and tripped sherif's multiple-dependency-versions check: - happy-dom ^20.0.11 -> ^20.0.10 (matches root) - dockerode ^4.0.12 -> ^4.0.2 (matches @tanstack/ai-sandbox-docker) - isolated-vm ^6.1.2 -> ^6.0.2 (matches @tanstack/ai-isolate-node) Each existing range still resolves to the same installed version, so this is a declared-range alignment only. sherif passes; affected builds + tests unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: apply automated fixes * fix: align ts-group-chat nitro version to fix sherif The ts-group-chat example (added in #962) kept nitro 3.0.1-alpha.2 while all other examples use 3.0.260610-beta, causing sherif's multiple-dependency-versions check to fail in CI. Bump it to match. * fix: resolve oxlint/knip failures from main merge under new toolchain The merge brought main's resumable-streams work into the oxc/oxlint/knip6 toolchain, surfacing three checks that were green on main's eslint/knip5 setup: - ai/stream-to-response.ts: oxlint no-control-regex flagged /[\0\r\n]/; replace with String.includes checks (same behavior, no control-char regex). - ai-durable-stream: still had eslint lint scripts (added on main); migrate to oxlint (test:oxlint + lint:fix) and vitest run, matching every other package. - ai-groq/schema-converter.ts: knip6 flagged a dead transformNullsToUndefined re-export (imported only to re-export, consumed nowhere); remove it. * chore: consume @tanstack/vite-config via pkg.pr.new, drop patch + dts override TanStack/config#403 fixes vite-config for vite-plugin-dts 5 / Vite 8 upstream. Point @tanstack/vite-config at that PR's pkg.pr.new build (SHA-pinned, integrity-locked) and remove the local workarounds it obviates: - delete patches/@tanstack__vite-config@0.5.2.patch + its patchedDependencies entry - drop the vite-plugin-dts: 5.0.3 override (the fixed config pins dts 5 itself, and it's ai's only path to vite-plugin-dts) - type durableStream's read(signal?: AbortSignal) — the fixed config's stricter dts pass surfaced a latent implicit-any - CLAUDE.md: correct the TS6-shim tool list (dts is native-TS7 now) Revert to the released @tanstack/vite-config once #403 lands (tracked in #975). * chore: use @tanstack/vite-config@0.6.0 (released dts-5/Vite-8 fix) TanStack/config#403 shipped in 0.6.0. Swap the pkg.pr.new preview for the real release. Added to minimumReleaseAgeExclude since 0.6.0 is fresh (<24h) and the build-time devDep is needed now. * chore: use kiira@0.6.0 (native TS7 engine), drop kiira TS6 shim kiira 0.6.0 type-checks doc snippets with the project's native TypeScript 7 compiler (engine: auto) and fixes the pnpm external-package install (ERR_PNPM_IGNORED_BUILDS false failure). It no longer needs the @typescript/typescript6 shim, so remove the kiira packageExtension. Refresh the minimumReleaseAge excludes to 0.6.0 (freshly published). --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
examples/ts-group-chatfor Cap'n Web 0.10 bidirectional push RPC (RpcStub+ clientChatNotifieraslocalMain, Vite WebSocket upgrade, typedChatApi)listTodos/addTodo/removeTodo)@Claude; active watches chat for todo intent/questions (silentNO_REPLYwhen unrelated, without sticky “responding” UI)pnpm-lock.yaml, move tovite.config.ts) and refresh the READMETest plan
cd examples/ts-group-chat && pnpm test:typescd examples/ts-group-chat && cp .env.example .env(setANTHROPIC_API_KEY) &&pnpm dev@Claude add milk to the todosand@Claude what's on the list?@Claude; ask a follow-up like approximate cost; unrelated chit-chat should not post a Claude replyMade with Cursor
Summary by CodeRabbit