mirror of
https://github.com/trycua/computer.git
synced 2026-02-17 20:10:07 -06:00
Rename to sandbox
This commit is contained in:
@@ -22,18 +22,17 @@ bun run ./index.ts -- --help
|
||||
- `cua auth pull` – writes/updates `.env` with `CUA_API_KEY`
|
||||
- `cua auth logout` – clears stored API key
|
||||
|
||||
- **VMs**
|
||||
- `cua vm list`
|
||||
- `cua vm create --os OS --configuration SIZE --region REGION` – creates a new VM
|
||||
- **Sandboxes**
|
||||
- `cua sandbox list` (aliases: `ls`, `ps`)
|
||||
- `cua sandbox create --os OS --configuration SIZE --region REGION` – creates a new sandbox
|
||||
- OS: `linux`, `windows`, `macos`
|
||||
- SIZE: `small`, `medium`, `large`
|
||||
- REGION: `north-america`, `europe`, `asia-pacific`, `south-america`
|
||||
- `cua vm delete NAME` – deletes a VM
|
||||
- `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
|
||||
- `cua sandbox delete NAME` – deletes a sandbox
|
||||
- `cua sandbox start NAME`
|
||||
- `cua sandbox stop NAME`
|
||||
- `cua sandbox restart NAME`
|
||||
- `cua sandbox open NAME` – opens NoVNC URL in your browser
|
||||
|
||||
## Auth Flow (Dynamic Callback Port)
|
||||
|
||||
@@ -49,7 +48,7 @@ bun run ./index.ts -- --help
|
||||
- `index.ts` – entry point (shebang + start CLI)
|
||||
- `src/cli.ts` – yargs bootstrapping
|
||||
- `src/commands/auth.ts` – auth/login/pull/logout commands
|
||||
- `src/commands/vm.ts` – vm list/start/stop/restart commands
|
||||
- `src/commands/sandbox.ts` – sandbox list/start/stop/restart commands
|
||||
- `src/auth.ts` – browser flow + local callback server (dynamic port)
|
||||
- `src/http.ts` – HTTP helper
|
||||
- `src/storage.ts` – SQLite-backed key-value storage
|
||||
@@ -72,5 +71,5 @@ 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?...
|
||||
cua sandbox open my-sandbox # opens NoVNC for the sandbox
|
||||
```
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@trycua/cli",
|
||||
"version": "0.1.2",
|
||||
"packageManager": "bun@1.1.38",
|
||||
"description": "Command-line interface for CUA cloud VMs and authentication",
|
||||
"description": "Command-line interface for CUA cloud sandboxes and authentication",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/trycua/cua/tree/main/libs/typescript/cua-cli",
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import yargs from 'yargs';
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
import { registerAuthCommands } from './commands/auth';
|
||||
import { registerVmCommands } from './commands/vm';
|
||||
import { registerSandboxCommands } from './commands/sandbox';
|
||||
|
||||
export async function runCli() {
|
||||
let argv = yargs(hideBin(process.argv)).scriptName('cua');
|
||||
argv = registerAuthCommands(argv);
|
||||
argv = registerVmCommands(argv);
|
||||
argv = registerSandboxCommands(argv);
|
||||
await argv.demandCommand(1).strict().help().parseAsync();
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ import { ensureApiKeyInteractive } from '../auth';
|
||||
import { WEBSITE_URL } from '../config';
|
||||
import { http } from '../http';
|
||||
import { clearApiKey } from '../storage';
|
||||
import type { VmItem } from '../util';
|
||||
import { openInBrowser, printVmList } from '../util';
|
||||
import type { SandboxItem } from '../util';
|
||||
import { openInBrowser, printSandboxList } from '../util';
|
||||
|
||||
export function registerVmCommands(y: Argv) {
|
||||
export function registerSandboxCommands(y: Argv) {
|
||||
return y
|
||||
.command(
|
||||
['list', 'ls', 'ps'],
|
||||
@@ -29,8 +29,8 @@ export function registerVmCommands(y: Argv) {
|
||||
console.error(`Request failed: ${res.status}`);
|
||||
process.exit(1);
|
||||
}
|
||||
const data = (await res.json()) as VmItem[];
|
||||
printVmList(data, Boolean(argv['show-passwords']));
|
||||
const data = (await res.json()) as SandboxItem[];
|
||||
printSandboxList(data, Boolean(argv['show-passwords']));
|
||||
}
|
||||
)
|
||||
.command(
|
||||
@@ -266,17 +266,17 @@ export function registerVmCommands(y: Argv) {
|
||||
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) {
|
||||
const sandboxes = (await listRes.json()) as SandboxItem[];
|
||||
const sandbox = sandboxes.find((s) => s.name === name);
|
||||
if (!sandbox) {
|
||||
console.error('Sandbox not found');
|
||||
process.exit(1);
|
||||
}
|
||||
const host =
|
||||
vm.host && vm.host.length
|
||||
? vm.host
|
||||
: `${vm.name}.containers.cloud.trycua.com`;
|
||||
const url = `https://${host}/vnc.html?autoconnect=true&password=${encodeURIComponent(vm.password)}`;
|
||||
sandbox.host && sandbox.host.length
|
||||
? sandbox.host
|
||||
: `${sandbox.name}.containers.cloud.trycua.com`;
|
||||
const url = `https://${host}/vnc.html?autoconnect=true&password=${encodeURIComponent(sandbox.password)}`;
|
||||
console.log(`Opening NoVNC: ${url}`);
|
||||
await openInBrowser(url);
|
||||
}
|
||||
@@ -298,18 +298,18 @@ export function registerVmCommands(y: Argv) {
|
||||
// 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) {
|
||||
// const sandboxes = (await listRes.json()) as SandboxItem[];
|
||||
// const sandbox = sandboxes.find((s) => s.name === name);
|
||||
// if (!sandbox) {
|
||||
// console.error('Sandbox not found');
|
||||
// process.exit(1);
|
||||
// }
|
||||
// const host =
|
||||
// vm.host && vm.host.length
|
||||
// ? vm.host
|
||||
// : `${vm.name}.containers.cloud.trycua.com`;
|
||||
// sandbox.host && sandbox.host.length
|
||||
// ? sandbox.host
|
||||
// : `${sandbox.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`;
|
||||
// const url = `${base}/dashboard/playground?host=${encodeURIComponent(host)}&id=${encodeURIComponent(sandbox.name)}&name=${encodeURIComponent(sandbox.name)}&vnc_password=${encodeURIComponent(sandbox.password)}&fullscreen=true`;
|
||||
// console.log(`Opening Playground: ${url}`);
|
||||
// await openInBrowser(url);
|
||||
// }
|
||||
@@ -12,20 +12,20 @@ export async function writeEnvFile(cwd: string, key: string) {
|
||||
return path;
|
||||
}
|
||||
|
||||
export type VmStatus =
|
||||
export type SandboxStatus =
|
||||
| 'pending'
|
||||
| 'running'
|
||||
| 'stopped'
|
||||
| 'terminated'
|
||||
| 'failed';
|
||||
export type VmItem = {
|
||||
export type SandboxItem = {
|
||||
name: string;
|
||||
password: string;
|
||||
status: VmStatus;
|
||||
status: SandboxStatus;
|
||||
host?: string;
|
||||
};
|
||||
|
||||
export function printVmList(items: VmItem[], showPasswords: boolean = false) {
|
||||
export function printSandboxList(items: SandboxItem[], showPasswords: boolean = false) {
|
||||
const headers = showPasswords
|
||||
? ['NAME', 'STATUS', 'PASSWORD', 'HOST']
|
||||
: ['NAME', 'STATUS', 'HOST'];
|
||||
@@ -49,7 +49,7 @@ export function printVmList(items: VmItem[], showPasswords: boolean = false) {
|
||||
for (const r of rows)
|
||||
console.log(r.map((c, i) => (c ?? '').padEnd(widths[i] ?? 0)).join(' '));
|
||||
|
||||
if (items.length === 0) console.log('No VMs found');
|
||||
if (items.length === 0) console.log('No sandboxes found');
|
||||
}
|
||||
|
||||
export async function openInBrowser(url: string) {
|
||||
|
||||
Reference in New Issue
Block a user