@agentorg/computer 0.0.15 → 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 +1 -2
- package/dist/agentcomputer.js +132 -56
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ The file tools stay inside the workspace. That's a check, not a boundary. Below
|
|
|
66
66
|
|
|
67
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
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. 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.
|
|
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.
|
|
70
70
|
|
|
71
71
|
## Commands
|
|
72
72
|
|
|
@@ -214,7 +214,6 @@ A shell of your own needs [node-pty](https://github.com/microsoft/node-pty), an
|
|
|
214
214
|
|
|
215
215
|
## Known limits
|
|
216
216
|
|
|
217
|
-
- 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.
|
|
218
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.
|
|
219
218
|
- In a container the browser runs without its own sandbox, which needs privileges a computer doesn't have. The container is the boundary.
|
|
220
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.
|
package/dist/agentcomputer.js
CHANGED
|
@@ -3804,44 +3804,73 @@ async function hostBrowser(options) {
|
|
|
3804
3804
|
}
|
|
3805
3805
|
|
|
3806
3806
|
// src/browser-mcp.ts
|
|
3807
|
+
import { mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "node:fs";
|
|
3807
3808
|
import { createRequire as createRequire2 } from "node:module";
|
|
3809
|
+
import { join as join2 } from "node:path";
|
|
3808
3810
|
var require2 = createRequire2(import.meta.url);
|
|
3809
3811
|
var mcpParts = () => require2("playwright-core/lib/coreBundle").tools;
|
|
3812
|
+
function listenOnSocket(socket) {
|
|
3813
|
+
const http = require2("node:http");
|
|
3814
|
+
const make = http.createServer;
|
|
3815
|
+
http.createServer = ((...args) => {
|
|
3816
|
+
http.createServer = make;
|
|
3817
|
+
const server = make(...args);
|
|
3818
|
+
const listen = server.listen.bind(server);
|
|
3819
|
+
server.listen = (() => listen(socket));
|
|
3820
|
+
server.address = () => ({ address: "127.0.0.1", family: "IPv4", port: 0 });
|
|
3821
|
+
return server;
|
|
3822
|
+
});
|
|
3823
|
+
}
|
|
3810
3824
|
async function serveBrowserMcp(options) {
|
|
3811
3825
|
const parts = mcpParts();
|
|
3812
3826
|
parts.setupExitWatchdog();
|
|
3827
|
+
const folder = mkdtempSync2(join2("/tmp", "agentcomputer-"));
|
|
3828
|
+
process.once("exit", () => rmSync2(folder, { recursive: true, force: true }));
|
|
3829
|
+
const socket = join2(folder, "mcp.sock");
|
|
3813
3830
|
const config3 = await parts.resolveCLIConfigForMCP({
|
|
3814
3831
|
endpoint: options.endpoint,
|
|
3815
3832
|
outputDir: options.outputDir,
|
|
3816
3833
|
host: "127.0.0.1",
|
|
3817
3834
|
port: 0,
|
|
3835
|
+
// What the proxy sends, which is all that can reach the socket.
|
|
3836
|
+
allowedHosts: ["localhost"],
|
|
3818
3837
|
// The tool that closes the browser refuses, as it does for any browser its clients share.
|
|
3819
3838
|
sharedBrowserContext: true
|
|
3820
3839
|
});
|
|
3821
3840
|
const tools = parts.filteredTools(config3);
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3841
|
+
listenOnSocket(socket);
|
|
3842
|
+
const say = console.error;
|
|
3843
|
+
console.error = () => {
|
|
3844
|
+
};
|
|
3845
|
+
try {
|
|
3846
|
+
await parts.start(
|
|
3847
|
+
{
|
|
3848
|
+
name: "Playwright",
|
|
3849
|
+
nameInConfig: "playwright",
|
|
3850
|
+
// playwright-core's, as Playwright MCP's program gives it.
|
|
3851
|
+
version: require2("playwright-core/package.json").version,
|
|
3852
|
+
toolSchemas: tools.map((tool) => tool.schema),
|
|
3853
|
+
ignoreRoots: config3.ignoreRoots,
|
|
3854
|
+
/** One for each client's session: a connection of its own to the one browser. */
|
|
3855
|
+
create: async () => {
|
|
3856
|
+
const browser = await playwright().chromium.connect(options.endpoint);
|
|
3857
|
+
const context = browser.contexts()[0];
|
|
3858
|
+
if (!context) {
|
|
3859
|
+
await browser.close();
|
|
3860
|
+
throw new Error("The browser has no context to work in.");
|
|
3861
|
+
}
|
|
3862
|
+
return new parts.BrowserBackend(config3, context, tools, {
|
|
3863
|
+
dispose: () => browser.close()
|
|
3864
|
+
});
|
|
3865
|
+
}
|
|
3866
|
+
},
|
|
3867
|
+
config3.server
|
|
3868
|
+
);
|
|
3869
|
+
} finally {
|
|
3870
|
+
console.error = say;
|
|
3871
|
+
}
|
|
3872
|
+
process.stdout.write(`${JSON.stringify({ socket })}
|
|
3873
|
+
`);
|
|
3845
3874
|
}
|
|
3846
3875
|
|
|
3847
3876
|
// src/container.ts
|
|
@@ -3856,7 +3885,9 @@ import { promisify as promisify2 } from "node:util";
|
|
|
3856
3885
|
|
|
3857
3886
|
// src/browser.ts
|
|
3858
3887
|
import { spawn } from "node:child_process";
|
|
3859
|
-
import {
|
|
3888
|
+
import { rmSync as rmSync3 } from "node:fs";
|
|
3889
|
+
import { request as ask } from "node:http";
|
|
3890
|
+
import { dirname, join as join3 } from "node:path";
|
|
3860
3891
|
import { createInterface } from "node:readline";
|
|
3861
3892
|
import { pipeline, Readable } from "node:stream";
|
|
3862
3893
|
import { fileURLToPath } from "node:url";
|
|
@@ -27982,6 +28013,42 @@ function sendAnswer(upstream, response) {
|
|
|
27982
28013
|
pipeline(Readable.fromWeb(upstream.body), response, () => {
|
|
27983
28014
|
});
|
|
27984
28015
|
}
|
|
28016
|
+
function socketFetch(socket) {
|
|
28017
|
+
return (url3, init = {}) => new Promise((done, failed) => {
|
|
28018
|
+
const { body } = init;
|
|
28019
|
+
if (body != null && typeof body !== "string" && !(body instanceof Uint8Array))
|
|
28020
|
+
return failed(new TypeError("A body to the browser's server is text or bytes."));
|
|
28021
|
+
const { pathname, search: search2 } = new URL(url3);
|
|
28022
|
+
const headers = Object.fromEntries(new Headers(init.headers));
|
|
28023
|
+
if (body != null) headers["content-length"] = String(Buffer.byteLength(body));
|
|
28024
|
+
const sent = ask(
|
|
28025
|
+
{
|
|
28026
|
+
socketPath: socket,
|
|
28027
|
+
path: pathname + search2,
|
|
28028
|
+
method: init.method ?? "GET",
|
|
28029
|
+
headers,
|
|
28030
|
+
signal: init.signal ?? void 0
|
|
28031
|
+
},
|
|
28032
|
+
(answer) => {
|
|
28033
|
+
const answered2 = new Headers();
|
|
28034
|
+
for (const [name, value] of Object.entries(answer.headers))
|
|
28035
|
+
for (const one of [value ?? []].flat()) answered2.append(name, one);
|
|
28036
|
+
const status = answer.statusCode ?? 502;
|
|
28037
|
+
const none2 = [204, 205, 304].includes(status);
|
|
28038
|
+
if (none2) answer.resume();
|
|
28039
|
+
done(
|
|
28040
|
+
new Response(none2 ? null : Readable.toWeb(answer), {
|
|
28041
|
+
status,
|
|
28042
|
+
headers: answered2
|
|
28043
|
+
})
|
|
28044
|
+
);
|
|
28045
|
+
}
|
|
28046
|
+
);
|
|
28047
|
+
sent.on("error", failed);
|
|
28048
|
+
sent.end(body ?? void 0);
|
|
28049
|
+
});
|
|
28050
|
+
}
|
|
28051
|
+
var MCP = "http://localhost/mcp";
|
|
27985
28052
|
var self = fileURLToPath(import.meta.url);
|
|
27986
28053
|
function changed(text3, change) {
|
|
27987
28054
|
const one = (json4) => {
|
|
@@ -28016,7 +28083,10 @@ async function end(child) {
|
|
|
28016
28083
|
var Browser = class {
|
|
28017
28084
|
#host;
|
|
28018
28085
|
#mcp;
|
|
28019
|
-
|
|
28086
|
+
/** Where its server answers, by way of its Unix socket. */
|
|
28087
|
+
#served;
|
|
28088
|
+
/** The folder its server made for its socket. */
|
|
28089
|
+
#socketFolder;
|
|
28020
28090
|
/** The bound browser's socket, for the live viewer. */
|
|
28021
28091
|
endpoint;
|
|
28022
28092
|
#hidden;
|
|
@@ -28038,7 +28108,7 @@ var Browser = class {
|
|
|
28038
28108
|
self,
|
|
28039
28109
|
"browser-host",
|
|
28040
28110
|
"--profile",
|
|
28041
|
-
|
|
28111
|
+
join3(folder, "profile"),
|
|
28042
28112
|
...config3.path ? ["--executable", config3.path] : ["--channel", config3.browser ?? "chrome"],
|
|
28043
28113
|
...config3.sandbox === false ? ["--no-sandbox"] : []
|
|
28044
28114
|
],
|
|
@@ -28061,12 +28131,12 @@ var Browser = class {
|
|
|
28061
28131
|
});
|
|
28062
28132
|
this.endpoint.catch(() => {
|
|
28063
28133
|
});
|
|
28064
|
-
this.#
|
|
28134
|
+
this.#served = this.endpoint.then(
|
|
28065
28135
|
(endpoint) => new Promise((done, failed) => {
|
|
28066
28136
|
if (this.#stopping) return failed(new Error("It stopped."));
|
|
28067
28137
|
const mcp = spawn(
|
|
28068
28138
|
process.execPath,
|
|
28069
|
-
[self, "browser-mcp", "--endpoint", endpoint, "--output",
|
|
28139
|
+
[self, "browser-mcp", "--endpoint", endpoint, "--output", join3(folder, "output")],
|
|
28070
28140
|
// Its own limit on which files it touches is the folder it starts in.
|
|
28071
28141
|
{ cwd, stdio: ["ignore", "pipe", "pipe"] }
|
|
28072
28142
|
);
|
|
@@ -28077,34 +28147,39 @@ var Browser = class {
|
|
|
28077
28147
|
(code) => failed(new Error(`The browser's server exited with ${code}.`))
|
|
28078
28148
|
);
|
|
28079
28149
|
mcp.once("exit", ended("The browser's server"));
|
|
28080
|
-
|
|
28081
|
-
|
|
28150
|
+
createInterface({ input: mcp.stdout }).on("line", (line) => {
|
|
28151
|
+
try {
|
|
28152
|
+
const { socket } = JSON.parse(line);
|
|
28153
|
+
log(`The browser's server is on ${socket}.`);
|
|
28154
|
+
this.#socketFolder = dirname(socket);
|
|
28155
|
+
done(socketFetch(socket));
|
|
28156
|
+
} catch {
|
|
28082
28157
|
log(line);
|
|
28083
|
-
|
|
28084
|
-
|
|
28085
|
-
|
|
28158
|
+
}
|
|
28159
|
+
});
|
|
28160
|
+
createInterface({ input: mcp.stderr }).on("line", log);
|
|
28086
28161
|
})
|
|
28087
28162
|
);
|
|
28088
|
-
this.#
|
|
28163
|
+
this.#served.catch(() => {
|
|
28089
28164
|
});
|
|
28090
28165
|
}
|
|
28091
28166
|
/** Wait until it answers, and read its tools. */
|
|
28092
28167
|
async ready() {
|
|
28093
|
-
const
|
|
28094
|
-
this.#
|
|
28168
|
+
const served = await Promise.race([
|
|
28169
|
+
this.#served,
|
|
28095
28170
|
new Promise(
|
|
28096
28171
|
(_, failed) => setTimeout(() => failed(new Error("The browser's server didn't start.")), START_MS)
|
|
28097
28172
|
)
|
|
28098
28173
|
]);
|
|
28099
28174
|
const client = new Client({ name: "agentcomputer", version: "0" });
|
|
28100
|
-
await client.connect(new StreamableHTTPClientTransport(new URL(
|
|
28175
|
+
await client.connect(new StreamableHTTPClientTransport(new URL(MCP), { fetch: served }));
|
|
28101
28176
|
const { tools } = await client.listTools();
|
|
28102
28177
|
await client.close();
|
|
28103
28178
|
this.tools = tools.map((tool) => tool.name).filter((name) => !this.#hidden.has(name));
|
|
28104
28179
|
}
|
|
28105
28180
|
/** Answer one MCP request by passing it on, enforcing what this computer may not do. */
|
|
28106
28181
|
async handle(request, response) {
|
|
28107
|
-
const
|
|
28182
|
+
const served = await this.#served;
|
|
28108
28183
|
const chunks = [];
|
|
28109
28184
|
let size = 0;
|
|
28110
28185
|
for await (const chunk of request) {
|
|
@@ -28148,7 +28223,7 @@ var Browser = class {
|
|
|
28148
28223
|
const session = headers["mcp-session-id"] ?? "";
|
|
28149
28224
|
if (request.method === "DELETE") this.gate?.sessionEnded(session);
|
|
28150
28225
|
if (tool && this.gate?.takeAnsweredChooser(session) && tool !== "browser_file_upload")
|
|
28151
|
-
await
|
|
28226
|
+
await served(MCP, {
|
|
28152
28227
|
method: "POST",
|
|
28153
28228
|
headers,
|
|
28154
28229
|
body: JSON.stringify({
|
|
@@ -28161,7 +28236,7 @@ var Browser = class {
|
|
|
28161
28236
|
});
|
|
28162
28237
|
if (tool === "browser_file_upload") this.gate?.agentAnsweredChooser();
|
|
28163
28238
|
if (message) headers["content-type"] = "application/json";
|
|
28164
|
-
const upstream = await
|
|
28239
|
+
const upstream = await served(MCP, {
|
|
28165
28240
|
method: request.method,
|
|
28166
28241
|
headers,
|
|
28167
28242
|
...message ? { body: JSON.stringify(message) } : {}
|
|
@@ -28176,6 +28251,7 @@ var Browser = class {
|
|
|
28176
28251
|
async stop() {
|
|
28177
28252
|
this.#stopping = true;
|
|
28178
28253
|
await Promise.all([this.#mcp, this.#host].map((child) => child ? end(child) : void 0));
|
|
28254
|
+
if (this.#socketFolder) rmSync3(this.#socketFolder, { recursive: true, force: true });
|
|
28179
28255
|
}
|
|
28180
28256
|
};
|
|
28181
28257
|
|
|
@@ -28188,7 +28264,7 @@ import { join as join7 } from "node:path";
|
|
|
28188
28264
|
import { chmodSync as chmodSync2, existsSync, statSync as statSync2 } from "node:fs";
|
|
28189
28265
|
import { createRequire as createRequire3 } from "node:module";
|
|
28190
28266
|
import { hostname as hostname3 } from "node:os";
|
|
28191
|
-
import { basename as basename2, dirname as
|
|
28267
|
+
import { basename as basename2, dirname as dirname4, join as join6 } from "node:path";
|
|
28192
28268
|
|
|
28193
28269
|
// node_modules/@agentorg/exec/dist/lib.js
|
|
28194
28270
|
import { realpathSync } from "node:fs";
|
|
@@ -28198,7 +28274,7 @@ import { Http2ServerRequest, constants } from "node:http2";
|
|
|
28198
28274
|
import { Readable as Readable2 } from "node:stream";
|
|
28199
28275
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
28200
28276
|
import { lstat as lstat2, open as open3, readdir as readdir2, rename as rename2, rm as rm2, stat as stat2 } from "node:fs/promises";
|
|
28201
|
-
import { dirname as dirname2, join as
|
|
28277
|
+
import { dirname as dirname2, join as join32 } from "node:path";
|
|
28202
28278
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
28203
28279
|
import {
|
|
28204
28280
|
chmod,
|
|
@@ -28212,7 +28288,7 @@ import {
|
|
|
28212
28288
|
stat,
|
|
28213
28289
|
writeFile
|
|
28214
28290
|
} from "node:fs/promises";
|
|
28215
|
-
import { basename, dirname, join as join4, resolve, sep as sep2 } from "node:path";
|
|
28291
|
+
import { basename, dirname as dirname3, join as join4, resolve, sep as sep2 } from "node:path";
|
|
28216
28292
|
import { spawn as spawn2 } from "node:child_process";
|
|
28217
28293
|
import { randomBytes } from "node:crypto";
|
|
28218
28294
|
import { StringDecoder } from "node:string_decoder";
|
|
@@ -66245,7 +66321,7 @@ async function inside(root, path) {
|
|
|
66245
66321
|
() => false
|
|
66246
66322
|
))
|
|
66247
66323
|
throw refused2();
|
|
66248
|
-
const above =
|
|
66324
|
+
const above = dirname3(at);
|
|
66249
66325
|
if (above === at) throw refused2();
|
|
66250
66326
|
return join4(await real(above), basename(at));
|
|
66251
66327
|
}
|
|
@@ -66333,7 +66409,7 @@ ${cut(shown.join("\n"), MAX_READ_CHARS)}`;
|
|
|
66333
66409
|
after = before.split(input2.old_text).join(input2.new_text);
|
|
66334
66410
|
}
|
|
66335
66411
|
if (after === before) throw new ExecRefused("That edit changes nothing.");
|
|
66336
|
-
const temporary = join4(
|
|
66412
|
+
const temporary = join4(dirname3(path), `.agentexec-${randomBytes2(6).toString("hex")}`);
|
|
66337
66413
|
try {
|
|
66338
66414
|
await writeFile(temporary, after, found ? { mode: found.mode } : {});
|
|
66339
66415
|
if (found) await chmod(temporary, found.mode & 511);
|
|
@@ -66472,7 +66548,7 @@ function createHostFiles(root, level) {
|
|
|
66472
66548
|
found.sort(foldersFirst);
|
|
66473
66549
|
const entries = await Promise.all(
|
|
66474
66550
|
found.slice(0, MAX_ENTRIES).map(async (entry) => {
|
|
66475
|
-
const own22 = await lstat2(
|
|
66551
|
+
const own22 = await lstat2(join32(folder, entry.name)).catch(() => void 0);
|
|
66476
66552
|
return own22 && {
|
|
66477
66553
|
name: entry.name,
|
|
66478
66554
|
kind: entry.isDirectory() ? "folder" : entry.isSymbolicLink() ? "link" : "file",
|
|
@@ -66519,7 +66595,7 @@ function createHostFiles(root, level) {
|
|
|
66519
66595
|
});
|
|
66520
66596
|
if (before?.isDirectory()) throw new ExecRefused(`${path} is a folder.`);
|
|
66521
66597
|
await stat2(dirname2(target));
|
|
66522
|
-
const temporary =
|
|
66598
|
+
const temporary = join32(dirname2(target), `.agentexec-${randomBytes3(6).toString("hex")}`);
|
|
66523
66599
|
const file2 = await open3(temporary, "wx");
|
|
66524
66600
|
const discard = async () => {
|
|
66525
66601
|
await file2.close().catch(() => {
|
|
@@ -67773,7 +67849,7 @@ var loadPty = () => {
|
|
|
67773
67849
|
} catch {
|
|
67774
67850
|
return fails("node-pty isn't installed with this service.");
|
|
67775
67851
|
}
|
|
67776
|
-
const root =
|
|
67852
|
+
const root = dirname4(require3.resolve("node-pty/package.json"));
|
|
67777
67853
|
for (const helper of [
|
|
67778
67854
|
join6(root, "prebuilds", `${process.platform}-${process.arch}`, "spawn-helper"),
|
|
67779
67855
|
join6(root, "build", "Release", "spawn-helper")
|
|
@@ -68203,7 +68279,7 @@ async function forward(url3, authorization, request, response) {
|
|
|
68203
68279
|
}
|
|
68204
68280
|
|
|
68205
68281
|
// src/handlers.ts
|
|
68206
|
-
var VERSION2 = "0.0.
|
|
68282
|
+
var VERSION2 = "0.0.16";
|
|
68207
68283
|
function createHandlers(computers) {
|
|
68208
68284
|
return {
|
|
68209
68285
|
getInfo: async () => ({
|
|
@@ -69101,7 +69177,7 @@ var Computer = class _Computer {
|
|
|
69101
69177
|
};
|
|
69102
69178
|
|
|
69103
69179
|
// src/service.ts
|
|
69104
|
-
import { readFileSync as readFileSync6, rmSync as
|
|
69180
|
+
import { readFileSync as readFileSync6, rmSync as rmSync5 } from "node:fs";
|
|
69105
69181
|
import {
|
|
69106
69182
|
createServer as createServer5,
|
|
69107
69183
|
STATUS_CODES as STATUS_CODES3
|
|
@@ -84921,7 +84997,7 @@ var NodeStreamableHTTPServerTransport2 = class {
|
|
|
84921
84997
|
|
|
84922
84998
|
// src/computers.ts
|
|
84923
84999
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
84924
|
-
import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync5, rmSync as
|
|
85000
|
+
import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync5, rmSync as rmSync4, statSync as statSync4 } from "node:fs";
|
|
84925
85001
|
import { isAbsolute, join as join10, resolve as resolve4 } from "node:path";
|
|
84926
85002
|
var READ = ["about", "read", "list", "search"];
|
|
84927
85003
|
var FILES = [...READ, "edit"];
|
|
@@ -85026,7 +85102,7 @@ var Computers = class {
|
|
|
85026
85102
|
this.#stored.delete(id);
|
|
85027
85103
|
await this.#runtimes[stored.isolation].remove(id).catch(() => {
|
|
85028
85104
|
});
|
|
85029
|
-
|
|
85105
|
+
rmSync4(this.#folder(id), { recursive: true, force: true });
|
|
85030
85106
|
throw refusalOf(error62);
|
|
85031
85107
|
}
|
|
85032
85108
|
this.#save();
|
|
@@ -85100,7 +85176,7 @@ var Computers = class {
|
|
|
85100
85176
|
}
|
|
85101
85177
|
this.#stored.delete(id);
|
|
85102
85178
|
this.#save();
|
|
85103
|
-
|
|
85179
|
+
rmSync4(this.#folder(id), { recursive: true, force: true });
|
|
85104
85180
|
}
|
|
85105
85181
|
logs(id) {
|
|
85106
85182
|
this.#found(id);
|
|
@@ -85271,7 +85347,7 @@ var OPENAPI = {
|
|
|
85271
85347
|
"openapi": "3.1.0",
|
|
85272
85348
|
"info": {
|
|
85273
85349
|
"title": "AgentComputer",
|
|
85274
|
-
"version": "0.0.
|
|
85350
|
+
"version": "0.0.16",
|
|
85275
85351
|
"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.",
|
|
85276
85352
|
"license": {
|
|
85277
85353
|
"name": "Apache-2.0",
|
|
@@ -88415,7 +88491,7 @@ ${JSON.stringify({ code: status, message })}
|
|
|
88415
88491
|
const scheme = options.tls ? "https" : "http";
|
|
88416
88492
|
base = options.publicUrl?.replace(/\/+$/, "") ?? `${scheme}://${bound.family === "IPv6" ? `[${bound.address}]` : bound.address}:${bound.port}`;
|
|
88417
88493
|
const record3 = recordOf(data);
|
|
88418
|
-
|
|
88494
|
+
rmSync5(record3, { force: true });
|
|
88419
88495
|
await computers.resume();
|
|
88420
88496
|
writePrivate(
|
|
88421
88497
|
record3,
|
|
@@ -88431,7 +88507,7 @@ ${JSON.stringify({ code: status, message })}
|
|
|
88431
88507
|
process.stderr.write(`${String(error62)}
|
|
88432
88508
|
`);
|
|
88433
88509
|
});
|
|
88434
|
-
|
|
88510
|
+
rmSync5(record3, { force: true });
|
|
88435
88511
|
process.exit(0);
|
|
88436
88512
|
};
|
|
88437
88513
|
for (const signal of ["SIGINT", "SIGTERM"]) process.once(signal, () => void stop());
|