diff --git a/Makefile b/Makefile index 5c08d5010..724a50bb3 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,12 @@ build-packages: done @echo " 📦 Building packages/server bundle..." @( cd packages/server && bun run build:server ) || exit $$? + @if [ -f packages/owletto/package.json ]; then \ + echo " 📦 Building packages/owletto (web UI)..."; \ + ( cd packages/owletto && bun run build ) || exit $$?; \ + else \ + echo " ⚠️ packages/owletto absent — CLI will ship headless (API only)"; \ + fi @echo " 📦 Building packages/cli..." @( cd packages/cli && bun run build ) || exit $$? @echo "✅ All packages built successfully!" diff --git a/package.json b/package.json index 3a65f4ab8..3c5e936bb 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "test:coverage": "bun test packages/core/src packages/agent-worker/src packages/landing/src --coverage", "typecheck": "tsc --noEmit", "dev": "./scripts/dev-native.sh", - "build:packages": "cd packages/core && bun run build && cd ../connector-sdk && bun run build && cd ../agent-worker && bun run build && cd ../openclaw-plugin && bun run build && cd ../embeddings && bun run build && cd ../connector-worker && bun run build && cd ../promptfoo-provider && bun run build && cd ../server && bun run build:server && cd ../cli && bun run build", + "build:packages": "cd packages/core && bun run build && cd ../connector-sdk && bun run build && cd ../agent-worker && bun run build && cd ../openclaw-plugin && bun run build && cd ../embeddings && bun run build && cd ../connector-worker && bun run build && cd ../promptfoo-provider && bun run build && cd ../server && bun run build:server && cd .. && if [ -f owletto/package.json ]; then (cd owletto && bun run build); else echo '[build:packages] owletto submodule absent — CLI ships headless (API only)'; fi && cd cli && bun run build", "build:lobu": "cd packages/embeddings && bun run build && cd ../..", "watch:packages": "tsc -b --watch packages/core packages/agent-worker", "test:packages": "cd packages/core && bun run test && cd ../agent-worker && bun run test", diff --git a/packages/cli/scripts/build.cjs b/packages/cli/scripts/build.cjs index 15526db95..dc9b718b6 100644 --- a/packages/cli/scripts/build.cjs +++ b/packages/cli/scripts/build.cjs @@ -38,6 +38,16 @@ copyDirIfExists("../connectors/src", "dist/connectors"); // Copy database migrations for the bundled PGlite local server. copyDirIfExists("../../db/migrations", "dist/db/migrations"); +// Copy the built owletto web UI (admin/console SPA) next to the server bundle +// so `lobu run` serves it — OAuth, MCP-client setup, and connection CRUD have +// no surface without it. owletto is a private submodule (`private: true`); +// only its compiled `dist/` ships in the CLI tarball, never the source. CI's +// publish flow builds it (`bun run build` in packages/owletto, gated on the +// submodule being present) before this script runs. Missing locally (fork or +// uninitialised submodule) → the copy is skipped and `lobu run` boots headless +// (API only), matching prior behaviour. `dev.ts` points WEB_DIST_DIR here. +copyDirIfExists("../owletto/dist", "dist/owletto/dist"); + // Copy server bundles so `lobu run` is self-contained. // @lobu/server is private (`private: true` in its package.json), // so `npx @lobu/cli` users can never resolve it via npm — they only get diff --git a/packages/cli/src/commands/dev.ts b/packages/cli/src/commands/dev.ts index e3d64ace0..dedfdcccb 100644 --- a/packages/cli/src/commands/dev.ts +++ b/packages/cli/src/commands/dev.ts @@ -323,12 +323,24 @@ export async function devCommand( envVars.LOBU_PROVIDER_REGISTRY_PATH || (existsSync(bundledProvidersPath) ? bundledProvidersPath : undefined); + // Bundled CLIs ship the built owletto web UI next to the server bundle (see + // packages/cli/scripts/build.cjs). Point the server at it unless the user or + // .env already set WEB_DIST_DIR. In a monorepo checkout the bundle's sibling + // dir has no owletto/dist, so this stays undefined and the server's own + // monorepo-relative lookup / Vite dev path takes over. + const bundledWebDistPath = join(dirname(bundlePath), "owletto", "dist"); + const webDistDir = + process.env.WEB_DIST_DIR || + envVars.WEB_DIST_DIR || + (existsSync(bundledWebDistPath) ? bundledWebDistPath : undefined); + const childEnv: Record = { ...mergedEnv, LOBU_DEV_PROJECT_PATH: projectPath, ...(providerRegistryPath ? { LOBU_PROVIDER_REGISTRY_PATH: providerRegistryPath } : {}), + ...(webDistDir ? { WEB_DIST_DIR: webDistDir } : {}), PORT: String(portNum), GATEWAY_PORT: String(portNum), ...(logLevel ? { LOG_LEVEL: logLevel } : {}),