@agentorg/computer 0.0.14 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,7 +7,7 @@ npm install -g @agentorg/computer
7
7
  agentcomputer serve
8
8
  ```
9
9
 
10
- In another terminal:
10
+ In another terminal, or after `agentcomputer up`, which runs it in the background instead:
11
11
 
12
12
  ```sh
13
13
  agentcomputer create --access terminal --browser --workspace ~/some/folder
@@ -15,14 +15,21 @@ agentcomputer create --access terminal --browser --workspace ~/some/folder
15
15
 
16
16
  That prints the computer's `computerID`, its endpoints and its `accessToken`, once. Give an MCP client the `computer` and `browser` URLs, with the token as `Authorization: Bearer <token>`.
17
17
 
18
- **By default a computer has no isolation.** It's processes of whoever started the service, and with `--access terminal` it can reach everything that user can. Use `--isolation container` wherever that isn't safe.
18
+ **By default a computer has no isolation.** It's processes of whoever started the service, and with `--access terminal` it can reach everything that user can. Make it with `--isolation container` wherever that isn't safe, or start the service with that to have it for every computer that doesn't say.
19
19
 
20
20
  ## Isolation
21
21
 
22
- `agentcomputer serve --isolation container` makes each computer a container of its own, which needs Docker on the same machine. The service follows your `DOCKER_HOST` or current context and never changes them.
22
+ Isolation is chosen for each computer when it is made, and it keeps it until it is killed: `create --isolation none`, processes of whoever started the service, or `create --isolation container`, a container of its own. `serve --isolation` only sets what a computer gets when none is asked for, and is `none` unless you say otherwise. A container needs Docker on the service's machine. The service follows your `DOCKER_HOST` or current context and never changes them.
23
23
 
24
- - The image holds AgentExec, Playwright MCP and a headless Chromium. It is `ghcr.io/uniac-ai/agentcomputer/computer` at the service's version; `--image` names another.
24
+ - `info` answers the service's own as `isolation`, and as `isolationsAvailable` the ones a computer can be made in now: `container` is among them while Docker answers. Asked for where it doesn't, a container is refused with 409: `A container needs Docker, which isn't answering on this machine.` The service itself comes up without Docker, unless its own isolation is `container`.
25
+ - A computer is never run in an isolation it wasn't made in, whatever the service is started with later. One in a container isn't started where Docker doesn't answer, and isn't killed there either, since its container couldn't be removed: both are refused with the same words, and it is kept.
26
+ - **Upgrading:** a computer recorded by an earlier version kept no isolation, and is given the one the service is started with. So start the service the first time as it was last started, with the same `--isolation`. A program that starts the service for a person should start it with the same `--isolation` every time.
27
+
28
+ A computer in a container:
29
+
30
+ - Its image holds AgentExec, Playwright MCP and a headless Chromium. It is `ghcr.io/uniac-ai/agentcomputer/computer` at the service's version; `--image` names another.
25
31
  - `--workspace` is mounted at `/workspace`, read-only at `--access read`, and nothing else of the machine is visible. The computer is told that folder's path on the machine and the machine's name, which `about` answers. Docker has to be able to share that folder. Without `--workspace`, the service makes one.
32
+ - The image is fetched the first time it is needed, which can take minutes: when the service starts if its own isolation is `container`, and otherwise when the first computer in a container is made, a call that then waits for it. `docker pull` it beforehand to spare that wait.
26
33
  - It runs as the user who started the service, with no capabilities.
27
34
  - `stop` stops the container and keeps it, so what was installed in it is there at `start`. `kill` removes it. Starting a stopped computer uses the image it was made from.
28
35
 
@@ -35,7 +42,7 @@ That prints the computer's `computerID`, its endpoints and its `accessToken`, on
35
42
  | `terminal` | Those, and `exec_command`, `write_stdin`, `list_sessions` |
36
43
  | `none` | No `computer` endpoint; needs `--browser` |
37
44
 
38
- `read` answers a text file as numbered lines, and a PNG, JPEG, GIF or WebP of up to 3 MiB as the picture itself: an image an MCP client can pass on to a model. The browser's `browser_take_screenshot` answers an image too, of whatever size it comes to: a `fullPage` one of a long page can be many megabytes. A container made by an earlier version keeps the program it was made with, and refuses a picture as a binary file until it is killed and made again.
45
+ `read` answers a text file as numbered lines, and a PNG, JPEG, GIF or WebP of up to 3 MiB as the picture itself: an image an MCP client can pass on to a model. The browser's `browser_take_screenshot` answers an image too, but not one of more than 3 MiB, which a `fullPage` screenshot of a long page can be many times over: it answers an error that gives the size and says to take it again without `fullPage`, or of one element. The most counts bytes only: a model may still refuse a smaller picture for its height or width. A container made by an earlier version keeps the program it was made with: it refuses a picture as a binary file, and passes on a screenshot of any size, until it is killed and made again.
39
46
 
