@agentorg/computer 0.0.16 → 0.0.17
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 +8 -6
- package/dist/agentcomputer.js +149 -44
- package/dist/types/generated/schema.d.ts +2 -0
- package/dist/types/sdk.d.ts +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,10 +28,12 @@ Isolation is chosen for each computer when it is made, and it keeps it until it
|
|
|
28
28
|
A computer in a container:
|
|
29
29
|
|
|
30
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.
|
|
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.
|
|
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
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.
|
|
33
33
|
- It runs as the user who started the service, with no capabilities.
|
|
34
|
-
-
|
|
34
|
+
- 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
|
+
- **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.
|
|
36
|
+
- A container made before 0.0.17 keeps its home inside it. At its first remake the home is copied out. If that fails, the container is kept and started as it was, its `logs` say why, and the copy is tried again at its next start. Until it is made again, its `version` is `null`.
|
|
35
37
|
|
|
36
38
|
## Access
|
|
37
39
|
|
|
@@ -42,7 +44,7 @@ A computer in a container:
|
|
|
42
44
|
| `terminal` | Those, and `exec_command`, `write_stdin`, `list_sessions` |
|
|
43
45
|
| `none` | No `computer` endpoint; needs `--browser` |
|
|
44
46
|
|
|
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.
|
|
47
|
+
`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.
|
|
46
48
|
|
|
47
49
|
`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:
|
|
48
50
|
|
|
@@ -58,13 +60,13 @@ A computer in a container:
|
|
|
58
60
|
|
|
59
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.
|
|
60
62
|
- **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.
|
|
61
|
-
- **Not every computer has it.** One with no `computer` endpoint has no `about`.
|
|
63
|
+
- **Not every computer has it.** One with no `computer` endpoint has no `about`.
|
|
62
64
|
|
|
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.
|
|
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.
|
|
64
66
|
|
|
65
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.
|
|
66
68
|
|
|
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
|
|
69
|
+
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.
|
|
68
70
|
|
|
69
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.
|
|
70
72
|
|
package/dist/agentcomputer.js
CHANGED
|
@@ -3875,7 +3875,7 @@ async function serveBrowserMcp(options) {
|
|
|
3875
3875
|
|
|
3876
3876
|
// src/container.ts
|
|
3877
3877
|
import { execFile as execFile2, spawn as spawn3 } from "node:child_process";
|
|
3878
|
-
import { readFileSync as readFileSync3 } from "node:fs";
|
|
3878
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, renameSync as renameSync2, rmSync as rmSync4 } from "node:fs";
|
|
3879
3879
|
import { connect } from "node:net";
|
|
3880
3880
|
import { hostname as hostname4 } from "node:os";
|
|
3881
3881
|
import { join as join8 } from "node:path";
|
|
@@ -67957,6 +67957,33 @@ var ProcessRuntime = class {
|
|
|
67957
67957
|
}
|
|
67958
67958
|
};
|
|
67959
67959
|
|
|
67960
|
+
// src/handlers.ts
|
|
67961
|
+
var VERSION2 = "0.0.17";
|
|
67962
|
+
function createHandlers(computers) {
|
|
67963
|
+
return {
|
|
67964
|
+
getInfo: async () => ({
|
|
67965
|
+
version: VERSION2,
|
|
67966
|
+
isolation: computers.isolation,
|
|
67967
|
+
isolationsAvailable: await computers.available()
|
|
67968
|
+
}),
|
|
67969
|
+
listComputers: async ({ state }) => computers.list(state),
|
|
67970
|
+
createComputer: (input2) => computers.create(input2),
|
|
67971
|
+
getComputer: async ({ computerID }) => computers.get(computerID),
|
|
67972
|
+
killComputer: async ({ computerID }) => {
|
|
67973
|
+
await computers.kill(computerID);
|
|
67974
|
+
return void 0;
|
|
67975
|
+
},
|
|
67976
|
+
setComputerTimeout: async ({ computerID, timeout }) => computers.setTimeout(computerID, timeout),
|
|
67977
|
+
stopComputer: ({ computerID }) => computers.stop(computerID),
|
|
67978
|
+
startComputer: ({ computerID, timeout }) => computers.start(computerID, timeout),
|
|
67979
|
+
getComputerLogs: async ({ computerID }) => ({ logs: computers.logs(computerID) }),
|
|
67980
|
+
createLiveSession: async ({ computerID, surface, mode }) => computers.liveSession(computerID, surface, mode ?? "watch"),
|
|
67981
|
+
openLiveSession: async () => {
|
|
67982
|
+
throw new ApiError(426, "Open it as a WebSocket.");
|
|
67983
|
+
}
|
|
67984
|
+
};
|
|
67985
|
+
}
|
|
67986
|
+
|
|
67960
67987
|
// src/inside.ts
|
|
67961
67988
|
var INNER_PORT = 8e3;
|
|
67962
67989
|
var INNER_TOKEN_VARIABLE = "AGENTCOMPUTER_INNER_TOKEN";
|
|
@@ -67997,7 +68024,7 @@ async function serveInside(options) {
|
|
|
67997
68024
|
if (pathname === "/ready") {
|
|
67998
68025
|
const { browserTools, surfaces } = await running2;
|
|
67999
68026
|
response.writeHead(200, { "Content-Type": "application/json" });
|
|
68000
|
-
return void response.end(JSON.stringify({ browserTools, surfaces }));
|
|
68027
|
+
return void response.end(JSON.stringify({ browserTools, surfaces, version: VERSION2 }));
|
|
68001
68028
|
}
|
|
68002
68029
|
const endpoint = /^\/mcp\/(computer|browser)$/.exec(pathname)?.[1];
|
|
68003
68030
|
if (!endpoint) return void response.writeHead(404).end();
|
|
@@ -68056,10 +68083,15 @@ var UPGRADE_HEADERS = [
|
|
|
68056
68083
|
"sec-websocket-extensions",
|
|
68057
68084
|
"sec-websocket-protocol"
|
|
68058
68085
|
];
|
|
68086
|
+
var messageOf = (error62) => error62 instanceof Error ? error62.message : String(error62);
|
|
68059
68087
|
var nameOf = (id) => `agentcomputer-${id}`;
|
|
68088
|
+
var HOME = "/home/computer";
|
|
68089
|
+
var homeOf = (folder) => join8(folder, "home");
|
|
68060
68090
|
var sleep5 = (ms) => new Promise((done) => setTimeout(done, ms));
|
|
68061
68091
|
var ContainerRuntime = class {
|
|
68062
68092
|
#image;
|
|
68093
|
+
/** The id of that image, as it is now on this machine. */
|
|
68094
|
+
#imageId;
|
|
68063
68095
|
constructor(image) {
|
|
68064
68096
|
this.#image = image;
|
|
68065
68097
|
}
|
|
@@ -68083,12 +68115,14 @@ var ContainerRuntime = class {
|
|
|
68083
68115
|
}
|
|
68084
68116
|
async prepare() {
|
|
68085
68117
|
await this.#docker();
|
|
68118
|
+
const id = () => docker(["image", "inspect", "--format", "{{.Id}}", this.#image]);
|
|
68086
68119
|
try {
|
|
68087
|
-
await
|
|
68120
|
+
this.#imageId = await id();
|
|
68088
68121
|
} catch {
|
|
68089
68122
|
process.stdout.write(`Pulling ${this.#image}
|
|
68090
68123
|
`);
|
|
68091
68124
|
await docker(["pull", this.#image]);
|
|
68125
|
+
this.#imageId = await id();
|
|
68092
68126
|
}
|
|
68093
68127
|
}
|
|
68094
68128
|
async #inspect(name) {
|
|
@@ -68098,7 +68132,39 @@ var ContainerRuntime = class {
|
|
|
68098
68132
|
return void 0;
|
|
68099
68133
|
}
|
|
68100
68134
|
}
|
|
68101
|
-
|
|
68135
|
+
/**
|
|
68136
|
+
* Remove a container made from another image, for it to be made again. What it keeps is outside
|
|
68137
|
+
* it: its workspace, and its home. One made before its home was outside has its home copied out
|
|
68138
|
+
* first, and if that can't be done it is kept as it is, to try again at its next start.
|
|
68139
|
+
*/
|
|
68140
|
+
async #remake(name, made, folder, events) {
|
|
68141
|
+
if (!made.Mounts.some((mount) => mount.Destination === HOME)) {
|
|
68142
|
+
const home = homeOf(folder);
|
|
68143
|
+
const copying = `${home}.copying`;
|
|
68144
|
+
rmSync4(copying, { recursive: true, force: true });
|
|
68145
|
+
try {
|
|
68146
|
+
const owners = process.getuid?.() ? [] : ["--archive"];
|
|
68147
|
+
await docker(["cp", ...owners, `${name}:${HOME}`, copying]);
|
|
68148
|
+
rmSync4(home, { recursive: true, force: true });
|
|
68149
|
+
renameSync2(copying, home);
|
|
68150
|
+
} catch (error62) {
|
|
68151
|
+
rmSync4(copying, { recursive: true, force: true });
|
|
68152
|
+
events.log(
|
|
68153
|
+
`Its home couldn't be copied out of its container (${messageOf(error62)}), so the container is kept and started as it was made. The copy is tried again at its next start.`
|
|
68154
|
+
);
|
|
68155
|
+
return;
|
|
68156
|
+
}
|
|
68157
|
+
events.log("Its home was copied out of its container, to keep.");
|
|
68158
|
+
}
|
|
68159
|
+
await docker(["rm", "--force", name]);
|
|
68160
|
+
events.log(
|
|
68161
|
+
`Its container was made from another image, so it is made again from ${this.#image}.`
|
|
68162
|
+
);
|
|
68163
|
+
}
|
|
68164
|
+
async #create(name, spec, token, folder) {
|
|
68165
|
+
const home = homeOf(folder);
|
|
68166
|
+
mkdirSync2(home, { recursive: true });
|
|
68167
|
+
chmodSync3(home, 1023);
|
|
68102
68168
|
const uid = process.getuid?.();
|
|
68103
68169
|
const told = {
|
|
68104
68170
|
[INNER_TOKEN_VARIABLE]: token,
|
|
@@ -68122,6 +68188,8 @@ var ContainerRuntime = class {
|
|
|
68122
68188
|
...Object.keys(told).flatMap((name2) => ["--env", name2]),
|
|
68123
68189
|
// Files it writes in the workspace belong to whoever runs the service.
|
|
68124
68190
|
...uid ? ["--user", `${uid}:${process.getgid?.()}`] : [],
|
|
68191
|
+
"--mount",
|
|
68192
|
+
`type=bind,source=${home},target=${HOME}`,
|
|
68125
68193
|
...spec.workspace ? [
|
|
68126
68194
|
"--mount",
|
|
68127
68195
|
`type=bind,source=${spec.workspace},target=/workspace${spec.access === "read" ? ",readonly" : ""}`
|
|
@@ -68149,7 +68217,10 @@ var ContainerRuntime = class {
|
|
|
68149
68217
|
async start(spec, folder, events) {
|
|
68150
68218
|
const name = nameOf(spec.id);
|
|
68151
68219
|
const token = this.#tokenIn(folder);
|
|
68152
|
-
|
|
68220
|
+
const made = await this.#inspect(name);
|
|
68221
|
+
if (made && this.#imageId && made.Image !== this.#imageId)
|
|
68222
|
+
await this.#remake(name, made, folder, events);
|
|
68223
|
+
if (!await this.#inspect(name)) await this.#create(name, spec, token, folder);
|
|
68153
68224
|
await docker(["start", name]);
|
|
68154
68225
|
const inspected = await this.#inspect(name);
|
|
68155
68226
|
const port = inspected?.NetworkSettings.Ports[`${INNER_PORT}/tcp`]?.[0]?.HostPort;
|
|
@@ -68186,6 +68257,7 @@ var ContainerRuntime = class {
|
|
|
68186
68257
|
}
|
|
68187
68258
|
return {
|
|
68188
68259
|
browserTools: ready.browserTools,
|
|
68260
|
+
version: ready.version,
|
|
68189
68261
|
/** As they are now: nothing of a container that has stopped can be opened. */
|
|
68190
68262
|
get surfaces() {
|
|
68191
68263
|
return ready.surfaces.map(
|
|
@@ -68278,33 +68350,6 @@ async function forward(url3, authorization, request, response) {
|
|
|
68278
68350
|
sendAnswer(upstream, response);
|
|
68279
68351
|
}
|
|
68280
68352
|
|
|
68281
|
-
// src/handlers.ts
|
|
68282
|
-
var VERSION2 = "0.0.16";
|
|
68283
|
-
function createHandlers(computers) {
|
|
68284
|
-
return {
|
|
68285
|
-
getInfo: async () => ({
|
|
68286
|
-
version: VERSION2,
|
|
68287
|
-
isolation: computers.isolation,
|
|
68288
|
-
isolationsAvailable: await computers.available()
|
|
68289
|
-
}),
|
|
68290
|
-
listComputers: async ({ state }) => computers.list(state),
|
|
68291
|
-
createComputer: (input2) => computers.create(input2),
|
|
68292
|
-
getComputer: async ({ computerID }) => computers.get(computerID),
|
|
68293
|
-
killComputer: async ({ computerID }) => {
|
|
68294
|
-
await computers.kill(computerID);
|
|
68295
|
-
return void 0;
|
|
68296
|
-
},
|
|
68297
|
-
setComputerTimeout: async ({ computerID, timeout }) => computers.setTimeout(computerID, timeout),
|
|
68298
|
-
stopComputer: ({ computerID }) => computers.stop(computerID),
|
|
68299
|
-
startComputer: ({ computerID, timeout }) => computers.start(computerID, timeout),
|
|
68300
|
-
getComputerLogs: async ({ computerID }) => ({ logs: computers.logs(computerID) }),
|
|
68301
|
-
createLiveSession: async ({ computerID, surface, mode }) => computers.liveSession(computerID, surface, mode ?? "watch"),
|
|
68302
|
-
openLiveSession: async () => {
|
|
68303
|
-
throw new ApiError(426, "Open it as a WebSocket.");
|
|
68304
|
-
}
|
|
68305
|
-
};
|
|
68306
|
-
}
|
|
68307
|
-
|
|
68308
68353
|
// src/running.ts
|
|
68309
68354
|
import { spawn as spawn4 } from "node:child_process";
|
|
68310
68355
|
import { closeSync, openSync, readFileSync as readFileSync4, statSync as statSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
@@ -69177,7 +69222,7 @@ var Computer = class _Computer {
|
|
|
69177
69222
|
};
|
|
69178
69223
|
|
|
69179
69224
|
// src/service.ts
|
|
69180
|
-
import { readFileSync as readFileSync6, rmSync as
|
|
69225
|
+
import { readFileSync as readFileSync6, rmSync as rmSync6 } from "node:fs";
|
|
69181
69226
|
import {
|
|
69182
69227
|
createServer as createServer5,
|
|
69183
69228
|
STATUS_CODES as STATUS_CODES3
|
|
@@ -84997,7 +85042,7 @@ var NodeStreamableHTTPServerTransport2 = class {
|
|
|
84997
85042
|
|
|
84998
85043
|
// src/computers.ts
|
|
84999
85044
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
85000
|
-
import { appendFileSync, existsSync as existsSync2, mkdirSync as
|
|
85045
|
+
import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync5, rmSync as rmSync5, statSync as statSync4 } from "node:fs";
|
|
85001
85046
|
import { isAbsolute, join as join10, resolve as resolve4 } from "node:path";
|
|
85002
85047
|
var READ = ["about", "read", "list", "search"];
|
|
85003
85048
|
var FILES = [...READ, "edit"];
|
|
@@ -85010,8 +85055,8 @@ var MAX_LOG2 = 256 * 1024;
|
|
|
85010
85055
|
var MAX_TIMER_S = 2e6;
|
|
85011
85056
|
var TICKET_MS = 6e4;
|
|
85012
85057
|
var expiry = (seconds2) => new Date(Date.now() + seconds2 * 1e3).toISOString();
|
|
85013
|
-
var
|
|
85014
|
-
var refusalOf = (error62) => error62 instanceof ApiError ? error62 : new ApiError(500,
|
|
85058
|
+
var messageOf2 = (error62) => error62 instanceof Error ? error62.message : String(error62);
|
|
85059
|
+
var refusalOf = (error62) => error62 instanceof ApiError ? error62 : new ApiError(500, messageOf2(error62));
|
|
85015
85060
|
var Computers = class {
|
|
85016
85061
|
#data;
|
|
85017
85062
|
#base;
|
|
@@ -85045,7 +85090,7 @@ var Computers = class {
|
|
|
85045
85090
|
if (stored.endAt && Date.parse(stored.endAt) <= Date.now()) {
|
|
85046
85091
|
stored.state = "stopped";
|
|
85047
85092
|
await this.#runtimes[stored.isolation].stopLeftover(stored.id).catch(
|
|
85048
|
-
(error62) => this.#log(stored.id, `What it left running wasn't stopped: ${
|
|
85093
|
+
(error62) => this.#log(stored.id, `What it left running wasn't stopped: ${messageOf2(error62)}`)
|
|
85049
85094
|
);
|
|
85050
85095
|
continue;
|
|
85051
85096
|
}
|
|
@@ -85053,7 +85098,7 @@ var Computers = class {
|
|
|
85053
85098
|
const live = this.#live.get(stored.id);
|
|
85054
85099
|
if (live) live.failed = true;
|
|
85055
85100
|
this.#arm(stored);
|
|
85056
|
-
this.#log(stored.id, `It didn't start again: ${
|
|
85101
|
+
this.#log(stored.id, `It didn't start again: ${messageOf2(error62)}`);
|
|
85057
85102
|
});
|
|
85058
85103
|
}
|
|
85059
85104
|
this.#save();
|
|
@@ -85092,7 +85137,7 @@ var Computers = class {
|
|
|
85092
85137
|
};
|
|
85093
85138
|
if (!workspace && access !== "none") {
|
|
85094
85139
|
stored.workspace = join10(this.#folder(id), "workspace");
|
|
85095
|
-
|
|
85140
|
+
mkdirSync3(stored.workspace, { recursive: true, mode: 448 });
|
|
85096
85141
|
}
|
|
85097
85142
|
this.#stored.set(id, stored);
|
|
85098
85143
|
try {
|
|
@@ -85102,7 +85147,7 @@ var Computers = class {
|
|
|
85102
85147
|
this.#stored.delete(id);
|
|
85103
85148
|
await this.#runtimes[stored.isolation].remove(id).catch(() => {
|
|
85104
85149
|
});
|
|
85105
|
-
|
|
85150
|
+
rmSync5(this.#folder(id), { recursive: true, force: true });
|
|
85106
85151
|
throw refusalOf(error62);
|
|
85107
85152
|
}
|
|
85108
85153
|
this.#save();
|
|
@@ -85176,7 +85221,7 @@ var Computers = class {
|
|
|
85176
85221
|
}
|
|
85177
85222
|
this.#stored.delete(id);
|
|
85178
85223
|
this.#save();
|
|
85179
|
-
|
|
85224
|
+
rmSync5(this.#folder(id), { recursive: true, force: true });
|
|
85180
85225
|
}
|
|
85181
85226
|
logs(id) {
|
|
85182
85227
|
this.#found(id);
|
|
@@ -85277,6 +85322,7 @@ var Computers = class {
|
|
|
85277
85322
|
state: stored.state === "running" && down2 ? "failed" : stored.state,
|
|
85278
85323
|
access: stored.access,
|
|
85279
85324
|
isolation: stored.isolation,
|
|
85325
|
+
version: stored.version ?? null,
|
|
85280
85326
|
browser: stored.browser,
|
|
85281
85327
|
workspace: stored.workspace ?? null,
|
|
85282
85328
|
startedAt: stored.startedAt,
|
|
@@ -85310,6 +85356,9 @@ var Computers = class {
|
|
|
85310
85356
|
}
|
|
85311
85357
|
}
|
|
85312
85358
|
);
|
|
85359
|
+
const version3 = stored.isolation === "none" ? VERSION2 : live.running.version;
|
|
85360
|
+
if (version3) stored.version = version3;
|
|
85361
|
+
else delete stored.version;
|
|
85313
85362
|
this.#arm(stored);
|
|
85314
85363
|
}
|
|
85315
85364
|
#arm(stored) {
|
|
@@ -85347,7 +85396,7 @@ var OPENAPI = {
|
|
|
85347
85396
|
"openapi": "3.1.0",
|
|
85348
85397
|
"info": {
|
|
85349
85398
|
"title": "AgentComputer",
|
|
85350
|
-
"version": "0.0.
|
|
85399
|
+
"version": "0.0.17",
|
|
85351
85400
|
"description": "Computers for agents. This file is the source of truth: the HTTP API, the MCP control tools and the SDK are all generated from it. An operation with `x-mcp-tool` is also an MCP tool of that name.",
|
|
85352
85401
|
"license": {
|
|
85353
85402
|
"name": "Apache-2.0",
|
|
@@ -85901,6 +85950,7 @@ var OPENAPI = {
|
|
|
85901
85950
|
"state",
|
|
85902
85951
|
"access",
|
|
85903
85952
|
"isolation",
|
|
85953
|
+
"version",
|
|
85904
85954
|
"browser",
|
|
85905
85955
|
"workspace",
|
|
85906
85956
|
"startedAt",
|
|
@@ -85925,6 +85975,13 @@ var OPENAPI = {
|
|
|
85925
85975
|
"$ref": "#/components/schemas/Isolation",
|
|
85926
85976
|
"description": "The isolation it was made in. It is never run in another."
|
|
85927
85977
|
},
|
|
85978
|
+
"version": {
|
|
85979
|
+
"type": [
|
|
85980
|
+
"string",
|
|
85981
|
+
"null"
|
|
85982
|
+
],
|
|
85983
|
+
"description": "The version of the program it ran at its last start. With no isolation it is the service's `version` (see `getInfo`). In a container it is the version inside its image, and null for a container made before 0.0.17, which doesn't say, until it is made again. It is kept from its last start, so a stopped computer's can be older than the service's until it starts. Compare it with the service's to show that a computer runs an older program."
|
|
85984
|
+
},
|
|
85928
85985
|
"browser": {
|
|
85929
85986
|
"type": "boolean"
|
|
85930
85987
|
},
|
|
@@ -87196,6 +87253,7 @@ var OPERATIONS = [
|
|
|
87196
87253
|
"state",
|
|
87197
87254
|
"access",
|
|
87198
87255
|
"isolation",
|
|
87256
|
+
"version",
|
|
87199
87257
|
"browser",
|
|
87200
87258
|
"workspace",
|
|
87201
87259
|
"startedAt",
|
|
@@ -87237,6 +87295,13 @@ var OPERATIONS = [
|
|
|
87237
87295
|
],
|
|
87238
87296
|
"description": "The isolation it was made in. It is never run in another."
|
|
87239
87297
|
},
|
|
87298
|
+
"version": {
|
|
87299
|
+
"type": [
|
|
87300
|
+
"string",
|
|
87301
|
+
"null"
|
|
87302
|
+
],
|
|
87303
|
+
"description": "The version of the program it ran at its last start. With no isolation it is the service's `version` (see `getInfo`). In a container it is the version inside its image, and null for a container made before 0.0.17, which doesn't say, until it is made again. It is kept from its last start, so a stopped computer's can be older than the service's until it starts. Compare it with the service's to show that a computer runs an older program."
|
|
87304
|
+
},
|
|
87240
87305
|
"browser": {
|
|
87241
87306
|
"type": "boolean"
|
|
87242
87307
|
},
|
|
@@ -87373,6 +87438,7 @@ var OPERATIONS = [
|
|
|
87373
87438
|
"state",
|
|
87374
87439
|
"access",
|
|
87375
87440
|
"isolation",
|
|
87441
|
+
"version",
|
|
87376
87442
|
"browser",
|
|
87377
87443
|
"workspace",
|
|
87378
87444
|
"startedAt",
|
|
@@ -87414,6 +87480,13 @@ var OPERATIONS = [
|
|
|
87414
87480
|
],
|
|
87415
87481
|
"description": "The isolation it was made in. It is never run in another."
|
|
87416
87482
|
},
|
|
87483
|
+
"version": {
|
|
87484
|
+
"type": [
|
|
87485
|
+
"string",
|
|
87486
|
+
"null"
|
|
87487
|
+
],
|
|
87488
|
+
"description": "The version of the program it ran at its last start. With no isolation it is the service's `version` (see `getInfo`). In a container it is the version inside its image, and null for a container made before 0.0.17, which doesn't say, until it is made again. It is kept from its last start, so a stopped computer's can be older than the service's until it starts. Compare it with the service's to show that a computer runs an older program."
|
|
87489
|
+
},
|
|
87417
87490
|
"browser": {
|
|
87418
87491
|
"type": "boolean"
|
|
87419
87492
|
},
|
|
@@ -87523,6 +87596,7 @@ var OPERATIONS = [
|
|
|
87523
87596
|
"state",
|
|
87524
87597
|
"access",
|
|
87525
87598
|
"isolation",
|
|
87599
|
+
"version",
|
|
87526
87600
|
"browser",
|
|
87527
87601
|
"workspace",
|
|
87528
87602
|
"startedAt",
|
|
@@ -87564,6 +87638,13 @@ var OPERATIONS = [
|
|
|
87564
87638
|
],
|
|
87565
87639
|
"description": "The isolation it was made in. It is never run in another."
|
|
87566
87640
|
},
|
|
87641
|
+
"version": {
|
|
87642
|
+
"type": [
|
|
87643
|
+
"string",
|
|
87644
|
+
"null"
|
|
87645
|
+
],
|
|
87646
|
+
"description": "The version of the program it ran at its last start. With no isolation it is the service's `version` (see `getInfo`). In a container it is the version inside its image, and null for a container made before 0.0.17, which doesn't say, until it is made again. It is kept from its last start, so a stopped computer's can be older than the service's until it starts. Compare it with the service's to show that a computer runs an older program."
|
|
87647
|
+
},
|
|
87567
87648
|
"browser": {
|
|
87568
87649
|
"type": "boolean"
|
|
87569
87650
|
},
|
|
@@ -87764,6 +87845,7 @@ var OPERATIONS = [
|
|
|
87764
87845
|
"state",
|
|
87765
87846
|
"access",
|
|
87766
87847
|
"isolation",
|
|
87848
|
+
"version",
|
|
87767
87849
|
"browser",
|
|
87768
87850
|
"workspace",
|
|
87769
87851
|
"startedAt",
|
|
@@ -87805,6 +87887,13 @@ var OPERATIONS = [
|
|
|
87805
87887
|
],
|
|
87806
87888
|
"description": "The isolation it was made in. It is never run in another."
|
|
87807
87889
|
},
|
|
87890
|
+
"version": {
|
|
87891
|
+
"type": [
|
|
87892
|
+
"string",
|
|
87893
|
+
"null"
|
|
87894
|
+
],
|
|
87895
|
+
"description": "The version of the program it ran at its last start. With no isolation it is the service's `version` (see `getInfo`). In a container it is the version inside its image, and null for a container made before 0.0.17, which doesn't say, until it is made again. It is kept from its last start, so a stopped computer's can be older than the service's until it starts. Compare it with the service's to show that a computer runs an older program."
|
|
87896
|
+
},
|
|
87808
87897
|
"browser": {
|
|
87809
87898
|
"type": "boolean"
|
|
87810
87899
|
},
|
|
@@ -87898,6 +87987,7 @@ var OPERATIONS = [
|
|
|
87898
87987
|
"state",
|
|
87899
87988
|
"access",
|
|
87900
87989
|
"isolation",
|
|
87990
|
+
"version",
|
|
87901
87991
|
"browser",
|
|
87902
87992
|
"workspace",
|
|
87903
87993
|
"startedAt",
|
|
@@ -87939,6 +88029,13 @@ var OPERATIONS = [
|
|
|
87939
88029
|
],
|
|
87940
88030
|
"description": "The isolation it was made in. It is never run in another."
|
|
87941
88031
|
},
|
|
88032
|
+
"version": {
|
|
88033
|
+
"type": [
|
|
88034
|
+
"string",
|
|
88035
|
+
"null"
|
|
88036
|
+
],
|
|
88037
|
+
"description": "The version of the program it ran at its last start. With no isolation it is the service's `version` (see `getInfo`). In a container it is the version inside its image, and null for a container made before 0.0.17, which doesn't say, until it is made again. It is kept from its last start, so a stopped computer's can be older than the service's until it starts. Compare it with the service's to show that a computer runs an older program."
|
|
88038
|
+
},
|
|
87942
88039
|
"browser": {
|
|
87943
88040
|
"type": "boolean"
|
|
87944
88041
|
},
|
|
@@ -88037,6 +88134,7 @@ var OPERATIONS = [
|
|
|
88037
88134
|
"state",
|
|
88038
88135
|
"access",
|
|
88039
88136
|
"isolation",
|
|
88137
|
+
"version",
|
|
88040
88138
|
"browser",
|
|
88041
88139
|
"workspace",
|
|
88042
88140
|
"startedAt",
|
|
@@ -88078,6 +88176,13 @@ var OPERATIONS = [
|
|
|
88078
88176
|
],
|
|
88079
88177
|
"description": "The isolation it was made in. It is never run in another."
|
|
88080
88178
|
},
|
|
88179
|
+
"version": {
|
|
88180
|
+
"type": [
|
|
88181
|
+
"string",
|
|
88182
|
+
"null"
|
|
88183
|
+
],
|
|
88184
|
+
"description": "The version of the program it ran at its last start. With no isolation it is the service's `version` (see `getInfo`). In a container it is the version inside its image, and null for a container made before 0.0.17, which doesn't say, until it is made again. It is kept from its last start, so a stopped computer's can be older than the service's until it starts. Compare it with the service's to show that a computer runs an older program."
|
|
88185
|
+
},
|
|
88081
88186
|
"browser": {
|
|
88082
88187
|
"type": "boolean"
|
|
88083
88188
|
},
|
|
@@ -88491,7 +88596,7 @@ ${JSON.stringify({ code: status, message })}
|
|
|
88491
88596
|
const scheme = options.tls ? "https" : "http";
|
|
88492
88597
|
base = options.publicUrl?.replace(/\/+$/, "") ?? `${scheme}://${bound.family === "IPv6" ? `[${bound.address}]` : bound.address}:${bound.port}`;
|
|
88493
88598
|
const record3 = recordOf(data);
|
|
88494
|
-
|
|
88599
|
+
rmSync6(record3, { force: true });
|
|
88495
88600
|
await computers.resume();
|
|
88496
88601
|
writePrivate(
|
|
88497
88602
|
record3,
|
|
@@ -88507,7 +88612,7 @@ ${JSON.stringify({ code: status, message })}
|
|
|
88507
88612
|
process.stderr.write(`${String(error62)}
|
|
88508
88613
|
`);
|
|
88509
88614
|
});
|
|
88510
|
-
|
|
88615
|
+
rmSync6(record3, { force: true });
|
|
88511
88616
|
process.exit(0);
|
|
88512
88617
|
};
|
|
88513
88618
|
for (const signal of ["SIGINT", "SIGTERM"]) process.once(signal, () => void stop());
|
|
@@ -231,6 +231,8 @@ export interface components {
|
|
|
231
231
|
access: components["schemas"]["Access"];
|
|
232
232
|
/** @description The isolation it was made in. It is never run in another. */
|
|
233
233
|
isolation: components["schemas"]["Isolation"];
|
|
234
|
+
/** @description The version of the program it ran at its last start. With no isolation it is the service's `version` (see `getInfo`). In a container it is the version inside its image, and null for a container made before 0.0.17, which doesn't say, until it is made again. It is kept from its last start, so a stopped computer's can be older than the service's until it starts. Compare it with the service's to show that a computer runs an older program. */
|
|
235
|
+
version: string | null;
|
|
234
236
|
browser: boolean;
|
|
235
237
|
workspace: string | null;
|
|
236
238
|
/**
|
package/dist/types/sdk.d.ts
CHANGED
|
@@ -174,6 +174,7 @@ export declare class Computer {
|
|
|
174
174
|
state: components["schemas"]["ComputerState"];
|
|
175
175
|
access: components["schemas"]["Access"];
|
|
176
176
|
isolation: components["schemas"]["Isolation"];
|
|
177
|
+
version: string | null;
|
|
177
178
|
browser: boolean;
|
|
178
179
|
workspace: string | null;
|
|
179
180
|
startedAt: string;
|
|
@@ -195,6 +196,7 @@ export declare class Computer {
|
|
|
195
196
|
state: components["schemas"]["ComputerState"];
|
|
196
197
|
access: components["schemas"]["Access"];
|
|
197
198
|
isolation: components["schemas"]["Isolation"];
|
|
199
|
+
version: string | null;
|
|
198
200
|
browser: boolean;
|
|
199
201
|
workspace: string | null;
|
|
200
202
|
startedAt: string;
|
|
@@ -208,6 +210,7 @@ export declare class Computer {
|
|
|
208
210
|
state: components["schemas"]["ComputerState"];
|
|
209
211
|
access: components["schemas"]["Access"];
|
|
210
212
|
isolation: components["schemas"]["Isolation"];
|
|
213
|
+
version: string | null;
|
|
211
214
|
browser: boolean;
|
|
212
215
|
workspace: string | null;
|
|
213
216
|
startedAt: string;
|
|
@@ -223,6 +226,7 @@ export declare class Computer {
|
|
|
223
226
|
state: components["schemas"]["ComputerState"];
|
|
224
227
|
access: components["schemas"]["Access"];
|
|
225
228
|
isolation: components["schemas"]["Isolation"];
|
|
229
|
+
version: string | null;
|
|
226
230
|
browser: boolean;
|
|
227
231
|
workspace: string | null;
|
|
228
232
|
startedAt: string;
|