Skip to content

Teach the OpenUI skill to integrate and migrate to Cloud#754

Open
vishxrad wants to merge 3 commits into
mainfrom
visharad/update-skill-cloud
Open

Teach the OpenUI skill to integrate and migrate to Cloud#754
vishxrad wants to merge 3 commits into
mainfrom
visharad/update-skill-cloud

Conversation

@vishxrad

@vishxrad vishxrad commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR teaches the OpenUI skill how to integrate OpenUI Cloud into an existing project and how to migrate an existing open-source/self-hosted OpenUI application to Cloud without discarding working behavior or inventing unsupported APIs.

It also reconciles the generated Cloud template and canonical documentation with that guidance. The rebased implementation preserves main's newer model-switcher, billing, and CLI setup architecture while adding a production fail-closed boundary, bounded request validation, safer error handling, and explicit migration methodology.

Feedback addressed

The OpenUI skill already handled open-source framework integration well, but it did not understand the managed Cloud architecture. In particular, it could not reliably:

  • add Cloud to an existing application in one pass;
  • migrate an existing self-hosted OpenUI application to Cloud;
  • distinguish code migration from historical-data migration;
  • preserve custom tools, component libraries, artifacts, authentication, and existing routes when Cloud does not yet provide an equivalent contract.

Methodology

1. Audited the actual Cloud contract

We started from repository sources instead of writing an isolated example from memory:

  • inspected the Cloud and self-hosted CLI templates;
  • traced the public exports from @openuidev/react-ui, @openuidev/react-headless, @openuidev/thesys, and @openuidev/thesys-server;
  • reviewed the Agent Interface storage, message-format, streaming-adapter, artifact, and thread contracts;
  • compared the generated template with the public Agent documentation and CLI behavior;
  • checked repository history around artifact streaming. The old custom response.artifact_call.delta event was intentionally retired when live artifacts moved into standard Responses function-call arguments, so stale claims were removed rather than reintroducing a private protocol extension.

2. Used independent design reviews

The design phase incorporated independent recommendations from Grok and Claude. Those reviews converged on the same approach:

  • make Cloud a first-class routing path in the skill;
  • keep the primary skill broad and concise, with detailed workflows in references;
  • model Cloud integration and self-hosted-to-Cloud migration as separate runbooks;
  • preserve working OSS behavior when Cloud cannot replace a custom capability;
  • treat authentication, identity, conversation ownership, and server-key isolation as invariants.

3. Added progressive-disclosure skill routing

skills/openui/SKILL.md now retains main's comprehensive package, framework, renderer, theming, and OpenUI Lang guidance while routing Cloud-specific work by starting state and desired outcome:

  • managed Cloud integration into an existing React app;
  • an explicit non-React managed-client boundary;
  • replacement or dual-mode migration from self-hosted OpenUI;
  • separate code-migration and historical-data-migration decisions.

Detailed workflows live in:

  • skills/openui/references/cloud-integration.md for existing-project integration;
  • skills/openui/references/cloud-migration.md for replace, dual-mode, code-migration, data-migration, and unsupported-capability decisions.

4. Defined and preserved the Cloud invariants

The integration runbook encodes two independent Cloud planes:

  1. ChatLLM posts to the application's server-side generation proxy, which uses THESYS_API_KEY.
  2. useOpenuiCloudStorage() accesses Cloud storage using a short-lived frontend token scoped to the authenticated user.

It also requires:

  • sending only the latest message while Cloud replays history from conversation: threadId;
  • pairing openAIResponsesAdapter() with openAIConversationMessageFormat;
  • keeping the server key out of client code;
  • preserving abort propagation and SSE termination;
  • loading browser-oriented Thesys code through a Next.js dynamic(..., { ssr: false }) boundary;
  • using the managed report/presentation renderers through defineArtifactCategories(...);
  • preserving host routing, design system, authentication, rate limits, and working behavior.

5. Made conversation authorization implementable

No stock canAccessConversation() helper exists, so the runbook documents two concrete production strategies:

  • a host-owned { conversationId, ownerUserId } mapping, preferably created transactionally through a trusted server path;
  • bootstrap verification through a frontend token minted for the authenticated user and the token-scoped Cloud conversation list.

The generation route should return 403 only for a confirmed ownership miss and a service error when verification itself fails. If neither verified path is supported by the installed version, the skill keeps production generation disabled and reports the boundary.

6. Hardened the generated Cloud template

