diff --git a/libs/typescript/cua-cli/README.md b/libs/typescript/cua-cli/README.md index 54d58f5e..5e802d83 100644 --- a/libs/typescript/cua-cli/README.md +++ b/libs/typescript/cua-cli/README.md @@ -27,6 +27,8 @@ bun run ./index.ts -- --help - `cua vm start NAME` - `cua vm stop NAME` - `cua vm restart NAME` + - `cua vm vnc NAME` – opens NoVNC URL in your browser + - `cua vm chat NAME` – opens Dashboard Playground for the VM ## Auth Flow (Dynamic Callback Port) @@ -52,5 +54,18 @@ bun run ./index.ts -- --help ## Notes - Stored API key lives at `~/.config/cua/cli.sqlite` under `kv(api_key)`. -- Public API base: `https://api.cua.ai`. +- Public API base defaults to `https://api.cua.ai` (override via `CUA_API_BASE`). +- Website base defaults to `https://cua.ai` (override via `CUA_WEBSITE_URL`). - Authorization header: `Authorization: Bearer `. + +### Environment overrides + +You can point the CLI to alternate deployments: + +```bash +export CUA_API_BASE=https://api.staging.cua.ai +export CUA_WEBSITE_URL=https://staging.cua.ai + +cua auth login +cua vm chat my-vm # opens https://staging.cua.ai/dashboard/playground?... +``` diff --git a/libs/typescript/cua-cli/src/commands/vm.ts b/libs/typescript/cua-cli/src/commands/vm.ts index 0fcb73be..3b7f2b20 100644 --- a/libs/typescript/cua-cli/src/commands/vm.ts +++ b/libs/typescript/cua-cli/src/commands/vm.ts @@ -2,6 +2,7 @@ import type { Argv } from "yargs"; import { ensureApiKeyInteractive } from "../auth"; import { http } from "../http"; import { printVmList, openInBrowser } from "../util"; +import { WEBSITE_URL } from "../config"; import type { VmItem } from "../util"; import { clearApiKey } from "../storage"; @@ -91,6 +92,26 @@ export function registerVmCommands(y: Argv) { await openInBrowser(url); } ) + .command( + "chat ", + "Open CUA dashboard playground for a VM", + (y) => y.positional("name", { type: "string", describe: "VM name" }), + async (argv: Record) => { + const token = await ensureApiKeyInteractive(); + const name = String((argv as any).name); + const listRes = await http("/v1/vms", { token }); + if (listRes.status === 401) { clearApiKey(); console.error("Unauthorized. Try 'cua auth login' again."); process.exit(1); } + if (!listRes.ok) { console.error(`Request failed: ${listRes.status}`); process.exit(1); } + const vms = (await listRes.json()) as VmItem[]; + const vm = vms.find(v => v.name === name); + if (!vm) { console.error("VM not found"); process.exit(1); } + const host = `${vm.name}.containers.cloud.trycua.com`; + const base = WEBSITE_URL.replace(/\/$/, ""); + const url = `${base}/dashboard/playground?host=${encodeURIComponent(host)}&id=${encodeURIComponent(vm.name)}&name=${encodeURIComponent(vm.name)}&vnc_password=${encodeURIComponent(vm.password)}&fullscreen=true`; + console.log(`Opening Playground: ${url}`); + await openInBrowser(url); + } + ) .demandCommand(1, "Specify a vm subcommand") ); } diff --git a/libs/typescript/cua-cli/src/config.ts b/libs/typescript/cua-cli/src/config.ts index 3ef686c2..1d4b9212 100644 --- a/libs/typescript/cua-cli/src/config.ts +++ b/libs/typescript/cua-cli/src/config.ts @@ -1,10 +1,11 @@ -export const API_BASE = "https://api.cua.ai"; -export const AUTH_PAGE = "https://cua.ai/cli-auth"; +export const WEBSITE_URL = Bun.env.CUA_WEBSITE_URL?.replace(/\/$/, "") || "https://cua.ai"; +export const API_BASE = Bun.env.CUA_API_BASE?.replace(/\/$/, "") || "https://api.cua.ai"; +export const AUTH_PAGE = `${WEBSITE_URL}/cli-auth`; export const CALLBACK_HOST = "127.0.0.1"; export function getConfigDir(): string { const home = Bun.env.HOME || Bun.env.USERPROFILE || "."; - const dir = `${home}/.cua/config`; + const dir = `${home}/.config/cua`; try { Bun.spawnSync(["mkdir", "-p", dir]); } catch {}