@agentorg/computer 0.0.18 → 0.0.19

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
@@ -1,6 +1,6 @@
1
1
  # AgentComputer
2
2
 
3
- Computers for agents, as a service. Each computer is a working folder, a terminal and files from [AgentExec](https://github.com/uniac-ai/AgentExec) at a level you choose, and a browser from Playwright MCP if you ask for one. Any MCP client can use them.
3
+ Computers for agents, as a service. Each computer is a working folder, a terminal and files from [AgentExec](https://github.com/uniac-ai/AgentExec) at a level you choose, and a browser from Playwright MCP if you ask for one. It is this computer, the machine the service runs on, attached whole, or one made in a container of its own. Any MCP client can use them.
4
4
 
5
5
  ```sh
6
6
  npm install -g @agentorg/computer
@@ -13,23 +13,49 @@ In another terminal, or after `agentcomputer up`, which runs it in the backgroun
13
13
  agentcomputer create --access terminal --browser --workspace ~/some/folder
14
14
  ```
15
15
 
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>`.
16
+ That makes a computer in a container, which needs Docker, and prints its `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. 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.
18
+ ```sh
19
+ agentcomputer attach --access terminal --workspace ~/some/folder
20
+ ```
21
+
22
+ That gives an agent this computer instead: the machine the service runs on, whole, acting as you. With `--access terminal` it can reach everything you can. The folder is where its work starts, not a wall.
23
+
24
+ ## This computer and containers
19
25
 
20
- ## Isolation
26
+ Each computer is this computer, attached with `attach`, or one made in a container of its own with `create`. A container needs Docker on the service's machine. The service follows your `DOCKER_HOST` or current context and never changes them, and comes up without Docker.
21
27
 
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.
28
+ - **`info` says what the service offers**, each part ready or not and why, in a line a person reads:
29
+ - `thisComputer`: its capabilities (`about`, `terminal`, `files` and `screen`) and the browsers that can go with it. Its screen isn't reached yet: `This service can't reach the screen yet.`
30
+ - `made`, each kind it makes: today a container, ready while Docker answers, with its capabilities and browsers.
31
+ - **A container is refused with 409 where Docker doesn't answer:** `A container needs Docker, which isn't answering on this machine.` One already made isn't started there, and isn't killed there either, since its container couldn't be removed: both are refused with the same words, and it is kept.
32
+ - **A computer with no isolation is no longer made.** `create --isolation none` is refused with 400, and `attach` is what does that now.
33
+ - **Attach can be called as often as you like.** Each call attaches this computer as a computer of its own, with its own id, token and name, to give to one agent.
23
34
 
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.
35
+ This computer:
36
+
37
+ - **It is offered only by a service that no other machine reaches:** one that listens on loopback, with no `--tls-proxy` and no `--public-url`. A service that other machines can reach is a server, and doesn't offer its own machine. There `info` says why, attaching is refused with 409 in the same words, and a computer attached before is refused at start.
38
+ - **`--workspace`, which `attach` needs, is its work folder.** Commands and relative paths start there, and `about` names it. But its files reach the whole machine, as whoever started the service, and so do its commands at `--access terminal`.
39
+ - **`kill` detaches it.** What the service kept for it goes, and nothing of the machine's.
40
+ - **Its browser,** with `--browser`, is a headless one with a profile of its own. It runs the Chrome installed on the machine, or what `serve --browser-name` or `--browser-path` names. `info` says whether that program is there.
41
+
42
+ **Upgrading from 0.0.18 or earlier:**
43
+
44
+ - **`create` with no `--isolation` used to make a computer with no isolation.** It now makes a container, which needs Docker, and is refused with 409 without it. To work on this machine as before, `attach` with `--workspace`.
45
+ - **`serve` and `up` no longer take `--isolation`, and won't start with it.** Remove it from whatever starts the service: a shell profile, a launchd or systemd unit, a `docker run` line.
46
+ - **A computer made with no isolation isn't started again.** Its record and folder are kept.
47
+ - One that was running when the service last stopped is failed when it starts, and its `logs` say why. One that was stopped stays stopped.
48
+ - Starting it is refused with 409, in words that say where its folder is and what to do instead: `A computer with no isolation is no longer made. Its folder is kept at <path>. Attach this computer with that folder as its work folder, or make a container whose workspace starts as a copy of it.`
49
+ - In the API it is the one computer with `isolation` `none` and `attached` false, and its `workspace` is that folder.
50
+ - Killing it removes the rest of it and keeps that folder, even one the service made in its data folder. Kill it first, then attach this computer with the folder as its `--workspace`, or make a container whose workspace starts as a copy of it: `create --copy-from <path>`.
51
+ - **A computer recorded by 0.0.14 or earlier kept no isolation,** and is taken as made with none, which was the default then. If you made computers in containers with 0.0.14 or earlier, run 0.0.18 once first, started as it was last started, so that each one's isolation is recorded. Otherwise each is refused as above, and killing one leaves its container behind.
27
52
 
28
53
  A computer in a container:
29
54
 
30
55
  - 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.
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, and the data folder, where its home is. 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.
56
+ - `--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, and the data folder, where its home is. Without `--workspace`, the service makes one, in the data folder.
57
+ - `--copy-from DIR` (`copyFrom`), used instead of `--workspace`, has the folder the service makes start with a copy of what is in `DIR`, taken once when the computer is made. `DIR` itself is never mounted or changed. Links are copied as they are, and sockets, pipes and devices are left out. It needs `--access` other than `none`.
58
+ - The image is fetched the first time it is needed, which can take minutes: when the first computer in a container is made, a call that then waits for it. `docker pull` it beforehand to spare that wait.
33
59
  - It runs as the user who started the service, with no capabilities.
34
60
  - Its home, `/home/computer`, is a folder of the machine's, in the computer's own folder in the data folder, mounted as the workspace is. What the agent keeps there stays, the browser's profile with its sign-ins among it. `stop` stops the container and keeps it, and `kill` removes it with the computer's folder.
35
61
  - **After an update,** a computer in a container is made again at its first start under a new version of the service, or under another `--image`: its container is removed and made again from the service's image. It keeps its workspace, its home, and its id, token, endpoints and settings. It loses its running commands, as at any restart, and everything else in the container: software installed there, and files outside `/workspace` and `/home/computer`, such as `/tmp`. Keep what must last in those two folders, or in an image of your own. Every computer's answer says the `version` of the program it runs.
@@ -53,45 +79,46 @@ A computer in a container:
53
79
  | `Where` | The machine's own name |
54
80
  | `Folder` | The workspace's path on that machine, as a path |
55
81
  | `Reaches` | `Read-only files`, `Files`, or `Files and terminal`; with a browser, `, Browser` after it |
56
- | `Isolation` | `None: it acts as you`, as a caution, or `A container of its own` |
82
+ | `Isolation` | `None: it acts as you, on the whole machine`, as a caution, or `A container of its own` |
57
83
  | `CPU` | Used, of all the machine's CPUs, as a whole percentage: `37%` |
58
84
  | `Memory` | Used of the machine's total, counted in 1024s and written GB: `9.2 of 16 GB` |
59
85
  | `Disk` | Used of total, of the volume the workspace is on, counted in 1000s: `212 of 494 GB` |
60
86
 
61
- - **In a container** the agent's commands find the folder somewhere else, so `Folder` says both and is not marked as a path: `/home/me/Research on the machine, mounted at /workspace in it`. CPU and Memory there are the computer's own; with no isolation they are the whole machine's.
87
+ - **In a container** the agent's commands find the folder somewhere else, so `Folder` says both and is not marked as a path: `/home/me/Research on the machine, mounted at /workspace in it`. CPU and Memory there are the computer's own; on this computer they are the whole machine's.
62
88
  - **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.
63
89
  - **Not every computer has it.** One with no `computer` endpoint has no `about`.
64
90
 
65
- 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.
91
+ 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, on this computer and in a container.
66
92
 
67
- 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.
93
+ In a container the file tools stay inside the workspace, which is a check and not a boundary: the container is the boundary. On this computer they reach the whole machine. 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.
68
94
 
69
95
  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 its container is made again.
70
96
 
71
- `--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.
97
+ 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.
72
98
 
73
99
  ## Commands
74
100
 
75
- | | |
76
- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
77
- | `serve` | Run the service: `--listen` (127.0.0.1:7878), `--data` |
78
- | `up`, `down`, `status` | Run the service in the background, stop it, say where it is running |
79
- | `info` | The service's version, its own isolation, and the isolations it can make now |
80
- | `create` | Make a computer: `--access`, `--browser`, `--isolation`, `--workspace`, `--name`, `--timeout`, `--metadata KEY=VALUE` |
81
- | `list [--state]`, `get <id>`, `logs <id>` | Look at them |
82
- | `timeout <id> <seconds>` | It now stops this long from now |
83
- | `stop <id>`, `start <id> [--timeout]` | Stop it, keeping its folder and token; start it again |
84
- | `live <id> --surface [--mode]` | A one-time ticket to open one of its surfaces live; see [Live sessions](#live-sessions) |
85
- | `kill <id>` | Stop it and remove what the service made |
86
-
87
- **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.
101
+ | | |
102
+ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
103
+ | `serve` | Run the service: `--listen` (127.0.0.1:7878), `--data` |
104
+ | `up`, `down`, `status` | Run the service in the background, stop it, say where it is running |
105
+ | `info` | The service's version and what it offers: this computer, and the kinds it makes, each ready or not |
106
+ | `create` | Make a computer: `--access`, `--browser`, `--isolation`, `--workspace` or `--copy-from`, `--name`, `--timeout`, `--metadata KEY=VALUE` |
107
+ | `attach` | Attach this computer: `--access`, `--workspace`, `--browser`, `--name`, `--timeout`, `--metadata KEY=VALUE` |
108
+ | `list [--state]`, `get <id>`, `logs <id>` | Look at them |
109
+ | `timeout <id> <seconds>` | It now stops this long from now |
110
+ | `stop <id>`, `start <id> [--timeout]` | Stop it, keeping its folder and token; start it again |
111
+ | `live <id> --surface [--mode]` | A one-time ticket to open one of its surfaces live; see [Live sessions](#live-sessions) |
112
+ | `kill <id>` | Stop it and remove what the service made; this computer, detach it |
113
+
114
+ **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` and version. 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.
88
115
 
89
116
  - What the service writes goes to `service.log` in the data folder, of which `up` keeps the last 1 MiB.
90
117
  - 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.
91
118
  - `up`, `down` and `status` are for a service on this machine that this machine can reach at its address.
92
119
  - `start` and `stop` are a computer's and take its id. With the id left out they stop nothing, and say so.
93
120
 
94
- 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.
121
+ Made with no `--workspace`, a computer has a folder the service makes, which goes when it is killed, unless it was made with no isolation by an earlier version. A folder you name is never deleted. A computer with a `--timeout` stops when it runs out, and its folder stays.
95
122
 
96
123
  The service listens on loopback unless you give it TLS; see [Across a network](#across-a-network).
97
124
 
@@ -105,6 +132,7 @@ The data folder is `--data`, else `$AGENTCOMPUTER_DATA`, else `$XDG_DATA_HOME/ag
105
132
  | ----------------------------------------- | ---------------------- |
106
133
  | `GET /v1/info` | `service_info` |
107
134
  | `POST /v1/computers` | `computer_create` |
135
+ | `POST /v1/computers/attach` | `computer_attach` |
108
136
  | `GET /v1/computers` | `computer_list` |
109
137
  | `GET /v1/computers/{computerID}` | `computer_get` |
110
138
  | `DELETE /v1/computers/{computerID}` | `computer_kill` |
@@ -121,7 +149,7 @@ These take the control token, kept in the data folder. A computer's own endpoint
121
149
  /v1/computers/{computerID}/mcp/browser MCP over Streamable HTTP
122
150
  ```
123
151
 
124
- `POST /v1/computers` is the only place an `accessToken` is shown. Failures are `{ "code": 404, "message": "..." }`.
152
+ `POST /v1/computers` and `POST /v1/computers/attach` are the only places an `accessToken` is shown. Failures are `{ "code": 404, "message": "..." }`.
125
153
 
126
154
  ## SDK
127
155
 
@@ -129,6 +157,7 @@ These take the control token, kept in the data folder. A computer's own endpoint
129
157
  import { Computer } from "@agentorg/computer";
130
158
 
131
159
  const computer = await Computer.create({ access: "terminal", browser: true, timeoutMs: 600_000 });
160
+ // Or this computer: await Computer.attach({ access: "terminal", workspace: "/home/me/work" });
132
161
  const { exitCode, output } = await computer.commands.run("ls -la");
133
162
  await computer.files.write("notes.txt", "hello\n");
134
163
  const notes = await computer.files.read("notes.txt");
@@ -162,14 +191,14 @@ docker run -d --name agentcomputer --network host \
162
191
  -v /var/run/docker.sock:/var/run/docker.sock \
163
192
  -v /srv/agentcomputer:/srv/agentcomputer \
164
193
  ghcr.io/uniac-ai/agentcomputer/service:VERSION \
165
- serve --isolation container --data /srv/agentcomputer --listen 0.0.0.0:7878 \
194
+ serve --data /srv/agentcomputer --listen 0.0.0.0:7878 \
166
195
  --tls-cert /srv/agentcomputer/cert.pem --tls-key /srv/agentcomputer/key.pem \
167
196
  --public-url https://computers.example.com:7878
168
197
  ```
169
198
 
170
199
  - Its data folder, and any `--workspace`, have to be mounted at the same path inside as outside, because Docker reads those paths on the machine.
171
200
  - `--network host` is how it reaches each computer's port on the machine's loopback, so this needs Linux.
172
- - The socket gives it full control of that machine's Docker. Whoever holds the control token can make computers, but not reach the socket.
201
+ - The socket gives it full control of that machine's Docker. Whoever holds the control token can make computers, but not reach the socket: a service that other machines reach doesn't offer this computer, which here is its own container.
173
202
 
174
203
  ## Live sessions
175
204
 
@@ -206,7 +235,7 @@ A computer with `--browser` has another:
206
235
  Every running computer has one more, to watch only:
207
236
 
208
237
  - **`load`** (protocol `metrics@1`): how busy it is. The service sends a reading every two seconds while a socket is open, the first two seconds after the first socket opens, and the last one at once to a socket that opens later: `{"type":"reading","scope":"machine","cpuUsedPct":37.2,"memUsed":…,"memTotal":…,"diskUsed":…,"diskTotal":…}`, in bytes. `openapi.yaml` has each field, as `LoadReading`.
209
- - **`scope` says whose numbers they are.** A computer in a container reads its own (`computer`), against the machine's totals, since a container has no limit of its own. A computer with no isolation has no edge to measure at, so it reads the whole machine's (`machine`), as every other computer of that service does; so does a container that can't read its own.
238
+ - **`scope` says whose numbers they are.** A computer in a container reads its own (`computer`), against the machine's totals, since a container has no limit of its own. This computer has no edge to measure at, so it reads the whole machine's (`machine`); so does a container that can't read its own.
210
239
  - **The disk is the volume its workspace is on,** not the workspace's own size.
211
240
  - **Nothing depends on it.** Nothing is read while nobody watches or asks, a reading that can't be taken is left out, and a socket that hasn't read the one before is not sent the next.
212
241
 
@@ -1,4 +1,4 @@
1
- @agentorg/exec 0.0.8 (Apache-2.0)
1
+ @agentorg/exec 0.0.9 (Apache-2.0)
2
2
 
3
3
  Apache License
4
4
  Version 2.0, January 2004