40
47
  `about` tells the agent what a person looking at the computer reads. It takes nothing and answers JSON text, `{"rows": [...]}`, each row a `label` and a `value`, with `"path": true` on a value that is a path and `"caution": true` on one to be read as a caution; a row that is neither has neither. The rows come in this order:
41
48
 
@@ -53,28 +60,40 @@ That prints the computer's `computerID`, its endpoints and its `accessToken`, on
53
60
  - **The last three** are a reading of its load taken over half a second when it is asked, in the same way the `load` surface reads. They come together, or not at all where a reading can't be taken.
54
61
  - **Not every computer has it.** One with no `computer` endpoint has no `about`. One in a container made by an earlier version keeps the program it was made with: `about` is listed among its tools and isn't there until it is killed and made again.
55
62
 
63
+ A client that calls a computer's tools can put the commands it starts in a group, and stop them together. At `--access terminal` it sends a word as `agentexec/group` in the `_meta` of an `exec_command` call, and the request `agentexec/group/stop` with `{"group": "<word>"}` on the `computer` endpoint, which ends every running command of that group and answers `{"stopped": <how many>}`. Giving up a call does not stop its command; only that request does. A shell a person opened is in no group. This is AgentExec's, described in [its README](https://github.com/uniac-ai/AgentExec#sessions), and the service passes both through, with no isolation and in a container. A container made by an earlier version has neither until it is killed and made again.
64
+
56
65
  The file tools stay inside the workspace. That's a check, not a boundary. Below `terminal`, the browser's `browser_run_code_unsafe` tool is hidden and refused, because it would otherwise be a terminal. The browser's endpoint takes one JSON-RPC request in each POST, as a JSON object, and refuses anything else with 400, a batch among them: it checks each request before passing it on, and passes on only what it read. The service enforces all of this, whatever the client does.
57
66
 
58
- `--browser` drives the Google Chrome installed on the machine, in a profile of the computer's own. `serve --browser-name` and `--browser-path` choose another. The browser has no debug port: a small host process starts it and shares it on a Unix socket in a folder only its user can enter, which the agent's tools and the live view both use. It lives as long as its computer does: a client that ends its session or goes away leaves the browser and its pages as they are, and the agent's `browser_close` is refused. Only an agent with `--access terminal` can stop it, with `browser_run_code_unsafe` or from its terminal.
67
+ Before 0.0.14 the browser's endpoint passed on a body it couldn't read as one request, unchecked. So on a computer made with `--access none`, `read` or `files` and `--browser`, a caller holding that computer's token could run code in its browser by sending the call in a batch or behind a byte order mark. It needed the computer's own token and a client that sends such a body, which MCP clients don't. 0.0.14 fixes it; a computer in a container made by an earlier version keeps the fault until it is killed and made again.
68
+
69
+ `--browser` drives the Google Chrome installed on the machine, in a profile of the computer's own. `serve --browser-name` and `--browser-path` choose another. The browser has no debug port: a small host process starts it and shares it on a Unix socket in a folder only its user can enter, which the agent's tools and the live view both use. Playwright MCP, which serves the tools, listens on a Unix socket in a second such folder, and no port either. Only the service's user can reach them; callers go through the computer's `browser` endpoint and its token. It lives as long as its computer does: a client that ends its session or goes away leaves the browser and its pages as they are, and the agent's `browser_close` is refused. Only an agent with `--access terminal` can stop it, with `browser_run_code_unsafe` or from its terminal.
59
70
 
60
71
  ## Commands
61
72
 
62
- | | |
63
- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------ |
64
- | `serve` | Run the service: `--listen` (127.0.0.1:7878), `--data` |
65
- | `info` | The service's version and isolation |
66
- | `create` | Make a computer: `--access`, `--browser`, `--workspace`, `--name`, `--timeout`, `--metadata KEY=VALUE` |
67
- | `list [--state]`, `get <id>`, `logs <id>` | Look at them |
68
- | `timeout <id> <seconds>` | It now stops this long from now |
69
- | `stop <id>`, `start <id> [--timeout]` | Stop it, keeping its folder and token; start it again |
70
- | `live <id> --surface [--mode]` | A one-time ticket to open one of its surfaces live; see [Live sessions](#live-sessions) |
71
- | `kill <id>` | Stop it and remove what the service made |
73
+ | | |
74
+ | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
75
+ | `serve` | Run the service: `--listen` (127.0.0.1:7878), `--data` |
76
+ | `up`, `down`, `status` | Run the service in the background, stop it, say where it is running |
77
+ | `info` | The service's version, its own isolation, and the isolations it can make now |
78
+ | `create` | Make a computer: `--access`, `--browser`, `--isolation`, `--workspace`, `--name`, `--timeout`, `--metadata KEY=VALUE` |
79
+ | `list [--state]`, `get <id>`, `logs <id>` | Look at them |
80
+ | `timeout <id> <seconds>` | It now stops this long from now |
81
+ | `stop <id>`, `start <id> [--timeout]` | Stop it, keeping its folder and token; start it again |
82
+ | `live <id> --surface [--mode]` | A one-time ticket to open one of its surfaces live; see [Live sessions](#live-sessions) |
83
+ | `kill <id>` | Stop it and remove what the service made |
84
+
85
+ **In the background.** `up` takes what `serve` takes, runs the service in the background for you, and returns once it answers, printing its `url`, `pid`, version and isolation. If one already answers for the data folder it prints that one and starts nothing. `status` prints the same, or exits 1 with none running. `down` ends it and says nothing; its computers stop with it, and start again when it next does. `serve` won't run beside a service that already answers for the same data folder. `--version` prints the program's version, with no service.
86
+
87
+ - What the service writes goes to `service.log` in the data folder, of which `up` keeps the last 1 MiB.
88
+ - It stays when whatever started it goes, and nothing starts it when the machine does. To have it at login, a shell profile can run `agentcomputer up`; a supervisor such as launchd or a systemd user unit is given `agentcomputer serve`, which it keeps in the foreground.
89
+ - `up`, `down` and `status` are for a service on this machine that this machine can reach at its address.
90
+ - `start` and `stop` are a computer's and take its id. With the id left out they stop nothing, and say so.
72
91
 
73
92
  With no `--workspace`, the service makes a folder, which goes when the computer is killed. A folder you name is never deleted. A computer with a `--timeout` stops when it runs out, and its folder stays.
74
93
 
75
94
  The service listens on loopback unless you give it TLS; see [Across a network](#across-a-network).
76
95
 
77
- The data folder is `--data`, else `$AGENTCOMPUTER_DATA`, else `$XDG_DATA_HOME/agentcomputer`, else `~/.local/share/agentcomputer`. It holds `control-token` and `server.json`, which the commands read.
96
+ The data folder is `--data`, else `$AGENTCOMPUTER_DATA`, else `$XDG_DATA_HOME/agentcomputer`, else `~/.local/share/agentcomputer`. It holds `control-token` and `server.json`, which the commands read; a `server.json` left by a service that crashed names nothing, and is seen through.
78
97
 
79
98
  ## API
80
99
 
@@ -195,10 +214,9 @@ A shell of your own needs [node-pty](https://github.com/microsoft/node-pty), an
195
214
 
196
215
  ## Known limits
197
216
 
198
- - With no isolation, each browser's Playwright MCP listens on a loopback port with no token of its own, so another user on the same machine could reach it directly. Don't run that on a machine you share.
199
217
  - A container has no CPU or memory limit, and its network is Docker's default, so it reaches the internet and anything else Docker's network does.
200
218
  - In a container the browser runs without its own sandbox, which needs privileges a computer doesn't have. The container is the boundary.
201
- - A browser that stops, or a container that ends by itself, shows the computer as `failed`, and what can no longer be opened live says so in `surfaces`. Stop the computer and start it again.
219
+ - A browser that stops, or a container that ends by itself, shows the computer as `failed`, and what can no longer be opened live says so in `surfaces`. So does a computer that couldn't be brought back when the service started, for one in a container because Docker didn't answer; its `logs` say why. Stop the computer and start it again.
202
220
  - A file being written through the `files` surface sits beside its path as `.agentexec-…` until its last part, where a listing, and the agent, can see it. It stays if the service dies meanwhile.
203
221
 
204
222
  ## Tests
@@ -1,4 +1,4 @@
1
- @agentorg/exec 0.0.7 (Apache-2.0)
1
+ @agentorg/exec 0.0.8 (Apache-2.0)
2
2
 
3
3
  Apache License
4
4
  Version 2.0, January 2004