Added CUA_API_BASE / CUA_WEBSITE_URL to the cua cli config, and vm chat <name> command

This commit is contained in:
Dillon DuPont
2025-10-20 17:09:53 -07:00
parent 789b7264b5
commit be8bb62bb4
3 changed files with 41 additions and 4 deletions

View File

@@ -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 <api_key>`.
### 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?...
```

View File

@@ -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 <name>",
"Open CUA dashboard playground for a VM",
(y) => y.positional("name", { type: "string", describe: "VM name" }),
async (argv: Record<string, unknown>) => {
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")
);
}

View File

@@ -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 {}