The scaffold remains convenient locally but is not accidentally deployable as a shared unauthenticated proxy:

  • both Cloud routes return 503 with Cache-Control: no-store in production until host authentication and authorization replace the demo guard;
  • the frontend-token response is private/non-cacheable and upstream details are not reflected to the browser;
  • the chat route reads at most 64 KiB, accepts one text user message of at most 32 KiB, rejects system/developer/function-call injection, and reconstructs the allowlisted provider item server-side;
  • an optional browser-selected model is accepted only when it belongs to main's curated MODEL_OPTIONS catalog;
  • billing-specific 429 UX from main is preserved, while non-billing request and stream failures are logged server-side and returned as generic client errors;
  • missing-key failures are explicit and stay inside route error handling;
  • app/page.tsx dynamically loads main's feature-rich components/cloud-chat.tsx with ssr: false, preserving the current model switcher and billing dialog without retaining a duplicate Cloud UI.

The request parser is intentionally text-only. Applications adding images or files must extend the allowlist and limits deliberately.

7. Rebased onto main without regressing newer work

The branch originally forked from a stale local main. During the rebase, the conflicts were resolved semantically rather than by choosing one side wholesale:

  • PR Improve OpenUI agent skill guidance #680's comprehensive OpenUI skill remains the backbone; this PR adds Cloud routing, security invariants, migration references, SSR guidance, unsupported boundaries, and Cloud verification;
  • PR Improve OpenUI Cloud model and billing UX #735's CloudChat, curated model switcher, billing dialog, selected-model transport, and billing-credit 429 handling are retained;
  • PR Front-load OpenUI Cloud setup in CLI #742's front-loaded Cloud authentication and EnvResult flow are retained, with OPENUI_MODEL added to the centrally written Cloud environment;
  • the template README keeps main's current model-switcher documentation and adds the production-authentication, conversation-ownership, and bounded-input guidance;
  • the stale duplicate app/cloud-agent.tsx implementation was removed.

8. Reconciled canonical sources

The implementation also removes drift found during the audit:

  • follows main's current split: headless adapters/formats from @openuidev/react-headless, AgentInterface from @openuidev/react-ui, Cloud client APIs from @openuidev/thesys, and server helpers from @openuidev/thesys-server;
  • keeps openai in production dependencies because the route imports it at runtime;
  • writes OPENUI_MODEL beside the Cloud key and demo identity;
  • aligns the default model and port documentation with the generated template;
  • makes an empty test suite non-failing while adding real parser/guard tests;
  • updates public Agent documentation and the Cloud quickstart to match the generated implementation;
  • corrects stale artifact-streaming language to describe function-argument streaming and settled tool results.

9. Ran scenario and adversarial reviews

The skill was exercised against independent scenarios:

  • adding Cloud to an existing authenticated React route without replacing its shell;
  • migrating a self-hosted Agent Interface app while preserving historical data as legacy/read-only when no import API exists;
  • handling a custom-library/custom-tool/high-history app through gated dual mode rather than claiming unsupported parity.

Post-implementation reviews covered security and conversation ownership, skill routing and OSS preservation, and code/template/documentation regressions. Findings were incorporated into the final runbooks and scaffold.

Validation on the rebased branch

  • pnpm --filter @openuidev/cli run ci — passed
  • pnpm --filter @openuidev/cli run build — passed, including CLI TypeScript and template packaging
  • pnpm --filter @openuidev/docs run types:check — passed
  • pnpm --filter @openuidev/react-ui run typecheck — passed
  • pnpm --filter @openuidev/react-ui run test — 6 tests passed
  • Cloud template cloud-request.test.ts and env.test.ts — 10 tests passed
  • Prettier checks for the touched source/documentation files — passed
  • git diff --check origin/main...HEAD — passed

The previous fresh-scaffold build results were not carried forward as a post-rebase claim; the list above contains only validation run against the combined rebased implementation.

Deliberate boundaries

  • Historical Cloud data import is not claimed because the repository does not expose a verified import contract.
  • Custom tool execution is not claimed to migrate automatically without a documented Responses continuation loop.
  • A client-side custom component library does not prove that managed generation has matching component instructions.
  • The verified managed client path is React; other frameworks require a current first-party runtime or remain on the OSS rendering path.

Checklist

  • Existing-project Cloud integration guidance
  • Self-hosted-to-Cloud migration guidance
  • Main's broad OSS/framework skill guidance preserved
  • Main's model-switcher, billing, and CLI setup work preserved
  • Generated Cloud template reconciled with the skill
  • Production fail-closed boundary
  • Bounded, allowlisted request parser with curated model validation
  • Canonical documentation updated
  • Rebased conflict-free onto current main
  • Validation rerun against the rebased implementation

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