feat(packages): shared ModelSwitcher + credits modal, fetchLLM - #893
Merged
Conversation
- react-ui: ModelSwitcher promoted to /blocks + main entry; theme-aware {light,dark} logo API (ModelLogo); v0.13.3
- react-headless: fetchLLM gains buildBody for custom request bodies (default AG-UI shape unchanged)
- devtools: OpenUICreditsModal (429 -> credits notice via observability) + CreditsModal; dev-only widget
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR
Wraps fetchLLM in a render-tolerant hook — consumers get a stable ChatLLM from one call, no useState(() => fetchLLM(...)) or ref boilerplate. Options are read fresh per send, so a buildBody closing over current state stays live without extra refs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR
Drops the custom pill markup + SCSS; the trigger keeps its compact dot (Tag has no icon-only mode). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR
…abhin/pkg-updates
… blocks scss - thread.scss: title self-hides when :empty; actions flex to fill (space-between) — replaces per-app overrides - modelSwitcher.scss now @forward'ed from components/index.scss like every other component; drop the TS scss import, scss.d.ts, and the cp-css .mjs/.cjs rewrite hack Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR
…esponses Adds getResponseErrorMessage (parses error.message / error / message from the body, falls back to status text); the chat store now throws that instead of a generic 'Request failed: <status>'. Restores the behavior the template's deleted chat-error.ts provided, at the framework level — e.g. the cloud route's 429 billing message reaches the thread error UI again. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR
System prefers-color-scheme via useSyncExternalStore; replaces per-app theme providers for system-driven apps. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR
Minor (not patch) bumps: both ship new public API and behavior changes (thread-header layout defaults; store error messages). A patch would flow silently into existing ^0.13.x / ^0.9.x consumers — minor makes it opt-in. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR
- adapters-and-formats: correct the default body (AG-UI shape, was documented as {threadId, messages}), document buildBody, add useFetchLLM example
- self-hosting/openui-cloud/skills: drop OPENUI_MODEL, hand-rolled ChatLLM example -> useFetchLLM, ModelSwitcher note
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR
Raw SSE forwarded untouched instead of NDJSON re-encoding via toReadableStream; signal propagated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR
abhithesys
reviewed
Jul 29, 2026
abhithesys
reviewed
Jul 29, 2026
abhithesys
reviewed
Jul 29, 2026
abhithesys
previously approved these changes
Jul 29, 2026
AbhinRustagi
enabled auto-merge (squash)
July 29, 2026 12:24
abhithesys
approved these changes
Jul 29, 2026
AbhinRustagi
added a commit
that referenced
this pull request
Jul 30, 2026
* refactor(openui-cloud): slim template onto shared @openuidev packages - ModelSwitcher: use @openuidev/react-ui (drop local model-switcher/); pass provider logos as {light,dark} - Billing: replace local BillingCreditsDialog with dev-only OpenUICreditsModal from @openuidev/devtools - LLM: swap createCloudChatLLM for fetchLLM + buildBody (429 flows via observability); hold LLM in a ref - Cleanup: remove unused deps, cloud-chat-llm, chat-error, cloud-chat-constants, orphaned CSS/logos Depends on #893 (packages) being merged + published first. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * Update package.json * refactor(openui-cloud): use the useFetchLLM hook for the chat LLM Drops the local llmRef + selectedModelRef plumbing for useFetchLLM, which holds a stable instance and reads options fresh per send — buildBody closes over selectedModel directly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-self-hosted): use fetchLLM; drop react-headless/react-lang/tailwind deps - page.tsx: replace hand-rolled ChatLLM with fetchLLM (imported from @openuidev/react-ui), buildBody sends { messages } - drop Tailwind (trivial usage): minimal globals.css reset, inline layout style, delete postcss.config.mjs - package.json: remove @openuidev/react-headless, @openuidev/react-lang, tailwindcss, @tailwindcss/postcss; react-ui -> 0.13.3 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-cloud): drop thread-header CSS overrides now in react-ui Title :empty-hide and actions flex are library defaults after the thread.scss change; the openui-cloud-thread-header hook class is unreferenced. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-cloud): adopt ref-commit simplifications - route.ts: badRequest helper, NextResponse, model allowlist (reject unknown), propagate upstream errors with status — billing.ts deleted (store now surfaces server messages) - theme: useSystemThemeMode from react-ui; delete use-system-theme.tsx; unwrap ThemeProvider in layout - globals.css: trim to page shell + artifact compat (~18 lines); drop Tailwind + postcss.config.mjs + tailwind deps + vitest - frontend-token: NextResponse, propagate upstream status Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * chore(templates): align to react-ui 0.14 / react-headless 0.10; add devtools to self-hosted - cloud: ^0.14.0 / ^0.10.0 - self-hosted: react-ui ^0.14.0; OpenUIDevtools rendered dev-only in layout (devDependency) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * docs(templates): refresh READMEs for the slimmed starters - cloud: drop OPENUI_MODEL, point at src/lib/models.tsx + /api/chat validation, list useFetchLLM/ModelSwitcher/devtools, pnpm-only - self-hosted: add setup section (OPENAI_API_KEY), fix route path, pnpm-only Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-self-hosted): forward raw SSE via .asResponse() + openAIAdapter Drops the NDJSON re-encode (toReadableStream); propagates browser aborts via req.signal; model overridable with OPENAI_MODEL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * chore(cli): bump to 0.3.0 for the slimmed templates Scaffolded output changes substantially (react-ui 0.14 / react-headless 0.10, fetchLLM/useFetchLLM wiring, devtools, removed billing/tailwind) — minor bump, matching the package versioning rationale. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-cloud): consolidate react-ui imports, extract starters, trim comments - import everything from @openuidev/react-ui (headless re-export); starters/prompt templates moved to src/lib/starters - drop the now-trivial handleModelChange wrapper; use the logoPath const - shorten route/model/component comments to the essentials (tool-loop's safety-rule docs kept) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * fix(openui-self-hosted): base sans font on body (Tailwind preflight used to provide it) react-ui sets fonts per component, not on body — text that merely inherits fell back to the browser serif once Tailwind's preflight was removed. Same latent gap exists in the reference commit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * feat(openui-self-hosted): load Inter via next/font like the cloud template Replaces the globals.css font-family fallback — next/font self-hosts Inter with built-in fallbacks, matching react-ui's --openui-font-body token. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * fix: update docs and match latest changes * fix: update readme * fix: add favicon * fix: version match * fix: format * fix: styles * fix: remove credits modal * fix: update lockfiles * update lock files * Update self-hosting.mdx * Update SKILL.md * fix: update minimumReleaseAge rule * fix: lockfiles * fix: naming refactor * rm pnpm-lock --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
AbhinRustagi
added a commit
that referenced
this pull request
Aug 4, 2026
* refactor(openui-cloud): slim template onto shared @openuidev packages - ModelSwitcher: use @openuidev/react-ui (drop local model-switcher/); pass provider logos as {light,dark} - Billing: replace local BillingCreditsDialog with dev-only OpenUICreditsModal from @openuidev/devtools - LLM: swap createCloudChatLLM for fetchLLM + buildBody (429 flows via observability); hold LLM in a ref - Cleanup: remove unused deps, cloud-chat-llm, chat-error, cloud-chat-constants, orphaned CSS/logos Depends on #893 (packages) being merged + published first. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * Update package.json * refactor(openui-cloud): use the useFetchLLM hook for the chat LLM Drops the local llmRef + selectedModelRef plumbing for useFetchLLM, which holds a stable instance and reads options fresh per send — buildBody closes over selectedModel directly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-self-hosted): use fetchLLM; drop react-headless/react-lang/tailwind deps - page.tsx: replace hand-rolled ChatLLM with fetchLLM (imported from @openuidev/react-ui), buildBody sends { messages } - drop Tailwind (trivial usage): minimal globals.css reset, inline layout style, delete postcss.config.mjs - package.json: remove @openuidev/react-headless, @openuidev/react-lang, tailwindcss, @tailwindcss/postcss; react-ui -> 0.13.3 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-cloud): drop thread-header CSS overrides now in react-ui Title :empty-hide and actions flex are library defaults after the thread.scss change; the openui-cloud-thread-header hook class is unreferenced. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-cloud): adopt ref-commit simplifications - route.ts: badRequest helper, NextResponse, model allowlist (reject unknown), propagate upstream errors with status — billing.ts deleted (store now surfaces server messages) - theme: useSystemThemeMode from react-ui; delete use-system-theme.tsx; unwrap ThemeProvider in layout - globals.css: trim to page shell + artifact compat (~18 lines); drop Tailwind + postcss.config.mjs + tailwind deps + vitest - frontend-token: NextResponse, propagate upstream status Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * chore(templates): align to react-ui 0.14 / react-headless 0.10; add devtools to self-hosted - cloud: ^0.14.0 / ^0.10.0 - self-hosted: react-ui ^0.14.0; OpenUIDevtools rendered dev-only in layout (devDependency) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * docs(templates): refresh READMEs for the slimmed starters - cloud: drop OPENUI_MODEL, point at src/lib/models.tsx + /api/chat validation, list useFetchLLM/ModelSwitcher/devtools, pnpm-only - self-hosted: add setup section (OPENAI_API_KEY), fix route path, pnpm-only Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-self-hosted): forward raw SSE via .asResponse() + openAIAdapter Drops the NDJSON re-encode (toReadableStream); propagates browser aborts via req.signal; model overridable with OPENAI_MODEL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * chore(cli): bump to 0.3.0 for the slimmed templates Scaffolded output changes substantially (react-ui 0.14 / react-headless 0.10, fetchLLM/useFetchLLM wiring, devtools, removed billing/tailwind) — minor bump, matching the package versioning rationale. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-cloud): consolidate react-ui imports, extract starters, trim comments - import everything from @openuidev/react-ui (headless re-export); starters/prompt templates moved to src/lib/starters - drop the now-trivial handleModelChange wrapper; use the logoPath const - shorten route/model/component comments to the essentials (tool-loop's safety-rule docs kept) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * fix(openui-self-hosted): base sans font on body (Tailwind preflight used to provide it) react-ui sets fonts per component, not on body — text that merely inherits fell back to the browser serif once Tailwind's preflight was removed. Same latent gap exists in the reference commit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * feat(openui-self-hosted): load Inter via next/font like the cloud template Replaces the globals.css font-family fallback — next/font self-hosts Inter with built-in fallbacks, matching react-ui's --openui-font-body token. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * fix: update docs and match latest changes * fix: update readme * fix: add favicon * fix: version match * fix: format * fix: styles * fix: remove credits modal * fix: update lockfiles * update lock files * Update self-hosting.mdx * Update SKILL.md * fix: update minimumReleaseAge rule * fix: lockfiles * fix: add interleaving for persisted data * fix: add streaming fix * fix: messageGroup * fix: format * fix: scroll issues * fix: revert pnpm-lock * fix: add url fetch * fix: format * fix: keep renderMessage clear * fix: update css * feat(react-ui): restyle the behind-the-scenes tool timeline Rework the timeline so a live run reads as one quiet, accumulating list rather than a stack of bordered cards: - Every revealed step stays on screen; only the newest shimmers + blinks, and the tray header reads "Working" while the model is still thinking. - Each tool row is now the collapsible trigger, expanding into either the result's links or a single block holding the request and response. - Glyphs are per tool family (web search, image search, artifact) with a generic fallback for app-defined tools, drawn in primary at 30% so they sit behind the copy. A failure is the only status that keeps a colour. - The height-capped list scrolls silently, fading each edge only while a row is actually hidden behind it. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(react-ui): make the tool-call shimmer actually render The effect paints text with gradients clipped to the glyphs, but every copy also set an opaque -webkit-text-fill-color, which paints over the clipped background — the animation ran invisibly. The fill has to be transparent, as the reduced-motion override already assumed. Its geometry mixed absolute and relative lengths: a 100px band inside an image sized to 250% of the label came out wider than a short label like "Working", lighting the whole word at once, and was still on screen when the loop restarted, which read as a jump. Sizing the band as a fraction of the label fixes both and keeps the sweep proportional at any length. Folds the three near-identical copies into one mixin so the geometry lives in a single place, and eases the duration to 3s. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(openui-cloud): declare a remote MCP server on the chat route Gives the example a source of app-defined tools to exercise: Cloud connects to the server and runs the calls itself, so the stream carries mcp_list_tools/mcp_call items the adapter already turns into ordinary timeline entries — no client-side tool loop. Defaults to DeepWiki (public, no auth) so a fresh clone can smoke-test it, with env overrides for pointing at another server. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor: trim the tool-timeline comments, drop the MCP env indirection The MCP server is a fixed demo default now — the env overrides only existed to be documented in .env.example, so both go. Co-authored-by: Cursor <cursoragent@cursor.com> * revert(openui-cloud): drop the demo MCP server from the chat route It was only there to exercise the timeline locally; the example keeps to Cloud's built-in tools. Co-authored-by: Cursor <cursoragent@cursor.com> * style(react-ui): unify the tool-row frames and hover states Both toggles lift their label to primary on hover, so the rows read as expandable without a hover fill. Raw request/response containers take the same border and radius as the sources list — a row expands into one or the other, so they can't look like different kinds of container — and a subtle tint separates the payloads from the sources, which keeps the plain surface. Thinking prose moves to primary as the model's own voice, the running icon pulses 0.6 -> 0.2, and the tray holds 24rem before scrolling. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(react-ui): only fade a timeline edge with real content behind it Two ways the mask lied. scrollHeight and clientHeight are rounded while rows are not, so a list that fits could report a pixel of overflow and fade an edge it never scrolled past; overflow now has to clear 8px, and each edge needs 4px of actual scroll offset. The measurement also ran only when this component rendered, but whether a row is expanded is the child's state — so the list could grow past its cap and drop back under it with no render here, leaving the fade stuck on. A ResizeObserver on the list catches both transitions, since its box is content-sized right up to the cap. That also covers width changes, so the window resize listener goes. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(react-ui): stop the thread shifting when a message grows scrollable Styling ::-webkit-scrollbar opts out of overlay scrollbars, so the bar takes real width: the centered column jumped sideways the moment a message got tall enough to scroll, e.g. on expanding a tool row. Reserve the gutter up front. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: refactor * fix: hoist interleaved turn tray + tray-open behaviour * refactor: extract focus-ring mixin, tighten comments * fix: format * refactor: make smaller fns * Update thread.scss * fix: comments * fix: openai responses adapter * fix: rename to web_search * fix: remove tool calls for deduplication * fix: styles * refactor: remove duplications * fix: version bump --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: pr3khar <prakhar19376@iiitd.ac.in> Co-authored-by: Cursor <cursoragent@cursor.com>
AbhinRustagi
added a commit
that referenced
this pull request
Aug 4, 2026
* refactor(openui-cloud): slim template onto shared @openuidev packages - ModelSwitcher: use @openuidev/react-ui (drop local model-switcher/); pass provider logos as {light,dark} - Billing: replace local BillingCreditsDialog with dev-only OpenUICreditsModal from @openuidev/devtools - LLM: swap createCloudChatLLM for fetchLLM + buildBody (429 flows via observability); hold LLM in a ref - Cleanup: remove unused deps, cloud-chat-llm, chat-error, cloud-chat-constants, orphaned CSS/logos Depends on #893 (packages) being merged + published first. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * Update package.json * refactor(openui-cloud): use the useFetchLLM hook for the chat LLM Drops the local llmRef + selectedModelRef plumbing for useFetchLLM, which holds a stable instance and reads options fresh per send — buildBody closes over selectedModel directly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-self-hosted): use fetchLLM; drop react-headless/react-lang/tailwind deps - page.tsx: replace hand-rolled ChatLLM with fetchLLM (imported from @openuidev/react-ui), buildBody sends { messages } - drop Tailwind (trivial usage): minimal globals.css reset, inline layout style, delete postcss.config.mjs - package.json: remove @openuidev/react-headless, @openuidev/react-lang, tailwindcss, @tailwindcss/postcss; react-ui -> 0.13.3 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-cloud): drop thread-header CSS overrides now in react-ui Title :empty-hide and actions flex are library defaults after the thread.scss change; the openui-cloud-thread-header hook class is unreferenced. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-cloud): adopt ref-commit simplifications - route.ts: badRequest helper, NextResponse, model allowlist (reject unknown), propagate upstream errors with status — billing.ts deleted (store now surfaces server messages) - theme: useSystemThemeMode from react-ui; delete use-system-theme.tsx; unwrap ThemeProvider in layout - globals.css: trim to page shell + artifact compat (~18 lines); drop Tailwind + postcss.config.mjs + tailwind deps + vitest - frontend-token: NextResponse, propagate upstream status Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * chore(templates): align to react-ui 0.14 / react-headless 0.10; add devtools to self-hosted - cloud: ^0.14.0 / ^0.10.0 - self-hosted: react-ui ^0.14.0; OpenUIDevtools rendered dev-only in layout (devDependency) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * docs(templates): refresh READMEs for the slimmed starters - cloud: drop OPENUI_MODEL, point at src/lib/models.tsx + /api/chat validation, list useFetchLLM/ModelSwitcher/devtools, pnpm-only - self-hosted: add setup section (OPENAI_API_KEY), fix route path, pnpm-only Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-self-hosted): forward raw SSE via .asResponse() + openAIAdapter Drops the NDJSON re-encode (toReadableStream); propagates browser aborts via req.signal; model overridable with OPENAI_MODEL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * chore(cli): bump to 0.3.0 for the slimmed templates Scaffolded output changes substantially (react-ui 0.14 / react-headless 0.10, fetchLLM/useFetchLLM wiring, devtools, removed billing/tailwind) — minor bump, matching the package versioning rationale. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * refactor(openui-cloud): consolidate react-ui imports, extract starters, trim comments - import everything from @openuidev/react-ui (headless re-export); starters/prompt templates moved to src/lib/starters - drop the now-trivial handleModelChange wrapper; use the logoPath const - shorten route/model/component comments to the essentials (tool-loop's safety-rule docs kept) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * fix(openui-self-hosted): base sans font on body (Tailwind preflight used to provide it) react-ui sets fonts per component, not on body — text that merely inherits fell back to the browser serif once Tailwind's preflight was removed. Same latent gap exists in the reference commit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * feat(openui-self-hosted): load Inter via next/font like the cloud template Replaces the globals.css font-family fallback — next/font self-hosts Inter with built-in fallbacks, matching react-ui's --openui-font-body token. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpABGCgS6C4HRdQSrwhPMR * fix: update docs and match latest changes * fix: update readme * fix: add favicon * fix: version match * fix: format * fix: styles * fix: remove credits modal * fix: update lockfiles * update lock files * Update self-hosting.mdx * Update SKILL.md * fix: update minimumReleaseAge rule * fix: lockfiles * fix: add interleaving for persisted data * fix: add streaming fix * fix: messageGroup * fix: format * fix: scroll issues * fix: revert pnpm-lock * fix: add url fetch * fix: format * fix: keep renderMessage clear * fix: update css * feat(react-ui): restyle the behind-the-scenes tool timeline Rework the timeline so a live run reads as one quiet, accumulating list rather than a stack of bordered cards: - Every revealed step stays on screen; only the newest shimmers + blinks, and the tray header reads "Working" while the model is still thinking. - Each tool row is now the collapsible trigger, expanding into either the result's links or a single block holding the request and response. - Glyphs are per tool family (web search, image search, artifact) with a generic fallback for app-defined tools, drawn in primary at 30% so they sit behind the copy. A failure is the only status that keeps a colour. - The height-capped list scrolls silently, fading each edge only while a row is actually hidden behind it. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(react-ui): make the tool-call shimmer actually render The effect paints text with gradients clipped to the glyphs, but every copy also set an opaque -webkit-text-fill-color, which paints over the clipped background — the animation ran invisibly. The fill has to be transparent, as the reduced-motion override already assumed. Its geometry mixed absolute and relative lengths: a 100px band inside an image sized to 250% of the label came out wider than a short label like "Working", lighting the whole word at once, and was still on screen when the loop restarted, which read as a jump. Sizing the band as a fraction of the label fixes both and keeps the sweep proportional at any length. Folds the three near-identical copies into one mixin so the geometry lives in a single place, and eases the duration to 3s. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(openui-cloud): declare a remote MCP server on the chat route Gives the example a source of app-defined tools to exercise: Cloud connects to the server and runs the calls itself, so the stream carries mcp_list_tools/mcp_call items the adapter already turns into ordinary timeline entries — no client-side tool loop. Defaults to DeepWiki (public, no auth) so a fresh clone can smoke-test it, with env overrides for pointing at another server. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor: trim the tool-timeline comments, drop the MCP env indirection The MCP server is a fixed demo default now — the env overrides only existed to be documented in .env.example, so both go. Co-authored-by: Cursor <cursoragent@cursor.com> * revert(openui-cloud): drop the demo MCP server from the chat route It was only there to exercise the timeline locally; the example keeps to Cloud's built-in tools. Co-authored-by: Cursor <cursoragent@cursor.com> * style(react-ui): unify the tool-row frames and hover states Both toggles lift their label to primary on hover, so the rows read as expandable without a hover fill. Raw request/response containers take the same border and radius as the sources list — a row expands into one or the other, so they can't look like different kinds of container — and a subtle tint separates the payloads from the sources, which keeps the plain surface. Thinking prose moves to primary as the model's own voice, the running icon pulses 0.6 -> 0.2, and the tray holds 24rem before scrolling. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(react-ui): only fade a timeline edge with real content behind it Two ways the mask lied. scrollHeight and clientHeight are rounded while rows are not, so a list that fits could report a pixel of overflow and fade an edge it never scrolled past; overflow now has to clear 8px, and each edge needs 4px of actual scroll offset. The measurement also ran only when this component rendered, but whether a row is expanded is the child's state — so the list could grow past its cap and drop back under it with no render here, leaving the fade stuck on. A ResizeObserver on the list catches both transitions, since its box is content-sized right up to the cap. That also covers width changes, so the window resize listener goes. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(react-ui): stop the thread shifting when a message grows scrollable Styling ::-webkit-scrollbar opts out of overlay scrollbars, so the bar takes real width: the centered column jumped sideways the moment a message got tall enough to scroll, e.g. on expanding a tool row. Reserve the gutter up front. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: refactor * fix: hoist interleaved turn tray + tray-open behaviour * refactor: extract focus-ring mixin, tighten comments * fix: format * refactor: make smaller fns * Update thread.scss * fix: comments * fix: openai responses adapter * fix: rename to web_search * fix: remove tool calls for deduplication * fix: styles * refactor: remove duplications * fix: version bump * chore: version bump --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: pr3khar <prakhar19376@iiitd.ac.in> Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Package updates that the
openui-cloud/openui-self-hostedtemplate slimming depends on. Merge + publish before the template PR (#894) so the template deps resolve on the registry.ModelSwitcherblock (/blocks+ main entry) with theme-aware{ light, dark }logo API and Tag-based badges;useSystemThemeModehook; thread-header defaults (title hides when:empty, actions flex) replacing per-app CSS overrides.fetchLLMgainsbuildBody;useFetchLLMhook (stable instance, live options);getResponseErrorMessage— the chat store now surfaces server error messages instead of generic status lines.OpenUICreditsModal(429 → credits notice via observability); dev-only gating.Minor (not patch) bumps for react-ui/react-headless: both ship new API + behavior changes, so existing
^0.13.x/^0.9.xconsumers opt in rather than silently receiving them.