diff --git a/apps/hosted/README.md b/apps/hosted/README.md index 4eee9763c9..53c9ba4884 100644 --- a/apps/hosted/README.md +++ b/apps/hosted/README.md @@ -4,14 +4,14 @@ that drives Studio's agent from a browser. It exposes the same capabilities the desktop app reaches over IPC, but over HTTP, so the portable `apps/ui` renderer can talk to it through the **web connector** -(`apps/ui/src/data/core/connectors/web`). +(`apps/ui/src/data/core/connectors/hosted`). Unlike the desktop app and CLI, this targets a hosted deployment — WordPress.com / Telex APIs and a server-side agent sandbox — not a local WordPress install. It deliberately depends on nothing in `apps/cli`. ``` -npm run build:web --workspace=apps/ui # once, or after UI changes +npm run build:hosted --workspace=apps/ui # once, or after UI changes npm run build --workspace=apps/hosted # build the server bundle npm run start --workspace=apps/hosted # listens on 127.0.0.1:8088 (STUDIO_WEB_SERVER_PORT) ``` diff --git a/apps/hosted/src/index.ts b/apps/hosted/src/index.ts index aa5429a631..97a700b7db 100644 --- a/apps/hosted/src/index.ts +++ b/apps/hosted/src/index.ts @@ -328,14 +328,14 @@ app.use( '/api', api ); // --- Web UI ------------------------------------------------------------------ -// Serve the built browser UI (apps/ui `npm run build:web`) so the server is the +// Serve the built browser UI (apps/ui `npm run build:hosted`) so the server is the // only process needed: API and SPA share one origin. When the build output // isn't there (API-only usage, or UI served by the Vite dev server on :5300), // the server still works and the startup message says how to get the UI. const uiDist = process.env.STUDIO_WEB_UI_DIST ?? - path.resolve( path.dirname( fileURLToPath( import.meta.url ) ), '../../ui/dist-web' ); -const uiIndex = path.join( uiDist, 'index.web.html' ); + path.resolve( path.dirname( fileURLToPath( import.meta.url ) ), '../../ui/dist-hosted' ); +const uiIndex = path.join( uiDist, 'index.hosted.html' ); const hasUi = existsSync( uiIndex ); if ( hasUi ) { app.use( express.static( uiDist ) ); @@ -374,7 +374,7 @@ const server = app.listen( port, '127.0.0.1', () => { if ( ! hasUi ) { console.log( `No web UI build found at ${ uiDist }.` ); console.log( - `Build it with \`npm run build:web --workspace=apps/ui\`, or run the dev server with \`npm run dev:web --workspace=apps/ui\` and open http://localhost:5300.` + `Build it with \`npm run build:hosted --workspace=apps/ui\`, or run the dev server with \`npm run dev:hosted --workspace=apps/ui\` and open http://localhost:5300.` ); console.log( '' ); } diff --git a/apps/ui/index.web.html b/apps/ui/index.hosted.html similarity index 68% rename from apps/ui/index.web.html rename to apps/ui/index.hosted.html index a5e1268de4..22b240c16f 100644 --- a/apps/ui/index.web.html +++ b/apps/ui/index.hosted.html @@ -3,10 +3,10 @@ - Studio Web + Studio Hosted
- + diff --git a/apps/ui/package.json b/apps/ui/package.json index 0310ac0313..694bc94646 100644 --- a/apps/ui/package.json +++ b/apps/ui/package.json @@ -5,13 +5,13 @@ "type": "module", "scripts": { "dev": "vite", - "dev:web": "STUDIO_TARGET=web vite", + "dev:hosted": "STUDIO_TARGET=hosted vite", "build": "vite build", - "build:web": "STUDIO_TARGET=web vite build", + "build:hosted": "STUDIO_TARGET=hosted vite build", "lint": "eslint src", "typecheck": "tsc -p tsconfig.json --noEmit", "preview": "vite preview", - "preview:web": "STUDIO_TARGET=web vite preview" + "preview:hosted": "STUDIO_TARGET=hosted vite preview" }, "dependencies": { "@base-ui/react": "^1.3.0", diff --git a/apps/ui/src/data/core/connectors/web/index.ts b/apps/ui/src/data/core/connectors/hosted/index.ts similarity index 98% rename from apps/ui/src/data/core/connectors/web/index.ts rename to apps/ui/src/data/core/connectors/hosted/index.ts index c874172f88..a0225643bd 100644 --- a/apps/ui/src/data/core/connectors/web/index.ts +++ b/apps/ui/src/data/core/connectors/hosted/index.ts @@ -15,8 +15,8 @@ import type { } from '../../types'; import type { AgentRunEvent } from '@studio/common/ai/agent-events'; -export interface WebConnectorOptions { - // Base URL of the Studio Web backend (`apps/hosted`), e.g. http://localhost:8088. +export interface HostedConnectorOptions { + // Base URL of the Studio hosted backend (`apps/hosted`), e.g. http://localhost:8088. apiBaseUrl: string; } @@ -56,7 +56,7 @@ type ServerEvent = * return benign defaults (so mount-time queries don't throw) or throw * `WebUnsupportedError` for user-triggered actions. */ -export function createWebConnector( { apiBaseUrl }: WebConnectorOptions ): Connector { +export function createHostedConnector( { apiBaseUrl }: HostedConnectorOptions ): Connector { // The backend namespaces its API under /api so the SPA's real-path routes // (also /sessions/:id, /sites/:id) can share the same origin. const base = `${ apiBaseUrl.replace( /\/$/, '' ) }/api`; diff --git a/apps/ui/src/main.web.tsx b/apps/ui/src/main.hosted.tsx similarity index 79% rename from apps/ui/src/main.web.tsx rename to apps/ui/src/main.hosted.tsx index 572986886c..c4498937e9 100644 --- a/apps/ui/src/main.web.tsx +++ b/apps/ui/src/main.hosted.tsx @@ -4,12 +4,12 @@ import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import { App } from '@/app'; import { persistPromise } from '@/data/core'; -import { createWebConnector } from '@/data/core/connectors/web'; +import { createHostedConnector } from '@/data/core/connectors/hosted'; import type { Connector } from '@/data/core'; -// Web entry point. Identical to `main.tsx` except it wires the HTTP/SSE web +// Web entry point. Identical to `main.tsx` except it wires the HTTP/SSE hosted // connector instead of the Electron IPC connector, so the same React app runs -// in a plain browser tab against the Studio Web backend (`apps/hosted`). +// in a plain browser tab against the Studio hosted backend (`apps/hosted`). async function loadTranslations( connector: Connector ) { const { locale } = await connector.getUserPreferences(); @@ -23,14 +23,14 @@ async function loadTranslations( connector: Connector ) { } function getDefaultApiBaseUrl(): string { - // Production builds are served by the Studio Web backend itself, so the API is + // Production builds are served by the Studio hosted backend itself, so the API is // same-origin. The Vite dev server (:5300) is a separate origin and targets // the backend's default port instead. return import.meta.env.DEV ? 'http://localhost:8088' : window.location.origin; } async function bootstrap() { - const connector = createWebConnector( { + const connector = createHostedConnector( { apiBaseUrl: import.meta.env.VITE_STUDIO_API_URL ?? getDefaultApiBaseUrl(), } ); @@ -38,7 +38,7 @@ async function bootstrap() { createRoot( document.getElementById( 'root' )! ).render( - { /* Studio Web stays on the agentic UI; it doesn't use the desk/agentic + { /* Studio hosted stays on the agentic UI; it doesn't use the desk/agentic mode switcher. */ } diff --git a/apps/ui/vite.config.ts b/apps/ui/vite.config.ts index e089992ebb..f4fd151f37 100644 --- a/apps/ui/vite.config.ts +++ b/apps/ui/vite.config.ts @@ -18,18 +18,18 @@ const directDeps = Object.entries( pkg.dependencies ?? {} ) .filter( ( [ , version ] ) => ! version.startsWith( 'file:' ) ) .map( ( [ name ] ) => name ); -// Web target (`STUDIO_TARGET=web`) builds a standalone browser app wired to the -// HTTP/SSE web connector. It uses a separate entry/output/port so the default +// Hosted target (`STUDIO_TARGET=hosted`) builds a standalone browser app wired to +// the HTTP/SSE hosted connector. It uses a separate entry/output/port so the default // Electron-renderer build (`dist/`, port 5200) stays byte-for-byte unchanged. -const isWeb = process.env.STUDIO_TARGET === 'web'; +const isHosted = process.env.STUDIO_TARGET === 'hosted'; // In dev, Vite serves the root `index.html` (which loads the Electron entry, // `main.tsx`) for every SPA navigation, regardless of `build` input options. -// Serve `index.web.html` instead for any document navigation (`/`, `/sites`, -// `/sessions/:id`, …) so the web entry + web connector load and client-side +// Serve `index.hosted.html` instead for any document navigation (`/`, `/sites`, +// `/sessions/:id`, …) so the hosted entry + hosted connector load and client-side // routing/refresh works. Module and asset requests pass through untouched. -const webDevEntryPlugin: Plugin = { - name: 'studio-web-dev-entry', +const hostedDevEntryPlugin: Plugin = { + name: 'studio-hosted-dev-entry', apply: 'serve', configureServer( server ) { server.middlewares.use( ( req, _res, next ) => { @@ -41,7 +41,7 @@ const webDevEntryPlugin: Plugin = { pathname.startsWith( '/node_modules/' ) || pathname.includes( '.' ); if ( accept.includes( 'text/html' ) && ! isInternal ) { - req.url = '/index.web.html'; + req.url = '/index.hosted.html'; } next(); } ); @@ -49,7 +49,7 @@ const webDevEntryPlugin: Plugin = { }; export default defineConfig( { - plugins: [ react(), dsTokenFallbacks(), ...( isWeb ? [ webDevEntryPlugin ] : [] ) ], + plugins: [ react(), dsTokenFallbacks(), ...( isHosted ? [ hostedDevEntryPlugin ] : [] ) ], css: { postcss: { plugins: [ dsTokenFallbacksPostcss ], @@ -74,12 +74,12 @@ export default defineConfig( { include: directDeps, }, server: { - port: isWeb ? 5300 : 5200, + port: isHosted ? 5300 : 5200, }, build: { - outDir: isWeb ? 'dist-web' : 'dist', + outDir: isHosted ? 'dist-hosted' : 'dist', rolldownOptions: { - input: resolve( __dirname, isWeb ? 'index.web.html' : 'index.html' ), + input: resolve( __dirname, isHosted ? 'index.hosted.html' : 'index.html' ), }, }, } );