Computers now mount only /home/gem/workspace from DATA_DIR/computers/<id>, so only the workspace persists and goes into the data archive. An older computer's whole home is moved aside to <id>-home-<ts> (kept, never archived) and its container recreated once by sync-computers. Each run works in bots/<bot>/users/<user> (also its cwd and HOME), with bots/<bot> for work every user shares and workspaces/<id> shared by a workspace's bots; the coordinator reaches the whole workspace. Computer tools are gated by withComputerDirs: bash and code start there, file tool paths and file: URLs outside the run's folders are refused, and so is sudo. search_computers, import_file and script tools start there too. The files browser shows members only the bots' folders they reach, their own user folder in each and their workspaces', with names on the id folders. Co-Authored-By: Claude Opus 5.5 <[email protected]>
150 lines
3.7 KiB
TypeScript
150 lines
3.7 KiB
TypeScript
/**
|
|
* A computer is an AIO sandbox running in its own docker container on the
|
|
* cobble network, created by the app (`createComputer`), only its
|
|
* workspace (`AppData.ComputerWorkspaceDir`) kept under
|
|
* `DATA_DIR/computers/<id>`.
|
|
*/
|
|
export const ComputerKinds = [
|
|
{
|
|
title: "Main",
|
|
value: "main",
|
|
},
|
|
{
|
|
title: "Sandbox",
|
|
value: "sandbox",
|
|
},
|
|
] as const;
|
|
|
|
export type ComputerKind = (typeof ComputerKinds)[number]["value"];
|
|
|
|
export const MainComputerName = "Main computer";
|
|
|
|
/**
|
|
* Docker container state as reported by `docker inspect` (`State.Status`),
|
|
* with `running` narrowed by its health check: `starting` until it first
|
|
* passes, `unhealthy` once it keeps failing. Plus `creating` while the app
|
|
* sets it up (until the health check passes), `failed` when that didn't
|
|
* work, and `unknown` for a record that hasn't been inspected yet. Only a
|
|
* `running` computer is reached.
|
|
*/
|
|
export const ContainerStatuses = [
|
|
{
|
|
title: "Creating",
|
|
value: "creating",
|
|
},
|
|
{
|
|
title: "Failed",
|
|
value: "failed",
|
|
},
|
|
{
|
|
title: "Created",
|
|
value: "created",
|
|
},
|
|
{
|
|
title: "Starting",
|
|
value: "starting",
|
|
},
|
|
{
|
|
title: "Running",
|
|
value: "running",
|
|
},
|
|
{
|
|
title: "Unhealthy",
|
|
value: "unhealthy",
|
|
},
|
|
{
|
|
title: "Paused",
|
|
value: "paused",
|
|
},
|
|
{
|
|
title: "Restarting",
|
|
value: "restarting",
|
|
},
|
|
{
|
|
title: "Exited",
|
|
value: "exited",
|
|
},
|
|
{
|
|
title: "Removing",
|
|
value: "removing",
|
|
},
|
|
{
|
|
title: "Dead",
|
|
value: "dead",
|
|
},
|
|
{
|
|
title: "Unknown",
|
|
value: "unknown",
|
|
},
|
|
] as const;
|
|
|
|
export type ContainerStatus = (typeof ContainerStatuses)[number]["value"];
|
|
|
|
/**
|
|
* What a recorded container is for. The main app container is never recorded.
|
|
*/
|
|
export const ContainerPurposes = [
|
|
{
|
|
title: "Computer",
|
|
value: "computer",
|
|
},
|
|
] as const;
|
|
|
|
export type ContainerPurpose = (typeof ContainerPurposes)[number]["value"];
|
|
|
|
/**
|
|
* Path of the AIO sandbox's MCP endpoint, on the computer's address.
|
|
*/
|
|
export const ComputerMcpPath = "/mcp";
|
|
|
|
/**
|
|
* Sandbox MCP tools bots don't get: noise (cdp urls), skills they have no
|
|
* use for, and raw display control that needs pixel coordinates (the page
|
|
* tools cover the same ground by element).
|
|
*/
|
|
export const ComputerMcpExcludedTools = [
|
|
"browser_get_info",
|
|
"sandbox_load_skill",
|
|
"browser_gui_screenshot",
|
|
"browser_gui_execute_action",
|
|
] as const;
|
|
|
|
/**
|
|
* How the user can open a computer, each one of the AIO sandbox's own
|
|
* apps at `path` (relative to the computer's address; `{prefix}` is the
|
|
* computer's app address without its leading slash, e.g. `computers/3/`).
|
|
* Desktop is the whole screen over VNC: the only view with the browser's
|
|
* toolbar (extensions) and a clipboard panel. More of them (opencode,
|
|
* codex) can join later.
|
|
*/
|
|
export const ComputerViewModes = [
|
|
{
|
|
title: "Browser",
|
|
value: "browser",
|
|
path: "browser-ui",
|
|
},
|
|
{
|
|
title: "Terminal",
|
|
value: "terminal",
|
|
path: "terminal",
|
|
},
|
|
{
|
|
title: "Code",
|
|
value: "code",
|
|
path: "code-server/",
|
|
},
|
|
{
|
|
title: "Desktop",
|
|
value: "desktop",
|
|
path: "vnc/vnc.html?autoconnect=true&resize=scale&reconnect=true&path={prefix}websockify",
|
|
},
|
|
] as const;
|
|
|
|
export type ComputerViewMode = (typeof ComputerViewModes)[number]["value"];
|
|
|
|
/**
|
|
* Where the app serves a computer to its owner's browser:
|
|
* `/computers/<id>/<path>`, proxied to the sandbox (`handleComputerProxy`).
|
|
*/
|
|
export const ComputerProxyPrefix = "/computers";
|